@ashlr/hub 2.2.0 → 3.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.
Files changed (177) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +95 -8
  3. package/dist/api/plugin.d.ts +1 -0
  4. package/dist/cli/backlog.js +2 -0
  5. package/dist/cli/backlog.js.map +1 -1
  6. package/dist/cli/digest.d.ts +6 -0
  7. package/dist/cli/digest.js +127 -2
  8. package/dist/cli/digest.js.map +1 -1
  9. package/dist/cli/eval-fixtures.d.ts +18 -0
  10. package/dist/cli/eval-fixtures.js +38 -0
  11. package/dist/cli/eval-fixtures.js.map +1 -0
  12. package/dist/cli/eval.d.ts +56 -0
  13. package/dist/cli/eval.js +283 -0
  14. package/dist/cli/eval.js.map +1 -0
  15. package/dist/cli/fleet.d.ts +27 -0
  16. package/dist/cli/fleet.js +222 -0
  17. package/dist/cli/fleet.js.map +1 -0
  18. package/dist/cli/goal.d.ts +15 -0
  19. package/dist/cli/goal.js +91 -0
  20. package/dist/cli/goal.js.map +1 -0
  21. package/dist/cli/help.js +10 -3
  22. package/dist/cli/help.js.map +1 -1
  23. package/dist/cli/inbox.d.ts +6 -0
  24. package/dist/cli/inbox.js +183 -8
  25. package/dist/cli/inbox.js.map +1 -1
  26. package/dist/cli/index.js +50 -0
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/cli/loop.d.ts +16 -0
  29. package/dist/cli/loop.js +66 -0
  30. package/dist/cli/loop.js.map +1 -0
  31. package/dist/cli/mcp.d.ts +12 -0
  32. package/dist/cli/mcp.js +148 -0
  33. package/dist/cli/mcp.js.map +1 -1
  34. package/dist/cli/onboard.d.ts +16 -0
  35. package/dist/cli/onboard.js +71 -0
  36. package/dist/cli/onboard.js.map +1 -1
  37. package/dist/cli/plugins.js +9 -8
  38. package/dist/cli/plugins.js.map +1 -1
  39. package/dist/cli/pulse.d.ts +10 -0
  40. package/dist/cli/pulse.js +261 -0
  41. package/dist/cli/pulse.js.map +1 -1
  42. package/dist/cli/run.js +21 -3
  43. package/dist/cli/run.js.map +1 -1
  44. package/dist/cli/stack.d.ts +34 -0
  45. package/dist/cli/stack.js +221 -0
  46. package/dist/cli/stack.js.map +1 -0
  47. package/dist/cli/update.js +12 -5
  48. package/dist/cli/update.js.map +1 -1
  49. package/dist/core/daemon/loop.d.ts +10 -5
  50. package/dist/core/daemon/loop.js +167 -37
  51. package/dist/core/daemon/loop.js.map +1 -1
  52. package/dist/core/env-bridge.js +3 -2
  53. package/dist/core/env-bridge.js.map +1 -1
  54. package/dist/core/fleet/automerge-pass.d.ts +33 -0
  55. package/dist/core/fleet/automerge-pass.js +61 -0
  56. package/dist/core/fleet/automerge-pass.js.map +1 -0
  57. package/dist/core/fleet/quota.d.ts +70 -0
  58. package/dist/core/fleet/quota.js +198 -0
  59. package/dist/core/fleet/quota.js.map +1 -0
  60. package/dist/core/fleet/router.d.ts +46 -0
  61. package/dist/core/fleet/router.js +121 -0
  62. package/dist/core/fleet/router.js.map +1 -0
  63. package/dist/core/fleet/self.d.ts +58 -0
  64. package/dist/core/fleet/self.js +187 -0
  65. package/dist/core/fleet/self.js.map +1 -0
  66. package/dist/core/fleet/status.d.ts +54 -0
  67. package/dist/core/fleet/status.js +157 -0
  68. package/dist/core/fleet/status.js.map +1 -0
  69. package/dist/core/foundry/provenance.d.ts +78 -0
  70. package/dist/core/foundry/provenance.js +172 -0
  71. package/dist/core/foundry/provenance.js.map +1 -0
  72. package/dist/core/git.d.ts +13 -0
  73. package/dist/core/git.js +26 -0
  74. package/dist/core/git.js.map +1 -1
  75. package/dist/core/inbox/merge.d.ts +151 -0
  76. package/dist/core/inbox/merge.js +858 -0
  77. package/dist/core/inbox/merge.js.map +1 -0
  78. package/dist/core/inbox/store.js +10 -1
  79. package/dist/core/inbox/store.js.map +1 -1
  80. package/dist/core/integrations/markdown.d.ts +66 -0
  81. package/dist/core/integrations/markdown.js +132 -0
  82. package/dist/core/integrations/markdown.js.map +1 -0
  83. package/dist/core/integrations/secrets.d.ts +37 -0
  84. package/dist/core/integrations/secrets.js +67 -0
  85. package/dist/core/integrations/secrets.js.map +1 -0
  86. package/dist/core/integrations/stack.d.ts +47 -0
  87. package/dist/core/integrations/stack.js +107 -0
  88. package/dist/core/integrations/stack.js.map +1 -0
  89. package/dist/core/mcp-native-engineer.d.ts +123 -0
  90. package/dist/core/mcp-native-engineer.js +936 -0
  91. package/dist/core/mcp-native-engineer.js.map +1 -0
  92. package/dist/core/mcp-native.js +20 -42
  93. package/dist/core/mcp-native.js.map +1 -1
  94. package/dist/core/mcp-registry.js +2 -0
  95. package/dist/core/mcp-registry.js.map +1 -1
  96. package/dist/core/observability/codex-source.d.ts +53 -0
  97. package/dist/core/observability/codex-source.js +390 -0
  98. package/dist/core/observability/codex-source.js.map +1 -0
  99. package/dist/core/observability/estimate.d.ts +12 -0
  100. package/dist/core/observability/estimate.js +26 -0
  101. package/dist/core/observability/estimate.js.map +1 -1
  102. package/dist/core/observability/limits.d.ts +52 -0
  103. package/dist/core/observability/limits.js +316 -0
  104. package/dist/core/observability/limits.js.map +1 -0
  105. package/dist/core/observability/usage-source.js +3 -1
  106. package/dist/core/observability/usage-source.js.map +1 -1
  107. package/dist/core/portfolio/scanners.d.ts +1 -0
  108. package/dist/core/portfolio/scanners.js +40 -1
  109. package/dist/core/portfolio/scanners.js.map +1 -1
  110. package/dist/core/providers.js +4 -0
  111. package/dist/core/providers.js.map +1 -1
  112. package/dist/core/quality/health.js +1 -0
  113. package/dist/core/quality/health.js.map +1 -1
  114. package/dist/core/run/agent-loop.d.ts +8 -0
  115. package/dist/core/run/agent-loop.js +24 -14
  116. package/dist/core/run/agent-loop.js.map +1 -1
  117. package/dist/core/run/engine-registry.d.ts +48 -0
  118. package/dist/core/run/engine-registry.js +190 -0
  119. package/dist/core/run/engine-registry.js.map +1 -0
  120. package/dist/core/run/engines.d.ts +17 -3
  121. package/dist/core/run/engines.js +63 -44
  122. package/dist/core/run/engines.js.map +1 -1
  123. package/dist/core/run/learned-router.d.ts +121 -0
  124. package/dist/core/run/learned-router.js +374 -0
  125. package/dist/core/run/learned-router.js.map +1 -0
  126. package/dist/core/run/model-manager.js +3 -3
  127. package/dist/core/run/model-manager.js.map +1 -1
  128. package/dist/core/run/model-profile.d.ts +67 -0
  129. package/dist/core/run/model-profile.js +132 -0
  130. package/dist/core/run/model-profile.js.map +1 -0
  131. package/dist/core/run/orchestrator.d.ts +1 -1
  132. package/dist/core/run/orchestrator.js +642 -510
  133. package/dist/core/run/orchestrator.js.map +1 -1
  134. package/dist/core/run/prompts/budget.d.ts +25 -0
  135. package/dist/core/run/prompts/budget.js +51 -0
  136. package/dist/core/run/prompts/budget.js.map +1 -0
  137. package/dist/core/run/prompts/index.d.ts +14 -0
  138. package/dist/core/run/prompts/index.js +59 -0
  139. package/dist/core/run/prompts/index.js.map +1 -0
  140. package/dist/core/run/prompts/layers.d.ts +26 -0
  141. package/dist/core/run/prompts/layers.js +73 -0
  142. package/dist/core/run/prompts/layers.js.map +1 -0
  143. package/dist/core/run/prompts/roles.d.ts +23 -0
  144. package/dist/core/run/prompts/roles.js +48 -0
  145. package/dist/core/run/prompts/roles.js.map +1 -0
  146. package/dist/core/run/prompts/types.d.ts +38 -0
  147. package/dist/core/run/prompts/types.js +5 -0
  148. package/dist/core/run/prompts/types.js.map +1 -0
  149. package/dist/core/run/provider-client.d.ts +6 -24
  150. package/dist/core/run/provider-client.js +125 -61
  151. package/dist/core/run/provider-client.js.map +1 -1
  152. package/dist/core/run/router.js +8 -0
  153. package/dist/core/run/router.js.map +1 -1
  154. package/dist/core/run/sandboxed-engine.d.ts +66 -0
  155. package/dist/core/run/sandboxed-engine.js +262 -0
  156. package/dist/core/run/sandboxed-engine.js.map +1 -0
  157. package/dist/core/run/verify-commands.d.ts +83 -0
  158. package/dist/core/run/verify-commands.js +234 -0
  159. package/dist/core/run/verify-commands.js.map +1 -0
  160. package/dist/core/run/verify.d.ts +31 -1
  161. package/dist/core/run/verify.js +48 -0
  162. package/dist/core/run/verify.js.map +1 -1
  163. package/dist/core/sandbox/audit.d.ts +27 -0
  164. package/dist/core/sandbox/audit.js +34 -0
  165. package/dist/core/sandbox/audit.js.map +1 -1
  166. package/dist/core/sandbox/confine.d.ts +134 -0
  167. package/dist/core/sandbox/confine.js +370 -0
  168. package/dist/core/sandbox/confine.js.map +1 -0
  169. package/dist/core/types.d.ts +227 -5
  170. package/dist/core/web/api.js +77 -28
  171. package/dist/core/web/api.js.map +1 -1
  172. package/dist/core/web/control.d.ts +116 -0
  173. package/dist/core/web/control.js +307 -0
  174. package/dist/core/web/control.js.map +1 -0
  175. package/dist/core/web/public/app.js +512 -6
  176. package/dist/core/web/public/styles.css +468 -0
  177. package/package.json +3 -2
@@ -0,0 +1,116 @@
1
+ /**
2
+ * control.ts — M61: Mission Control aggregator.
3
+ *
4
+ * `buildControlSnapshot(cfg)` assembles a unified read-only snapshot for the
5
+ * Mission Control dashboard. Each section is independently guarded — a broken
6
+ * subsystem degrades ONLY that slice; the rest still resolves. Never throws.
7
+ *
8
+ * JSON contract (verbatim, frontend depends on this):
9
+ * ControlSnapshot.ts — ISO stamp
10
+ * ControlSnapshot.models — live local-model provider state
11
+ * ControlSnapshot.fleet — FleetStatus (reuses buildFleetStatus)
12
+ * ControlSnapshot.daemon — running/pid/lastTickAt/todaySpentUsd
13
+ * ControlSnapshot.usage — 7d rollup: totals + byProvider
14
+ * ControlSnapshot.limits — per-backend rate-window standing ([] when none)
15
+ * ControlSnapshot.subscriptionLimits — rolling-window usage + honest provider notes (M63)
16
+ * ControlSnapshot.logs — most-recent-first, capped 50
17
+ */
18
+ import type { AshlrConfig } from '../types.js';
19
+ import { type FleetStatus } from '../fleet/status.js';
20
+ import { type UsageWindow, type ProviderLimitEntry } from '../observability/limits.js';
21
+ export interface ControlProviderEntry {
22
+ id: string;
23
+ kind: 'local' | 'cloud';
24
+ up: boolean;
25
+ baseUrl: string | null;
26
+ models: string[];
27
+ }
28
+ export interface ControlModels {
29
+ activeProvider: string | null;
30
+ providers: ControlProviderEntry[];
31
+ }
32
+ export interface ControlDaemon {
33
+ running: boolean;
34
+ pid: number | null;
35
+ lastTickAt: string | null;
36
+ todaySpentUsd: number;
37
+ }
38
+ export interface ControlUsageByProvider {
39
+ provider: string;
40
+ tier: 'local' | 'cloud';
41
+ tokens: number;
42
+ costUsd: number;
43
+ sharePct: number;
44
+ }
45
+ export interface ControlUsage {
46
+ window: '7d';
47
+ totalTokens: number;
48
+ totalCostUsd: number;
49
+ localSavingsUsd: number;
50
+ byProvider: ControlUsageByProvider[];
51
+ }
52
+ export interface ControlLimit {
53
+ backend: string;
54
+ window: string;
55
+ max: number;
56
+ used: number;
57
+ standing: 'ok' | 'warn' | 'over' | 'unlimited';
58
+ }
59
+ export interface ControlSubscriptionLimits {
60
+ connected: boolean;
61
+ note: string;
62
+ windows: UsageWindow[];
63
+ providers: ProviderLimitEntry[];
64
+ }
65
+ export interface ControlLogEntry {
66
+ ts: string;
67
+ kind: 'tick' | 'merge' | 'info';
68
+ msg: string;
69
+ }
70
+ export interface ControlSecurityFinding {
71
+ /** Basename of the repo the finding came from. */
72
+ repo: string;
73
+ title: string;
74
+ severity: string;
75
+ /** The WorkItem source — always 'security' for binshield items. */
76
+ source: string;
77
+ }
78
+ export interface ControlSecurityCounts {
79
+ critical: number;
80
+ high: number;
81
+ medium: number;
82
+ low: number;
83
+ }
84
+ export interface ControlSecurity {
85
+ /**
86
+ * True when at least one security WorkItem was found in the cached backlog.
87
+ * False when the backlog is absent, empty, or has no security-source items.
88
+ */
89
+ available: boolean;
90
+ findings: ControlSecurityFinding[];
91
+ counts: ControlSecurityCounts;
92
+ }
93
+ export interface ControlSnapshot {
94
+ ts: string;
95
+ models: ControlModels;
96
+ fleet: FleetStatus;
97
+ daemon: ControlDaemon;
98
+ usage: ControlUsage;
99
+ limits: ControlLimit[];
100
+ subscriptionLimits: ControlSubscriptionLimits;
101
+ logs: ControlLogEntry[];
102
+ /** M67: supply-chain / binshield security findings from cached backlog. */
103
+ security: ControlSecurity;
104
+ }
105
+ /**
106
+ * Aggregate security WorkItems from the persisted backlog (~/.ashlr/backlog.json).
107
+ * Reads cached data only — never shells out to binshield live so /api/control
108
+ * stays fast. Degrades gracefully to available:false when the backlog is absent.
109
+ * Never throws.
110
+ */
111
+ export declare function buildSecurity(): ControlSecurity;
112
+ /**
113
+ * Assemble a full ControlSnapshot. Each section is independently guarded so a
114
+ * broken subsystem never causes the whole snapshot to fail. Never throws.
115
+ */
116
+ export declare function buildControlSnapshot(cfg: AshlrConfig): Promise<ControlSnapshot>;
@@ -0,0 +1,307 @@
1
+ /**
2
+ * control.ts — M61: Mission Control aggregator.
3
+ *
4
+ * `buildControlSnapshot(cfg)` assembles a unified read-only snapshot for the
5
+ * Mission Control dashboard. Each section is independently guarded — a broken
6
+ * subsystem degrades ONLY that slice; the rest still resolves. Never throws.
7
+ *
8
+ * JSON contract (verbatim, frontend depends on this):
9
+ * ControlSnapshot.ts — ISO stamp
10
+ * ControlSnapshot.models — live local-model provider state
11
+ * ControlSnapshot.fleet — FleetStatus (reuses buildFleetStatus)
12
+ * ControlSnapshot.daemon — running/pid/lastTickAt/todaySpentUsd
13
+ * ControlSnapshot.usage — 7d rollup: totals + byProvider
14
+ * ControlSnapshot.limits — per-backend rate-window standing ([] when none)
15
+ * ControlSnapshot.subscriptionLimits — rolling-window usage + honest provider notes (M63)
16
+ * ControlSnapshot.logs — most-recent-first, capped 50
17
+ */
18
+ import { buildFleetStatus } from '../fleet/status.js';
19
+ import { getProviderRegistry } from '../providers.js';
20
+ import { buildRollup, modelToProviderKey, LOCAL_PROVIDER_KEYS } from '../observability/rollup.js';
21
+ import { loadDaemonState } from '../daemon/state.js';
22
+ import { usesInWindow, evalQuota, windowToMs } from '../fleet/quota.js';
23
+ import { resolveUsageWindows } from '../observability/limits.js';
24
+ import { loadBacklog } from '../portfolio/backlog.js';
25
+ // ---------------------------------------------------------------------------
26
+ // Section builders — each is independently guarded
27
+ // ---------------------------------------------------------------------------
28
+ /** Safe fallback for the models section. */
29
+ function fallbackModels() {
30
+ return { activeProvider: null, providers: [] };
31
+ }
32
+ async function buildModels(cfg) {
33
+ try {
34
+ const registry = await getProviderRegistry(cfg);
35
+ const LOCAL_IDS = new Set(['lmstudio', 'ollama']);
36
+ const providers = registry.providers.map((ep) => ({
37
+ id: ep.id,
38
+ kind: LOCAL_IDS.has(ep.id) ? 'local' : 'cloud',
39
+ up: ep.up,
40
+ baseUrl: ep.url ?? null,
41
+ models: ep.models,
42
+ }));
43
+ return { activeProvider: registry.activeProvider, providers };
44
+ }
45
+ catch {
46
+ return fallbackModels();
47
+ }
48
+ }
49
+ /** Safe fallback for the daemon section. */
50
+ function fallbackDaemon() {
51
+ return { running: false, pid: null, lastTickAt: null, todaySpentUsd: 0 };
52
+ }
53
+ function buildDaemon() {
54
+ try {
55
+ const ds = loadDaemonState();
56
+ return {
57
+ running: ds.running === true,
58
+ pid: typeof ds.pid === 'number' ? ds.pid : null,
59
+ lastTickAt: ds.lastTickAt ?? null,
60
+ todaySpentUsd: typeof ds.todaySpentUsd === 'number' ? ds.todaySpentUsd : 0,
61
+ };
62
+ }
63
+ catch {
64
+ return fallbackDaemon();
65
+ }
66
+ }
67
+ /** Safe fallback for the usage section. */
68
+ function fallbackUsage() {
69
+ return {
70
+ window: '7d',
71
+ totalTokens: 0,
72
+ totalCostUsd: 0,
73
+ localSavingsUsd: 0,
74
+ byProvider: [],
75
+ };
76
+ }
77
+ function buildUsage(cfg) {
78
+ try {
79
+ const rollup = buildRollup('7d', cfg);
80
+ // Aggregate byModel into byProvider buckets
81
+ const totalCostUsd = rollup.totals.estCostUsd;
82
+ const totalTokens = rollup.totals.tokensIn + rollup.totals.tokensOut;
83
+ // per-provider accumulators
84
+ const providerMap = new Map();
85
+ for (const mu of rollup.byModel) {
86
+ const provKey = modelToProviderKey(mu.model);
87
+ const tier = LOCAL_PROVIDER_KEYS.has(provKey) ? 'local' : 'cloud';
88
+ const tokens = mu.tokensIn + mu.tokensOut;
89
+ const existing = providerMap.get(provKey);
90
+ if (existing) {
91
+ existing.tokens += tokens;
92
+ existing.costUsd += mu.estCostUsd;
93
+ }
94
+ else {
95
+ providerMap.set(provKey, { tier, tokens, costUsd: mu.estCostUsd });
96
+ }
97
+ }
98
+ const byProvider = [];
99
+ for (const [provider, acc] of providerMap.entries()) {
100
+ const sharePct = totalCostUsd > 0
101
+ ? Math.round((acc.costUsd / totalCostUsd) * 1000) / 10
102
+ : totalTokens > 0
103
+ ? Math.round((acc.tokens / totalTokens) * 1000) / 10
104
+ : 0;
105
+ byProvider.push({ provider, tier: acc.tier, tokens: acc.tokens, costUsd: acc.costUsd, sharePct });
106
+ }
107
+ byProvider.sort((a, b) => b.costUsd - a.costUsd || b.tokens - a.tokens);
108
+ // Normalise shares to sum exactly to 100 when there is usage
109
+ if (byProvider.length > 0) {
110
+ const rawSum = byProvider.reduce((s, p) => s + p.sharePct, 0);
111
+ if (rawSum > 0) {
112
+ // Proportionally rescale so sum === 100
113
+ const scale = 100 / rawSum;
114
+ let running = 0;
115
+ for (let i = 0; i < byProvider.length - 1; i++) {
116
+ byProvider[i].sharePct = Math.round(byProvider[i].sharePct * scale * 10) / 10;
117
+ running += byProvider[i].sharePct;
118
+ }
119
+ // Last entry gets the remainder to guarantee exact 100 sum
120
+ byProvider[byProvider.length - 1].sharePct =
121
+ Math.round((100 - running) * 10) / 10;
122
+ }
123
+ }
124
+ // localSavingsUsd: what the local tokens would have cost if cloud-priced.
125
+ // We use a conservative $3/$15 estimate for what a cloud provider would charge,
126
+ // then subtract $0 (local cost). Simple heuristic: localTokens * $3/1M in-tokens.
127
+ let localSavingsUsd = 0;
128
+ for (const p of byProvider) {
129
+ if (p.tier === 'local' && p.tokens > 0) {
130
+ // $3/1M tokens — the conservative cloud input price
131
+ localSavingsUsd += (p.tokens / 1_000_000) * 3;
132
+ }
133
+ }
134
+ localSavingsUsd = Math.round(localSavingsUsd * 10000) / 10000;
135
+ return { window: '7d', totalTokens, totalCostUsd, localSavingsUsd, byProvider };
136
+ }
137
+ catch {
138
+ return fallbackUsage();
139
+ }
140
+ }
141
+ function buildLimits(cfg) {
142
+ try {
143
+ const rawLimits = cfg.foundry?.limits;
144
+ if (!rawLimits)
145
+ return [];
146
+ const result = [];
147
+ for (const [backend, limit] of Object.entries(rawLimits)) {
148
+ if (!limit)
149
+ continue;
150
+ const windowMs = windowToMs(limit.window);
151
+ const used = usesInWindow(backend, windowMs);
152
+ const standing = evalQuota(backend, cfg);
153
+ result.push({ backend, window: limit.window, max: limit.max, used, standing });
154
+ }
155
+ return result;
156
+ }
157
+ catch {
158
+ return [];
159
+ }
160
+ }
161
+ async function buildSubscriptionLimits(cfg) {
162
+ try {
163
+ const result = await resolveUsageWindows(cfg);
164
+ return {
165
+ connected: result.connected,
166
+ note: result.note,
167
+ windows: result.windows,
168
+ providers: result.providers,
169
+ };
170
+ }
171
+ catch {
172
+ return {
173
+ connected: false,
174
+ note: 'Usage window data unavailable.',
175
+ windows: [],
176
+ providers: [],
177
+ };
178
+ }
179
+ }
180
+ const LOG_CAP = 50;
181
+ function buildLogs(cap = LOG_CAP) {
182
+ try {
183
+ const ds = loadDaemonState();
184
+ const ticks = Array.isArray(ds.ticks) ? ds.ticks : [];
185
+ // ticks are oldest-first in the state; reverse for most-recent-first
186
+ const reversed = [...ticks].reverse();
187
+ const entries = [];
188
+ for (const tick of reversed) {
189
+ if (entries.length >= cap)
190
+ break;
191
+ // Merge event (if any merges happened this tick, emit a separate line first)
192
+ if (typeof tick.merged === 'number' && tick.merged > 0) {
193
+ entries.push({
194
+ ts: tick.ts,
195
+ kind: 'merge',
196
+ msg: `${tick.merged} proposal(s) auto-merged`,
197
+ });
198
+ if (entries.length >= cap)
199
+ break;
200
+ }
201
+ // Tick event
202
+ const backendStr = tick.backends && Object.keys(tick.backends).length > 0
203
+ ? ' backends=' + Object.entries(tick.backends).map(([k, v]) => `${k}:${v}`).join(',')
204
+ : '';
205
+ const spendStr = typeof tick.spentUsd === 'number'
206
+ ? ` spend=$${tick.spentUsd.toFixed(4)}`
207
+ : '';
208
+ entries.push({
209
+ ts: tick.ts,
210
+ kind: 'tick',
211
+ msg: `tick reason=${tick.reason ?? 'ok'}${backendStr}${spendStr}`,
212
+ });
213
+ }
214
+ return entries;
215
+ }
216
+ catch {
217
+ return [];
218
+ }
219
+ }
220
+ // ---------------------------------------------------------------------------
221
+ // M67: Security builder — reads cached backlog, never re-scans live.
222
+ // ---------------------------------------------------------------------------
223
+ /** Safe fallback for the security section. */
224
+ function fallbackSecurity() {
225
+ return {
226
+ available: false,
227
+ findings: [],
228
+ counts: { critical: 0, high: 0, medium: 0, low: 0 },
229
+ };
230
+ }
231
+ /**
232
+ * Aggregate security WorkItems from the persisted backlog (~/.ashlr/backlog.json).
233
+ * Reads cached data only — never shells out to binshield live so /api/control
234
+ * stays fast. Degrades gracefully to available:false when the backlog is absent.
235
+ * Never throws.
236
+ */
237
+ export function buildSecurity() {
238
+ try {
239
+ const backlog = loadBacklog();
240
+ if (!backlog)
241
+ return fallbackSecurity();
242
+ const secItems = backlog.items.filter((item) => item.source === 'security');
243
+ if (secItems.length === 0)
244
+ return fallbackSecurity();
245
+ const counts = { critical: 0, high: 0, medium: 0, low: 0 };
246
+ const findings = [];
247
+ for (const item of secItems) {
248
+ // Severity is the third tag when tags = ['security', 'binshield', <sev>].
249
+ // Fall back to scanning all tags for a known severity keyword.
250
+ const tags = Array.isArray(item.tags) ? item.tags : [];
251
+ const sev = tags[2] ??
252
+ tags.find((t) => ['critical', 'high', 'medium', 'low'].includes(t)) ??
253
+ 'low';
254
+ if (sev === 'critical')
255
+ counts.critical++;
256
+ else if (sev === 'high')
257
+ counts.high++;
258
+ else if (sev === 'medium')
259
+ counts.medium++;
260
+ else
261
+ counts.low++;
262
+ findings.push({
263
+ repo: item.repo.split('/').pop() ?? item.repo,
264
+ title: item.title,
265
+ severity: sev,
266
+ source: item.source,
267
+ });
268
+ }
269
+ // Sort: critical first, then high, medium, low — same order as backlog display.
270
+ const SEV_ORDER = { critical: 0, high: 1, medium: 2, low: 3 };
271
+ findings.sort((a, b) => (SEV_ORDER[a.severity] ?? 4) - (SEV_ORDER[b.severity] ?? 4));
272
+ return { available: true, findings, counts };
273
+ }
274
+ catch {
275
+ return fallbackSecurity();
276
+ }
277
+ }
278
+ // ---------------------------------------------------------------------------
279
+ // Main export
280
+ // ---------------------------------------------------------------------------
281
+ /**
282
+ * Assemble a full ControlSnapshot. Each section is independently guarded so a
283
+ * broken subsystem never causes the whole snapshot to fail. Never throws.
284
+ */
285
+ export async function buildControlSnapshot(cfg) {
286
+ const ts = new Date().toISOString();
287
+ const [models, fleet] = await Promise.all([
288
+ buildModels(cfg),
289
+ buildFleetStatus(cfg).catch(() => ({
290
+ generatedAt: ts,
291
+ daemon: { running: false, lastTickAt: null, todaySpentUsd: 0 },
292
+ backends: [],
293
+ queue: { backlogItems: 0 },
294
+ proposals: { pending: 0, frontierPending: 0, applied: 0 },
295
+ merges: { recent: 0 },
296
+ killed: false,
297
+ })),
298
+ ]);
299
+ const daemon = buildDaemon();
300
+ const usage = buildUsage(cfg);
301
+ const limits = buildLimits(cfg);
302
+ const subscriptionLimits = await buildSubscriptionLimits(cfg);
303
+ const logs = buildLogs(LOG_CAP);
304
+ const security = buildSecurity();
305
+ return { ts, models, fleet, daemon, usage, limits, subscriptionLimits, logs, security };
306
+ }
307
+ //# sourceMappingURL=control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.js","sourceRoot":"","sources":["../../../src/core/web/control.ts"],"names":[],"mappings":"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"}