pi-mega-compact 0.9.2 → 0.10.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 (143) hide show
  1. package/README.md +3 -2
  2. package/dist/extensions/dashboard-server/api-contracts/endpoints.js +95 -47
  3. package/dist/extensions/dashboard-server/api-contracts/index.js +1 -1
  4. package/dist/extensions/dashboard-server/api-contracts/turns.js +10 -0
  5. package/dist/extensions/dashboard-server/api-contracts.test.js +3 -2
  6. package/dist/extensions/dashboard-server/routes-topics.js +87 -0
  7. package/dist/extensions/dashboard-server/routes-turns.js +251 -0
  8. package/dist/extensions/dashboard-server/routes.js +3 -1
  9. package/dist/extensions/dashboard-server/server.js +6 -2
  10. package/dist/extensions/mega-compact.js +10 -6
  11. package/dist/extensions/mega-config.js +4 -0
  12. package/dist/extensions/mega-events/agent-handlers.js +62 -49
  13. package/dist/extensions/mega-events/context-handler.js +48 -2
  14. package/dist/extensions/mega-events/session-handlers.js +24 -0
  15. package/dist/extensions/mega-metrics-cmds.js +90 -0
  16. package/dist/extensions/mega-pipeline/recall.js +47 -17
  17. package/dist/extensions/mega-topics-cmds.js +111 -0
  18. package/dist/extensions/mega-turn-store.js +110 -0
  19. package/dist/extensions/mega-turn-store.test.js +68 -0
  20. package/dist/src/config/turns.js +48 -0
  21. package/dist/src/fork.js +33 -0
  22. package/dist/src/fork.test.js +81 -0
  23. package/dist/src/intent.js +51 -0
  24. package/dist/src/intent.test.js +78 -0
  25. package/dist/src/metrics/index.js +4 -0
  26. package/dist/src/metrics/turns.js +118 -0
  27. package/dist/src/metrics/turns.test.js +152 -0
  28. package/dist/src/store/sqlite/raw-transcript.js +5 -3
  29. package/dist/src/store/sqlite.dbmirror.test.js +9 -0
  30. package/dist/src/store/turns/connection.js +123 -0
  31. package/dist/src/store/turns/contract-compliance.test.js +428 -0
  32. package/dist/src/store/turns/index.js +31 -0
  33. package/dist/src/store/turns/memory-store.js +357 -0
  34. package/dist/src/store/turns/memory-store.test.js +9 -0
  35. package/dist/src/store/turns/migrations.js +178 -0
  36. package/dist/src/store/turns/migrations.test.js +138 -0
  37. package/dist/src/store/turns/schema.js +115 -0
  38. package/dist/src/store/turns/sqlite-store.js +455 -0
  39. package/dist/src/store/turns/sqlite-store.test.js +144 -0
  40. package/dist/src/store/turns/types.js +16 -0
  41. package/dist/src/topics/cluster.js +141 -0
  42. package/dist/src/topics/cluster.test.js +150 -0
  43. package/dist/src/topics/index.js +6 -0
  44. package/dist/src/topics/kselection.js +142 -0
  45. package/dist/src/topics/labels.js +56 -0
  46. package/dist/src/topics/store.js +119 -0
  47. package/dist/src/topics/store.test.js +117 -0
  48. package/dist/src/topics/types.js +8 -0
  49. package/dist/src/wiki.js +133 -0
  50. package/dist/src/wiki.test.js +171 -0
  51. package/extensions/dashboard-client/dist/assets/{AchievementTiles-QPo46Pwg.js → AchievementTiles-DUulvXUY.js} +2 -2
  52. package/extensions/dashboard-client/dist/assets/{AchievementTiles-QPo46Pwg.js.map → AchievementTiles-DUulvXUY.js.map} +1 -1
  53. package/extensions/dashboard-client/dist/assets/{AchievementsTab-BDJxRXRY.js → AchievementsTab-Dx0YtCNf.js} +2 -2
  54. package/extensions/dashboard-client/dist/assets/{AchievementsTab-BDJxRXRY.js.map → AchievementsTab-Dx0YtCNf.js.map} +1 -1
  55. package/extensions/dashboard-client/dist/assets/{CacheTab-CUMqXQjd.js → CacheTab-DtkaUo1v.js} +2 -2
  56. package/extensions/dashboard-client/dist/assets/{CacheTab-CUMqXQjd.js.map → CacheTab-DtkaUo1v.js.map} +1 -1
  57. package/extensions/dashboard-client/dist/assets/{ConfigTab-j1dRzurG.js → ConfigTab-CLa4KfiZ.js} +2 -2
  58. package/extensions/dashboard-client/dist/assets/{ConfigTab-j1dRzurG.js.map → ConfigTab-CLa4KfiZ.js.map} +1 -1
  59. package/extensions/dashboard-client/dist/assets/{EventsTab-CMglXK4p.js → EventsTab-Q6tEIBBi.js} +2 -2
  60. package/extensions/dashboard-client/dist/assets/{EventsTab-CMglXK4p.js.map → EventsTab-Q6tEIBBi.js.map} +1 -1
  61. package/extensions/dashboard-client/dist/assets/{GameTab-fpaDoyxi.js → GameTab-Hq7GNWSY.js} +2 -2
  62. package/extensions/dashboard-client/dist/assets/{GameTab-fpaDoyxi.js.map → GameTab-Hq7GNWSY.js.map} +1 -1
  63. package/extensions/dashboard-client/dist/assets/{MetricsTab-CWG2crG_.js → MetricsTab-BtmBV6lU.js} +2 -2
  64. package/extensions/dashboard-client/dist/assets/{MetricsTab-CWG2crG_.js.map → MetricsTab-BtmBV6lU.js.map} +1 -1
  65. package/extensions/dashboard-client/dist/assets/{OverviewTab-BaV2D2nf.js → OverviewTab-CL10PwVU.js} +2 -2
  66. package/extensions/dashboard-client/dist/assets/{OverviewTab-BaV2D2nf.js.map → OverviewTab-CL10PwVU.js.map} +1 -1
  67. package/extensions/dashboard-client/dist/assets/{ReposTab-C-0kuZ_0.js → ReposTab-DAwANwbI.js} +2 -2
  68. package/extensions/dashboard-client/dist/assets/{ReposTab-C-0kuZ_0.js.map → ReposTab-DAwANwbI.js.map} +1 -1
  69. package/extensions/dashboard-client/dist/assets/{SessionsTab-CSYhddCA.js → SessionsTab-Ec08TZRQ.js} +2 -2
  70. package/extensions/dashboard-client/dist/assets/{SessionsTab-CSYhddCA.js.map → SessionsTab-Ec08TZRQ.js.map} +1 -1
  71. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Dy4KRjSM.js → TimeSavedCard-COb8dpTy.js} +2 -2
  72. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Dy4KRjSM.js.map → TimeSavedCard-COb8dpTy.js.map} +1 -1
  73. package/extensions/dashboard-client/dist/assets/TopicsTab-kvX3F3dY.js +2 -0
  74. package/extensions/dashboard-client/dist/assets/TopicsTab-kvX3F3dY.js.map +1 -0
  75. package/extensions/dashboard-client/dist/assets/TurnsTab-CCUE73Aa.js +2 -0
  76. package/extensions/dashboard-client/dist/assets/TurnsTab-CCUE73Aa.js.map +1 -0
  77. package/extensions/dashboard-client/dist/assets/{index-D_WtU2TV.js → index-UMrussFX.js} +10 -10
  78. package/extensions/dashboard-client/dist/assets/index-UMrussFX.js.map +1 -0
  79. package/extensions/dashboard-client/dist/assets/{index-og3ghxyY.css → index-gn66lYD2.css} +1 -1
  80. package/extensions/dashboard-client/dist/assets/{useSSE-C9yVJlGP.js → useSSE-BDHZ7CeS.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{useSSE-C9yVJlGP.js.map → useSSE-BDHZ7CeS.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/index.html +2 -2
  83. package/extensions/dashboard-client/src/App.tsx +10 -2
  84. package/extensions/dashboard-client/src/api/client.ts +84 -1
  85. package/extensions/dashboard-client/src/main.tsx +1 -0
  86. package/extensions/dashboard-client/src/styles/turns.css +142 -0
  87. package/extensions/dashboard-client/src/tabs/TopicsTab.tsx +185 -0
  88. package/extensions/dashboard-client/src/tabs/TurnsTab.tsx +326 -0
  89. package/extensions/dashboard-server/api-contracts/endpoints.ts +389 -291
  90. package/extensions/dashboard-server/api-contracts/game-types.ts +141 -88
  91. package/extensions/dashboard-server/api-contracts/index.ts +153 -133
  92. package/extensions/dashboard-server/api-contracts/turns.ts +114 -0
  93. package/extensions/dashboard-server/api-contracts.test.ts +920 -919
  94. package/extensions/dashboard-server/routes-topics.ts +119 -0
  95. package/extensions/dashboard-server/routes-turns.ts +282 -0
  96. package/extensions/dashboard-server/routes.ts +8 -1
  97. package/extensions/dashboard-server/server.ts +6 -2
  98. package/extensions/mega-compact.ts +75 -59
  99. package/extensions/mega-config.ts +232 -220
  100. package/extensions/mega-events/agent-handlers.ts +194 -151
  101. package/extensions/mega-events/context-handler.ts +50 -1
  102. package/extensions/mega-events/session-handlers.ts +23 -0
  103. package/extensions/mega-metrics-cmds.ts +114 -0
  104. package/extensions/mega-pipeline/recall.ts +215 -152
  105. package/extensions/mega-topics-cmds.ts +151 -0
  106. package/extensions/mega-turn-store.test.ts +108 -0
  107. package/extensions/mega-turn-store.ts +169 -0
  108. package/package.json +3 -1
  109. package/src/config/turns.ts +69 -0
  110. package/src/fork.test.ts +94 -0
  111. package/src/fork.ts +78 -0
  112. package/src/intent.test.ts +87 -0
  113. package/src/intent.ts +115 -0
  114. package/src/metrics/index.ts +9 -0
  115. package/src/metrics/turns.test.ts +165 -0
  116. package/src/metrics/turns.ts +201 -0
  117. package/src/store/sqlite/raw-transcript.ts +9 -3
  118. package/src/store/sqlite.dbmirror.test.ts +10 -0
  119. package/src/store/turns/connection.ts +137 -0
  120. package/src/store/turns/contract-compliance.test.ts +562 -0
  121. package/src/store/turns/index.ts +65 -0
  122. package/src/store/turns/memory-store.test.ts +15 -0
  123. package/src/store/turns/memory-store.ts +469 -0
  124. package/src/store/turns/migrations.test.ts +161 -0
  125. package/src/store/turns/migrations.ts +203 -0
  126. package/src/store/turns/schema.ts +158 -0
  127. package/src/store/turns/sqlite-store.test.ts +161 -0
  128. package/src/store/turns/sqlite-store.ts +656 -0
  129. package/src/store/turns/types.ts +181 -0
  130. package/src/topics/cluster.test.ts +176 -0
  131. package/src/topics/cluster.ts +191 -0
  132. package/src/topics/index.ts +18 -0
  133. package/src/topics/kselection.ts +182 -0
  134. package/src/topics/labels.ts +67 -0
  135. package/src/topics/store.test.ts +132 -0
  136. package/src/topics/store.ts +208 -0
  137. package/src/topics/types.ts +64 -0
  138. package/src/wiki.test.ts +217 -0
  139. package/src/wiki.ts +198 -0
  140. package/dist/extensions/openclaw-mega-compact.js +0 -291
  141. package/dist/src/minilm.js +0 -92
  142. package/dist/src/wordpiece.js +0 -129
  143. package/extensions/dashboard-client/dist/assets/index-D_WtU2TV.js.map +0 -1
@@ -9,36 +9,52 @@
9
9
  * PREVENT-011: no `any` type — all types are explicit.
10
10
  */
11
11
 
12
- import type { EndpointDef } from './core.js';
13
- import type { SnapshotResponse } from './snapshot.js';
14
- import type { IndexesIndexRow, IndexesSummaryResponse } from './multi-repo.js';
15
- import type { GameStateResponse } from './game.js';
16
- import type { SseEvent } from './index.js';
12
+ import type { EndpointDef } from "./core.js";
13
+ import type { SnapshotResponse } from "./snapshot.js";
14
+ import type { IndexesIndexRow, IndexesSummaryResponse } from "./multi-repo.js";
15
+ import type { GameStateResponse } from "./game.js";
16
+ import type { SseEvent } from "./index.js";
17
+ import type {
18
+ TurnsResponse,
19
+ ConversationTurnsResponse,
20
+ RewindIntentsResponse,
21
+ ForkRequest,
22
+ ForkResponse,
23
+ PostIntentRequest,
24
+ PruneRequest,
25
+ PruneTurnsResponse,
26
+ TopicMemoriesResponse,
27
+ } from "./turns.js";
17
28
 
18
29
  import type {
19
- GameScoreRow,
20
- GameScoresQuery,
21
- AchievementRow,
22
- SessionsResponse,
23
- SessionTimeseriesQuery,
24
- SessionTimeseriesResponse,
25
- GameStatePatch,
26
- SseEndpointDef,
27
- } from './game-types.js';
30
+ GameScoreRow,
31
+ GameScoresQuery,
32
+ AchievementRow,
33
+ SessionsResponse,
34
+ SessionTimeseriesQuery,
35
+ SessionTimeseriesResponse,
36
+ GameStatePatch,
37
+ SseEndpointDef,
38
+ TopicsResponse,
39
+ } from "./game-types.js";
28
40
 
29
41
  export type {
30
- GameScoreRow,
31
- GameScoresQuery,
32
- AchievementRow,
33
- ActiveSession,
34
- SessionsResponse,
35
- SessionDataPoint,
36
- SessionSeries,
37
- SessionTimeseriesQuery,
38
- SessionTimeseriesResponse,
39
- GameStatePatch,
40
- SseEndpointDef,
41
- } from './game-types.js';
42
+ GameScoreRow,
43
+ GameScoresQuery,
44
+ AchievementRow,
45
+ ActiveSession,
46
+ SessionsResponse,
47
+ SessionDataPoint,
48
+ SessionSeries,
49
+ SessionTimeseriesQuery,
50
+ SessionTimeseriesResponse,
51
+ GameStatePatch,
52
+ SseEndpointDef,
53
+ TopicRow,
54
+ TopicAssignmentRow,
55
+ TopicsResponse,
56
+ TopicDetailResponse,
57
+ } from "./game-types.js";
42
58
 
43
59
  // ─── New Response Types (inline) ───────────────────────────────────────────
44
60
 
@@ -47,8 +63,8 @@ export type {
47
63
  * so the launcher can detect stale servers from older builds.
48
64
  */
49
65
  export interface VersionResponse {
50
- /** Semver-style version string of the running dashboard server. */
51
- readonly version: string;
66
+ /** Semver-style version string of the running dashboard server. */
67
+ readonly version: string;
52
68
  }
53
69
 
54
70
  /**
@@ -56,8 +72,11 @@ export interface VersionResponse {
56
72
  * Used by GET /api/summary for lightweight header tiles.
57
73
  */
58
74
  export type IndexSummary = Pick<
59
- IndexesSummaryResponse,
60
- 'totalRepos' | 'totalCheckpoints' | 'totalTokensSaved' | 'totalCompressedOriginalBytes'
75
+ IndexesSummaryResponse,
76
+ | "totalRepos"
77
+ | "totalCheckpoints"
78
+ | "totalTokensSaved"
79
+ | "totalCompressedOriginalBytes"
61
80
  >;
62
81
 
63
82
  /**
@@ -65,12 +84,12 @@ export type IndexSummary = Pick<
65
84
  * (no index.sqlite file or read error). All fields are null/empty.
66
85
  */
67
86
  export interface IndexFallbackResponse {
68
- /** Always null — no index data available. */
69
- readonly updatedAt: null;
70
- /** Always null — no summary available. */
71
- readonly summary: null;
72
- /** Always an empty array — no repos registered. */
73
- readonly repos: IndexesIndexRow[];
87
+ /** Always null — no index data available. */
88
+ readonly updatedAt: null;
89
+ /** Always null — no summary available. */
90
+ readonly summary: null;
91
+ /** Always an empty array — no repos registered. */
92
+ readonly repos: IndexesIndexRow[];
74
93
  }
75
94
 
76
95
  /**
@@ -78,8 +97,8 @@ export interface IndexFallbackResponse {
78
97
  * seen within the last N hours (format: "<N>h", e.g. "24h").
79
98
  */
80
99
  export interface ReposQuery {
81
- /** Active-window filter in format "<hours>h" (e.g. "24h"). Optional. */
82
- readonly active?: string;
100
+ /** Active-window filter in format "<hours>h" (e.g. "24h"). Optional. */
101
+ readonly active?: string;
83
102
  }
84
103
 
85
104
  /**
@@ -87,12 +106,12 @@ export interface ReposQuery {
87
106
  * active-window filter applied.
88
107
  */
89
108
  export interface ReposResponse {
90
- /** ISO timestamp of the last index update, or null if unavailable. */
91
- readonly updatedAt: string | null;
92
- /** Array of repo index rows. */
93
- readonly repos: IndexesIndexRow[];
94
- /** Number of repos in the response (after filtering). */
95
- readonly count: number;
109
+ /** ISO timestamp of the last index update, or null if unavailable. */
110
+ readonly updatedAt: string | null;
111
+ /** Array of repo index rows. */
112
+ readonly repos: IndexesIndexRow[];
113
+ /** Number of repos in the response (after filtering). */
114
+ readonly count: number;
96
115
  }
97
116
 
98
117
  /**
@@ -100,51 +119,51 @@ export interface ReposResponse {
100
119
  * repo list (keeps payload small for embed scenarios).
101
120
  */
102
121
  export interface SummaryResponse {
103
- /** ISO timestamp of the last index update, or null if unavailable. */
104
- readonly updatedAt: string | null;
105
- /** Aggregate index summary, or null if no index exists. */
106
- readonly summary: IndexSummary | null;
107
- /** Number of repos active within the last 24 hours. */
108
- readonly activeRepos: number;
109
- /** Total number of repos in the registry. */
110
- readonly totalRepos: number;
122
+ /** ISO timestamp of the last index update, or null if unavailable. */
123
+ readonly updatedAt: string | null;
124
+ /** Aggregate index summary, or null if no index exists. */
125
+ readonly summary: IndexSummary | null;
126
+ /** Number of repos active within the last 24 hours. */
127
+ readonly activeRepos: number;
128
+ /** Total number of repos in the registry. */
129
+ readonly totalRepos: number;
111
130
  }
112
131
 
113
132
  // ─── Drift Report Types ─────────────────────────────────────────────────────
114
133
 
115
134
  /** Severity level for a drift signal. */
116
- export type DriftSeverity = 'warn' | 'info';
135
+ export type DriftSeverity = "warn" | "info";
117
136
 
118
137
  /**
119
138
  * A single drift signal for a repo.
120
139
  */
121
140
  export interface DriftSignal {
122
- /** The kind of drift detected. */
123
- readonly kind: 'stale' | 'compaction_lag' | 'model_churn';
124
- /** Severity level of the signal. */
125
- readonly severity: DriftSeverity;
126
- /** Human-readable detail describing the drift. */
127
- readonly detail: string;
141
+ /** The kind of drift detected. */
142
+ readonly kind: "stale" | "compaction_lag" | "model_churn";
143
+ /** Severity level of the signal. */
144
+ readonly severity: DriftSeverity;
145
+ /** Human-readable detail describing the drift. */
146
+ readonly detail: string;
128
147
  }
129
148
 
130
149
  /**
131
150
  * Drift classification for a single repo.
132
151
  */
133
152
  export interface RepoDrift {
134
- /** Absolute path to the repo root. */
135
- readonly repoRoot: string;
136
- /** Display name of the repo. */
137
- readonly displayName: string;
138
- /** Unix timestamp (seconds) of the last dashboard activity. */
139
- readonly lastSeen: number;
140
- /** Unix timestamp (seconds) of the last compaction, or null if never. */
141
- readonly lastCompactedAt: number | null;
142
- /** Unix timestamp (seconds) of the last model capture, or null. */
143
- readonly modelCapturedAt: number | null;
144
- /** Array of drift signals detected for this repo. */
145
- readonly signals: DriftSignal[];
146
- /** Highest severity across signals; "ok" if none. */
147
- readonly status: 'ok' | 'warn';
153
+ /** Absolute path to the repo root. */
154
+ readonly repoRoot: string;
155
+ /** Display name of the repo. */
156
+ readonly displayName: string;
157
+ /** Unix timestamp (seconds) of the last dashboard activity. */
158
+ readonly lastSeen: number;
159
+ /** Unix timestamp (seconds) of the last compaction, or null if never. */
160
+ readonly lastCompactedAt: number | null;
161
+ /** Unix timestamp (seconds) of the last model capture, or null. */
162
+ readonly modelCapturedAt: number | null;
163
+ /** Array of drift signals detected for this repo. */
164
+ readonly signals: DriftSignal[];
165
+ /** Highest severity across signals; "ok" if none. */
166
+ readonly status: "ok" | "warn";
148
167
  }
149
168
 
150
169
  /**
@@ -152,23 +171,23 @@ export interface RepoDrift {
152
171
  * repo_registry, flagging stale repos, compaction lag, and model churn.
153
172
  */
154
173
  export interface DriftReportResponse {
155
- /** Unix timestamp (seconds) when the report was generated. */
156
- readonly generatedAt: number;
157
- /** Aggregate counts by status/signal. */
158
- readonly totals: {
159
- /** Repos with no drift signals. */
160
- readonly ok: number;
161
- /** Repos with at least one warning signal. */
162
- readonly warn: number;
163
- /** Repos with the "stale" signal. */
164
- readonly stale: number;
165
- /** Repos with the "compaction_lag" signal. */
166
- readonly compactionLag: number;
167
- /** Repos with the "model_churn" signal. */
168
- readonly modelChurn: number;
169
- };
170
- /** Per-repo drift classifications. */
171
- readonly repos: RepoDrift[];
174
+ /** Unix timestamp (seconds) when the report was generated. */
175
+ readonly generatedAt: number;
176
+ /** Aggregate counts by status/signal. */
177
+ readonly totals: {
178
+ /** Repos with no drift signals. */
179
+ readonly ok: number;
180
+ /** Repos with at least one warning signal. */
181
+ readonly warn: number;
182
+ /** Repos with the "stale" signal. */
183
+ readonly stale: number;
184
+ /** Repos with the "compaction_lag" signal. */
185
+ readonly compactionLag: number;
186
+ /** Repos with the "model_churn" signal. */
187
+ readonly modelChurn: number;
188
+ };
189
+ /** Per-repo drift classifications. */
190
+ readonly repos: RepoDrift[];
172
191
  }
173
192
 
174
193
  // ─── Servers Types ──────────────────────────────────────────────────────────
@@ -178,40 +197,49 @@ export interface DriftReportResponse {
178
197
  * recently-active repo with its live dashboard snapshot data.
179
198
  */
180
199
  export interface ServerEntry {
181
- /** Absolute path to the repo root. */
182
- readonly repoRoot: string;
183
- /** Display name of the repo. */
184
- readonly displayName: string;
185
- /** Model name, or null if not set. */
186
- readonly model: string | null;
187
- /** Provider display name, or null if not set. */
188
- readonly provider: string | null;
189
- /** Unix timestamp (seconds) of the last dashboard activity. */
190
- readonly lastSeen: number;
191
- /** Unix timestamp (seconds) of the last compaction, or null. */
192
- readonly lastCompactedAt: number | null;
193
- /** Current compaction tier, or null if no live snapshot. Present when a live dashboard.json exists. */
194
- readonly tier?: string | null;
195
- /** Current context pressure percentage (0–100), or null. Present when a live snapshot has context data. */
196
- readonly contextPct?: number | null;
197
- /** Current session state string, or null. Present when a live snapshot has session data. */
198
- readonly state?: string | null;
199
- /** Cache hit counters from the live snapshot, or null. Present when a live snapshot has cacheHits. */
200
- readonly cacheHits?: {
201
- readonly session: number;
202
- readonly total: number;
203
- readonly sessionTokensSaved: number;
204
- readonly totalTokensSaved: number;
205
- } | null;
206
- /** Compaction counters from the live snapshot, or null. Present when a live snapshot has compacts. */
207
- readonly compacts?: { readonly session: number; readonly total: number } | null;
208
- /** Time saved counters from the live snapshot, or null. Present when a live snapshot has timeSaved. */
209
- readonly timeSaved?: {
210
- readonly compact: { readonly sessionSec: number; readonly totalSec: number };
211
- readonly cacheHit: { readonly sessionSec: number; readonly totalSec: number };
212
- } | null;
213
- /** ISO timestamp of the live snapshot, or null. Present when a live snapshot has updatedAt. */
214
- readonly updatedAt?: string | null;
200
+ /** Absolute path to the repo root. */
201
+ readonly repoRoot: string;
202
+ /** Display name of the repo. */
203
+ readonly displayName: string;
204
+ /** Model name, or null if not set. */
205
+ readonly model: string | null;
206
+ /** Provider display name, or null if not set. */
207
+ readonly provider: string | null;
208
+ /** Unix timestamp (seconds) of the last dashboard activity. */
209
+ readonly lastSeen: number;
210
+ /** Unix timestamp (seconds) of the last compaction, or null. */
211
+ readonly lastCompactedAt: number | null;
212
+ /** Current compaction tier, or null if no live snapshot. Present when a live dashboard.json exists. */
213
+ readonly tier?: string | null;
214
+ /** Current context pressure percentage (0–100), or null. Present when a live snapshot has context data. */
215
+ readonly contextPct?: number | null;
216
+ /** Current session state string, or null. Present when a live snapshot has session data. */
217
+ readonly state?: string | null;
218
+ /** Cache hit counters from the live snapshot, or null. Present when a live snapshot has cacheHits. */
219
+ readonly cacheHits?: {
220
+ readonly session: number;
221
+ readonly total: number;
222
+ readonly sessionTokensSaved: number;
223
+ readonly totalTokensSaved: number;
224
+ } | null;
225
+ /** Compaction counters from the live snapshot, or null. Present when a live snapshot has compacts. */
226
+ readonly compacts?: {
227
+ readonly session: number;
228
+ readonly total: number;
229
+ } | null;
230
+ /** Time saved counters from the live snapshot, or null. Present when a live snapshot has timeSaved. */
231
+ readonly timeSaved?: {
232
+ readonly compact: {
233
+ readonly sessionSec: number;
234
+ readonly totalSec: number;
235
+ };
236
+ readonly cacheHit: {
237
+ readonly sessionSec: number;
238
+ readonly totalSec: number;
239
+ };
240
+ } | null;
241
+ /** ISO timestamp of the live snapshot, or null. Present when a live snapshot has updatedAt. */
242
+ readonly updatedAt?: string | null;
215
243
  }
216
244
 
217
245
  /**
@@ -219,58 +247,58 @@ export interface ServerEntry {
219
247
  * live snapshot data.
220
248
  */
221
249
  export interface ServersResponse {
222
- /** ISO timestamp when the response was generated. */
223
- readonly updatedAt: string;
224
- /** Array of server entries, sorted by lastSeen descending. */
225
- readonly servers: ServerEntry[];
250
+ /** ISO timestamp when the response was generated. */
251
+ readonly updatedAt: string;
252
+ /** Array of server entries, sorted by lastSeen descending. */
253
+ readonly servers: ServerEntry[];
226
254
  }
227
255
 
228
256
  // ─── Perf Types ─────────────────────────────────────────────────────────────
229
257
 
230
258
  /** Percentile statistics for a latency metric (in milliseconds). */
231
259
  export interface PerfPercentile {
232
- /** 50th percentile (median) in milliseconds. */
233
- readonly p50: number;
234
- /** 95th percentile in milliseconds. */
235
- readonly p95: number;
236
- /** Number of samples in the window. */
237
- readonly n: number;
260
+ /** 50th percentile (median) in milliseconds. */
261
+ readonly p50: number;
262
+ /** 95th percentile in milliseconds. */
263
+ readonly p95: number;
264
+ /** Number of samples in the window. */
265
+ readonly n: number;
238
266
  }
239
267
 
240
268
  /** Average statistics for a rate metric. */
241
269
  export interface PerfAverage {
242
- /** Average value across all samples in the window. */
243
- readonly avg: number;
244
- /** Number of samples in the window. */
245
- readonly n: number;
270
+ /** Average value across all samples in the window. */
271
+ readonly avg: number;
272
+ /** Number of samples in the window. */
273
+ readonly n: number;
246
274
  }
247
275
 
248
276
  /** Latest-value statistics for a gauge metric. */
249
277
  export interface PerfLatest {
250
- /** Most recent value in the window. */
251
- readonly latest: number;
252
- /** Number of samples in the window. */
253
- readonly n: number;
278
+ /** Most recent value in the window. */
279
+ readonly latest: number;
280
+ /** Number of samples in the window. */
281
+ readonly n: number;
254
282
  }
255
283
 
256
284
  /** Average + latest statistics for cache hit percentage. */
257
285
  export interface PerfCacheHit {
258
- /** Average cache hit percentage (0–100). */
259
- readonly avg: number;
260
- /** Most recent cache hit percentage (0–100). */
261
- readonly latest: number;
262
- /** Number of samples in the window. */
263
- readonly n: number;
286
+ /** Average cache hit percentage (0–100). */
287
+ readonly avg: number;
288
+ /** Most recent cache hit percentage (0–100). */
289
+ readonly latest: number;
290
+ /** Number of samples in the window. */
291
+ readonly n: number;
264
292
  }
265
293
 
266
294
  /** Diagnostic counters from the live dashboard snapshot. */
267
295
  export interface PerfDiag {
268
- /** Number of fast-gate context trim fires. */
269
- readonly ctxFastGate: number;
270
- /** Number of live trim fires. */
271
- readonly liveTrimFires: number;
272
- /** Number of live trim replays. */
273
- readonly liveTrimReplays: number;
296
+ /** Number of fast-gate context trim fires. */
297
+ readonly ctxFastGate: number;
298
+ /** Number of live trim fires. */
299
+ readonly liveTrimFires: number;
300
+ /** Number of live trim replays. */
301
+ readonly liveTrimReplays: number;
274
302
  }
275
303
 
276
304
  /**
@@ -278,8 +306,8 @@ export interface PerfDiag {
278
306
  * rolling window size.
279
307
  */
280
308
  export interface PerfQuery {
281
- /** Rolling window size in minutes (default: 30, max: 1440). Optional. */
282
- readonly minutes?: number;
309
+ /** Rolling window size in minutes (default: 30, max: 1440). Optional. */
310
+ readonly minutes?: number;
283
311
  }
284
312
 
285
313
  /**
@@ -287,34 +315,34 @@ export interface PerfQuery {
287
315
  * with per-kind p50/p95, latest rss/heap, cpu counters, and diagnostic data.
288
316
  */
289
317
  export interface PerfResponse {
290
- /** ISO timestamp when the response was generated. */
291
- readonly updatedAt: string;
292
- /** Rolling window size in minutes. */
293
- readonly windowMinutes: number;
294
- /** Total number of perf samples in the window. */
295
- readonly sampleCount: number;
296
- /** Turn latency statistics in milliseconds. */
297
- readonly turn_latency_ms: PerfPercentile;
298
- /** Provider latency statistics in milliseconds. */
299
- readonly provider_latency_ms: PerfPercentile;
300
- /** Tokens-per-second statistics. */
301
- readonly tps: PerfAverage;
302
- /** Cache hit percentage statistics. */
303
- readonly cache_hit_pct: PerfCacheHit;
304
- /** Database recompute duration statistics in milliseconds. */
305
- readonly db_recompute_ms: PerfPercentile;
306
- /** Disk write duration statistics in milliseconds. */
307
- readonly disk_write_ms: PerfPercentile;
308
- /** RSS memory usage in MB (latest value). */
309
- readonly rss_mb: PerfLatest;
310
- /** Heap memory usage in MB (latest value). */
311
- readonly heap_mb: PerfLatest;
312
- /** CPU user time in milliseconds (latest value). */
313
- readonly cpu_user_ms: PerfLatest;
314
- /** CPU system time in milliseconds (latest value). */
315
- readonly cpu_sys_ms: PerfLatest;
316
- /** Diagnostic counters from the live snapshot, or null if unavailable. */
317
- readonly diag: PerfDiag | null;
318
+ /** ISO timestamp when the response was generated. */
319
+ readonly updatedAt: string;
320
+ /** Rolling window size in minutes. */
321
+ readonly windowMinutes: number;
322
+ /** Total number of perf samples in the window. */
323
+ readonly sampleCount: number;
324
+ /** Turn latency statistics in milliseconds. */
325
+ readonly turn_latency_ms: PerfPercentile;
326
+ /** Provider latency statistics in milliseconds. */
327
+ readonly provider_latency_ms: PerfPercentile;
328
+ /** Tokens-per-second statistics. */
329
+ readonly tps: PerfAverage;
330
+ /** Cache hit percentage statistics. */
331
+ readonly cache_hit_pct: PerfCacheHit;
332
+ /** Database recompute duration statistics in milliseconds. */
333
+ readonly db_recompute_ms: PerfPercentile;
334
+ /** Disk write duration statistics in milliseconds. */
335
+ readonly disk_write_ms: PerfPercentile;
336
+ /** RSS memory usage in MB (latest value). */
337
+ readonly rss_mb: PerfLatest;
338
+ /** Heap memory usage in MB (latest value). */
339
+ readonly heap_mb: PerfLatest;
340
+ /** CPU user time in milliseconds (latest value). */
341
+ readonly cpu_user_ms: PerfLatest;
342
+ /** CPU system time in milliseconds (latest value). */
343
+ readonly cpu_sys_ms: PerfLatest;
344
+ /** Diagnostic counters from the live snapshot, or null if unavailable. */
345
+ readonly diag: PerfDiag | null;
318
346
  }
319
347
 
320
348
  // ─── Game Score & Achievement Types ─────────────────────────────────────────
@@ -329,7 +357,6 @@ export interface PerfResponse {
329
357
  // ─── SSE Endpoint Definition ────────────────────────────────────────────────
330
358
  // (moved to game-types.ts; re-exported for backwards compatibility)
331
359
 
332
-
333
360
  // ─── ENDPOINTS Registry ─────────────────────────────────────────────────────
334
361
 
335
362
  /**
@@ -344,110 +371,181 @@ export interface PerfResponse {
344
371
  * ENDPOINTS.snapshot.method // 'GET'
345
372
  */
346
373
  export const ENDPOINTS = {
347
- /** GET /api/snapshot — Full session, store, compression, and context snapshot. */
348
- snapshot: {
349
- method: 'GET',
350
- path: '/api/snapshot',
351
- description: 'Full session, store, compression, and context snapshot.',
352
- } as const satisfies EndpointDef<'GET', undefined, SnapshotResponse>,
353
-
354
- /** GET /api/version — Dashboard server version string. */
355
- version: {
356
- method: 'GET',
357
- path: '/api/version',
358
- description: 'Dashboard server version for stale-server detection.',
359
- } as const satisfies EndpointDef<'GET', undefined, VersionResponse>,
360
-
361
- /** GET /api/index — Multi-repo aggregate index (or fallback when unavailable). */
362
- index: {
363
- method: 'GET',
364
- path: '/api/index',
365
- description: 'Machine-wide multi-repo registry with checkpoints, tokens, and model info.',
366
- } as const satisfies EndpointDef<'GET', undefined, IndexesSummaryResponse | IndexFallbackResponse>,
367
-
368
- /** GET /api/repos — Registry list with optional active-window filter. */
369
- repos: {
370
- method: 'GET',
371
- path: '/api/repos',
372
- description: 'Repo registry list, optionally filtered by recent activity.',
373
- } as const satisfies EndpointDef<'GET', ReposQuery, ReposResponse>,
374
-
375
- /** GET /api/summary — Lightweight header tiles without the full repo list. */
376
- summary: {
377
- method: 'GET',
378
- path: '/api/summary',
379
- description: 'Aggregate summary with active/total repo counts (no repo list).',
380
- } as const satisfies EndpointDef<'GET', undefined, SummaryResponse>,
381
-
382
- /** GET /api/drift — Cross-repo drift report. */
383
- drift: {
384
- method: 'GET',
385
- path: '/api/drift',
386
- description: 'Cross-repo drift report flagging stale repos, compaction lag, and model churn.',
387
- } as const satisfies EndpointDef<'GET', undefined, DriftReportResponse>,
388
-
389
- /** GET /api/servers — Recently-active repo servers with live snapshot data. */
390
- servers: {
391
- method: 'GET',
392
- path: '/api/servers',
393
- description: 'Recently-active repo servers with live snapshot data.',
394
- } as const satisfies EndpointDef<'GET', undefined, ServersResponse>,
395
-
396
- /** GET /api/eventsSSE stream of dashboard events. */
397
- events: {
398
- type: 'sse',
399
- method: 'GET',
400
- path: '/api/events',
401
- description: 'Server-Sent Events stream of all dashboard events.',
402
- event: 'data',
403
- } as const satisfies SseEndpointDef<SseEvent>,
404
-
405
- /** GET /api/game-state — Current game-mode settings. */
406
- getGameState: {
407
- method: 'GET',
408
- path: '/api/game-state',
409
- description: 'Current game-mode configuration and active ritual state.',
410
- } as const satisfies EndpointDef<'GET', undefined, GameStateResponse>,
411
-
412
- /** PUT /api/game-state — Apply a partial patch to game-mode settings. */
413
- putGameState: {
414
- method: 'PUT',
415
- path: '/api/game-state',
416
- description: 'Apply a partial patch to game-mode settings and return the updated state.',
417
- } as const satisfies EndpointDef<'PUT', GameStatePatch, GameStateResponse>,
418
-
419
- /** GET /api/game-scoresHigh-score leaderboard for a metric. */
420
- gameScores: {
421
- method: 'GET',
422
- path: '/api/game-scores',
423
- description: 'High-score leaderboard for a game metric.',
424
- } as const satisfies EndpointDef<'GET', GameScoresQuery, GameScoreRow[]>,
425
-
426
- /** GET /api/perf — Rolling-window performance aggregates. */
427
- perf: {
428
- method: 'GET',
429
- path: '/api/perf',
430
- description: 'Rolling-window performance aggregates over perf_samples.',
431
- } as const satisfies EndpointDef<'GET', PerfQuery, PerfResponse>,
432
-
433
- /** GET /api/achievements — Achievement tiles with unlock state. */
434
- achievements: {
435
- method: 'GET',
436
- path: '/api/achievements',
437
- description: 'All achievement rows with unlock state.',
438
- } as const satisfies EndpointDef<'GET', undefined, AchievementRow[]>,
439
-
440
- /** GET /api/sessions — Active sessions with latest token usage (S39). */
441
- sessions: {
442
- method: 'GET',
443
- path: '/api/sessions',
444
- description: 'Active pi sessions with latest token usage + heartbeat.',
445
- } as const satisfies EndpointDef<'GET', undefined, SessionsResponse>,
446
-
447
- /** GET /api/sessions/timeseries — Stacked per-session token timeseries (S39). */
448
- sessionTimeseries: {
449
- method: 'GET',
450
- path: '/api/sessions/timeseries',
451
- description: 'Recharts-ready per-session token timeseries for the stacked memory graph.',
452
- } as const satisfies EndpointDef<'GET', SessionTimeseriesQuery, SessionTimeseriesResponse>,
374
+ /** GET /api/snapshot — Full session, store, compression, and context snapshot. */
375
+ snapshot: {
376
+ method: "GET",
377
+ path: "/api/snapshot",
378
+ description: "Full session, store, compression, and context snapshot.",
379
+ } as const satisfies EndpointDef<"GET", undefined, SnapshotResponse>,
380
+
381
+ /** GET /api/version — Dashboard server version string. */
382
+ version: {
383
+ method: "GET",
384
+ path: "/api/version",
385
+ description: "Dashboard server version for stale-server detection.",
386
+ } as const satisfies EndpointDef<"GET", undefined, VersionResponse>,
387
+
388
+ /** GET /api/index — Multi-repo aggregate index (or fallback when unavailable). */
389
+ index: {
390
+ method: "GET",
391
+ path: "/api/index",
392
+ description:
393
+ "Machine-wide multi-repo registry with checkpoints, tokens, and model info.",
394
+ } as const satisfies EndpointDef<
395
+ "GET",
396
+ undefined,
397
+ IndexesSummaryResponse | IndexFallbackResponse
398
+ >,
399
+
400
+ /** GET /api/repos Registry list with optional active-window filter. */
401
+ repos: {
402
+ method: "GET",
403
+ path: "/api/repos",
404
+ description: "Repo registry list, optionally filtered by recent activity.",
405
+ } as const satisfies EndpointDef<"GET", ReposQuery, ReposResponse>,
406
+
407
+ /** GET /api/summary Lightweight header tiles without the full repo list. */
408
+ summary: {
409
+ method: "GET",
410
+ path: "/api/summary",
411
+ description:
412
+ "Aggregate summary with active/total repo counts (no repo list).",
413
+ } as const satisfies EndpointDef<"GET", undefined, SummaryResponse>,
414
+
415
+ /** GET /api/drift — Cross-repo drift report. */
416
+ drift: {
417
+ method: "GET",
418
+ path: "/api/drift",
419
+ description:
420
+ "Cross-repo drift report flagging stale repos, compaction lag, and model churn.",
421
+ } as const satisfies EndpointDef<"GET", undefined, DriftReportResponse>,
422
+
423
+ /** GET /api/serversRecently-active repo servers with live snapshot data. */
424
+ servers: {
425
+ method: "GET",
426
+ path: "/api/servers",
427
+ description: "Recently-active repo servers with live snapshot data.",
428
+ } as const satisfies EndpointDef<"GET", undefined, ServersResponse>,
429
+
430
+ /** GET /api/events SSE stream of dashboard events. */
431
+ events: {
432
+ type: "sse",
433
+ method: "GET",
434
+ path: "/api/events",
435
+ description: "Server-Sent Events stream of all dashboard events.",
436
+ event: "data",
437
+ } as const satisfies SseEndpointDef<SseEvent>,
438
+
439
+ /** GET /api/game-state — Current game-mode settings. */
440
+ getGameState: {
441
+ method: "GET",
442
+ path: "/api/game-state",
443
+ description: "Current game-mode configuration and active ritual state.",
444
+ } as const satisfies EndpointDef<"GET", undefined, GameStateResponse>,
445
+
446
+ /** PUT /api/game-stateApply a partial patch to game-mode settings. */
447
+ putGameState: {
448
+ method: "PUT",
449
+ path: "/api/game-state",
450
+ description:
451
+ "Apply a partial patch to game-mode settings and return the updated state.",
452
+ } as const satisfies EndpointDef<"PUT", GameStatePatch, GameStateResponse>,
453
+
454
+ /** GET /api/game-scores — High-score leaderboard for a metric. */
455
+ gameScores: {
456
+ method: "GET",
457
+ path: "/api/game-scores",
458
+ description: "High-score leaderboard for a game metric.",
459
+ } as const satisfies EndpointDef<"GET", GameScoresQuery, GameScoreRow[]>,
460
+
461
+ /** GET /api/perf — Rolling-window performance aggregates. */
462
+ perf: {
463
+ method: "GET",
464
+ path: "/api/perf",
465
+ description: "Rolling-window performance aggregates over perf_samples.",
466
+ } as const satisfies EndpointDef<"GET", PerfQuery, PerfResponse>,
467
+
468
+ /** GET /api/achievements — Achievement tiles with unlock state. */
469
+ achievements: {
470
+ method: "GET",
471
+ path: "/api/achievements",
472
+ description: "All achievement rows with unlock state.",
473
+ } as const satisfies EndpointDef<"GET", undefined, AchievementRow[]>,
474
+
475
+ /** GET /api/sessions — Active sessions with latest token usage (S39). */
476
+ sessions: {
477
+ method: "GET",
478
+ path: "/api/sessions",
479
+ description: "Active pi sessions with latest token usage + heartbeat.",
480
+ } as const satisfies EndpointDef<"GET", undefined, SessionsResponse>,
481
+
482
+ /** GET /api/sessions/timeseries — Stacked per-session token timeseries (S39). */
483
+ sessionTimeseries: {
484
+ method: "GET",
485
+ path: "/api/sessions/timeseries",
486
+ description:
487
+ "Recharts-ready per-session token timeseries for the stacked memory graph.",
488
+ } as const satisfies EndpointDef<
489
+ "GET",
490
+ SessionTimeseriesQuery,
491
+ SessionTimeseriesResponse
492
+ >,
493
+
494
+ /** GET /api/topics — Auto-categorizing wiki topics (S51). */
495
+ topics: {
496
+ method: "GET",
497
+ path: "/api/topics",
498
+ description:
499
+ "Auto-categorized wiki topics from k-means + TF-IDF over real embeddings.",
500
+ } as const satisfies EndpointDef<"GET", undefined, TopicsResponse>,
501
+
502
+ /** GET /api/turns — Turn-by-turn memory tracking + recall (S52). */
503
+ turns: {
504
+ method: "GET",
505
+ path: "/api/turns",
506
+ description:
507
+ "Per-conversation turn list with recall + epoch provenance (turn-by-turn memory tracking).",
508
+ } as const satisfies EndpointDef<"GET", undefined, TurnsResponse>,
509
+
510
+ /** GET /api/turns/conversation/:convId — per-turn detail + recall hits. */
511
+ conversationTurns: {
512
+ method: "GET",
513
+ path: "/api/turns/conversation/:convId",
514
+ description: "Per-turn metrics + injected-checkpoint recall provenance for one conversation.",
515
+ } as const satisfies EndpointDef<"GET", undefined, ConversationTurnsResponse>,
516
+
517
+ /** GET /api/turns/intents — pending rewind intents (S52A). */
518
+ turnIntents: {
519
+ method: "GET",
520
+ path: "/api/turns/intents",
521
+ description: "Pending rewind intents queued by the dashboard for the host to consume.",
522
+ } as const satisfies EndpointDef<"GET", undefined, RewindIntentsResponse>,
523
+
524
+ /** POST /api/turns/intent — post a rewind intent. */
525
+ postTurnIntent: {
526
+ method: "POST",
527
+ path: "/api/turns/intent",
528
+ description: "Queue a rewind-to-turn-N intent for the host to apply at before_agent_start.",
529
+ } as const satisfies EndpointDef<"POST", PostIntentRequest, unknown>,
530
+
531
+ /** POST /api/fork — fork a conversation at a turn. */
532
+ fork: {
533
+ method: "POST",
534
+ path: "/api/fork",
535
+ description: "Branch a child conversation off a parent turn + return the recall set to rehydrate.",
536
+ } as const satisfies EndpointDef<"POST", ForkRequest, ForkResponse>,
537
+
538
+ /** POST /api/turns/prune — admin prune (capability-gated). */
539
+ pruneTurns: {
540
+ method: "POST",
541
+ path: "/api/turns/prune",
542
+ description: "Prune old turns (admin capability — dashboard uses asAdmin()).",
543
+ } as const satisfies EndpointDef<"POST", PruneRequest, PruneTurnsResponse>,
544
+
545
+ /** GET /api/topics/:topicId/memories — wiki topic drill-down (S52). */
546
+ topicMemories: {
547
+ method: "GET",
548
+ path: "/api/topics/:topicId/memories",
549
+ description: "Member memories assigned to a wiki topic (drill-down).",
550
+ } as const satisfies EndpointDef<"GET", undefined, TopicMemoriesResponse>,
453
551
  } as const;