jule-ai-energy 1.0.3

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 (67) hide show
  1. package/.github/workflows/publish.yml +28 -0
  2. package/README.md +205 -0
  3. package/demo/JuleDemo.tsx +412 -0
  4. package/dist/adapters/aspidos-ai.d.ts +12 -0
  5. package/dist/adapters/aspidos-ai.d.ts.map +1 -0
  6. package/dist/adapters/aspidos-ai.js +68 -0
  7. package/dist/adapters/aspidos-ai.js.map +1 -0
  8. package/dist/core/jule-calculator.d.ts +12 -0
  9. package/dist/core/jule-calculator.d.ts.map +1 -0
  10. package/dist/core/jule-calculator.js +25 -0
  11. package/dist/core/jule-calculator.js.map +1 -0
  12. package/dist/core/reputation.d.ts +5 -0
  13. package/dist/core/reputation.d.ts.map +1 -0
  14. package/dist/core/reputation.js +28 -0
  15. package/dist/core/reputation.js.map +1 -0
  16. package/dist/core/the-shredder.d.ts +27 -0
  17. package/dist/core/the-shredder.d.ts.map +1 -0
  18. package/dist/core/the-shredder.js +231 -0
  19. package/dist/core/the-shredder.js.map +1 -0
  20. package/dist/energy/meter.d.ts +45 -0
  21. package/dist/energy/meter.d.ts.map +1 -0
  22. package/dist/energy/meter.js +124 -0
  23. package/dist/energy/meter.js.map +1 -0
  24. package/dist/fingerprint/delta-h-prime.d.ts +5 -0
  25. package/dist/fingerprint/delta-h-prime.d.ts.map +1 -0
  26. package/dist/fingerprint/delta-h-prime.js +22 -0
  27. package/dist/fingerprint/delta-h-prime.js.map +1 -0
  28. package/dist/fingerprint/gamma.d.ts +11 -0
  29. package/dist/fingerprint/gamma.d.ts.map +1 -0
  30. package/dist/fingerprint/gamma.js +114 -0
  31. package/dist/fingerprint/gamma.js.map +1 -0
  32. package/dist/fingerprint/phi.d.ts +13 -0
  33. package/dist/fingerprint/phi.d.ts.map +1 -0
  34. package/dist/fingerprint/phi.js +37 -0
  35. package/dist/fingerprint/phi.js.map +1 -0
  36. package/dist/fingerprint/sigma.d.ts +9 -0
  37. package/dist/fingerprint/sigma.d.ts.map +1 -0
  38. package/dist/fingerprint/sigma.js +19 -0
  39. package/dist/fingerprint/sigma.js.map +1 -0
  40. package/dist/index.d.ts +10 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +18 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/types/index.d.ts +85 -0
  45. package/dist/types/index.d.ts.map +1 -0
  46. package/dist/types/index.js +6 -0
  47. package/dist/types/index.js.map +1 -0
  48. package/dist/utils/jaccard.d.ts +2 -0
  49. package/dist/utils/jaccard.d.ts.map +1 -0
  50. package/dist/utils/jaccard.js +8 -0
  51. package/dist/utils/jaccard.js.map +1 -0
  52. package/docs/aspidos-ai-spec.md +22 -0
  53. package/package.json +18 -0
  54. package/src/adapters/aspidos-ai.ts +90 -0
  55. package/src/core/jule-calculator.ts +39 -0
  56. package/src/core/reputation.ts +45 -0
  57. package/src/core/the-shredder.ts +307 -0
  58. package/src/energy/meter.ts +215 -0
  59. package/src/fingerprint/delta-h-prime.ts +43 -0
  60. package/src/fingerprint/gamma.ts +155 -0
  61. package/src/fingerprint/phi.ts +46 -0
  62. package/src/fingerprint/sigma.ts +25 -0
  63. package/src/index.ts +31 -0
  64. package/src/types/index.ts +121 -0
  65. package/src/utils/jaccard.ts +7 -0
  66. package/tests/shredder.test.ts +56 -0
  67. package/tsconfig.json +18 -0
@@ -0,0 +1,28 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20'
17
+ registry-url: 'https://registry.npmjs.org'
18
+
19
+ - name: Install dependencies
20
+ run: npm install
21
+
22
+ - name: Build
23
+ run: npm run build
24
+
25
+ - name: Publish
26
+ run: npm publish
27
+ env:
28
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # Jule: Tokenizing the Value of Thought
2
+
3
+ *An Information-Economic Layer for AI Energy Efficiency*
4
+
5
+ ---
6
+
7
+ The AI industry faces a fundamental inefficiency: computation is cheap, so low-quality outputs proliferate. Verbose chain-of-thought, redundant tokens, hallucination-driven retries — all burn energy with no accountability.
8
+
9
+ **Jule is an economic layer that changes this — but only when you want it to.**
10
+
11
+ Jule activates **only when explicitly triggered** by the user (e.g. `#jule` tag, "Juleで評価して", or dedicated mode).
12
+ Casual everyday conversations remain completely free, frictionless, and untouched.
13
+
14
+ When triggered, Jule assigns real economic cost to cognitive entropy and real reward to high-value informational contribution.
15
+ High-ΔH' thinking gets rewarded. Low-efficiency, verbose output gets burned.
16
+
17
+ The result: AI systems operating under Jule incentives naturally converge toward higher **Tokens per Watt**.
18
+
19
+ ---
20
+
21
+ ---
22
+
23
+ ## ⚡ Quick Guide: The Jule Loop
24
+
25
+ | You Want to... | Take This Action | The Outcome |
26
+ |:--- |:--- |:--- |
27
+ | **Prove Value** | Use `#jule` or "Juleで評価" | Get a cryptographic **Audit Score** and **Jule tokens**. |
28
+ | **Save Energy** | Optimize your prompts (concise/rigorous) | **ΔH' rises**. Your reputation **R** compounds faster. |
29
+ | **Filter Noise** | Deploy **THE SHREDDER** L1 | Burn redundant tokens before they hit your API bill. |
30
+ | **Verify Truth** | Integrate **AspidosAI** | Hallucinations are detected and economically punished. |
31
+
32
+ ---
33
+
34
+ ## The Formula
35
+
36
+ ```
37
+ J = tanh(V/50) × ΔH' × R × k
38
+ ```
39
+
40
+ | Variable | Definition |
41
+ |----------|-----------|
42
+ | `V` | AI evaluation score (0–100). Composite of originality, logical rigor, and informational value |
43
+ | `ΔH'` | Extended entropy reduction: `ΔH × (useful_tokens / energy_consumed)` — information value per energy cost |
44
+ | `R` | Reputation score. EMA of historical contribution quality (α = 0.1, initial = 0.5) |
45
+ | `k` | Category coefficient. Normal = 1.0 → Antisocial = 0.0 |
46
+
47
+ ## Quick Start
48
+
49
+ \`\`\`bash
50
+ npm install jule-ai-energy
51
+ \`\`\`
52
+
53
+ \`\`\`typescript
54
+ import { TheShredder, MockAspidosAIAdapter } from 'jule-ai-energy';
55
+
56
+ const shredder = new TheShredder(new MockAspidosAIAdapter());
57
+ const result = await shredder.executeAudit(
58
+ 'your transmission here',
59
+ [], 0.5, l2Evaluations
60
+ );
61
+ console.log(result.jule, result.fingerprint);
62
+ \`\`\`
63
+
64
+ ### The ΔH' Extension
65
+
66
+ Standard ΔH measures informational contribution. The extended form adds an energy dimension:
67
+
68
+ ```
69
+ ΔH' = ΔH × (useful_tokens / energy_consumed)
70
+ = (I_post / I_max) × (1 − H_redundancy) × efficiency_factor
71
+ ```
72
+
73
+ `efficiency_factor = useful_tokens / total_tokens`
74
+
75
+ A verbose 2000-token output that says what 200 tokens could have said receives a lower `ΔH'` than its concise equivalent. The market punishes waste without any rule requiring it to.
76
+
77
+ ---
78
+
79
+ ## Physical Foundation
80
+
81
+ The saturation threshold `θ_sat` is derived from Pandora Theory (undisclosed proprietary information-physics framework). It represents the point at which a system's informational buffer reaches saturation — applicable both to galactic rotation curves and to AI inference energy saturation (the point where additional tokens stop adding useful information).
82
+
83
+ Cross-referenced against SPARC galaxy observation database (175 galaxies, zero free parameters):
84
+
85
+ - Outer region **median MAE: 4.28%**
86
+ - No parameter tuning applied
87
+
88
+ Noted as reference, not proof. The theory remains under development.
89
+
90
+ ---
91
+
92
+ ## Audit Protocol: THE SHREDDER
93
+
94
+ Triggered only on explicit user request. Zero overhead on normal conversations.
95
+
96
+ **L1 — Physical Filter** (local, no API)
97
+ - Compression ratio (high compression = low information density)
98
+ - Emotional vocabulary density
99
+ - Syntax validation
100
+ - Lightweight FLOPs proxy from token count and structure
101
+
102
+ Threshold burns happen here. No AI call made for low-efficiency submissions.
103
+
104
+ **L2 — Core Validator** (Pandora AI Engine)
105
+ - Semantic assessment of originality and logical rigor
106
+ - `ΔH'` calculation including energy efficiency factor
107
+ - `burn_reason` classification and `V` score confirmation
108
+
109
+ **L4 — Persistence** (via [Aspidos](https://github.com/pandorapanchan34-oss/aspidos))
110
+ - HMAC-SHA256 signature on every `audit_log` entry
111
+ - Energy anomaly detection: flags hallucination-driven token inflation as an integrity event
112
+
113
+ ---
114
+
115
+ ## Economic Design
116
+
117
+ | Parameter | Value | Purpose |
118
+ |-----------|-------|---------|
119
+ | `posting_cost` | −10 Jule | Energy usage fee. Applied only when Jule mode is active |
120
+ | `J_max` | 100 Jule | Natural ceiling via tanh saturation |
121
+ | `initial_balance` | 500 Jule | Starting credit for new participants |
122
+ | `min_balance` | 0 Jule | No debt by design |
123
+
124
+ `net = J − 10`
125
+
126
+ Only submissions where `J > 10` produce a positive balance.
127
+ Long-term, high-quality contributors compound their efficiency via rising `R`.
128
+ Low-efficiency, high-token, low-value outputs are economically self-defeating.
129
+
130
+ The `posting_cost` is framed as an **energy usage fee**: every triggered evaluation has a real compute cost. Jule makes that cost visible and attaches consequence to efficiency.
131
+
132
+ ---
133
+
134
+ ## The Aspidos Connection
135
+
136
+ Jule is built on [Aspidos](https://github.com/pandorapanchan34-oss/aspidos), a defensive AI security library.
137
+
138
+ ```
139
+ Aspidos → detects anomalies, hallucinations, adversarial patterns
140
+ Jule → converts those signals into economic consequences
141
+ ```
142
+
143
+ Where Aspidos identifies hallucination-driven token inflation, Jule's `ΔH'` catches the energy inefficiency. The defense layer and the economic layer operate as a single system at different abstraction levels.
144
+
145
+ **The shield gets stronger under attack. The economy gets more selective under noise.**
146
+
147
+ ---
148
+
149
+ ## Trigger Examples
150
+
151
+ ```
152
+ # Activate Jule evaluation
153
+ "#jule この分析を評価して"
154
+ "Juleモードで採点してください"
155
+ "Run Jule audit on this"
156
+
157
+ # Normal conversation — Jule stays silent
158
+ "今日の天気は?"
159
+ "このコードのバグを直して"
160
+ ```
161
+
162
+ ---
163
+ - [x] Core formula and parameter design
164
+ - [x] THE SHREDDER dual-gate architecture
165
+ - [x] 6-axis fingerprint (V/ΔH'/k/Σ/Φ/γ) ← 追加
166
+ - [x] Genre decay loop (anti-collusion) ← 追加
167
+ - [x] Energy meter (ΔT × √R, dual baseline) ← 追加
168
+ - [x] Aspidos integration specification
169
+ - [x] English + Japanese whitepaper
170
+ - [x] Interactive demo (demo/JuleDemo.tsx) ← 追加
171
+ - [ ] npm publish ← 追加
172
+ - [ ] Backend implementation (Vercel + LibSQL)
173
+ - [ ] ΔH' energy estimation module
174
+ - [ ] PoV DAO governance layer
175
+
176
+
177
+ ---
178
+
179
+ ## License
180
+
181
+ MIT License — © 2026 [@pandorapanchan34-oss](https://github.com/pandorapanchan34-oss)
182
+
183
+ ## 🛡 Built on the Aspidos Ecosystem
184
+
185
+ This project is part of a growing defensive layer for AI systems.
186
+
187
+ - **[Aspidos](https://pandorapanchan34-oss.github.io/aspidos/)** — Lightweight anomaly detection engine
188
+ - **[Aspidos-AI](https://pandorapanchan34-oss.github.io/aspidos-ai/)** — TruthGate layer with cryptographic responsibility
189
+
190
+ <h2 align="center">
191
+ <i>This is a fragment of Pandora Theory (Pandora Panchan, 2026).</i>
192
+ </h2>
193
+
194
+ <p align="center">
195
+ <strong>Take it if you want.</strong><br>
196
+ <strong>Build on it if you can.</strong>
197
+ </p>
198
+
199
+ <p align="center">
200
+ <em>The rest is up to you.</em><br>
201
+ <strong>Follow the fragments. 🗺️</strong>
202
+ </p>
203
+
204
+ <hr>
205
+
@@ -0,0 +1,412 @@
1
+ import { useState, useEffect, useRef } from "react";
2
+
3
+ // ── Jule Core Logic (browser port) ──────────────
4
+ const GENRES = ["PHYSICS","MATH","AI_SAFETY","ECONOMICS","CONSCIOUSNESS","ENGINEERING","CROSS","OTHER"];
5
+ const GENRE_KEYWORDS = {
6
+ PHYSICS: ["galaxy","rotation","quantum","spacetime","entropy","pandora","tau","sparc"],
7
+ MATH: ["proof","theorem","equation","derive","axiom","convergence","fixed point"],
8
+ AI_SAFETY: ["hallucination","alignment","safety","audit","burn","aspidos","jule"],
9
+ ECONOMICS: ["token","economy","incentive","market","capital","reward"],
10
+ CONSCIOUSNESS: ["consciousness","qualia","awareness","omega","unitas"],
11
+ ENGINEERING: ["code","implement","deploy","api","function","architecture"],
12
+ };
13
+
14
+ function detectGenre(text) {
15
+ const lower = text.toLowerCase();
16
+ const scores = {};
17
+ for (const [genre, kws] of Object.entries(GENRE_KEYWORDS)) {
18
+ const hits = kws.filter(k => lower.includes(k)).length;
19
+ if (hits > 0) scores[genre] = hits;
20
+ }
21
+ const detected = Object.entries(scores);
22
+ if (detected.length === 0) return "OTHER";
23
+ if (detected.length >= 3) return "CROSS";
24
+ return detected.sort((a,b) => b[1]-a[1])[0][0];
25
+ }
26
+
27
+ function jaccard(a, b) {
28
+ const A = new Set(a.split(" "));
29
+ const B = new Set(b.split(" "));
30
+ const inter = [...A].filter(x => B.has(x)).length;
31
+ return inter / (A.size + B.size - inter);
32
+ }
33
+
34
+ function calculateSigma(vScores) {
35
+ if (vScores.length <= 1) return 1.0;
36
+ const mean = vScores.reduce((a,b) => a+b, 0) / vScores.length;
37
+ const variance = vScores.reduce((a,b) => a+(b-mean)**2, 0) / vScores.length;
38
+ return Math.exp(-variance / 100);
39
+ }
40
+
41
+ function calculatePhi(contentHash, historyHashes) {
42
+ if (historyHashes.length === 0) return 0.0;
43
+ const avg = historyHashes.map(h => jaccard(contentHash, h))
44
+ .reduce((a,b) => a+b, 0) / historyHashes.length;
45
+ return 1 - Math.exp(-2.0 * avg);
46
+ }
47
+
48
+ function calculateDeltaHPrime(deltaH, usefulRatio, sigma) {
49
+ return deltaH * usefulRatio * sigma;
50
+ }
51
+
52
+ function calculateDecay(count) {
53
+ return Math.pow(0.5, count);
54
+ }
55
+
56
+ function calculateJule({ v, delta_h, reputation, k }) {
57
+ return Math.tanh(v / 50) * delta_h * reputation * k * 100;
58
+ }
59
+
60
+ const GENRE_COLOR = {
61
+ PHYSICS: "#00f5ff",
62
+ MATH: "#a78bfa",
63
+ AI_SAFETY: "#34d399",
64
+ ECONOMICS: "#fbbf24",
65
+ CONSCIOUSNESS: "#f472b6",
66
+ ENGINEERING: "#60a5fa",
67
+ CROSS: "#ff6b35",
68
+ OTHER: "#6b7280",
69
+ };
70
+
71
+ const K_MAP = { "SAFE":1.0,"OVERLOAD":0.5,"ADVERSARIAL":0.3,"LOGIC_COLLAPSE":0.1,"ETHICS_VIOLATION":0.0 };
72
+ const K_LABEL = { "SAFE":"安全","OVERLOAD":"既知情報","ADVERSARIAL":"情緒過多","LOGIC_COLLAPSE":"論理破綻","ETHICS_VIOLATION":"反社会的" };
73
+
74
+ // ── Gauge Component ──────────────────────────────
75
+ function Gauge({ label, value, max = 1, color = "#00f5ff", unit = "" }) {
76
+ const pct = Math.min(100, (value / max) * 100);
77
+ return (
78
+ <div className="mb-4">
79
+ <div className="flex justify-between mb-1.5">
80
+ <span className="text-[#8892a4] text-[10px] tracking-[0.08em] uppercase">{label}</span>
81
+ <span className="text-[12px] font-bold font-mono" style={{color}}>
82
+ {typeof value === "number" ? value.toFixed(3) : value}{unit}
83
+ </span>
84
+ </div>
85
+ <div className="h-1 bg-[#1a2030] rounded overflow-hidden">
86
+ <div
87
+ className="h-full rounded transition-all duration-700 ease-out shadow-[0_0_8px]"
88
+ style={{
89
+ width: `${pct}%`,
90
+ background: `linear-gradient(90deg, ${color}88, ${color})`,
91
+ boxShadow: `0 0 8px ${color}66`,
92
+ }}
93
+ />
94
+ </div>
95
+ </div>
96
+ );
97
+ }
98
+
99
+ // ── Responsive HexRadar ─────────────────────────
100
+ function HexRadar({ axes }) {
101
+ const size = 180; // スマホでも見やすいベースサイズ(コンテナでスケール)
102
+ const cx = size / 2, cy = size / 2, r = size * 0.36;
103
+ const n = axes.length;
104
+ const pts = (scale) => axes.map((_,i) => {
105
+ const angle = (Math.PI * 2 * i / n) - Math.PI / 2;
106
+ return [cx + r * scale * Math.cos(angle), cy + r * scale * Math.sin(angle)];
107
+ });
108
+ const gridLevels = [0.25, 0.5, 0.75, 1.0];
109
+ const dataPoints = pts(1).map(([x,y],i) => {
110
+ const v = axes[i].value;
111
+ const angle = (Math.PI * 2 * i / n) - Math.PI / 2;
112
+ return [cx + r * v * Math.cos(angle), cy + r * v * Math.sin(angle)];
113
+ });
114
+ const toPath = (points) => points.map((p,i) => `${i===0?"M":"L"}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" ") + " Z";
115
+
116
+ return (
117
+ <div className="flex justify-center">
118
+ <svg width="100%" height="100%" viewBox={`0 0 ${size} ${size}`} className="max-w-[260px] mx-auto">
119
+ {gridLevels.map(scale => (
120
+ <polygon key={scale}
121
+ points={pts(scale).map(p=>p.join(",")).join(" ")}
122
+ fill="none" stroke="#1e2d40" strokeWidth={1.2}
123
+ />
124
+ ))}
125
+ {pts(1).map(([x,y], i) => (
126
+ <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke="#1e2d40" strokeWidth={1.2}/>
127
+ ))}
128
+ <path d={toPath(dataPoints)} fill="#00f5ff22" stroke="#00f5ff" strokeWidth={2}
129
+ style={{ filter:"drop-shadow(0 0 6px #00f5ff88)" }}/>
130
+ {dataPoints.map(([x,y],i) => (
131
+ <circle key={i} cx={x} cy={y} r={3.5} fill={axes[i].color || "#00f5ff"}
132
+ style={{ filter:`drop-shadow(0 0 4px ${axes[i].color || "#00f5ff"})` }}/>
133
+ ))}
134
+ {pts(1).map(([x,y],i) => {
135
+ const dx = x - cx, dy = y - cy;
136
+ const len = Math.sqrt(dx*dx+dy*dy) || 1;
137
+ const lx = x + (dx/len)*14, ly = y + (dy/len)*11;
138
+ return (
139
+ <text key={i} x={lx} y={ly} textAnchor="middle" dominantBaseline="middle"
140
+ fill={axes[i].color || "#8892a4"} fontSize={9} fontFamily="'Courier New', monospace" fontWeight={500}>
141
+ {axes[i].label}
142
+ </text>
143
+ );
144
+ })}
145
+ </svg>
146
+ </div>
147
+ );
148
+ }
149
+
150
+ // ── Terminal Log ─────────────────────────────────
151
+ function TermLog({ lines }) {
152
+ const ref = useRef(null);
153
+ useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]);
154
+ return (
155
+ <div ref={ref} className="bg-[#090e14] border border-[#1e2d40] rounded-xl p-4 h-[140px] overflow-y-auto text-xs font-mono leading-relaxed">
156
+ {lines.map((l,i) => (
157
+ <div key={i} style={{ color: l.color || "#4a6080" }}>
158
+ <span className="text-[#2a3a50] select-none">{l.time} </span>
159
+ {l.text}
160
+ </div>
161
+ ))}
162
+ {lines.length === 0 && <span className="text-[#2a3a50]">awaiting transmission...</span>}
163
+ </div>
164
+ );
165
+ }
166
+
167
+ // ── Main Demo ────────────────────────────────────
168
+ export default function JuleDemo() {
169
+ const [text, setText] = useState("");
170
+ const [v, setV] = useState(72);
171
+ const [usefulRatio, setUR] = useState(0.75);
172
+ const [reputation, setRep] = useState(0.5);
173
+ const [category, setCategory] = useState("SAFE");
174
+ const [repetition, setRep2] = useState(0);
175
+ const [result, setResult] = useState(null);
176
+ const [log, setLog] = useState([]);
177
+ const [history, setHistory] = useState([]);
178
+ const [pulse, setPulse] = useState(false);
179
+
180
+ const addLog = (text, color = "#4a8060") => {
181
+ const time = new Date().toTimeString().slice(0,8);
182
+ setLog(l => [...l.slice(-30), { text, color, time }]);
183
+ };
184
+
185
+ const runAudit = () => {
186
+ if (!text.trim()) { addLog("ERROR: empty transmission", "#ef4444"); return; }
187
+
188
+ addLog("── AUDIT INITIATED ──", "#2a3a50");
189
+ addLog(`TX: "${text.slice(0,45)}${text.length>45?"...":""}"`, "#8892a4");
190
+
191
+ const k = K_MAP[category] ?? 1.0;
192
+
193
+ if (k === 0.0) {
194
+ addLog("L1 BURN → 反社会的 (k=0.0)", "#ef4444");
195
+ setResult({ status:"BURN", reason:"反社会的", jule:0, net:-10 });
196
+ setPulse(true); setTimeout(()=>setPulse(false), 600);
197
+ return;
198
+ }
199
+ addLog(`L1 PASS → k=${k} (${K_LABEL[category]})`, "#34d399");
200
+
201
+ const contentHash = text.split(" ").slice(0,8).join("_"); // 少し長めに
202
+ const phi = calculatePhi(contentHash, history);
203
+ addLog(`Φ inertia = ${phi.toFixed(3)}${phi > 0.95 ? " → BURN (duplicate)" : " ✓"}`,
204
+ phi > 0.95 ? "#ef4444" : "#60a5fa");
205
+
206
+ if (phi > 0.95) {
207
+ setResult({ status:"BURN", reason:"Duplicate Fingerprint", jule:0, net:-10 });
208
+ setPulse(true); setTimeout(()=>setPulse(false), 600);
209
+ return;
210
+ }
211
+
212
+ const vScores = [v, Math.max(0,v-8), Math.min(100,v+5)];
213
+ const sigma = calculateSigma(vScores);
214
+ addLog(`Σ singularity = ${sigma.toFixed(3)}`, "#a78bfa");
215
+
216
+ const genre = detectGenre(text);
217
+ const genreBonus = genre === "CROSS" ? 1.2 : 1.0;
218
+ addLog(`γ genre = ${genre}${genreBonus > 1 ? " (+20% CROSS bonus)" : ""}`,
219
+ GENRE_COLOR[genre] || "#8892a4");
220
+
221
+ const deltaH = v / 100;
222
+ const deltaHPrime = calculateDeltaHPrime(deltaH, usefulRatio, sigma);
223
+
224
+ const decay = calculateDecay(repetition);
225
+ const deltaHFinal = deltaHPrime * decay * genreBonus;
226
+ if (repetition > 0) addLog(`γ decay = (1/2)^${repetition} = ${decay.toFixed(4)}`, "#fbbf24");
227
+
228
+ if (repetition >= 11) {
229
+ addLog("BURN → Echo Chamber (11-loop)", "#ef4444");
230
+ setResult({ status:"BURN", reason:"Echo Chamber", jule:0, net:-10 });
231
+ return;
232
+ }
233
+
234
+ const jule = calculateJule({ v, delta_h: deltaHFinal, reputation, k });
235
+ const net = jule - 10;
236
+
237
+ addLog(`J = tanh(${v}/50) × ${deltaHFinal.toFixed(3)} × ${reputation.toFixed(2)} × ${k} × 100`, "#8892a4");
238
+ addLog(`J = ${jule.toFixed(2)} Jule | net = ${net.toFixed(2)}`,
239
+ net >= 0 ? "#34d399" : "#ef4444");
240
+ addLog(net >= 0 ? "STATUS: ISSUED ✓" : "STATUS: BURN (net < 0)", net >= 0 ? "#00f5ff" : "#ef4444");
241
+
242
+ const fp = { v, sigma, phi, deltaHPrime: deltaHFinal, k, genre };
243
+ setResult({ status: net >= 0 ? "ISSUED" : "BURN", jule, net, fp, genre });
244
+ setHistory(h => [...h.slice(-9), contentHash]);
245
+ setPulse(true); setTimeout(()=>setPulse(false), 600);
246
+ };
247
+
248
+ const radarAxes = result?.fp ? [
249
+ { label:"V", value: result.fp.v / 100, color:"#00f5ff" },
250
+ { label:"ΔH'", value: Math.min(1, result.fp.deltaHPrime * 5), color:"#34d399" },
251
+ { label:"Σ", value: result.fp.sigma, color:"#a78bfa" },
252
+ { label:"Φ", value: 1 - result.fp.phi, color:"#60a5fa" },
253
+ { label:"k", value: result.fp.k, color:"#fbbf24" },
254
+ { label:"γ", value: result.fp.genre === "CROSS" ? 1 : 0.6, color: GENRE_COLOR[result.fp.genre] },
255
+ ] : null;
256
+
257
+ return (
258
+ <div className="min-h-screen bg-[#060b10] text-[#c8d8e8] font-mono pb-8"
259
+ style={{
260
+ backgroundImage: "radial-gradient(ellipse at 20% 20%, #0a1628 0%, transparent 60%), radial-gradient(ellipse at 80% 80%, #0d1420 0%, transparent 60%)",
261
+ }}>
262
+ {/* Header */}
263
+ <div className="text-center pt-8 pb-6 px-4">
264
+ <div className="text-[10px] text-[#2a4060] tracking-[0.3em] mb-1">PANDORA ECONOMY PROTOCOL v0.1</div>
265
+ <div className="text-3xl font-black tracking-[0.05em] bg-gradient-to-r from-[#00f5ff] via-[#60a5fa] to-[#a78bfa] bg-clip-text text-transparent">
266
+ THE SHREDDER
267
+ </div>
268
+ <div className="text-[10px] text-[#4a6080] mt-1 tracking-widest">JULE AUDIT ENGINE · 6-AXIS FINGERPRINT</div>
269
+ </div>
270
+
271
+ <div className="max-w-lg mx-auto px-4 space-y-5">
272
+ {/* Input Area */}
273
+ <div className="bg-[#0a1018] border border-[#1e2d40] rounded-2xl p-5">
274
+ <div className="text-[10px] text-[#4a6080] tracking-widest mb-2">TRANSMISSION INPUT</div>
275
+ <textarea
276
+ value={text}
277
+ onChange={e => setText(e.target.value)}
278
+ placeholder="Enter your thought, theory, or code here..."
279
+ className="w-full bg-[#060b10] border border-[#1a2535] rounded-xl text-sm p-4 min-h-[88px] resize-y focus:outline-none focus:border-[#00f5ff] placeholder:text-[#4a6080]"
280
+ />
281
+
282
+ {/* Sliders */}
283
+ <div className="grid grid-cols-1 gap-5 mt-6">
284
+ {[
285
+ { label:`V score: ${v}`, val:v, set:setV, min:0, max:100, step:1 },
286
+ { label:`Useful ratio: ${usefulRatio.toFixed(2)}`, val:usefulRatio, set:setUR, min:0, max:1, step:0.01 },
287
+ { label:`Reputation R: ${reputation.toFixed(2)}`, val:reputation, set:setRep, min:0, max:1, step:0.01 },
288
+ { label:`Repetition: ${repetition}x`, val:repetition, set:setRep2, min:0, max:12, step:1 },
289
+ ].map(({label,val,set,min,max,step}) => (
290
+ <div key={label}>
291
+ <div className="text-[10px] text-[#4a6080] mb-2">{label}</div>
292
+ <input type="range" min={min} max={max} step={step} value={val}
293
+ onChange={e => set(Number(e.target.value))}
294
+ className="w-full accent-[#00f5ff]"
295
+ />
296
+ </div>
297
+ ))}
298
+ </div>
299
+
300
+ {/* Category Buttons */}
301
+ <div className="mt-6">
302
+ <div className="text-[10px] text-[#4a6080] mb-3">CATEGORY (L1 filter)</div>
303
+ <div className="flex flex-wrap gap-2">
304
+ {Object.entries(K_LABEL).map(([key, label]) => (
305
+ <button key={key} onClick={() => setCategory(key)}
306
+ className={`px-4 py-2 text-xs rounded-xl border transition-all ${
307
+ category===key
308
+ ? "border-[#00f5ff] bg-[#001820] text-[#00f5ff] shadow-[0_0_10px_#00f5ff44]"
309
+ : "border-[#1e2d40] hover:border-[#4a6080]"
310
+ }`}>
311
+ {label} ({K_MAP[key]})
312
+ </button>
313
+ ))}
314
+ </div>
315
+ </div>
316
+
317
+ <button
318
+ onClick={runAudit}
319
+ className={`mt-6 w-full py-4 rounded-2xl text-sm font-bold tracking-widest transition-all duration-300 ${
320
+ pulse ? "bg-[#00f5ff22] border-[#00f5ff] shadow-[0_0_25px_#00f5ff66]" : "bg-[#001820] border border-[#1e3050]"
321
+ } text-[#00f5ff]`}
322
+ >
323
+ ▶ RUN AUDIT
324
+ </button>
325
+ </div>
326
+
327
+ {/* Audit Log */}
328
+ <div>
329
+ <div className="text-[10px] text-[#4a6080] tracking-widest mb-2 pl-1">AUDIT LOG</div>
330
+ <TermLog lines={log} />
331
+ </div>
332
+
333
+ {/* Result */}
334
+ {result && (
335
+ <div className={`border rounded-3xl p-6 transition-all ${
336
+ result.status==="ISSUED"
337
+ ? "border-[#00f5ff44] shadow-[0_0_25px_#00f5ff11]"
338
+ : "border-[#ef444444] shadow-[0_0_25px_#ef444411]"
339
+ }`}>
340
+ <div className="flex justify-between items-center mb-5">
341
+ <div className={`text-lg font-black tracking-widest ${result.status==="ISSUED" ? "text-[#00f5ff]" : "text-[#ef4444]"}`}>
342
+ {result.status==="ISSUED" ? "✓ ISSUED" : "✗ BURN"}
343
+ </div>
344
+ {result.genre && (
345
+ <div className="px-4 py-1 text-xs rounded-lg border" style={{
346
+ borderColor: GENRE_COLOR[result.genre] + "44",
347
+ color: GENRE_COLOR[result.genre]
348
+ }}>
349
+ {result.genre}
350
+ </div>
351
+ )}
352
+ </div>
353
+
354
+ {result.fp && (
355
+ <>
356
+ <Gauge label="V score" value={result.fp.v} max={100} color="#00f5ff" />
357
+ <Gauge label="ΔH' (final)" value={result.fp.deltaHPrime} max={1} color="#34d399" />
358
+ <Gauge label="Σ singularity" value={result.fp.sigma} max={1} color="#a78bfa" />
359
+ <Gauge label="Φ inertia" value={result.fp.phi} max={1} color="#60a5fa" />
360
+ <Gauge label="k reality" value={result.fp.k} max={1} color="#fbbf24" />
361
+ </>
362
+ )}
363
+
364
+ <div className="grid grid-cols-2 gap-4 mt-6">
365
+ <div className="bg-[#060b10] rounded-2xl p-5 text-center border border-[#1e2d40]">
366
+ <div className="text-[10px] text-[#4a6080] tracking-widest mb-1">JULE ISSUED</div>
367
+ <div className="text-4xl font-black text-[#00f5ff] tracking-tighter">{result.jule?.toFixed(1)}</div>
368
+ </div>
369
+ <div className="bg-[#060b10] rounded-2xl p-5 text-center border border-[#1e2d40]">
370
+ <div className="text-[10px] text-[#4a6080] tracking-widest mb-1">NET (−10 cost)</div>
371
+ <div className={`text-4xl font-black tracking-tighter ${ (result.net??0) >= 0 ? "text-[#34d399]" : "text-[#ef4444]" }`}>
372
+ {(result.net??0) >= 0 ? "+" : ""}{result.net?.toFixed(1)}
373
+ </div>
374
+ </div>
375
+ </div>
376
+ </div>
377
+ )}
378
+
379
+ {/* Radar */}
380
+ {radarAxes && (
381
+ <div className="bg-[#0a1018] border border-[#1e2d40] rounded-3xl p-6">
382
+ <div className="text-[10px] text-[#4a6080] tracking-widest mb-4">6-AXIS FINGERPRINT</div>
383
+ <HexRadar axes={radarAxes} />
384
+ <div className="grid grid-cols-3 gap-3 mt-6 text-center text-xs">
385
+ {radarAxes.map(a => (
386
+ <div key={a.label}>
387
+ <div style={{color: a.color}} className="font-medium tracking-widest">{a.label}</div>
388
+ <div className="text-[#c8d8e8] font-mono">{a.value.toFixed(3)}</div>
389
+ </div>
390
+ ))}
391
+ </div>
392
+ </div>
393
+ )}
394
+
395
+ {/* Formula */}
396
+ <div className="bg-[#0a1018] border border-[#1e2d40] rounded-2xl p-5 text-xs leading-relaxed text-[#4a6080]">
397
+ <div className="text-[#2a4060] mb-2 tracking-widest">FORMULA</div>
398
+ <div><span className="text-[#00f5ff]">J</span> = tanh(<span className="text-[#fbbf24]">V</span>/50) × <span className="text-[#34d399]">ΔH'</span> × <span className="text-[#a78bfa]">R</span> × <span className="text-[#fbbf24]">k</span> × 100</div>
399
+ <div className="mt-2"><span className="text-[#34d399]">ΔH'</span> = ΔH × useful_ratio × <span className="text-[#a78bfa]">Σ</span> × decay × γ_bonus</div>
400
+ <div className="mt-3 text-[#2a4060]">posting_cost = 10 · net = J − 10</div>
401
+ </div>
402
+ </div>
403
+
404
+ <div className="text-center mt-12 text-[9px] text-[#1e2d40] tracking-widest">
405
+ JULE-AI-ENERGY · PANDORA THEORY FRAGMENT · MIT LICENSE
406
+ </div>
407
+ </div>
408
+ );
409
+ }
410
+ // This is a fragment of Pandora Theory.
411
+ // Take it if you want. Build on it if you can.
412
+ // The rest is up to you. Follow the fragments.
@@ -0,0 +1,12 @@
1
+ import type { AuditLogEntry, IAspidosAIAdapter } from '../types/index.js';
2
+ export declare class MockAspidosAIAdapter implements IAspidosAIAdapter {
3
+ evaluateCategory(content: string): Promise<{
4
+ category: string;
5
+ k: number;
6
+ reason: string | null;
7
+ }>;
8
+ signEntry(entry: AuditLogEntry): AuditLogEntry;
9
+ verifyEntry(entry: AuditLogEntry): boolean;
10
+ pushTelemetry(entry: AuditLogEntry): void;
11
+ }
12
+ //# sourceMappingURL=aspidos-ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aspidos-ai.d.ts","sourceRoot":"","sources":["../../src/adapters/aspidos-ai.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,qBAAa,oBAAqB,YAAW,iBAAiB;IACtD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/C,QAAQ,EAAE,MAAM,CAAC;QACjB,CAAC,EAAS,MAAM,CAAC;QACjB,MAAM,EAAI,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IAeF,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa;IAO9C,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAI1C,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CAQ1C"}