@aiwayds/dsh-topics-memory 0.16.1-next.1 → 0.18.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/src/store.ts CHANGED
@@ -140,6 +140,31 @@ export class BundleStore {
140
140
  return join(this.metaDir(), 'injections.jsonl')
141
141
  }
142
142
 
143
+ /**
144
+ * Fast-lane heartbeat (0.17.0): tail timestamps of the two lane sidecars —
145
+ * the last injection round (`injections.jsonl`) and the last observation
146
+ * (`observations.jsonl`). Feeds the /topics status stale check that makes
147
+ * "observer still recording, injection lane silently dead" visible within
148
+ * a day instead of weeks (the 0.1.5-rc.2 claim-order incident shape).
149
+ * Full-file reads are fine here: /topics status is interactive and both
150
+ * logs are append-per-round small; unreadable logs degrade to undefined.
151
+ */
152
+ async readLaneHeartbeat(): Promise<{ lastInjectionAt?: string; lastObservationAt?: string }> {
153
+ const tailAt = async (file: string): Promise<string | undefined> => {
154
+ try {
155
+ const lines = (await readFile(file, 'utf8')).trimEnd().split('\n')
156
+ const at = (JSON.parse(lines.at(-1) ?? '') as { at?: unknown }).at
157
+ return typeof at === 'string' ? at : undefined
158
+ } catch {
159
+ return undefined
160
+ }
161
+ }
162
+ return {
163
+ lastInjectionAt: await tailAt(this.injectionsPath()),
164
+ lastObservationAt: await tailAt(this.observationsPath()),
165
+ }
166
+ }
167
+
143
168
  private conflictsPath(): string {
144
169
  return join(this.metaDir(), 'conflicts.json')
145
170
  }