segreant 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSING.md +5 -3
- package/README.md +57 -19
- package/bin/segreant-statusline.mjs +20 -0
- package/bin/segreant.mjs +19 -8
- package/dist/alerts/detect.js +13 -0
- package/dist/billing/epistemic.js +4 -0
- package/dist/billing/importer.js +29 -10
- package/dist/billing/reconcile.js +122 -32
- package/dist/billing/scope.js +7 -0
- package/dist/budget/guard.js +33 -4
- package/dist/cli/allocCmd.js +73 -4
- package/dist/cli/askModelPrices.js +59 -0
- package/dist/cli/backupCmd.js +2 -1
- package/dist/cli/basisLines.js +45 -0
- package/dist/cli/billingCmd.js +68 -9
- package/dist/cli/capitalCmd.js +2 -1
- package/dist/cli/connectCmd.js +50 -9
- package/dist/cli/egressCmd.js +15 -3
- package/dist/cli/evidenceCmd.js +6 -3
- package/dist/cli/flags.js +68 -0
- package/dist/cli/homeCmd.js +117 -0
- package/dist/cli/importCmd.js +210 -54
- package/dist/cli/launchCmd.js +2 -1
- package/dist/cli/opsCmd.js +49 -2
- package/dist/cli/planCmd.js +181 -0
- package/dist/cli/pricingDeclareCmd.js +178 -0
- package/dist/cli/quotaCmd.js +190 -0
- package/dist/cli/runCmd.js +203 -51
- package/dist/cli/showCmd.js +37 -11
- package/dist/cli/teamCmd.js +5 -5
- package/dist/cli/ui.js +24 -8
- package/dist/cli/valueCmd.js +189 -14
- package/dist/cli.js +102 -21
- package/dist/config.js +95 -6
- package/dist/connect/antigravity.js +310 -0
- package/dist/connect/claudeCode.js +43 -3
- package/dist/connect/codex.js +38 -1
- package/dist/connect/importShared.js +58 -5
- package/dist/connect/opencode.js +37 -9
- package/dist/connect/protobuf.js +126 -0
- package/dist/connect/registry.js +46 -0
- package/dist/connect/repoRoot.js +112 -0
- package/dist/cost/basis.js +168 -0
- package/dist/cost/declarations.js +37 -0
- package/dist/cost/exactPricing.js +4 -1
- package/dist/cost/firstSight.js +98 -0
- package/dist/cost/overrides.js +230 -0
- package/dist/cost/pricing.js +228 -15
- package/dist/cost/reprice.js +130 -0
- package/dist/dashboard/claim-support.js +11 -8
- package/dist/dashboard/contracts.js +23 -3
- package/dist/dashboard/routes.js +980 -112
- package/dist/dashboard/sessions.js +345 -0
- package/dist/dashboard/settings.js +2 -1
- package/dist/dashboard/value-cache.js +105 -0
- package/dist/dashboard/web/app/components/claimInspector.js +6 -5
- package/dist/dashboard/web/app/components/drawer.js +105 -35
- package/dist/dashboard/web/app/components/ruleFields.js +144 -0
- package/dist/dashboard/web/app/components/spine.js +54 -24
- package/dist/dashboard/web/app/components/workflow.js +82 -0
- package/dist/dashboard/web/app/core/actions.js +734 -23
- package/dist/dashboard/web/app/core/api.js +37 -1
- package/dist/dashboard/web/app/core/chain.js +11 -4
- package/dist/dashboard/web/app/core/claimLayers.js +179 -51
- package/dist/dashboard/web/app/core/claimTypes.js +30 -0
- package/dist/dashboard/web/app/core/fmt.js +19 -2
- package/dist/dashboard/web/app/core/generated-contract.js +23 -3
- package/dist/dashboard/web/app/core/generated-payload-contract.js +1944 -465
- package/dist/dashboard/web/app/core/generated-types.js +1 -1
- package/dist/dashboard/web/app/core/griffin.js +10 -0
- package/dist/dashboard/web/app/core/jobs.js +12 -0
- package/dist/dashboard/web/app/core/period.js +35 -0
- package/dist/dashboard/web/app/core/periodWords.js +10 -0
- package/dist/dashboard/web/app/core/periods.js +32 -0
- package/dist/dashboard/web/app/core/pricingActions.js +264 -0
- package/dist/dashboard/web/app/core/privacyText.js +78 -0
- package/dist/dashboard/web/app/core/reconcileWords.js +63 -0
- package/dist/dashboard/web/app/core/registry.js +79 -46
- package/dist/dashboard/web/app/core/slug.js +9 -0
- package/dist/dashboard/web/app/core/theme.js +48 -0
- package/dist/dashboard/web/app/core/view.js +69 -0
- package/dist/dashboard/web/app/main.js +197 -15
- package/dist/dashboard/web/app/views/allocation.js +249 -61
- package/dist/dashboard/web/app/views/control.js +57 -16
- package/dist/dashboard/web/app/views/data.js +4 -4
- package/dist/dashboard/web/app/views/evidence.js +336 -87
- package/dist/dashboard/web/app/views/privacy.js +13 -0
- package/dist/dashboard/web/app/views/spend.js +30 -15
- package/dist/dashboard/web/app/views/statement.js +189 -0
- package/dist/dashboard/web/app/views/system.js +44 -4
- package/dist/dashboard/web/app/views/value.js +105 -59
- package/dist/dashboard/web/app/views/workbench.js +312 -0
- package/dist/dashboard/web/classic.html +16 -4
- package/dist/dashboard/web/index.html +1 -1
- package/dist/dashboard/web/styles/app.css +536 -23
- package/dist/demo/seed.js +153 -14
- package/dist/economics/ledger.js +1 -1
- package/dist/egress/policy.js +129 -5
- package/dist/export/allocationCsv.js +70 -0
- package/dist/export/billingCsv.js +6 -2
- package/dist/export/csv.js +10 -2
- package/dist/export/economic.js +6 -2
- package/dist/export/statementCsv.js +104 -0
- package/dist/git/correlate.js +86 -9
- package/dist/git/quality.js +107 -24
- package/dist/git/repoScope.js +207 -0
- package/dist/git/survivalStore.js +186 -0
- package/dist/guide.js +9 -4
- package/dist/plans/detect.js +147 -0
- package/dist/proxy/server.js +134 -14
- package/dist/proxy/usage.js +9 -4
- package/dist/quota/limits.js +138 -0
- package/dist/quota/statusline.js +68 -0
- package/dist/quota/view.js +122 -0
- package/dist/scan/knownApps.js +6 -2
- package/dist/scan/scan.js +9 -0
- package/dist/store/allocation.js +14 -0
- package/dist/store/db.js +259 -34
- package/dist/store/realization.js +78 -14
- package/dist/store/schema.js +59 -1
- package/dist/store/scopeEvidence.js +67 -0
- package/dist/util/pool.js +19 -0
- package/dist/util/time.js +7 -0
- package/dist/value/realization.js +321 -30
- package/dist/value/report.js +28 -8
- package/dist/value/selfReported.js +10 -9
- package/docs/ARCHITECTURE.md +8 -4
- package/docs/CAPABILITY-EVIDENCE-CONTRACT.md +33 -11
- package/docs/CLI-JSON-CONTRACT.md +38 -0
- package/docs/DATA-BOUNDARIES.md +66 -6
- package/docs/FAQ.md +43 -9
- package/docs/GETTING-STARTED.md +19 -12
- package/docs/GUIDE.md +81 -18
- package/docs/INTEGRATIONS.md +9 -9
- package/docs/METHODOLOGY.md +3 -2
- package/docs/NEUTRALITY.md +1 -1
- package/docs/PRIVACY.md +51 -0
- package/docs/README.md +1 -0
- package/docs/RELEASE-GATE.md +52 -7
- package/docs/THREAT-MODEL.md +2 -1
- package/package.json +3 -2
- package/pricing/models.json +1366 -60
|
@@ -22,30 +22,35 @@
|
|
|
22
22
|
import { h } from '../core/dom.js';
|
|
23
23
|
import { signal, scopedEffect } from '../core/signal.js';
|
|
24
24
|
import { api } from '../core/api.js';
|
|
25
|
-
import { usd, count, pct, isPrecise } from '../core/fmt.js';
|
|
25
|
+
import { usd, count, pct, share, isPrecise } from '../core/fmt.js';
|
|
26
26
|
import { actionCard } from './spend.js';
|
|
27
|
-
/**
|
|
27
|
+
/** Each gate as a step name, for the passed / failed / not checked table. */
|
|
28
28
|
const GATE_WORDS = {
|
|
29
|
-
proposed: '
|
|
30
|
-
accepted: '
|
|
31
|
-
committed: '
|
|
32
|
-
tested: '
|
|
33
|
-
merged: '
|
|
34
|
-
shipped: '
|
|
35
|
-
survived: '
|
|
36
|
-
clean: '
|
|
29
|
+
proposed: 'Suggested by the AI',
|
|
30
|
+
accepted: 'Accepted',
|
|
31
|
+
committed: 'Committed',
|
|
32
|
+
tested: 'Tests passed',
|
|
33
|
+
merged: 'Merged',
|
|
34
|
+
shipped: 'Shipped',
|
|
35
|
+
survived: 'Still in the code after 14 days',
|
|
36
|
+
clean: 'Kept without rework',
|
|
37
37
|
};
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The waste breakdown is keyed by `diedAt`, the FIRST FAILED gate, so each
|
|
40
|
+
* label says what went wrong. It used to read "stopped after surviving in
|
|
41
|
+
* production" for work that failed the survival check.
|
|
42
|
+
*/
|
|
43
|
+
const FAILED_AT = {
|
|
44
|
+
proposed: 'Suggestion not used',
|
|
45
|
+
accepted: 'Not accepted',
|
|
46
|
+
committed: 'Never committed',
|
|
47
|
+
tested: 'Tests failed',
|
|
48
|
+
merged: 'Not merged',
|
|
49
|
+
shipped: 'Not shipped',
|
|
50
|
+
survived: 'Gone from the code within 14 days',
|
|
51
|
+
clean: 'Needed rework',
|
|
52
|
+
unverified: 'No signal to judge it by',
|
|
53
|
+
conflicted: 'Results disagree',
|
|
49
54
|
};
|
|
50
55
|
const plural = (n, one, many) => (n === 1 ? one : many);
|
|
51
56
|
/** Operator reports have their own basis and never feed the git realization card. */
|
|
@@ -111,13 +116,25 @@ function selfReportedCard(report, refresh) {
|
|
|
111
116
|
if (report.status === 'disabled') {
|
|
112
117
|
return h('section', { class: 'section' }, h('h2', { class: 'section-title', text: 'Chat, image and other work' }), h('p', { class: 'basis', text: 'Self-reported value is disabled; nothing was computed.' }));
|
|
113
118
|
}
|
|
114
|
-
return h('section', { class: 'section' }, h('h2', { class: 'section-title', text: 'Chat, image and other work' }), h('p', { class: 'basis', text: report.basis }), h('p', { class: 'basis', text: `${report.units.length} reported results · ${report.unlinkedOutcomes} without matched spend · ${report.inferredLinks} inferred links. Coding git outcomes have a separate basis.` }), ...rows.map((row) => h('p', { class: 'basis', text: `${row.key}: ${row.accepted}/${row.outcomes} accepted, ${row.used} used; cost/accepted ${row.costPerAcceptedUsd === null ? 'unknown' : usd(row.costPerAcceptedUsd)}; cost/used ${row.costPerUsedUsd === null ? 'unknown' : usd(row.costPerUsedUsd)} (self-reported, ${row.linked}/${row.outcomes} linked)` })), h('details', { class: 'card', style: 'margin-top: var(--s4)' }, h('summary', { text: 'Record a result' }), h('p', { class: 'basis', text: 'Preview first. The result and your
|
|
119
|
+
return h('section', { class: 'section' }, h('h2', { class: 'section-title', text: 'Chat, image and other work' }), h('p', { class: 'basis', text: report.basis }), h('p', { class: 'basis', text: `${report.units.length} reported results · ${report.unlinkedOutcomes} without matched spend · ${report.inferredLinks} inferred links. Coding git outcomes have a separate basis.` }), ...rows.map((row) => h('p', { class: 'basis', text: `${row.key}: ${row.accepted}/${row.outcomes} accepted, ${row.used} used; cost/accepted ${row.costPerAcceptedUsd === null ? 'unknown' : usd(row.costPerAcceptedUsd)}; cost/used ${row.costPerUsedUsd === null ? 'unknown' : usd(row.costPerUsedUsd)} (self-reported, ${row.linked}/${row.outcomes} linked)` })), h('details', { class: 'card', style: 'margin-top: var(--s4)' }, h('summary', { text: 'Record a result' }), h('p', { class: 'basis', text: 'Preview first. The result and your answer stay on this machine.' }), field('Result ID', outcomeId, 'my-result-1'), choice('Kind', kind, [['chat', 'Chat'], ['image', 'Image'], ['other', 'Other']]), choice('Spend link', linkType, [['session', 'Session ID'], ['request', 'Request ID'], ['window', 'Time window + tool (inferred)']]), () => linkType() === 'window'
|
|
115
120
|
? h('div', null, field('From (ISO time)', from), field('To (ISO time)', to), field('Tool/source', tool))
|
|
116
121
|
: field(linkType() === 'request' ? 'Request ID' : 'Session ID', linkId), field('Rating 1–5 (optional)', rating), field('Short note (optional)', note), choice('Decision', decision, [['', 'Unknown'], ['accepted_as_is', 'Accepted as-is'], ['edited_before_use', 'Edited before use'], ['rejected', 'Rejected']]), choice('Used afterward', use, [['', 'Unknown'], ['exported', 'Exported'], ['copied', 'Copied'], ['shipped', 'Shipped'], ['published', 'Published'], ['not_used', 'Not used']]), field('Attempts until accepted (optional)', attempts), choice('Regenerated', regenerated, [['', 'Unknown'], ['true', 'Yes'], ['false', 'No']]), choice('Still in use', stillInUse, [['', 'Unknown'], ['true', 'Yes'], ['false', 'No']]), h('div', { class: 'actions' }, h('button', { class: 'btn-ghost', type: 'button', disabled: () => busy(), onclick: () => { void submit(false); }, text: 'Preview' }), () => preview() && !preview().apply
|
|
117
122
|
? h('button', { class: 'btn-primary', type: 'button', disabled: () => busy(), onclick: () => { void submit(true); }, text: 'Apply record' })
|
|
118
123
|
: null), () => error() ? h('p', { class: 'drawer-error', role: 'alert', text: error() }) : null, () => preview() ? h('p', { class: 'basis', role: 'status', text: `${preview().apply ? 'Recorded' : 'Preview'}: ${preview().matchedRequests} request(s) matched; ${preview().linkStatus}; ${preview().event.link.basis} link; ${preview().basis}` }) : null));
|
|
119
124
|
}
|
|
120
125
|
const MARKET_ROWS = 8;
|
|
126
|
+
function publicPrice(price) {
|
|
127
|
+
if (price === null)
|
|
128
|
+
return 'no public price';
|
|
129
|
+
const amount = typeof price.blendedUsdPerMillion === 'number'
|
|
130
|
+
? `${usd(price.blendedUsdPerMillion)}/M tokens`
|
|
131
|
+
: typeof price.usdPerImage === 'number'
|
|
132
|
+
? `${usd(price.usdPerImage)}/image`
|
|
133
|
+
: null;
|
|
134
|
+
if (amount === null)
|
|
135
|
+
return 'no public price';
|
|
136
|
+
return amount + (price.match === 'normalized' ? ` (as ${price.pricedAs})` : '');
|
|
137
|
+
}
|
|
121
138
|
function marketBoard(b) {
|
|
122
139
|
const head = h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: b.label }), h('span', { class: 'basis', text: `${b.licence}` }));
|
|
123
140
|
if (b.status !== 'available') {
|
|
@@ -137,9 +154,7 @@ function marketBoard(b) {
|
|
|
137
154
|
return h('tr', null, h('td', { text: x.model }), h('td', { text: `${x.passRatePercent.toFixed(1)}%` }), h('td', { text: x.runCostUsd === null ? 'not published' : usd(x.runCostUsd) }), h('td', { text: x.costPerSolvedTaskUsd === null ? '—' : usd(x.costPerSolvedTaskUsd) }), h('td', { text: x.frontier === null ? '—' : x.frontier ? 'yes' : '' }));
|
|
138
155
|
}
|
|
139
156
|
const x = r;
|
|
140
|
-
const price = x.price
|
|
141
|
-
: (x.price.blendedUsdPerMillion !== undefined ? `${usd(x.price.blendedUsdPerMillion)}/M tokens` : `${usd(x.price.usdPerImage ?? 0)}/image`)
|
|
142
|
-
+ (x.price.match === 'normalized' ? ` (as ${x.price.pricedAs})` : '');
|
|
157
|
+
const price = publicPrice(x.price);
|
|
143
158
|
return h('tr', null, h('td', { text: x.model }), h('td', { text: `${x.rating.toFixed(0)} (${x.ratingLower.toFixed(0)}–${x.ratingUpper.toFixed(0)})` }), h('td', { text: count(x.votes) }), h('td', { text: price }), h('td', { text: x.frontier === null ? '—' : x.frontier ? 'yes' : '' }));
|
|
144
159
|
}))));
|
|
145
160
|
return h('div', { class: 'card', style: 'margin-top: var(--s3)' }, head, h('p', { class: 'basis', text: when }), table, b.rows.length > rows.length ? h('p', { class: 'basis', text: `${b.rows.length - rows.length} more on the command line: segreant market --all` }) : null, b.frontier.length ? h('p', { class: 'basis', text: `Frontier: ${b.frontier.slice(0, 10).join(', ')}${b.frontier.length > 10 ? ` and ${b.frontier.length - 10} more` : ''}` }) : null, ...b.notes.map((n) => h('p', { class: 'basis', text: n })));
|
|
@@ -149,11 +164,11 @@ function consensusTable(c) {
|
|
|
149
164
|
if (c.status !== 'available')
|
|
150
165
|
return h('div', { class: 'card', style: 'margin-top: var(--s3)' }, title, ...c.notes.map((n) => h('p', { class: 'basis', text: n })));
|
|
151
166
|
const rows = c.rows.slice(0, 10);
|
|
152
|
-
return h('div', { class: 'card', style: 'margin-top: var(--s3)' }, title, h('p', { class: 'basis', text: 'Expected score on a typical benchmark of this kind, 0–100. The range is how far it moves if any one benchmark is dropped.' }), h('div', { class: 'table-wrap' }, h('table', { 'aria-label': 'Consensus quality score, top models' }, h('thead', null, h('tr', null, ...['Model', 'Score', 'Range', 'Benchmarks', 'List price', 'Frontier'].map((t) => h('th', { scope: 'col', text: t })))), h('tbody', null, ...rows.map((r) => h('tr', null, h('td', { text: r.label }), h('td', { text: r.score.toFixed(0) }), h('td', { text: `${r.low.toFixed(0)}–${r.high.toFixed(0)}` }), h('td', { text: String(r.benchmarks.length), title: r.benchmarks.map((b) => `${b.benchmark}: ${(b.score * 100).toFixed(0)}`).join('\n') }), h('td', { text:
|
|
167
|
+
return h('div', { class: 'card', style: 'margin-top: var(--s3)' }, title, h('p', { class: 'basis', text: 'Expected score on a typical benchmark of this kind, 0–100. The range is how far it moves if any one benchmark is dropped.' }), h('div', { class: 'table-wrap' }, h('table', { 'aria-label': 'Consensus quality score, top models' }, h('thead', null, h('tr', null, ...['Model', 'Score', 'Range', 'Benchmarks', 'List price', 'Frontier'].map((t) => h('th', { scope: 'col', text: t })))), h('tbody', null, ...rows.map((r) => h('tr', null, h('td', { text: r.label }), h('td', { text: r.score.toFixed(0) }), h('td', { text: `${r.low.toFixed(0)}–${r.high.toFixed(0)}` }), h('td', { text: String(r.benchmarks.length), title: r.benchmarks.map((b) => `${b.benchmark}: ${(b.score * 100).toFixed(0)}`).join('\n') }), h('td', { text: publicPrice(r.price) }), h('td', { text: r.frontier === null ? '—' : r.frontier ? 'yes' : `beaten by ${r.beatenBy?.label ?? '—'}${r.beatenBy && !r.beatenBy.clear ? ' (within range)' : ''}` })))))), h('details', null, h('summary', { text: 'How each benchmark is weighted' }), ...c.weights.map((w) => h('p', { class: 'basis', text: `${w.benchmark}: weight ${w.weight.toFixed(2)} = independence ${w.independence} × contamination resistance ${w.contamination} × currency ${w.currency} (newest ${w.newest ?? 'undated'}, ${w.models} models). ${w.why}` }))), ...c.notes.map((n) => h('p', { class: 'basis', text: n })));
|
|
153
168
|
}
|
|
154
169
|
/** Public evidence only. It never reads the ledger and never enters a figure above it. */
|
|
155
|
-
function marketCard(payload, failure) {
|
|
156
|
-
const title = h('h2', { class: 'section-title', text: 'Public model market — public evidence, not your results' });
|
|
170
|
+
function marketCard(payload, failure, titled = true) {
|
|
171
|
+
const title = titled ? h('h2', { class: 'section-title', text: 'Public model market — public evidence, not your results' }) : null;
|
|
157
172
|
if (failure)
|
|
158
173
|
return h('section', { class: 'section' }, title, h('p', { class: 'drawer-error', role: 'alert', text: failure }));
|
|
159
174
|
if (!payload)
|
|
@@ -201,9 +216,12 @@ function usageCoverageCard(usage) {
|
|
|
201
216
|
if (!usage)
|
|
202
217
|
return null;
|
|
203
218
|
const retention = usage.retention;
|
|
219
|
+
const before = retention.prunedBeforeMs;
|
|
220
|
+
const boundary = typeof before === 'number' && Number.isFinite(before) && before > 0 && before <= 8.64e15
|
|
221
|
+
? new Date(before).toISOString() : 'an unrecorded boundary';
|
|
204
222
|
return h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Usage without code signals' : 'Chat, research, and drafting') })), h('div', { class: 'facts' }, h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'observed sessions' : 'sessions') }), h('span', { class: 'fact-val', text: count(usage.units.length) })), h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'reported realized' : 'realized') }), h('span', { class: 'fact-val', text: count(usage.realizedUnits) })), h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'surviving cost' : 'cost recorded') }), h('span', { class: 'fact-val', text: usd(usage.totalCostUsd) }))), retention.truncated
|
|
205
223
|
? h('p', { class: 'drawer-error', role: 'status', text: () => (isPrecise()
|
|
206
|
-
? `This usage window reaches behind retention: ${count(retention.rowsRemoved)} request row(s) were deleted before ${
|
|
224
|
+
? `This usage window reaches behind retention: ${count(retention.rowsRemoved)} request row(s) were deleted before ${boundary}. Figures cover what survived, not everything metered.`
|
|
207
225
|
: 'Some requests in this usage window were deleted by retention, so these figures cover what remains rather than everything metered.') })
|
|
208
226
|
: null, h('p', { class: 'basis', text: () => (isPrecise()
|
|
209
227
|
? 'These sessions have no captured code proposals; reported outcomes remain observational and do not become coding value.'
|
|
@@ -241,7 +259,7 @@ function modelSwitchCoverageCard(frontier) {
|
|
|
241
259
|
: null, retentionUnknown > 0
|
|
242
260
|
? h('p', { class: 'basis', role: 'status', text: () => (isPrecise()
|
|
243
261
|
? `${count(retentionUnknown)} included unit(s) predate the retention-coverage record, so whether their spend window lost rows is unknown.`
|
|
244
|
-
: `For ${count(retentionUnknown)} included unit(s)
|
|
262
|
+
: `For ${count(retentionUnknown)} included unit(s) there's no record of whether old spend was deleted: they're older than that record.`) })
|
|
245
263
|
: null, h('p', { class: 'basis', text: () => (isPrecise()
|
|
246
264
|
? `Observed headroom ${usd(recommendation.historicalEquivalentHeadroomUsd)}; this is a local list-price comparison, not provider-billed savings.`
|
|
247
265
|
: `Observed headroom ${usd(recommendation.historicalEquivalentHeadroomUsd)}; this is not a promise of future savings.`) }));
|
|
@@ -266,7 +284,7 @@ export function valueView() {
|
|
|
266
284
|
.then((payload) => causal.set(payload))
|
|
267
285
|
.catch((e) => causalError.set(e instanceof Error ? e.message : String(e)));
|
|
268
286
|
});
|
|
269
|
-
return h('div', null, h('div', { class: 'view-head' }, h('h1', { class: 'view-title', text: '
|
|
287
|
+
return h('div', null, h('div', { class: 'view-head' }, h('h1', { class: 'view-title', text: 'Value' }), h('p', { class: 'view-plain', text: () => isPrecise()
|
|
270
288
|
? 'Realized value over matured work units, rework-discounted. Acceptance is not an outcome and is never counted as one.'
|
|
271
289
|
: 'What the AI spend actually produced — counting only work that shipped and stayed shipped, not work that merely got accepted.' })), () => {
|
|
272
290
|
const err = error();
|
|
@@ -278,13 +296,15 @@ export function valueView() {
|
|
|
278
296
|
const matured = d.realization?.matured ?? null;
|
|
279
297
|
const established = (matured?.realizedUnits ?? 0) > 0;
|
|
280
298
|
if (!established) {
|
|
281
|
-
return h('div', null, h('div', { class: 'notyet' }, h('h2', { text: () => (isPrecise() ? 'Realized value is not established' : '
|
|
299
|
+
return h('div', null, h('div', { class: 'notyet' }, h('h2', { text: () => (isPrecise() ? 'Realized value is not established' : 'Nothing to show yet') }), h('p', { text: () => (isPrecise()
|
|
282
300
|
? 'No work units have matured into verified outcomes on this machine. This is an absence of evidence, not a realized value of zero — the two must not be reported alike.'
|
|
283
|
-
: '
|
|
301
|
+
: 'No work has been followed all the way to shipped and kept yet. That is missing evidence, not zero.') }), h('p', { class: 'basis', text: () => (isPrecise()
|
|
284
302
|
? 'Maturation requires observable outcomes: a repository whose history can be read, or imported units with recorded gate results.'
|
|
285
|
-
: 'Segreant needs somewhere to watch outcomes happen — usually a code repository — before it can say what the spend produced.') })),
|
|
303
|
+
: 'Segreant needs somewhere to watch outcomes happen — usually a code repository — before it can say what the spend produced.') })), selfReportedCard(d.selfReported, refresh), fold(() => (isPrecise() ? 'Usage without code signals' : 'Chat, research and drafting'), usageCoverageCard(d.usage)), fold(() => (isPrecise() ? 'Causal study evidence' : 'Is any of this proven to be caused by AI?'), causalStudyCard(causal(), causalError())), fold(() => 'Public model market: public evidence, not your results', marketCard(market(), marketError(), false)), actions());
|
|
286
304
|
}
|
|
287
305
|
const funnel = matured?.instrumentation ?? {};
|
|
306
|
+
const gatePasses = matured?.gatePasses ?? {};
|
|
307
|
+
const maturedUnits = matured?.units ?? 0;
|
|
288
308
|
// Gates where two sources disagreed. Shown separately from the counts
|
|
289
309
|
// because a contradiction is not a measurement of the gate, and because
|
|
290
310
|
// the legacy projection renders it as a plain failure (AII-003).
|
|
@@ -296,7 +316,7 @@ export function valueView() {
|
|
|
296
316
|
const drift = d.drift ?? null;
|
|
297
317
|
const ret = d.roi?.returnRatio ?? null;
|
|
298
318
|
const economic = matured?.economic ?? null;
|
|
299
|
-
return h('div', null, d.demo ? h('div', { class: 'banner banner-demo' }, h('span', { class: 'pill pill-demo', text: 'demo' }), h('p', null, h('strong', { text: 'Sample data. ' }), 'These outcomes were seeded, not observed on your machine.')) : null,
|
|
319
|
+
return h('div', null, d.demo ? h('div', { class: 'banner banner-demo' }, h('span', { class: 'pill pill-demo', text: 'demo' }), h('p', null, h('strong', { text: 'Sample data. ' }), 'These outcomes were seeded, not observed on your machine.')) : null,
|
|
300
320
|
// Basis before figure. Which of the two sources produced this, and whether
|
|
301
321
|
// the dollars are scoped to the project or merely summed over a window,
|
|
302
322
|
// change what the headline means.
|
|
@@ -335,13 +355,13 @@ export function valueView() {
|
|
|
335
355
|
(matured?.spendWindowUnknownUnits ?? 0) > 0
|
|
336
356
|
? h('span', { class: 'basis', text: () => (isPrecise()
|
|
337
357
|
? `${count(matured?.spendWindowUnknownUnits)} unit(s) predate the retention-coverage record, so whether their spend window lost rows is unknown.`
|
|
338
|
-
: `For ${count(matured?.spendWindowUnknownUnits)} of these
|
|
358
|
+
: `For ${count(matured?.spendWindowUnknownUnits)} of these, Segreant has no record of whether any cost rows were deleted.`) })
|
|
339
359
|
: null), economic
|
|
340
360
|
? h('p', { class: 'basis', role: 'status', text: () => {
|
|
341
361
|
if (economic.coverage === 'legacy_unknown' || economic.total === null) {
|
|
342
362
|
return isPrecise()
|
|
343
363
|
? 'Exact economic coverage: legacy_unknown — these snapshots predate exact request evidence, so numeric costs are compatibility projections.'
|
|
344
|
-
: '
|
|
364
|
+
: 'These older snapshots have no exact per-request prices, so their costs are approximate totals.';
|
|
345
365
|
}
|
|
346
366
|
const total = economic.total;
|
|
347
367
|
if (economic.coverage === 'partial' || total.unresolvedRequests > 0) {
|
|
@@ -373,22 +393,22 @@ export function valueView() {
|
|
|
373
393
|
: ret.supervisionPriced
|
|
374
394
|
? 'the AI spend plus your own measured time, priced at your labour rate'
|
|
375
395
|
: 'the AI spend plus an estimate of the time it took you') })))
|
|
376
|
-
: h('div', { class: 'notyet', style: 'margin-top: var(--s4)' }, h('h2', { text: () => (isPrecise() ? '
|
|
377
|
-
? 'Work matured, but no labour rate is
|
|
378
|
-
: 'Work did get finished, but Segreant has no hourly rate to value it against
|
|
396
|
+
: h('div', { class: 'notyet', style: 'margin-top: var(--s4)' }, h('h2', { text: () => (isPrecise() ? 'Value of kept work: no price set' : 'No dollar figure yet') }), h('p', { text: () => (isPrecise()
|
|
397
|
+
? 'Work matured, but no labour rate is set, so its value has no dollar figure. The rate below is still computed.'
|
|
398
|
+
: 'Work did get finished, but Segreant has no hourly rate to value it against. It can tell you how much you kept, not what it was worth.') })),
|
|
379
399
|
// The money face is an observed/manual-equivalent scenario. A separate
|
|
380
400
|
// qualified randomized study is required for causal economics.
|
|
381
401
|
ret && typeof ret.grossRatio === 'number'
|
|
382
402
|
? h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Observed value scenario' : 'The value it looks like it delivered') }), h('span', {
|
|
383
403
|
class: 'pill pill-warn',
|
|
384
|
-
text: 'not causal evidence',
|
|
404
|
+
text: () => (isPrecise() ? 'not causal evidence' : "doesn't prove cause"),
|
|
385
405
|
})), h('div', { class: 'stat', text: `${ret.grossRatio.toFixed(2)}\u00d7` }), h('span', { class: 'basis', text: () => (isPrecise()
|
|
386
406
|
? 'realized manual-equivalent value divided by tokens plus measured time; a qualified randomized study is required for causal net benefit'
|
|
387
|
-
:
|
|
407
|
+
: "This compares the value of work you kept with what it cost in AI and time. It doesn't show what would have happened without AI.") }))
|
|
388
408
|
: null,
|
|
389
409
|
// Realization rate with its partial-identification bounds. A point estimate
|
|
390
410
|
// alone would overstate how precisely this is known.
|
|
391
|
-
h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Realization rate' : 'How much of the work
|
|
411
|
+
h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Realization rate' : 'How much of the work you kept') })), h('div', { class: 'stat', text: pct(matured?.realizationRate, 0) }), bounds
|
|
392
412
|
? h('span', { class: 'basis', text: () => (isPrecise()
|
|
393
413
|
? `partial-identification bounds ${pct(bounds.lower, 0)}–${pct(bounds.upper, 0)} over n=${count(bounds.n)}`
|
|
394
414
|
: `somewhere between ${pct(bounds.lower, 0)} and ${pct(bounds.upper, 0)}, based on ${count(bounds.n)} pieces of work`) })
|
|
@@ -398,26 +418,26 @@ export function valueView() {
|
|
|
398
418
|
text: () => (drift.alarm
|
|
399
419
|
? (isPrecise()
|
|
400
420
|
? `Drift alarm: the recent realization rate (${pct(drift.recentRate, 0)}) has departed from the overall rate (${pct(drift.overallRate, 0)}) beyond chance.`
|
|
401
|
-
: `
|
|
421
|
+
: `Change alert: lately, much less of the work has been kept (${pct(drift.recentRate, 0)}, against ${pct(drift.overallRate, 0)} overall).`)
|
|
402
422
|
: (isPrecise()
|
|
403
423
|
? `The drift alarm did not fire over n=${count(drift.n)} mature units.`
|
|
404
424
|
+ (drift.referenceDriftWouldFire === false
|
|
405
425
|
? ' At this length the same test does not fire even on a total regime change, so its silence carries no information.'
|
|
406
426
|
: ' An e-process bounds false alarms and not missed ones, so this is not evidence that the rate held.')
|
|
407
|
-
: `
|
|
427
|
+
: `No change alert fired over ${count(drift.n)} pieces of work`
|
|
408
428
|
+ (drift.referenceDriftWouldFire === false
|
|
409
|
-
?
|
|
410
|
-
:
|
|
429
|
+
? ", but that's too few for the check to notice a change yet."
|
|
430
|
+
: ". That doesn't prove the rate held steady."))),
|
|
411
431
|
})
|
|
412
432
|
: null),
|
|
413
433
|
// The actionable part: where units die and what that costs.
|
|
414
434
|
waste.length > 0
|
|
415
|
-
? h('section', { class: 'section' }, h('h2', { class: 'section-title', text: () => (isPrecise() ? 'Where value is lost' : 'Where
|
|
416
|
-
? `Of ${usd(matured?.totalCostUsd)} attributed to matured units, ${usd(matured?.spendOnRealizedUnitsUsd)} reached a
|
|
417
|
-
: `Of the ${usd(matured?.totalCostUsd)} spent on this work, ${usd(matured?.spendOnRealizedUnitsUsd)} went on work
|
|
435
|
+
? h('section', { class: 'section' }, h('h2', { class: 'section-title', text: () => (isPrecise() ? 'Where value is lost' : 'Where work was lost') }), h('p', { class: 'view-plain', text: () => (isPrecise()
|
|
436
|
+
? `Of ${usd(matured?.totalCostUsd)} attributed to matured units, ${usd(matured?.spendOnRealizedUnitsUsd)} reached a realized outcome and ${usd(wasteCost)} did not. These are spend figures, not value.`
|
|
437
|
+
: `Of the ${usd(matured?.totalCostUsd)} spent on this work, ${usd(matured?.spendOnRealizedUnitsUsd)} went on work you kept and ${usd(wasteCost)} on work you didn't.`) }), h('div', { class: 'ledger', role: 'table', 'aria-label': 'Where value was lost, by stopping stage' }, h('div', { class: 'ledger-head', role: 'row' }, h('span', { role: 'columnheader', text: () => (isPrecise() ? 'First failed gate' : 'What went wrong') }), h('span', { class: 'num cell-calls', role: 'columnheader', text: 'Units' }), h('span', { class: 'num cell-cost', role: 'columnheader', text: 'Cost' }), h('span', { class: 'num cell-share', role: 'columnheader', text: 'Share' })), ...waste
|
|
418
438
|
.slice()
|
|
419
439
|
.sort((a, b) => b.costUsd - a.costUsd)
|
|
420
|
-
.map((w) => h('div', { class: 'ledger-row', role: 'row' }, h('span', { class: 'ledger-key', role: 'cell', text: () => (isPrecise() ? w.stage :
|
|
440
|
+
.map((w) => h('div', { class: 'ledger-row', role: 'row' }, h('span', { class: 'ledger-key', role: 'cell', text: () => (isPrecise() ? w.stage : (FAILED_AT[w.stage] ?? w.stage)) }), h('span', { class: 'num cell-calls', role: 'cell', text: `${count(w.units)} ${plural(w.units, 'unit', 'units')}` }), h('span', { class: 'num cell-cost ledger-cost', role: 'cell', text: usd(w.costUsd) }), h('span', { class: 'num cell-share', role: 'cell', text: wasteCost > 0 ? share(w.costUsd / wasteCost) : '—' }), h('span', {
|
|
421
441
|
class: 'ledger-bar',
|
|
422
442
|
'aria-hidden': 'true',
|
|
423
443
|
style: `--fill: ${wasteCost > 0 ? Math.max(0.5, (w.costUsd / wasteCost) * 100) : 0}%`,
|
|
@@ -425,11 +445,26 @@ export function valueView() {
|
|
|
425
445
|
: null,
|
|
426
446
|
// The funnel, as counts. Deliberately after the waste breakdown: the
|
|
427
447
|
// question worth asking is where work dies, not how big the pipeline is.
|
|
448
|
+
// Passed, failed and not checked, side by side. This list used to show
|
|
449
|
+
// only how many units were CHECKED at each gate, under words like "was
|
|
450
|
+
// merged", so it read as a funnel that grew: merged 10, shipped 10,
|
|
451
|
+
// survived 13 (more work surviving than shipped).
|
|
428
452
|
Object.keys(funnel).length > 0
|
|
429
|
-
? h('section', { class: 'section' }, h('h2', { class: 'section-title', text: () => (isPrecise() ? '
|
|
453
|
+
? h('section', { class: 'section' }, h('h2', { class: 'section-title', text: () => (isPrecise() ? 'Checks passed at each step' : 'How far the work got') }), h('p', { class: 'view-plain', text: () => (isPrecise()
|
|
454
|
+
? `Matured units: ${count(maturedUnits)}. Each gate is judged on its own evidence, so a later gate can pass more often than an earlier one that had no signal.${gateConflicts.length > 0 ? ' Failed counts include contradicted evidence, listed below.' : ''}`
|
|
455
|
+
: `Out of ${count(maturedUnits)} finished ${plural(maturedUnits, 'piece', 'pieces')} of work. "Not checked" means Segreant had no signal for that step, not that it failed.`) }), h('div', { class: 'ledger ledger-gates', role: 'table', 'aria-label': 'Checks passed at each step, finished work' }, h('div', { class: 'ledger-head', role: 'row' }, h('span', { role: 'columnheader', text: () => (isPrecise() ? 'Gate' : 'Step') }), h('span', { class: 'num', role: 'columnheader', text: 'Passed' }), h('span', { class: 'num', role: 'columnheader', text: 'Failed' }), h('span', { class: 'num', role: 'columnheader', text: 'Not checked' })), ...Object.entries(funnel).map(([stage, checked]) => {
|
|
456
|
+
const passed = gatePasses[stage] ?? 0;
|
|
457
|
+
const failed = Math.max(0, checked - passed);
|
|
458
|
+
const unchecked = Math.max(0, maturedUnits - checked);
|
|
459
|
+
return h('div', { class: 'ledger-row', role: 'row' }, h('span', { class: 'ledger-key', role: 'cell', text: () => (isPrecise() ? stage : (GATE_WORDS[stage] ?? stage)) }), h('span', { class: 'num gate-pass', role: 'cell', text: count(passed) }), h('span', { class: failed > 0 ? 'num gate-fail' : 'num', role: 'cell', text: count(failed) }), h('span', { class: 'num gate-unchecked', role: 'cell', text: count(unchecked) }), h('span', {
|
|
460
|
+
class: 'ledger-bar',
|
|
461
|
+
'aria-hidden': 'true',
|
|
462
|
+
style: `--fill: ${maturedUnits > 0 ? (passed / maturedUnits) * 100 : 0}%`,
|
|
463
|
+
}));
|
|
464
|
+
})), gateConflicts.length > 0
|
|
430
465
|
? h('p', { class: 'section-note', text: () => (isPrecise()
|
|
431
|
-
? `
|
|
432
|
-
: `
|
|
466
|
+
? `Conflicting results at ${gateConflicts.map(([stage, n]) => `${stage} (${n})`).join(', ')}: some sources passed these steps and others failed them. They count as failed only because a step has no third "disputed" value; the conflict is unresolved, not a fail.`
|
|
467
|
+
: `Results disagree with each other at ${gateConflicts.map(([stage]) => (GATE_WORDS[stage] ?? stage)).join(', ')}. That needs resolving; it isn't a result.`) })
|
|
433
468
|
: null)
|
|
434
469
|
: null, d.reclaimed && typeof d.reclaimed.workWeeksSaved === 'number'
|
|
435
470
|
? h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Time reclaimed' : 'Time this saved') })), h('div', { class: 'stat', text: `${d.reclaimed.workWeeksSaved.toFixed(1)} work weeks` }),
|
|
@@ -457,10 +492,15 @@ export function valueView() {
|
|
|
457
492
|
? `${count(d.reclaimed?.uncreditedUnits)} matured ${plural(d.reclaimed?.uncreditedUnits ?? 0, 'unit', 'units')} earned no time credit (died, or had no baseline).`
|
|
458
493
|
: `${count(d.reclaimed?.uncreditedUnits)} ${plural(d.reclaimed?.uncreditedUnits ?? 0, 'piece', 'pieces')} of work got no credit here — they either failed, or we had nothing to compare them against.`) })
|
|
459
494
|
: null)
|
|
460
|
-
: null,
|
|
495
|
+
: null, selfReportedCard(d.selfReported, refresh),
|
|
496
|
+
// Supporting evidence, folded. It used to run at full length after the
|
|
497
|
+
// answer, which made this a 7,500 px page (13,000 on a phone) with the
|
|
498
|
+
// public market tables alone longer than everything above them. Each
|
|
499
|
+
// fold says what it holds; nothing is removed.
|
|
500
|
+
h('h2', { class: 'section-title fold-head', text: () => (isPrecise() ? 'Supporting evidence' : 'More detail, if you want it') }), fold(() => (isPrecise() ? 'Model-switch trials' : 'Cheaper model trials'), modelSwitchCoverageCard(d.frontier)), fold(() => (isPrecise() ? 'Usage without code signals' : 'Chat, research and drafting'), usageCoverageCard(d.usage)), fold(() => (isPrecise() ? 'Causal study evidence' : 'Is any of this proven to be caused by AI?'), causalStudyCard(causal(), causalError())), fold(() => 'Public model market: public evidence, not your results', marketCard(market(), marketError(), false)),
|
|
461
501
|
// Per-user. The guardrail state is the content when the cohort is suppressed.
|
|
462
502
|
team
|
|
463
|
-
? h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Cohort distribution' : 'Across the people using it') }), h('span', {
|
|
503
|
+
? fold(() => (isPrecise() ? 'Cohort distribution' : 'Across the people using it'), h('div', { class: 'card', style: 'margin-top: var(--s4)' }, h('div', { class: 'card-head' }, h('span', { class: 'card-title', text: () => (isPrecise() ? 'Cohort distribution' : 'Across the people using it') }), h('span', {
|
|
464
504
|
class: `pill ${team.suppressed || !team.enabled ? 'pill-unverified' : 'pill-ok'}`,
|
|
465
505
|
text: !team.enabled ? 'off' : team.suppressed ? 'suppressed' : 'distribution only',
|
|
466
506
|
})), !team.enabled
|
|
@@ -475,14 +515,20 @@ export function valueView() {
|
|
|
475
515
|
? `Distribution over ${count(team.distribution?.cohortSize)} users; individuals are never identified.`
|
|
476
516
|
: `Spread across ${count(team.distribution?.cohortSize)} people. Segreant never shows who is who.`) }), h('div', { class: 'facts' }, h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'median extraction' : 'typical person gets back') }), h('span', { class: 'fact-val', text: pct(team.distribution.medianExtraction, 0) })), h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'dispersion' : 'how evenly spread') }), h('span', { class: 'fact-val', text: team.distribution.broadBased
|
|
477
517
|
? (isPrecise() ? `${team.distribution.dispersion.toFixed(2)} — broad-based` : 'fairly even')
|
|
478
|
-
: (isPrecise() ? `${team.distribution.dispersion.toFixed(2)} — concentrated` : 'concentrated in a few') })), h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'coaching headroom' : 'possible if everyone matched the middle') }), h('span', { class: 'fact-val', text: usd(team.distribution.coachingHeadroomUsd) })))))
|
|
518
|
+
: (isPrecise() ? `${team.distribution.dispersion.toFixed(2)} — concentrated` : 'concentrated in a few') })), h('div', { class: 'fact' }, h('span', { class: 'fact-key', text: () => (isPrecise() ? 'coaching headroom' : 'possible if everyone matched the middle') }), h('span', { class: 'fact-val', text: usd(team.distribution.coachingHeadroomUsd) }))))))
|
|
479
519
|
: null, (d.roi?.notes?.length ?? 0) > 0
|
|
480
|
-
?
|
|
520
|
+
? fold(() => (isPrecise() ? 'Method notes' : 'How this was worked out'), h('section', null, h('p', { class: 'scope-note', text: () => (isPrecise()
|
|
481
521
|
? 'These notes are stated on the manual-equivalent value basis (the figures in Realized value and Honest cost above), not on the attributed-spend basis used in the waste breakdown.'
|
|
482
|
-
: 'These notes talk about what the work was worth and what your time cost — not the smaller AI-spend figures further down the page.') }), h('ul', { class: 'drawer-notes' }, ...(d.roi?.notes ?? []).slice(0, 8).map((n) => h('li', { text: n }))))
|
|
522
|
+
: 'These notes talk about what the work was worth and what your time cost — not the smaller AI-spend figures further down the page.') }), h('ul', { class: 'drawer-notes' }, ...(d.roi?.notes ?? []).slice(0, 8).map((n) => h('li', { text: n })))))
|
|
483
523
|
: null, actions());
|
|
484
524
|
});
|
|
485
525
|
}
|
|
526
|
+
/** A closed section whose summary names what it holds. Nothing in it is hidden from the DOM. */
|
|
527
|
+
function fold(title, body) {
|
|
528
|
+
if (body === null)
|
|
529
|
+
return null;
|
|
530
|
+
return h('details', { class: 'fold' }, h('summary', { class: 'fold-summary', text: title }), body);
|
|
531
|
+
}
|
|
486
532
|
function actions() {
|
|
487
533
|
return h('section', { class: 'section' }, h('h2', { class: 'section-title', text: () => (isPrecise() ? 'Actions on this layer' : 'Things you can do with this') }), h('div', { class: 'actions' }, actionCard('roi'), actionCard('realize'), actionCard('frontier'), actionCard('saved'), actionCard('judge'), actionCard('team')));
|
|
488
534
|
}
|