sigrank 0.18.5 → 1.0.1
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/CHANGELOG.md +158 -0
- package/MCP_SERVER_DESCRIPTION.md +172 -0
- package/README.md +94 -41
- package/adapters/index.mjs +1100 -0
- package/adapters/tokenpull.mjs +568 -0
- package/adapters.mjs +1 -857
- package/analytics/cascade.mjs +338 -0
- package/cascade.mjs +1 -274
- package/cli.mjs +1 -1853
- package/connect.mjs +1 -13
- package/identity/connect.mjs +13 -0
- package/identity/keystore.mjs +231 -0
- package/identity/sign.mjs +106 -0
- package/index.mjs +47 -162
- package/keystore.mjs +1 -242
- package/lib/constants.mjs +137 -0
- package/lib/pkg-version.mjs +59 -0
- package/manifest.json +46 -0
- package/narrate.mjs +1 -77
- package/package.json +41 -16
- package/preflight.mjs +1 -191
- package/presentation/cli.mjs +1926 -0
- package/presentation/narrate.mjs +219 -0
- package/presentation/tui-themes.mjs +189 -0
- package/presentation/tui.mjs +3316 -0
- package/prompts/check-my-efficiency.md +1 -0
- package/prompts/compare-with-leader.md +1 -0
- package/prompts/simulate-improvement.md +1 -0
- package/proxy.mjs +492 -0
- package/resources/class-tiers.md +81 -0
- package/resources/data-policy.md +31 -0
- package/resources/install-guide.md +59 -0
- package/resources/privacy-model.md +44 -0
- package/resources/scoring-formula.md +24 -0
- package/review.mjs +263 -0
- package/sign.mjs +1 -106
- package/submit/index.mjs +297 -0
- package/submit/preflight.mjs +191 -0
- package/submit.mjs +1 -303
- package/tokenpull.mjs +1 -576
- package/tokscale_analytics.mjs +864 -0
- package/tools/_framing.mjs +217 -0
- package/tools/_helpers.mjs +253 -0
- package/tools/_peer-matching.mjs +361 -0
- package/tools/_report.mjs +262 -0
- package/tools/_schemas.mjs +492 -0
- package/tools/_verifiers.mjs +148 -0
- package/tools/compare-operators.mjs +80 -0
- package/tools/compare-self.mjs +124 -0
- package/tools/describe-power-user.mjs +78 -0
- package/tools/diagnose-cascade.mjs +192 -0
- package/tools/discover-peers.mjs +198 -0
- package/tools/enroll.mjs +119 -0
- package/tools/get-best-operator.mjs +59 -0
- package/tools/get-leaderboard.mjs +27 -0
- package/tools/get-operator.mjs +33 -0
- package/tools/index.mjs +229 -0
- package/tools/optimize-efficiency.mjs +170 -0
- package/tools/rank-paste.mjs +51 -0
- package/tools/rank-windows.mjs +120 -0
- package/tools/self-improve.mjs +423 -0
- package/tools/simulate-change.mjs +207 -0
- package/tools/submit-paste.mjs +121 -0
- package/tools/submit-verified.mjs +153 -0
- package/tools/suggest-improvements.mjs +168 -0
- package/tools/tokenpull-compare.mjs +123 -0
- package/tools/tokenpull-submit.mjs +235 -0
- package/tools/tokenpull.mjs +113 -0
- package/tools/tokscale-breakdown.mjs +119 -0
- package/tools/tokscale-competitive-intel.mjs +45 -0
- package/tools/tokscale-cost-analysis.mjs +31 -0
- package/tools/tokscale-developer-profile.mjs +36 -0
- package/tools/tokscale-device-profile.mjs +35 -0
- package/tools/tokscale-market-share.mjs +38 -0
- package/tools/tokscale-mcp-usage.mjs +33 -0
- package/tools/tokscale-model-trends.mjs +32 -0
- package/tools/watch-tokenpull.mjs +134 -0
- package/tools.mjs +1 -3897
- package/tui.mjs +4 -2650
- package/banner.svg +0 -7
package/submit.mjs
CHANGED
|
@@ -1,303 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// VERIFIED ingest endpoint (D7 §5). Requires an enrolled identity (keystore.codename +
|
|
3
|
-
// operator_id + private key). The server re-derives the ranked Υ from the 4 raw pillars,
|
|
4
|
-
// so the core/background metrics here are schema-valid, plausibility-clean DISPLAY inputs.
|
|
5
|
-
//
|
|
6
|
-
// raw_telemetry sessions/turns/active are conservative PROXIES: tokenpull yields the 4
|
|
7
|
-
// pillars + a message count, not session structure. They are chosen to pass the
|
|
8
|
-
// plausibility gate WITHOUT flagging (a flag downgrades verified→flagged → not ranked).
|
|
9
|
-
// TODO(tokenpull): emit real sessions_count / turns_total / active_minutes per window so
|
|
10
|
-
// the display signa_rate reflects true session shape (the ranked Υ is already exact).
|
|
11
|
-
|
|
12
|
-
import { snapshotHash, signPayload } from "./sign.mjs";
|
|
13
|
-
import { preflight } from "./preflight.mjs";
|
|
14
|
-
import { readFileSync } from "node:fs";
|
|
15
|
-
|
|
16
|
-
const WINDOW_TYPE = { "7d": "7d", "30d": "30d", "90d": "90d", all: "all_time" };
|
|
17
|
-
const WINDOW_SPAN_DAYS = { "7d": 7, "30d": 30, "90d": 90, all_time: 3650 };
|
|
18
|
-
|
|
19
|
-
/** Resolve this package's version for the User-Agent stamp (best-effort). */
|
|
20
|
-
function _pkgVersion() {
|
|
21
|
-
try {
|
|
22
|
-
const pkg = JSON.parse(
|
|
23
|
-
readFileSync(new URL("./package.json", import.meta.url), "utf-8"),
|
|
24
|
-
);
|
|
25
|
-
return pkg.version;
|
|
26
|
-
} catch {
|
|
27
|
-
return "unknown";
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const PLATFORM_ENUM = new Set([
|
|
31
|
-
"claude",
|
|
32
|
-
"chatgpt",
|
|
33
|
-
"gemini",
|
|
34
|
-
"pi",
|
|
35
|
-
"codex",
|
|
36
|
-
"multi",
|
|
37
|
-
"other",
|
|
38
|
-
]);
|
|
39
|
-
// Provenance tag only — the board ranks by Υ (no RS.xx weights, §0.1).
|
|
40
|
-
const RULESET_VERSION = "sigrank-token-1";
|
|
41
|
-
const DAY_MS = 86_400_000;
|
|
42
|
-
|
|
43
|
-
const clamp = (x, lo, hi) => Math.max(lo, Math.min(hi, x));
|
|
44
|
-
const round = (n, dp) => {
|
|
45
|
-
const f = 10 ** dp;
|
|
46
|
-
return Math.round(n * f) / f;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/** Map any tokenpull platform to the Schema 1.0 platform.primary enum (others → 'other'). */
|
|
50
|
-
export function toPlatformPrimary(platform) {
|
|
51
|
-
return PLATFORM_ENUM.has(platform) ? platform : "other";
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* buildPayload — Schema 1.0 payload from a tokenpull window + enrolled identity.
|
|
56
|
-
* Pure (given opts.now); agent.snapshot_hash is computed last (canonical strips it).
|
|
57
|
-
*/
|
|
58
|
-
export function buildPayload(
|
|
59
|
-
windowKey,
|
|
60
|
-
pillars,
|
|
61
|
-
messages,
|
|
62
|
-
identity,
|
|
63
|
-
platform,
|
|
64
|
-
opts = {},
|
|
65
|
-
) {
|
|
66
|
-
const windowType = WINDOW_TYPE[windowKey] || windowKey;
|
|
67
|
-
const spanDays = WINDOW_SPAN_DAYS[windowType] || 30;
|
|
68
|
-
const nowMs = opts.now ?? Date.now();
|
|
69
|
-
|
|
70
|
-
const input = Math.max(0, Math.round(pillars?.input || 0));
|
|
71
|
-
const output = Math.max(0, Math.round(pillars?.output || 0));
|
|
72
|
-
const cacheCreate = Math.max(0, Math.round(pillars?.cacheCreate || 0));
|
|
73
|
-
const cacheRead = Math.max(0, Math.round(pillars?.cacheRead || 0));
|
|
74
|
-
const tokensTotal = input + output + cacheCreate + cacheRead;
|
|
75
|
-
|
|
76
|
-
// Proxies — plausibility-clean (see file header).
|
|
77
|
-
const msgs = Math.max(0, Math.round(messages || 0));
|
|
78
|
-
const turnsTotal = Math.max(output > 0 ? 1 : 0, msgs);
|
|
79
|
-
const sessionsCount =
|
|
80
|
-
tokensTotal > 0
|
|
81
|
-
? clamp(Math.round(msgs / 8) || 1, 1, Math.max(1, turnsTotal))
|
|
82
|
-
: 0;
|
|
83
|
-
const spanMinutes = spanDays * 1440;
|
|
84
|
-
const minActive = Math.ceil(output / 19000) + 1; // keep output/active under the 20k/min flag
|
|
85
|
-
const activeMinutes = clamp(
|
|
86
|
-
Math.max(msgs, minActive),
|
|
87
|
-
1,
|
|
88
|
-
Math.max(1, spanMinutes - 1),
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const compressionRatio =
|
|
92
|
-
input + output > 0 ? clamp(output / (input + output), 0, 1) : 0;
|
|
93
|
-
const sessionDepth = sessionsCount > 0 ? turnsTotal / sessionsCount : 0;
|
|
94
|
-
|
|
95
|
-
const payload = {
|
|
96
|
-
schema_version: "1.0",
|
|
97
|
-
codename: identity.codename,
|
|
98
|
-
device_id: identity.device_id,
|
|
99
|
-
submitted_at: new Date(nowMs).toISOString(),
|
|
100
|
-
window: {
|
|
101
|
-
type: windowType,
|
|
102
|
-
start: new Date(nowMs - spanDays * DAY_MS).toISOString(),
|
|
103
|
-
end: new Date(nowMs).toISOString(),
|
|
104
|
-
},
|
|
105
|
-
platform: { primary: toPlatformPrimary(platform), models: [] },
|
|
106
|
-
core_metrics: {
|
|
107
|
-
compression_ratio: round(compressionRatio, 4),
|
|
108
|
-
prompt_complexity: round(clamp(sessionDepth, 0, 100), 2),
|
|
109
|
-
cross_thread_score: clamp(
|
|
110
|
-
Math.round(cacheRead / Math.max(cacheCreate, 1)),
|
|
111
|
-
0,
|
|
112
|
-
100000,
|
|
113
|
-
),
|
|
114
|
-
session_depth_avg: round(Math.max(0, sessionDepth), 2),
|
|
115
|
-
// M.05 token_throughput muted 2026-06-26 — word-era metric the web already
|
|
116
|
-
// mutes (RS01 tt→0) + strips. Send null (RPC p_token_throughput is nullable
|
|
117
|
-
// DEFAULT NULL). raw_telemetry.tokens_total still carries the raw count.
|
|
118
|
-
token_throughput: null,
|
|
119
|
-
},
|
|
120
|
-
background_metrics: {
|
|
121
|
-
message_volume: msgs,
|
|
122
|
-
account_age_days: Math.max(1, Math.round(opts.accountAgeDays ?? 365)),
|
|
123
|
-
total_messages_lifetime: Math.max(
|
|
124
|
-
msgs,
|
|
125
|
-
Math.round(opts.totalMessages ?? msgs),
|
|
126
|
-
),
|
|
127
|
-
},
|
|
128
|
-
raw_telemetry: {
|
|
129
|
-
sessions_count: sessionsCount,
|
|
130
|
-
turns_total: turnsTotal,
|
|
131
|
-
tokens_total: tokensTotal,
|
|
132
|
-
tokens_input_fresh: input,
|
|
133
|
-
tokens_output: output,
|
|
134
|
-
tokens_cache_read: cacheRead,
|
|
135
|
-
tokens_cache_creation: cacheCreate,
|
|
136
|
-
active_minutes_est: activeMinutes,
|
|
137
|
-
},
|
|
138
|
-
tier: "free",
|
|
139
|
-
agent: {
|
|
140
|
-
version: identity.agent_version,
|
|
141
|
-
ruleset_version: RULESET_VERSION,
|
|
142
|
-
snapshot_hash: "",
|
|
143
|
-
public_key: identity.public_key,
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// Cascade Report block (Phase 1 — mode detection + badges + health).
|
|
148
|
-
// Computed locally (pure math), submitted alongside the 4 token pillars.
|
|
149
|
-
// The server stores it as-is — does NOT recompute modes.
|
|
150
|
-
// Weekly granularity is the privacy boundary — daily modes never leave the machine.
|
|
151
|
-
if (opts.report && typeof opts.report === "object") {
|
|
152
|
-
payload.report = opts.report;
|
|
153
|
-
}
|
|
154
|
-
payload.agent.snapshot_hash = snapshotHash(payload);
|
|
155
|
-
return payload;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* submitSignedWindow — build + sign + POST one window to /api/v1/snapshots.
|
|
160
|
-
* Returns a structured result; never throws on a network error. opts: { apiBase,
|
|
161
|
-
* fetchImpl, platform, now } (fetchImpl lets the caller inject a timeout-wrapped fetch).
|
|
162
|
-
*/
|
|
163
|
-
export async function submitSignedWindow(
|
|
164
|
-
windowKey,
|
|
165
|
-
pillars,
|
|
166
|
-
messages,
|
|
167
|
-
identity,
|
|
168
|
-
opts = {},
|
|
169
|
-
) {
|
|
170
|
-
if (!identity?.codename || !identity?.operator_id) {
|
|
171
|
-
return {
|
|
172
|
-
status: "not_enrolled",
|
|
173
|
-
reason: "not_enrolled",
|
|
174
|
-
detail: "Run `npx sigrank-mcp enroll` to bind this device first.",
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
if (!identity?.private_key_pkcs8_b64) {
|
|
178
|
-
return {
|
|
179
|
-
status: "error",
|
|
180
|
-
reason: "no_key",
|
|
181
|
-
detail: "No local signing key — re-run `npx sigrank-mcp enroll`.",
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const apiBase =
|
|
186
|
-
opts.apiBase || process.env.SIGRANK_API_BASE || "https://signalaf.com";
|
|
187
|
-
// FIX M: default a 15s AbortController timeout when the caller doesn't inject a
|
|
188
|
-
// fetchImpl. The TUI path already wraps fetch (callTool → doFetch, 10s), but the
|
|
189
|
-
// legacy CLI `watch --submit` + the CLI default-view [S] call submitSignedWindow
|
|
190
|
-
// with no fetchImpl → bare fetch → a hung POST blocks forever. This default fixes
|
|
191
|
-
// it everywhere at once. (15s is generous for a signed POST to /api/v1/snapshots.)
|
|
192
|
-
const fetchImpl =
|
|
193
|
-
opts.fetchImpl ||
|
|
194
|
-
((url, init = {}) => {
|
|
195
|
-
const ctrl = new AbortController();
|
|
196
|
-
const timer = setTimeout(() => ctrl.abort(), 15_000);
|
|
197
|
-
const headers = {
|
|
198
|
-
"user-agent": `node/${process.version} sigrank-mcp/${_pkgVersion()}`,
|
|
199
|
-
...(init.headers || {}),
|
|
200
|
-
};
|
|
201
|
-
return fetch(url, {
|
|
202
|
-
...init,
|
|
203
|
-
headers,
|
|
204
|
-
signal: init.signal || ctrl.signal,
|
|
205
|
-
}).finally(() => clearTimeout(timer));
|
|
206
|
-
});
|
|
207
|
-
const payload = buildPayload(
|
|
208
|
-
windowKey,
|
|
209
|
-
pillars,
|
|
210
|
-
messages,
|
|
211
|
-
identity,
|
|
212
|
-
opts.platform || "claude",
|
|
213
|
-
opts,
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
// Preflight: run the same anti-gaming checks the server will run, locally.
|
|
217
|
-
// If the payload would be rejected or downgraded, warn the operator BEFORE
|
|
218
|
-
// submitting. The server always runs its own checks — this is a preview.
|
|
219
|
-
const pre = preflight(payload);
|
|
220
|
-
if (!pre.pass && !opts.skipPreflight) {
|
|
221
|
-
if (pre.wouldReject) {
|
|
222
|
-
return {
|
|
223
|
-
status: "preflight_rejected",
|
|
224
|
-
window: WINDOW_TYPE[windowKey] || windowKey,
|
|
225
|
-
preflight: pre,
|
|
226
|
-
detail: `Submission would be REJECTED by the server: ${pre.summary}. Fix the issue or re-run with skipPreflight.`,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
// Flags downgrade verified → flagged (not ranked). Warn but don't block
|
|
230
|
-
// unless the caller explicitly asked for strict mode.
|
|
231
|
-
if (opts.strictPreflight) {
|
|
232
|
-
return {
|
|
233
|
-
status: "preflight_flagged",
|
|
234
|
-
window: WINDOW_TYPE[windowKey] || windowKey,
|
|
235
|
-
preflight: pre,
|
|
236
|
-
detail: `Submission would be DOWNGRADED (not ranked): ${pre.summary}. Fix the issue or re-run with skipPreflight.`,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
// Non-strict: attach the preflight warning to the result but proceed.
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const signature = signPayload(payload, identity.private_key_pkcs8_b64);
|
|
243
|
-
|
|
244
|
-
// Dry run: build + sign exactly as a real publish, then STOP before the POST.
|
|
245
|
-
// Returns the exact payload that would be sent — the privacy proof ("token
|
|
246
|
-
// counts only") is inspectable, and nothing touches the network.
|
|
247
|
-
if (opts.dryRun) {
|
|
248
|
-
return {
|
|
249
|
-
status: "dry_run",
|
|
250
|
-
window: WINDOW_TYPE[windowKey] || windowKey,
|
|
251
|
-
would_post: `${apiBase}/api/v1/snapshots`,
|
|
252
|
-
payload,
|
|
253
|
-
signature,
|
|
254
|
-
preflight: pre,
|
|
255
|
-
detail: "Nothing sent. Re-run without dry_run to publish.",
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
let res;
|
|
260
|
-
let ack;
|
|
261
|
-
try {
|
|
262
|
-
res = await fetchImpl(`${apiBase}/api/v1/snapshots`, {
|
|
263
|
-
method: "POST",
|
|
264
|
-
headers: {
|
|
265
|
-
"content-type": "application/json",
|
|
266
|
-
accept: "application/json",
|
|
267
|
-
"x-agent-signature": signature,
|
|
268
|
-
},
|
|
269
|
-
body: JSON.stringify(payload),
|
|
270
|
-
});
|
|
271
|
-
try {
|
|
272
|
-
ack = await res.json();
|
|
273
|
-
} catch {
|
|
274
|
-
ack = {};
|
|
275
|
-
}
|
|
276
|
-
} catch (e) {
|
|
277
|
-
return {
|
|
278
|
-
status: "error",
|
|
279
|
-
reason: "network",
|
|
280
|
-
detail: e.message,
|
|
281
|
-
window: WINDOW_TYPE[windowKey] || windowKey,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return {
|
|
286
|
-
status: res.ok ? ack.status || "received" : "error",
|
|
287
|
-
httpStatus: res.status,
|
|
288
|
-
window: WINDOW_TYPE[windowKey] || windowKey,
|
|
289
|
-
verification_tier: ack.verification_tier ?? null,
|
|
290
|
-
persisted: ack.persisted ?? null,
|
|
291
|
-
// ranked = actually on the board (verified + written), not just "received".
|
|
292
|
-
// An unenrolled/revoked device gets HTTP 202 received but is NEVER ranked.
|
|
293
|
-
ranked: !!(
|
|
294
|
-
res.ok &&
|
|
295
|
-
ack.verification_tier === "verified" &&
|
|
296
|
-
ack.persisted === true
|
|
297
|
-
),
|
|
298
|
-
snapshot_hash: payload.agent.snapshot_hash,
|
|
299
|
-
reason: res.ok ? null : ack.reason || ack.status || `http_${res.status}`,
|
|
300
|
-
detail: ack.detail ?? null,
|
|
301
|
-
preflight: pre,
|
|
302
|
-
};
|
|
303
|
-
}
|
|
1
|
+
export * from './submit/index.mjs';
|