enigma-cli 1.15.8 → 1.15.9
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.
- package/README.md +37 -7
- package/assets/dashboard/index.html +263 -51
- package/assets/skills/anti-overengineering-policy/SKILL.md +1 -0
- package/assets/skills/anti-overengineering-policy/skill.json +3 -3
- package/assets/skills/anti-overengineering-review/skill.json +1 -1
- package/assets/skills/backend-policy/skill.json +1 -1
- package/assets/skills/ciphera-style-policy/skill.json +1 -1
- package/assets/skills/code-review-policy/skill.json +1 -1
- package/assets/skills/core-engineering-policy/skill.json +1 -1
- package/assets/skills/database-expert/skill.json +1 -1
- package/assets/skills/debugging-policy/skill.json +1 -1
- package/assets/skills/dependency-policy/skill.json +1 -1
- package/assets/skills/frontend-design/skill.json +1 -1
- package/assets/skills/frontend-policy/skill.json +1 -1
- package/assets/skills/git-policy/skill.json +1 -1
- package/assets/skills/security-policy/skill.json +1 -1
- package/assets/skills/skill-creator/skill.json +1 -1
- package/assets/skills/task-completion-policy/skill.json +1 -1
- package/assets/skills/testing-policy/skill.json +1 -1
- package/assets/skills/validation-policy/skill.json +1 -1
- package/bin/checksums.json +4 -4
- package/bin/platform.mjs +8 -5
- package/package.json +1 -1
- /package/assets/dashboard/lib/{lightweight-charts.standalone.production.js → chart.min.js} +0 -0
package/README.md
CHANGED
|
@@ -8,18 +8,29 @@ committed.
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
agent at user level:
|
|
11
|
+
Recommended - install the `enigma` command globally, then run the interactive hub:
|
|
13
12
|
|
|
14
13
|
```bash
|
|
15
|
-
|
|
14
|
+
npm install -g enigma-cli@latest # provides the `enigma` command
|
|
15
|
+
enigma # interactive hub: pick what to set up
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or via the install script (clears the npm cache, installs the latest version, then
|
|
19
|
+
runs `enigma install` for you - handy where npm `postinstall` scripts are disabled):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# macOS / Linux
|
|
23
|
+
curl -fsSL https://raw.githubusercontent.com/FJRG2007/enigma/main/install.sh | sh
|
|
24
|
+
|
|
25
|
+
# Windows (PowerShell)
|
|
26
|
+
irm https://raw.githubusercontent.com/FJRG2007/enigma/main/install.ps1 | iex
|
|
16
27
|
```
|
|
17
28
|
|
|
18
|
-
Or install the
|
|
29
|
+
Or one-shot, no global install, no prompts - deploy the skills to every supported
|
|
30
|
+
agent at user level:
|
|
19
31
|
|
|
20
32
|
```bash
|
|
21
|
-
|
|
22
|
-
enigma # interactive hub: pick what to set up
|
|
33
|
+
npx enigma-cli@latest install --all --yes
|
|
23
34
|
```
|
|
24
35
|
|
|
25
36
|
That first install is the only one you ever need to run by hand: afterwards,
|
|
@@ -72,8 +83,11 @@ enigma account ... Manage per-tool accounts (list/add/use/login/remove)
|
|
|
72
83
|
enigma profile ... Group one account per tool (list/add/use/set/unset/remove)
|
|
73
84
|
enigma skills ... List skills and manage discards (list/discard/restore)
|
|
74
85
|
enigma compress [file] Compress JSON/logs/text to fewer tokens (reversible via CCR);
|
|
75
|
-
--retrieve <hash> restores, --stats shows total savings
|
|
86
|
+
--retrieve <hash> restores, --stats shows total savings,
|
|
87
|
+
--clear wipes all dashboard data (stats/history/cache)
|
|
76
88
|
enigma mcp Run the context-compression MCP server over stdio
|
|
89
|
+
enigma dashboard|dash Open the local savings dashboard in your browser (http://enigma,
|
|
90
|
+
or http://localhost:24282 if :80/hosts is unavailable)
|
|
77
91
|
enigma seal Maintenance: (re)compute skill content hashes
|
|
78
92
|
enigma check Integrity gate: verify skills are well-formed and sealed
|
|
79
93
|
enigma help | version
|
|
@@ -462,8 +476,24 @@ cat tool-output.json | enigma compress # compressed to stdout, savings to st
|
|
|
462
476
|
enigma compress big.log # compress a file
|
|
463
477
|
enigma compress --retrieve <hash> # restore a cached original
|
|
464
478
|
enigma compress --stats # cumulative token savings
|
|
479
|
+
enigma compress --clear # wipe all dashboard data (stats/history/cache)
|
|
465
480
|
```
|
|
466
481
|
|
|
482
|
+
### Savings dashboard
|
|
483
|
+
|
|
484
|
+
`enigma dashboard` (alias `dash`) serves a local, loopback-only browser dashboard
|
|
485
|
+
of the token savings - totals, **estimated money saved**, average/best per call, a
|
|
486
|
+
per-day graph (toggle tokens/$ and daily/cumulative), breakdowns by the app that
|
|
487
|
+
requested each compression (Claude Code, OpenCode, Codex, or the CLI) and by content
|
|
488
|
+
type (JSON/logs/text...), a daily/weekly/monthly savings history, a recent-compressions
|
|
489
|
+
table, and reversible-cache (CCR) stats. It runs only while open; `enigma config
|
|
490
|
+
dashboard always` keeps a lightweight background daemon, and `enigma compress --clear`
|
|
491
|
+
resets the data.
|
|
492
|
+
|
|
493
|
+
The money figure is an estimate: enigma isn't a proxy, so it can't see the model -
|
|
494
|
+
it prices saved tokens per source with sensible defaults. Override the rate with
|
|
495
|
+
`enigma config token-price <usd-per-1M-input-tokens>` (0 restores the defaults).
|
|
496
|
+
|
|
467
497
|
### As an MCP server
|
|
468
498
|
|
|
469
499
|
`enigma mcp` runs a stdio MCP server exposing three tools - `enigma_compress`,
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
.wordmark { font-size: 20px; font-weight: 700; letter-spacing: 0.5px; }
|
|
21
21
|
.wordmark span { color: var(--accent); }
|
|
22
22
|
.sub { color: var(--muted); font-size: 13px; }
|
|
23
|
-
.live {
|
|
23
|
+
.live { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; }
|
|
24
24
|
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); box-shadow: 0 0 8px var(--good); }
|
|
25
25
|
.dot.stale { background: var(--muted); box-shadow: none; }
|
|
26
|
-
.grid { display: grid; grid-template-columns: repeat(
|
|
26
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 20px; }
|
|
27
27
|
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 16px; }
|
|
28
28
|
.card .label { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.6px; }
|
|
29
29
|
.card .value { font-size: 28px; font-weight: 700; margin-top: 6px; }
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
.panel-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
|
|
35
35
|
.panel h2 { font-size: 14px; font-weight: 600; margin: 0; color: var(--text); }
|
|
36
36
|
.panel h2 small { color: var(--muted); font-weight: 400; margin-left: 8px; }
|
|
37
|
-
.
|
|
37
|
+
.ctrls { margin-left: auto; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
|
|
38
|
+
.ranges { display: flex; gap: 4px; }
|
|
38
39
|
.ranges button {
|
|
39
40
|
background: var(--surface2); color: var(--muted); border: 1px solid var(--border);
|
|
40
41
|
border-radius: 7px; padding: 4px 10px; font-size: 12px; cursor: pointer; font-family: inherit;
|
|
@@ -42,6 +43,13 @@
|
|
|
42
43
|
.ranges button:hover { color: var(--text); }
|
|
43
44
|
.ranges button.active { background: var(--accent); color: #1a1206; border-color: var(--accent); font-weight: 600; }
|
|
44
45
|
.chartwrap { position: relative; width: 100%; height: 280px; }
|
|
46
|
+
/* Suppress the charting library's attribution logo. */
|
|
47
|
+
#tv-attr-logo { display: none !important; }
|
|
48
|
+
.nav { margin-left: auto; display: flex; align-items: center; gap: 18px; }
|
|
49
|
+
.links { display: flex; gap: 14px; align-items: center; }
|
|
50
|
+
.links a { color: var(--muted); display: inline-flex; transition: color 0.15s; }
|
|
51
|
+
.links a:hover { color: var(--accent); }
|
|
52
|
+
.links svg { width: 19px; height: 19px; display: block; }
|
|
45
53
|
.tip {
|
|
46
54
|
position: absolute; pointer-events: none; z-index: 5; background: var(--surface2);
|
|
47
55
|
border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; font-size: 12px;
|
|
@@ -54,7 +62,18 @@
|
|
|
54
62
|
.bar-track { flex: 1; height: 14px; background: var(--surface2); border-radius: 7px; overflow: hidden; }
|
|
55
63
|
.bar-fill { height: 100%; border-radius: 7px; }
|
|
56
64
|
.bar-row .num { width: 90px; text-align: right; font-variant-numeric: tabular-nums; }
|
|
65
|
+
.bar-row .money { width: 78px; text-align: right; color: var(--good); font-variant-numeric: tabular-nums; }
|
|
57
66
|
.empty { color: var(--muted); font-size: 14px; text-align: center; padding: 40px 0; }
|
|
67
|
+
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
68
|
+
.tbl th { text-align: left; color: var(--muted); font-weight: 500; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; padding: 6px 10px; border-bottom: 1px solid var(--border); }
|
|
69
|
+
.tbl td { padding: 7px 10px; border-bottom: 1px solid var(--surface2); font-variant-numeric: tabular-nums; }
|
|
70
|
+
.tbl tr:last-child td { border-bottom: none; }
|
|
71
|
+
.tbl .r { text-align: right; }
|
|
72
|
+
.tbl .good { color: var(--good); }
|
|
73
|
+
.tbl-wrap { max-height: 320px; overflow-y: auto; }
|
|
74
|
+
.stat-line { display: flex; gap: 24px; margin-bottom: 12px; flex-wrap: wrap; }
|
|
75
|
+
.stat-line div { font-size: 13px; color: var(--muted); }
|
|
76
|
+
.stat-line b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
58
77
|
footer { color: var(--muted); font-size: 12px; line-height: 1.6; margin-top: 8px; }
|
|
59
78
|
code { background: var(--surface2); padding: 1px 6px; border-radius: 5px; color: var(--accent2); }
|
|
60
79
|
@media (max-width: 720px) { .grid { grid-template-columns: repeat(2, 1fr); } }
|
|
@@ -66,24 +85,49 @@
|
|
|
66
85
|
<div class="wordmark">Enigma<span>.</span></div>
|
|
67
86
|
<div class="sub">Context Compression Savings</div>
|
|
68
87
|
</div>
|
|
69
|
-
<div class="
|
|
88
|
+
<div class="nav">
|
|
89
|
+
<span class="live"><span id="dot" class="dot stale"></span><span id="updated">Connecting...</span></span>
|
|
90
|
+
<nav class="links">
|
|
91
|
+
<a href="https://github.com/FJRG2007/enigma" target="_blank" rel="noopener noreferrer" title="GitHub repository" aria-label="GitHub repository">
|
|
92
|
+
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.52 11.52 0 0 1 12 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
|
93
|
+
</a>
|
|
94
|
+
<a href="https://tpe.li/dsc" target="_blank" rel="noopener noreferrer" title="Discord" aria-label="Discord">
|
|
95
|
+
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.317 4.3698a19.7913 19.7913 0 0 0-4.8851-1.5152.0741.0741 0 0 0-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 0 0-.0785-.037 19.7363 19.7363 0 0 0-4.8852 1.515.0699.0699 0 0 0-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 0 0 .0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 0 0 .0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 0 0-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 0 1-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 0 1 .0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 0 1 .0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 0 1-.0066.1276 12.2986 12.2986 0 0 1-1.873.8914.0766.0766 0 0 0-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 0 0 .0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 0 0 .0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 0 0-.0312-.0286ZM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189Zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9461 2.4189-2.1568 2.4189Z"/></svg>
|
|
96
|
+
</a>
|
|
97
|
+
<a href="https://ko-fi.com/fjrg2007" target="_blank" rel="noopener noreferrer" title="Support on Ko-fi" aria-label="Support on Ko-fi">
|
|
98
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17 8h1a4 4 0 1 1 0 8h-1"/><path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z"/><line x1="6" y1="2" x2="6" y2="4"/><line x1="10" y1="2" x2="10" y2="4"/><line x1="14" y1="2" x2="14" y2="4"/></svg>
|
|
99
|
+
</a>
|
|
100
|
+
</nav>
|
|
101
|
+
</div>
|
|
70
102
|
</header>
|
|
71
103
|
|
|
72
104
|
<div class="grid">
|
|
73
|
-
<div class="card"><div class="label">
|
|
105
|
+
<div class="card"><div class="label">Money Saved</div><div id="money" class="value good">-</div><div id="moneyFoot" class="foot">Estimated, by source</div></div>
|
|
106
|
+
<div class="card"><div class="label">Tokens Saved</div><div id="saved" class="value">-</div><div id="savedFoot" class="foot">Across all compressions</div></div>
|
|
74
107
|
<div class="card"><div class="label">Savings Rate</div><div id="rate" class="value accent">-</div><div class="foot">Of input tokens removed</div></div>
|
|
75
108
|
<div class="card"><div class="label">Compressions</div><div id="calls" class="value">-</div><div class="foot">Reversible via CCR</div></div>
|
|
76
|
-
<div class="card"><div class="label">
|
|
109
|
+
<div class="card"><div class="label">Avg / Compression</div><div id="avg" class="value">-</div><div class="foot">Tokens saved per call</div></div>
|
|
110
|
+
<div class="card"><div class="label">Best Compression</div><div id="best" class="value">-</div><div class="foot">Most saved in one call</div></div>
|
|
77
111
|
</div>
|
|
78
112
|
|
|
79
113
|
<div class="panel">
|
|
80
114
|
<div class="panel-head">
|
|
81
|
-
<h2>
|
|
82
|
-
<div class="
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
<h2>Savings Per Day <small id="rangeLabel"></small></h2>
|
|
116
|
+
<div class="ctrls">
|
|
117
|
+
<div class="ranges" id="metricToggle">
|
|
118
|
+
<button type="button" data-m="tokens" class="active">Tokens</button>
|
|
119
|
+
<button type="button" data-m="usd">$</button>
|
|
120
|
+
</div>
|
|
121
|
+
<div class="ranges" id="modeToggle">
|
|
122
|
+
<button type="button" data-o="daily" class="active">Daily</button>
|
|
123
|
+
<button type="button" data-o="cumulative">Cumulative</button>
|
|
124
|
+
</div>
|
|
125
|
+
<div class="ranges" id="ranges">
|
|
126
|
+
<button type="button" data-d="7">7D</button>
|
|
127
|
+
<button type="button" data-d="30" class="active">30D</button>
|
|
128
|
+
<button type="button" data-d="90">90D</button>
|
|
129
|
+
<button type="button" data-d="0">All</button>
|
|
130
|
+
</div>
|
|
87
131
|
</div>
|
|
88
132
|
</div>
|
|
89
133
|
<div id="chartWrap" class="chartwrap"></div>
|
|
@@ -96,17 +140,47 @@
|
|
|
96
140
|
</div>
|
|
97
141
|
|
|
98
142
|
<div class="panel">
|
|
99
|
-
<h2 style="margin-bottom:14px">
|
|
143
|
+
<h2 style="margin-bottom:14px">Savings By Content Type <small>what enigma compressed</small></h2>
|
|
144
|
+
<div id="types"></div>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="panel">
|
|
148
|
+
<h2 style="margin-bottom:14px">Before vs. After <small id="ratioLabel">cumulative tokens</small></h2>
|
|
100
149
|
<div class="bar-row"><span class="name">Before</span><div class="bar-track"><div id="barBefore" class="bar-fill" style="background:var(--accent2)"></div></div><span id="numBefore" class="num">-</span></div>
|
|
101
150
|
<div class="bar-row"><span class="name">After</span><div class="bar-track"><div id="barAfter" class="bar-fill" style="background:var(--good)"></div></div><span id="numAfter" class="num">-</span></div>
|
|
151
|
+
<div class="stat-line" style="margin:14px 0 0"><div>Removed <b id="removed">-</b></div><div>Reduction <b id="reduction">-</b></div><div>Compression ratio <b id="ratio">-</b></div></div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div class="panel">
|
|
155
|
+
<div class="panel-head">
|
|
156
|
+
<h2>Savings History <small id="histStats"></small></h2>
|
|
157
|
+
<div class="ctrls">
|
|
158
|
+
<div class="ranges" id="histToggle">
|
|
159
|
+
<button type="button" data-p="day" class="active">Daily</button>
|
|
160
|
+
<button type="button" data-p="week">Weekly</button>
|
|
161
|
+
<button type="button" data-p="month">Monthly</button>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="tbl-wrap"><div id="histBody"></div></div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<div class="panel">
|
|
169
|
+
<h2 style="margin-bottom:14px">Recent Compressions <small>newest first</small></h2>
|
|
170
|
+
<div class="tbl-wrap"><div id="recent"></div></div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="panel">
|
|
174
|
+
<h2 style="margin-bottom:14px">Reversible Cache (CCR) <small>recoverable originals on disk</small></h2>
|
|
175
|
+
<div id="cache"></div>
|
|
102
176
|
</div>
|
|
103
177
|
|
|
104
178
|
<footer>
|
|
105
179
|
Polling pauses automatically when this tab is hidden, and the server caches each snapshot - so an open dashboard costs almost nothing.
|
|
106
|
-
Data source: <code>~/.enigma/ccr/stats.json</code> + <code>history.jsonl</code>. Enigma <span id="ver"></span>
|
|
180
|
+
Data source: <code>~/.enigma/ccr/stats.json</code> + <code>history.jsonl</code> - reset it with <code>enigma compress --clear</code>. Enigma <span id="ver"></span>
|
|
107
181
|
</footer>
|
|
108
182
|
|
|
109
|
-
<script src="/lib/
|
|
183
|
+
<script src="/lib/chart.min.js"></script>
|
|
110
184
|
<script>
|
|
111
185
|
const POLL_MS = 5000;
|
|
112
186
|
const DAY = 86400000;
|
|
@@ -119,32 +193,56 @@
|
|
|
119
193
|
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
120
194
|
return String(Math.round(n));
|
|
121
195
|
}
|
|
196
|
+
function fmtUsd(n) {
|
|
197
|
+
n = Number(n) || 0;
|
|
198
|
+
if (n >= 1e3) return "$" + (n / 1e3).toFixed(2) + "k";
|
|
199
|
+
if (n >= 1) return "$" + n.toFixed(2);
|
|
200
|
+
return "$" + n.toFixed(n >= 0.1 ? 2 : 3);
|
|
201
|
+
}
|
|
202
|
+
function fmtBytes(n) {
|
|
203
|
+
n = Number(n) || 0;
|
|
204
|
+
if (n >= 1048576) return (n / 1048576).toFixed(1) + " MB";
|
|
205
|
+
if (n >= 1024) return (n / 1024).toFixed(1) + " KB";
|
|
206
|
+
return n + " B";
|
|
207
|
+
}
|
|
122
208
|
|
|
123
|
-
//
|
|
209
|
+
// Estimated price per 1M INPUT tokens, by source. enigma is not a proxy, so it
|
|
210
|
+
// can't know the real model - these are sensible defaults, overridable globally
|
|
211
|
+
// with `enigma config token-price <usd>` (priceOverride from the payload).
|
|
212
|
+
const PRICE_1M = {
|
|
213
|
+
"claude-code": 3, "claude": 3, "claude-desktop": 3,
|
|
214
|
+
"opencode": 3, "codex": 2.5, "codex-cli": 2.5, "cli": 3, "unknown": 3,
|
|
215
|
+
};
|
|
216
|
+
const DEFAULT_PRICE_1M = 3;
|
|
217
|
+
let priceOverride = 0;
|
|
218
|
+
function priceFor(source) { return priceOverride > 0 ? priceOverride : (PRICE_1M[source] ?? DEFAULT_PRICE_1M); }
|
|
219
|
+
function moneyOf(source, savedTokens) { return savedTokens * priceFor(source) / 1e6; }
|
|
220
|
+
|
|
221
|
+
// Friendly names for known MCP clients / content types; unknown -> title-cased raw.
|
|
124
222
|
const SOURCE_LABELS = {
|
|
125
223
|
"claude-code": "Claude Code", "claude": "Claude Code", "claude-desktop": "Claude Desktop",
|
|
126
224
|
"opencode": "OpenCode", "codex": "Codex", "codex-cli": "Codex",
|
|
127
225
|
"cli": "CLI (enigma compress)", "unknown": "Unattributed",
|
|
128
226
|
};
|
|
129
|
-
function prettySource(k) {
|
|
130
|
-
|
|
131
|
-
}
|
|
227
|
+
function prettySource(k) { return SOURCE_LABELS[k] || String(k).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); }
|
|
228
|
+
const TYPE_LABELS = { json: "JSON", log: "Logs", text: "Text", code: "Code", diff: "Diffs", markdown: "Markdown", unknown: "Other" };
|
|
229
|
+
function prettyType(k) { return TYPE_LABELS[k] || String(k).replace(/\b\w/g, (c) => c.toUpperCase()); }
|
|
132
230
|
|
|
133
|
-
// One bar per
|
|
134
|
-
function
|
|
135
|
-
const
|
|
136
|
-
const entries = Object.entries(bySource || {}).sort((a, b) => (b[1].tokensSaved || 0) - (a[1].tokensSaved || 0));
|
|
231
|
+
// One bar per key (source or type), sorted by tokens saved, with an optional $ column.
|
|
232
|
+
function renderBreakdown(el, map, label, money) {
|
|
233
|
+
const entries = Object.entries(map || {}).sort((a, b) => (b[1].tokensSaved || 0) - (a[1].tokensSaved || 0));
|
|
137
234
|
if (!entries.length) {
|
|
138
|
-
el.innerHTML = '<div class="empty" style="padding:20px 0">No
|
|
235
|
+
el.innerHTML = '<div class="empty" style="padding:20px 0">No data yet - this fills in as compressions are recorded.</div>';
|
|
139
236
|
return;
|
|
140
237
|
}
|
|
141
238
|
const max = Math.max(1, ...entries.map(([, v]) => v.tokensSaved || 0));
|
|
142
239
|
el.innerHTML = entries.map(([k, v]) => {
|
|
143
240
|
const saved = v.tokensSaved || 0, pct = Math.round(saved / max * 100);
|
|
144
|
-
|
|
241
|
+
const m = money ? '<span class="money">' + fmtUsd(moneyOf(k, saved)) + '</span>' : '';
|
|
242
|
+
return '<div class="bar-row"><span class="name" style="width:140px">' + label(k)
|
|
145
243
|
+ '</span><div class="bar-track"><div class="bar-fill" style="width:' + pct + '%;background:var(--accent)"></div></div>'
|
|
146
|
-
+ '<span class="num">' + fmt(saved) + '</span>'
|
|
147
|
-
+ '<span class="foot" style="width:
|
|
244
|
+
+ '<span class="num">' + fmt(saved) + '</span>' + m
|
|
245
|
+
+ '<span class="foot" style="width:64px;text-align:right;margin:0">' + fmt(v.calls || 0) + ' calls</span></div>';
|
|
148
246
|
}).join("");
|
|
149
247
|
}
|
|
150
248
|
|
|
@@ -152,19 +250,99 @@
|
|
|
152
250
|
// chart's time scale expects (matches the server's UTC-day history buckets).
|
|
153
251
|
function dayKey(ms) { return new Date(ms).toISOString().slice(0, 10); }
|
|
154
252
|
|
|
155
|
-
|
|
156
|
-
|
|
253
|
+
const savedOf = (p) => Math.max(0, (p.b || 0) - (p.a || 0));
|
|
254
|
+
|
|
255
|
+
// Recent compressions table (newest first), one row per history point.
|
|
256
|
+
function renderRecent(history) {
|
|
257
|
+
const rows = (history || []).slice(-20).reverse();
|
|
258
|
+
const el = $("recent");
|
|
259
|
+
if (!rows.length) { el.innerHTML = '<div class="empty" style="padding:24px 0">No compressions recorded yet.</div>'; return; }
|
|
260
|
+
el.innerHTML = '<table class="tbl"><thead><tr><th>Time</th><th>Type</th><th>Source</th>'
|
|
261
|
+
+ '<th class="r">Before</th><th class="r">After</th><th class="r">Saved</th></tr></thead><tbody>'
|
|
262
|
+
+ rows.map((p) => {
|
|
263
|
+
const saved = savedOf(p), pct = p.b ? Math.round(saved / p.b * 100) : 0;
|
|
264
|
+
return '<tr><td>' + new Date(p.t).toLocaleString() + '</td><td>' + prettyType(p.c || "unknown")
|
|
265
|
+
+ '</td><td>' + prettySource(p.s || "unknown") + '</td><td class="r">' + fmt(p.b || 0)
|
|
266
|
+
+ '</td><td class="r">' + fmt(p.a || 0) + '</td><td class="r good">' + fmt(saved) + " (" + pct + "%)</td></tr>";
|
|
267
|
+
}).join("") + "</tbody></table>";
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ISO-ish period key for grouping (day = YYYY-MM-DD, week = YYYY-Www, month = YYYY-MM).
|
|
271
|
+
function periodKey(t, period) {
|
|
272
|
+
const d = new Date(t);
|
|
273
|
+
if (period === "month") return d.toISOString().slice(0, 7);
|
|
274
|
+
if (period === "week") {
|
|
275
|
+
const onejan = Date.UTC(d.getUTCFullYear(), 0, 1);
|
|
276
|
+
const week = Math.ceil(((d.getTime() - onejan) / DAY + 1) / 7);
|
|
277
|
+
return d.getUTCFullYear() + "-W" + String(week).padStart(2, "0");
|
|
278
|
+
}
|
|
279
|
+
return dayKey(t);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let histPeriod = "day";
|
|
283
|
+
function renderHistory(history) {
|
|
284
|
+
const hist = history || [];
|
|
285
|
+
const days = new Set(hist.map((p) => dayKey(p.t))).size;
|
|
286
|
+
const total = hist.reduce((s, p) => s + savedOf(p), 0);
|
|
287
|
+
$("histStats").textContent = days ? days + " active day" + (days === 1 ? "" : "s") + " · avg " + fmt(Math.round(total / days)) + "/day" : "";
|
|
288
|
+
const byP = new Map();
|
|
289
|
+
for (const p of hist) {
|
|
290
|
+
const k = periodKey(p.t, histPeriod);
|
|
291
|
+
const cur = byP.get(k) || { tokens: 0, usd: 0, calls: 0 };
|
|
292
|
+
cur.tokens += savedOf(p);
|
|
293
|
+
cur.usd += moneyOf(p.s || "unknown", savedOf(p));
|
|
294
|
+
cur.calls++;
|
|
295
|
+
byP.set(k, cur);
|
|
296
|
+
}
|
|
297
|
+
const rows = [...byP.entries()].sort((a, b) => a[0] < b[0] ? 1 : -1);
|
|
298
|
+
const el = $("histBody");
|
|
299
|
+
if (!rows.length) { el.innerHTML = '<div class="empty" style="padding:24px 0">No history yet.</div>'; return; }
|
|
300
|
+
el.innerHTML = '<table class="tbl"><thead><tr><th>Period</th><th class="r">Compressions</th>'
|
|
301
|
+
+ '<th class="r">Tokens Saved</th><th class="r">$ Saved</th></tr></thead><tbody>'
|
|
302
|
+
+ rows.map(([k, v]) => '<tr><td>' + k + '</td><td class="r">' + v.calls + '</td><td class="r good">'
|
|
303
|
+
+ fmt(v.tokens) + '</td><td class="r">' + fmtUsd(v.usd) + "</td></tr>").join("") + "</tbody></table>";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function renderCache(c) {
|
|
307
|
+
const el = $("cache");
|
|
308
|
+
if (!c) { el.innerHTML = '<div class="empty" style="padding:20px 0">No cache data.</div>'; return; }
|
|
309
|
+
const pct = c.cap ? Math.round((c.count || 0) / c.cap * 100) : 0;
|
|
310
|
+
el.innerHTML = '<div class="bar-row"><span class="name" style="width:170px">Cached originals</span>'
|
|
311
|
+
+ '<div class="bar-track"><div class="bar-fill" style="width:' + pct + '%;background:var(--accent)"></div></div>'
|
|
312
|
+
+ '<span class="num">' + fmt(c.count || 0) + " / " + fmt(c.cap || 0) + '</span></div>'
|
|
313
|
+
+ '<div class="stat-line" style="margin-top:6px"><div>On disk <b>' + fmtBytes(c.bytes || 0) + '</b></div>'
|
|
314
|
+
+ '<div>Retention <b>newest ' + fmt(c.cap || 0) + '</b></div>'
|
|
315
|
+
+ '<div>Restore <b>enigma compress --retrieve <hash></b></div></div>';
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Aggregate raw history points into one {time, tokens, usd} per day (ascending,
|
|
319
|
+
// unique times). $ per point uses that point's recorded source price.
|
|
157
320
|
function dailySeries(history) {
|
|
158
321
|
const byDay = new Map();
|
|
159
322
|
for (const p of history || []) {
|
|
160
323
|
const saved = Math.max(0, (p.b || 0) - (p.a || 0));
|
|
161
324
|
const key = dayKey(p.t);
|
|
162
|
-
|
|
325
|
+
const cur = byDay.get(key) || { tokens: 0, usd: 0 };
|
|
326
|
+
cur.tokens += saved;
|
|
327
|
+
cur.usd += moneyOf(p.s || "unknown", saved);
|
|
328
|
+
byDay.set(key, cur);
|
|
163
329
|
}
|
|
164
|
-
return [...byDay.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1)
|
|
330
|
+
return [...byDay.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1)
|
|
331
|
+
.map(([time, v]) => ({ time, tokens: v.tokens, usd: v.usd }));
|
|
165
332
|
}
|
|
166
333
|
|
|
167
|
-
let chart = null, series = null,
|
|
334
|
+
let chart = null, series = null, dailyData = [], lastHistory = [], currentRange = 30, metric = "tokens", mode = "daily";
|
|
335
|
+
const metricFmt = (v) => metric === "usd" ? fmtUsd(v) : fmt(v);
|
|
336
|
+
|
|
337
|
+
// Map the per-day data to LC {time, value} for the active metric and mode.
|
|
338
|
+
function seriesValues() {
|
|
339
|
+
let cum = 0;
|
|
340
|
+
return dailyData.map((d) => {
|
|
341
|
+
const base = metric === "usd" ? d.usd : d.tokens;
|
|
342
|
+
if (mode === "cumulative") { cum += base; return { time: d.time, value: cum }; }
|
|
343
|
+
return { time: d.time, value: base };
|
|
344
|
+
});
|
|
345
|
+
}
|
|
168
346
|
|
|
169
347
|
function initChart() {
|
|
170
348
|
if (!window.LightweightCharts) return false;
|
|
@@ -185,20 +363,24 @@
|
|
|
185
363
|
series = chart.addSeries(LC.AreaSeries, {
|
|
186
364
|
lineColor: "#e0a458", topColor: "rgba(224,164,88,0.35)", bottomColor: "rgba(224,164,88,0.02)",
|
|
187
365
|
lineWidth: 2, priceLineVisible: false, lastValueVisible: false,
|
|
188
|
-
priceFormat: { type: "custom", minMove: 1, formatter:
|
|
366
|
+
priceFormat: { type: "custom", minMove: 1, formatter: metricFmt },
|
|
189
367
|
});
|
|
190
368
|
setupTooltip(el);
|
|
191
|
-
|
|
369
|
+
// Button groups: select one, restyle siblings, run the picker.
|
|
370
|
+
const group = (id, onPick) => $(id).addEventListener("click", (e) => {
|
|
192
371
|
const b = e.target.closest("button");
|
|
193
372
|
if (!b) return;
|
|
194
|
-
for (const x of $(
|
|
195
|
-
|
|
196
|
-
applyRange();
|
|
373
|
+
for (const x of $(id).children) x.classList.toggle("active", x === b);
|
|
374
|
+
onPick(b);
|
|
197
375
|
});
|
|
376
|
+
group("ranges", (b) => { currentRange = Number(b.dataset.d); applyRange(); });
|
|
377
|
+
group("metricToggle", (b) => { metric = b.dataset.m; redraw(); });
|
|
378
|
+
group("modeToggle", (b) => { mode = b.dataset.o; redraw(); });
|
|
379
|
+
group("histToggle", (b) => { histPeriod = b.dataset.p; renderHistory(lastHistory); });
|
|
198
380
|
return true;
|
|
199
381
|
}
|
|
200
382
|
|
|
201
|
-
// Floating crosshair tooltip:
|
|
383
|
+
// Floating crosshair tooltip: hovered date + that point's value (tokens or $).
|
|
202
384
|
function setupTooltip(container) {
|
|
203
385
|
const tip = document.createElement("div");
|
|
204
386
|
tip.className = "tip";
|
|
@@ -208,47 +390,77 @@
|
|
|
208
390
|
if (!param.time || !param.point || param.point.x < 0 || param.point.y < 0) { tip.style.display = "none"; return; }
|
|
209
391
|
const d = param.seriesData.get(series);
|
|
210
392
|
if (!d) { tip.style.display = "none"; return; }
|
|
211
|
-
|
|
393
|
+
const suffix = (metric === "usd" ? " saved" : " tokens saved") + (mode === "cumulative" ? " (total)" : "");
|
|
394
|
+
tip.innerHTML = '<div class="tip-d">' + param.time + '</div><div class="tip-v">' + metricFmt(d.value) + suffix + "</div>";
|
|
212
395
|
tip.style.display = "block";
|
|
213
|
-
const left = Math.max(0, Math.min(param.point.x + 14, container.clientWidth -
|
|
396
|
+
const left = Math.max(0, Math.min(param.point.x + 14, container.clientWidth - 160));
|
|
214
397
|
tip.style.left = left + "px";
|
|
215
398
|
tip.style.top = Math.max(0, param.point.y - 10) + "px";
|
|
216
399
|
});
|
|
217
400
|
}
|
|
218
401
|
|
|
402
|
+
// Push the active metric/mode data into the series and reformat the axis.
|
|
403
|
+
function redraw() {
|
|
404
|
+
if (!series) return;
|
|
405
|
+
series.applyOptions({ priceFormat: { type: "custom", minMove: metric === "usd" ? 0.0001 : 1, formatter: metricFmt } });
|
|
406
|
+
const has = dailyData.length > 0;
|
|
407
|
+
$("chartEmpty").style.display = has ? "none" : "block";
|
|
408
|
+
$("chartWrap").style.display = has ? "block" : "none";
|
|
409
|
+
if (has) { series.setData(seriesValues()); applyRange(); }
|
|
410
|
+
}
|
|
411
|
+
|
|
219
412
|
// Constrain the visible window to the selected range (All = fit everything).
|
|
220
413
|
function applyRange() {
|
|
221
|
-
if (!chart || !
|
|
414
|
+
if (!chart || !dailyData.length) return;
|
|
222
415
|
const ts = chart.timeScale();
|
|
223
416
|
if (currentRange === 0) { ts.fitContent(); $("rangeLabel").textContent = "all time"; return; }
|
|
224
|
-
const to =
|
|
417
|
+
const to = dailyData[dailyData.length - 1].time;
|
|
225
418
|
const from = dayKey(Date.now() - currentRange * DAY);
|
|
226
419
|
try { ts.setVisibleRange({ from, to }); }
|
|
227
420
|
catch { ts.fitContent(); }
|
|
228
421
|
$("rangeLabel").textContent = "last " + currentRange + " days";
|
|
229
422
|
}
|
|
230
423
|
|
|
424
|
+
// Total estimated $ saved: sum each source's saved tokens at its price (legacy
|
|
425
|
+
// data with no attribution falls back to the default price).
|
|
426
|
+
function totalMoney(s) {
|
|
427
|
+
const bs = s.bySource || {};
|
|
428
|
+
const keys = Object.keys(bs);
|
|
429
|
+
if (keys.length) return keys.reduce((sum, k) => sum + moneyOf(k, bs[k].tokensSaved || 0), 0);
|
|
430
|
+
return moneyOf("unknown", s.tokensSaved || 0);
|
|
431
|
+
}
|
|
432
|
+
|
|
231
433
|
function render(data) {
|
|
434
|
+
priceOverride = Number(data.priceOverride) || 0;
|
|
232
435
|
const s = data.stats || {};
|
|
233
|
-
const before = s.tokensBefore || 0, after = s.tokensAfter || 0, saved = s.tokensSaved || 0;
|
|
436
|
+
const before = s.tokensBefore || 0, after = s.tokensAfter || 0, saved = s.tokensSaved || 0, calls = s.calls || 0;
|
|
234
437
|
const rate = before ? Math.round((saved / before) * 100) : 0;
|
|
438
|
+
$("money").textContent = fmtUsd(totalMoney(s));
|
|
439
|
+
$("moneyFoot").textContent = priceOverride > 0 ? "~$" + priceOverride + "/1M tokens" : "Estimated, by source";
|
|
235
440
|
$("saved").textContent = fmt(saved);
|
|
236
441
|
$("savedFoot").textContent = saved ? "~" + saved.toLocaleString() + " tokens" : "Across all compressions";
|
|
237
442
|
$("rate").textContent = rate + "%";
|
|
238
|
-
$("calls").textContent = fmt(
|
|
239
|
-
$("
|
|
443
|
+
$("calls").textContent = fmt(calls);
|
|
444
|
+
$("avg").textContent = calls ? fmt(Math.round(saved / calls)) : "0";
|
|
445
|
+
$("best").textContent = fmt(s.best || 0);
|
|
240
446
|
$("numBefore").textContent = fmt(before);
|
|
241
447
|
$("numAfter").textContent = fmt(after);
|
|
242
448
|
const max = Math.max(1, before);
|
|
243
449
|
$("barBefore").style.width = (before / max * 100) + "%";
|
|
244
450
|
$("barAfter").style.width = (after / max * 100) + "%";
|
|
245
|
-
|
|
451
|
+
$("removed").textContent = fmt(saved) + " (" + rate + "%)";
|
|
452
|
+
$("reduction").textContent = before ? (100 - rate) + "% of input sent" : "-";
|
|
453
|
+
$("ratio").textContent = after ? "~" + (before / after).toFixed(1) + ":1" : "-";
|
|
454
|
+
renderBreakdown($("sources"), s.bySource, prettySource, true);
|
|
455
|
+
renderBreakdown($("types"), s.byType, prettyType, false);
|
|
246
456
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
457
|
+
lastHistory = data.history || [];
|
|
458
|
+
renderRecent(lastHistory);
|
|
459
|
+
renderHistory(lastHistory);
|
|
460
|
+
renderCache(data.cache);
|
|
461
|
+
|
|
462
|
+
dailyData = dailySeries(data.history);
|
|
463
|
+
redraw();
|
|
252
464
|
|
|
253
465
|
$("ver").textContent = data.version ? "v" + data.version : "";
|
|
254
466
|
$("dot").classList.remove("stale");
|
|
@@ -28,6 +28,7 @@ higher one and move on. The first lazy solution that works is the right one.
|
|
|
28
28
|
## Rules
|
|
29
29
|
|
|
30
30
|
- No unrequested abstractions: no interface with one implementation, no factory for one product, no config for a value that never changes.
|
|
31
|
+
- No passthrough indirection: a lookup table whose keys equal its values (`{ win32: "win32" }`), a wrapper that only forwards its arguments, a constant aliasing another constant, a variable used once. If a construct maps a thing to itself, delete it - use the value directly, or a `Set` when the real intent is an allowlist/membership test.
|
|
31
32
|
- No boilerplate or scaffolding "for later"; later can scaffold for itself.
|
|
32
33
|
- Deletion over addition. Boring over clever - clever is what someone decodes at 3am.
|
|
33
34
|
- Fewest files possible. The shortest working diff wins.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anti-overengineering-policy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Minimal-code discipline - YAGNI ladder, deletion over addition, no unrequested abstractions, and the enigma: shortcut-marking convention; intensity via the minimal-code setting.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
7
|
-
"sha": "
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
|
+
"sha": "3469a7e554b63a5ae3b1a4a127a0765d760649511fa9dfa9cdbcb04b4431fd64"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "On-demand over-engineering review - diff review, whole-repo audit, and enigma: debt-marker ledger (tags delete/stdlib/native/yagni/shrink, line/dep scoring); lists cuts, applies nothing.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "f742a2be3f328b9ea1ff9a35a449177c2cbec35ad16e46f7054b7a873a2ab017"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.1.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Backend/API architecture: controller-service-repository layering, API and request optimization, server-side caching (Redis), and Zod boundary validation.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "a46c3cd00aa5f47adb1e7907f1d2bc6f5562f7a272890dee9b1121976ac04ae1"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.1.1",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Ciphera code style conventions (formatting, naming, imports, comments, code-level anti-patterns; TypeScript-first, language-agnostic).",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "74f638aec13e8c93257fe1ad604c28b07e9a7c456796a4ceefcc99217d9e7039"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Pre-delivery self-review gate, prioritized review dimensions, and change-quality criteria.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "3d3bbe0602d5bbb4afe37648fe3c2fa39376b1bcbac5d8c441f01fad1e866ed0"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.9.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Core engineering execution policy and harness orchestration (highest-authority rules).",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "82d246faa4770248a36f143926fbf06bd3ffc082959014184548b57193770fab"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.1.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Senior database architecture policy: query optimization, anti-duplication/normalization, scalability, and RGPD/GDPR encryption.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "2883bcecb3202683ae6f81b073c3d6a9cec9c55029e011bdd06ba7ac3537297e"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Reproduce-isolate-fix debugging methodology with root-cause discipline and regression verification.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "14b0064c8b33a0dc85e51464b05005cf5801c756b1101789a6924b9548420f6b"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Dependency and supply-chain security: lockfiles and reproducible installs, version pinning, vulnerability auditing, vetting/minimizing packages, vendoring, and SBOM/provenance.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "6375d835c2aef2c9bd31ce116444dc3d796f510f9970a213aa3ac4696d7e21b9"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "431645565aec8a4ab4cd17247139f78c377a9bcfcfc4ee1d6f252199c332d86f"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.3.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Frontend architecture: reusable components, abstraction thresholds, state management, no-op save detection, large-list rendering (infinite scroll/pagination, virtualization, skeletons, progressive loading), and optimistic UI with rollback.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "26962db5a8b607e95098a6d88977aee59a10bd14e03afe97245f2b013fd21a9a"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Application and AI-agent security: secrets, authn/authz (least privilege), OWASP Top 10, transport/crypto baseline, secure logging, and agent/MCP/tool-use safety.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "9971e9d9127397d0152e89d24aad3191e2935e55a8483db7fd15f5d4d7a60e7a"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Create new skills, modify and improve existing skills, and measure skill performance with evals and benchmarks.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "699586cce82ec0a5458288b598ee7e5ebdddb3dfcf19db354d8bc5e85e47c1c7"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.1.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Exhaustive completion discipline for long/multi-item tasks - inventory, coverage ledger, verified done.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "6e3facba307eb2b55cefbab2e4b2a346a2b82f93c3ef47e11ebeb78c3c9453a8"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.2.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Test strategy, coverage gates, deterministic tests, mocking discipline, regression-first bug fixing, and test-suite organization (layout by type/domain, mirrored paths, file naming, fixture/helper placement).",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "3bdf591057b760f674fb2b1425f63acb426cda2c4f042e1a74c5a5d3807df664"
|
|
8
8
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Strict frontend + backend schema validation, schema consistency, and safe client-facing error handling.",
|
|
6
|
-
"cliVersion": "1.15.
|
|
6
|
+
"cliVersion": "1.15.9",
|
|
7
7
|
"sha": "a33622a2f810ee4cea39824cb1a7ca34b355a917d4224025df50d77dd74f0b3a"
|
|
8
8
|
}
|
package/bin/checksums.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"enigma-darwin-arm64": "
|
|
3
|
-
"enigma-linux-arm64": "
|
|
4
|
-
"enigma-linux-x64": "
|
|
5
|
-
"enigma-win32-x64.exe": "
|
|
2
|
+
"enigma-darwin-arm64": "500c3c44723b5b545d3174ac7cb8c47cd4faa01fb794fe331e0e1e5a5b09930c",
|
|
3
|
+
"enigma-linux-arm64": "b47ebfeb8acd6c6636107d26a71e81f1041993e670935a86bb0a1f0ac4b011c5",
|
|
4
|
+
"enigma-linux-x64": "a0a0bd7f418124fc4868b66423cf552a1c1df78c200722dd3e6c1fc910c6ab86",
|
|
5
|
+
"enigma-win32-x64.exe": "917a4fe077b3897f9f128a384c955452717df9ab394b8280fd59ef2449befcdf"
|
|
6
6
|
}
|
package/bin/platform.mjs
CHANGED
|
@@ -16,12 +16,15 @@ import { fileURLToPath } from "node:url";
|
|
|
16
16
|
import { dirname, join } from "node:path";
|
|
17
17
|
import { existsSync, readFileSync } from "node:fs";
|
|
18
18
|
|
|
19
|
-
// npm/Node "os" identifiers (win32, not
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
// Allowlists of the npm/Node "os" identifiers we publish binaries for (win32, not
|
|
20
|
+
// "windows"). An unsupported host resolves to undefined, which platformKeys() turns
|
|
21
|
+
// into "no binary for this host" rather than guessing a non-existent asset name.
|
|
22
|
+
const SUPPORTED_PLATFORMS = new Set(["win32", "darwin", "linux"]);
|
|
23
|
+
const SUPPORTED_ARCHES = new Set(["x64", "arm64"]);
|
|
24
|
+
const allowed = (set, value) => (set.has(value) ? value : undefined);
|
|
22
25
|
|
|
23
|
-
export const PLATFORM =
|
|
24
|
-
export const ARCH =
|
|
26
|
+
export const PLATFORM = allowed(SUPPORTED_PLATFORMS, os.platform());
|
|
27
|
+
export const ARCH = allowed(SUPPORTED_ARCHES, os.arch());
|
|
25
28
|
export const isWindows = PLATFORM === "win32";
|
|
26
29
|
|
|
27
30
|
/** This package's root (the directory holding package.json), i.e. <pkg>/bin/.. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "enigma-cli",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.9",
|
|
4
4
|
"description": "Everything you need to work with a coding agent: install shared policy skills for Claude Code, OpenAI Codex and opencode, and set up portable git security hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
File without changes
|