@letta-ai/letta-code 0.30.27 → 0.30.29

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 (74) hide show
  1. package/dist/agent-presets.js +17 -17
  2. package/dist/agent-presets.js.map +1 -1
  3. package/dist/mcp-client.js +2 -2
  4. package/dist/mcp-client.js.map +1 -1
  5. package/dist/types/agent/client-skills.d.ts +3 -0
  6. package/dist/types/agent/client-skills.d.ts.map +1 -1
  7. package/dist/types/agent/memory-git.d.ts +2 -0
  8. package/dist/types/agent/memory-git.d.ts.map +1 -1
  9. package/dist/types/agent/shared-memory-skills.d.ts +18 -0
  10. package/dist/types/agent/shared-memory-skills.d.ts.map +1 -0
  11. package/dist/types/backend/dev/pi-model-factory.d.ts +6 -0
  12. package/dist/types/backend/dev/pi-model-factory.d.ts.map +1 -1
  13. package/dist/types/backend/dev/pi-provider-registry.d.ts.map +1 -1
  14. package/dist/types/backend/local/local-provider-auth-store.d.ts.map +1 -1
  15. package/dist/types/tools/impl/skill.d.ts +10 -5
  16. package/dist/types/tools/impl/skill.d.ts.map +1 -1
  17. package/dist/types/tools/secret-substitution.d.ts.map +1 -1
  18. package/dist/types/types/loop-status-protocol.d.ts +17 -0
  19. package/dist/types/types/loop-status-protocol.d.ts.map +1 -0
  20. package/dist/types/types/protocol_v2.d.ts +2 -19
  21. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  22. package/dist/types/websocket/listener/inbound-queue.d.ts +5 -0
  23. package/dist/types/websocket/listener/inbound-queue.d.ts.map +1 -0
  24. package/dist/types/websocket/listener/protocol-outbound-routing.d.ts +9 -0
  25. package/dist/types/websocket/listener/protocol-outbound-routing.d.ts.map +1 -0
  26. package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
  27. package/dist/types/websocket/listener/runtime.d.ts.map +1 -1
  28. package/dist/types/websocket/listener/turn-correlation.d.ts +10 -0
  29. package/dist/types/websocket/listener/turn-correlation.d.ts.map +1 -0
  30. package/dist/types/websocket/listener/types.d.ts +4 -0
  31. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  32. package/image-resize-worker.js +42 -20
  33. package/letta.js +85237 -138922
  34. package/package.json +4 -3
  35. package/scripts/claude-watch/agent-watch.ts +622 -0
  36. package/scripts/claude-watch/docs-snapshot.test.ts +259 -0
  37. package/scripts/claude-watch/docs-snapshot.ts +672 -0
  38. package/scripts/claude-watch/fixtures/historical-replays.json +52 -0
  39. package/scripts/claude-watch/github.ts +137 -0
  40. package/scripts/claude-watch/release-analysis.test.ts +235 -0
  41. package/scripts/claude-watch/release-analysis.ts +297 -0
  42. package/scripts/claude-watch/release-source.test.ts +179 -0
  43. package/scripts/claude-watch/release-source.ts +369 -0
  44. package/scripts/claude-watch/runtime-observations.ts +98 -0
  45. package/scripts/claude-watch/runtime-probe.test.ts +576 -0
  46. package/scripts/claude-watch/runtime-probe.ts +911 -0
  47. package/scripts/claude-watch/runtime-sandbox.ts +170 -0
  48. package/scripts/claude-watch/state-branch.test.ts +211 -0
  49. package/scripts/claude-watch/state-branch.ts +316 -0
  50. package/scripts/claude-watch/tracker.test.ts +148 -0
  51. package/scripts/claude-watch/tracker.ts +325 -0
  52. package/scripts/claude-watch/types.ts +186 -0
  53. package/scripts/claude-watch/update-tracker.ts +201 -0
  54. package/scripts/codex-watch/agent-watch.ts +65 -10
  55. package/scripts/codex-watch/release-analysis.test.ts +57 -0
  56. package/scripts/codex-watch/release-analysis.ts +45 -3
  57. package/scripts/codex-watch/tracker.test.ts +243 -6
  58. package/scripts/codex-watch/tracker.ts +222 -23
  59. package/scripts/pi-ai-watch/agent-watch.ts +253 -0
  60. package/scripts/pi-ai-watch/github.ts +145 -0
  61. package/scripts/pi-ai-watch/release-analysis.test.ts +137 -0
  62. package/scripts/pi-ai-watch/release-analysis.ts +371 -0
  63. package/scripts/pi-ai-watch/tracker.test.ts +138 -0
  64. package/scripts/pi-ai-watch/tracker.ts +303 -0
  65. package/scripts/pi-ai-watch/update-tracker.ts +215 -0
  66. package/scripts/run-unit-tests.cjs +2 -0
  67. package/scripts/source-file-size-baseline.json +3 -3
  68. package/skills/creating-mods/references/commands.md +1 -1
  69. package/skills/creating-mods/references/ui.md +1 -1
  70. package/skills/customizing-commands/SKILL.md +1 -1
  71. package/skills/initializing-memory/SKILL.md +7 -7
  72. package/skills/self-configuration/SKILL.md +4 -4
  73. package/scripts/codex-watch/check-release.ts +0 -128
  74. package/scripts/codex-watch/render-issue.ts +0 -273
@@ -1,14 +1,17 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import type { CodexWatchAnalysis } from "./release-analysis.ts";
3
3
  import {
4
+ advanceCodexAuditCursor,
4
5
  emptyTrackerState,
5
- hasProcessedTag,
6
+ getCodexAuditCursorTag,
7
+ hasProcessedRange,
6
8
  parseTrackerState,
7
9
  recordAnalysis,
8
10
  renderTrackerBody,
9
11
  serializeTrackerState,
10
12
  type TrackerEntry,
11
13
  upsertTrackerEntry,
14
+ validateLegacyCodexAuditCursor,
12
15
  } from "./tracker.ts";
13
16
 
14
17
  function analysis(
@@ -18,6 +21,7 @@ function analysis(
18
21
  return {
19
22
  previous_tag: "rust-v0.1.0",
20
23
  current_tag: tag,
24
+ is_adjacent_release: true,
21
25
  release_url: `https://github.com/openai/codex/releases/tag/${tag}`,
22
26
  release_notes_md: "",
23
27
  verdict,
@@ -31,6 +35,12 @@ function analysis(
31
35
  };
32
36
  }
33
37
 
38
+ function withoutAuditCursor(body: string): string {
39
+ return body
40
+ .replace(/ "audit_cursor_tag": (?:null|"[^"]+"),\n/, "")
41
+ .replace(' "audit_cursor_validated": true,\n', "");
42
+ }
43
+
34
44
  function entry(index: number, outcome: TrackerEntry["outcome"]): TrackerEntry {
35
45
  const verdict =
36
46
  outcome === "recorded_noop" ? "no-op" : "tool-surface review needed";
@@ -51,11 +61,38 @@ function entry(index: number, outcome: TrackerEntry["outcome"]): TrackerEntry {
51
61
  }
52
62
 
53
63
  describe("tracker state", () => {
54
- test("returns empty state when hidden state is absent or malformed", () => {
55
- expect(parseTrackerState("plain body")).toEqual(emptyTrackerState());
56
- expect(
64
+ test("fails closed when hidden state is absent or malformed", () => {
65
+ expect(() => parseTrackerState("plain body")).toThrow(
66
+ "Codex tracker hidden state is missing",
67
+ );
68
+ expect(() =>
57
69
  parseTrackerState("<!-- codex-agent-watch-state\nnot json\n-->"),
58
- ).toEqual(emptyTrackerState());
70
+ ).toThrow("Codex tracker hidden state is invalid");
71
+ expect(() =>
72
+ parseTrackerState(
73
+ '<!-- codex-agent-watch-state\n{"last_checked_tag":null,"last_checked_at":null,"processed":[{}]}\n-->',
74
+ ),
75
+ ).toThrow("Codex tracker hidden state is invalid");
76
+ expect(() =>
77
+ parseTrackerState(
78
+ '<!-- codex-agent-watch-state\n{"audit_cursor_tag":null,"last_checked_tag":"rust-v0.2.0","last_checked_at":"2026-08-20T00:00:00Z","processed":[]}\n-->',
79
+ ),
80
+ ).toThrow("Codex tracker hidden state is invalid");
81
+ });
82
+
83
+ test("fails closed on an unsupported durable cursor", () => {
84
+ const state = upsertTrackerEntry(
85
+ emptyTrackerState(),
86
+ entry(1, "no_local_impact"),
87
+ );
88
+ const body = renderTrackerBody(state).replace(
89
+ '"audit_cursor_tag": "rust-v0.1.0"',
90
+ '"audit_cursor_tag": "rust-v0.5.0"',
91
+ );
92
+
93
+ expect(() => parseTrackerState(body)).toThrow(
94
+ "Codex tracker hidden state is invalid",
95
+ );
59
96
  });
60
97
 
61
98
  test("round-trips hidden state through rendered body", () => {
@@ -72,6 +109,85 @@ describe("tracker state", () => {
72
109
  expect(body).toContain("upstream-only router change");
73
110
  });
74
111
 
112
+ test("derives the durable cursor from legacy hidden state", () => {
113
+ const state = recordAnalysis(emptyTrackerState(), {
114
+ analysis: analysis("rust-v0.2.0"),
115
+ outcome: "recorded_noop",
116
+ notes: "no watched changes",
117
+ processedAt: "2026-07-02T00:00:00.000Z",
118
+ });
119
+ const legacyBody = withoutAuditCursor(renderTrackerBody(state));
120
+
121
+ const legacy = parseTrackerState(legacyBody);
122
+ expect(legacy.audit_cursor_validated).toBe(false);
123
+ const migrated = validateLegacyCodexAuditCursor(legacy, [
124
+ "rust-v0.1.0",
125
+ "rust-v0.2.0",
126
+ ]);
127
+ expect(migrated.audit_cursor_validated).toBe(true);
128
+ expect(getCodexAuditCursorTag(migrated)).toBe("rust-v0.2.0");
129
+ });
130
+
131
+ test("migrates a legacy cursor independently of an older replay", () => {
132
+ let state = upsertTrackerEntry(
133
+ emptyTrackerState(),
134
+ entry(1, "no_local_impact"),
135
+ );
136
+ state = upsertTrackerEntry(state, entry(2, "no_local_impact"));
137
+ state = upsertTrackerEntry(state, entry(3, "no_local_impact"));
138
+ state = upsertTrackerEntry(state, entry(1, "no_local_impact"));
139
+
140
+ const legacy = parseTrackerState(
141
+ withoutAuditCursor(renderTrackerBody(state)),
142
+ );
143
+ const migrated = validateLegacyCodexAuditCursor(legacy, [
144
+ "rust-v0.0.0",
145
+ "rust-v0.1.0",
146
+ "rust-v0.2.0",
147
+ "rust-v0.3.0",
148
+ ]);
149
+ expect(migrated.last_checked_tag).toBe("rust-v0.1.0");
150
+ expect(getCodexAuditCursorTag(migrated)).toBe("rust-v0.3.0");
151
+ });
152
+
153
+ test("fails closed on a disconnected future legacy replay", () => {
154
+ let state = upsertTrackerEntry(
155
+ emptyTrackerState(),
156
+ entry(1, "no_local_impact"),
157
+ );
158
+ state = upsertTrackerEntry(state, entry(2, "no_local_impact"));
159
+ state = upsertTrackerEntry(state, entry(5, "no_local_impact"));
160
+
161
+ expect(() =>
162
+ parseTrackerState(withoutAuditCursor(renderTrackerBody(state))),
163
+ ).toThrow("Codex tracker hidden state is invalid");
164
+ });
165
+
166
+ test("fails closed on a cumulative legacy replay", () => {
167
+ const cumulative = {
168
+ ...analysis("rust-v0.5.0", "tool-surface review needed"),
169
+ is_adjacent_release: false,
170
+ };
171
+ const state = recordAnalysis(emptyTrackerState(), {
172
+ analysis: cumulative,
173
+ outcome: "no_local_impact",
174
+ notes: "legacy cumulative replay",
175
+ });
176
+ const legacy = parseTrackerState(
177
+ withoutAuditCursor(renderTrackerBody(state)),
178
+ );
179
+
180
+ expect(() =>
181
+ validateLegacyCodexAuditCursor(legacy, [
182
+ "rust-v0.1.0",
183
+ "rust-v0.2.0",
184
+ "rust-v0.3.0",
185
+ "rust-v0.4.0",
186
+ "rust-v0.5.0",
187
+ ]),
188
+ ).toThrow("Legacy Codex tracker range is not adjacent");
189
+ });
190
+
75
191
  test("records noops in hidden state without adding visible table rows", () => {
76
192
  const state = recordAnalysis(emptyTrackerState(), {
77
193
  analysis: analysis("rust-v0.2.0"),
@@ -81,11 +197,132 @@ describe("tracker state", () => {
81
197
  });
82
198
 
83
199
  const body = renderTrackerBody(state);
84
- expect(hasProcessedTag(parseTrackerState(body), "rust-v0.2.0")).toBe(true);
200
+ expect(
201
+ hasProcessedRange(
202
+ parseTrackerState(body),
203
+ "rust-v0.1.0",
204
+ "rust-v0.2.0",
205
+ ),
206
+ ).toBe(true);
85
207
  expect(body).toContain("_No actionable releases recorded yet._");
86
208
  expect(body).toContain("no watched changes");
87
209
  });
88
210
 
211
+ test("retries an errored release from its previous tag", () => {
212
+ let state = upsertTrackerEntry(
213
+ emptyTrackerState(),
214
+ entry(1, "recorded_noop"),
215
+ );
216
+ state = upsertTrackerEntry(state, entry(2, "error"));
217
+
218
+ expect(
219
+ hasProcessedRange(state, "rust-v0.1.0", "rust-v0.2.0"),
220
+ ).toBe(false);
221
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.1.0");
222
+
223
+ state = upsertTrackerEntry(state, entry(2, "no_local_impact"));
224
+ expect(
225
+ hasProcessedRange(state, "rust-v0.1.0", "rust-v0.2.0"),
226
+ ).toBe(true);
227
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.2.0");
228
+ });
229
+
230
+ test("uses an errored release baseline when no terminal entry exists", () => {
231
+ const state = upsertTrackerEntry(
232
+ emptyTrackerState(),
233
+ entry(2, "error"),
234
+ );
235
+
236
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.1.0");
237
+ });
238
+
239
+ test("does not regress the cursor after an older replay", () => {
240
+ let state = upsertTrackerEntry(
241
+ emptyTrackerState(),
242
+ entry(10, "no_local_impact"),
243
+ );
244
+ state = upsertTrackerEntry(state, entry(5, "no_local_impact"));
245
+
246
+ expect(state.last_checked_tag).toBe("rust-v0.5.0");
247
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.10.0");
248
+ });
249
+
250
+ test("does not let a future replay skip an errored release", () => {
251
+ let state = upsertTrackerEntry(
252
+ emptyTrackerState(),
253
+ entry(1, "no_local_impact"),
254
+ );
255
+ state = upsertTrackerEntry(state, entry(2, "error"));
256
+ state = upsertTrackerEntry(state, entry(5, "no_local_impact"));
257
+
258
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.1.0");
259
+
260
+ state = upsertTrackerEntry(state, entry(2, "no_local_impact"));
261
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.2.0");
262
+ });
263
+
264
+ test("does not advance for an explicit non-adjacent range", () => {
265
+ const initial = upsertTrackerEntry(
266
+ emptyTrackerState(),
267
+ entry(1, "no_local_impact"),
268
+ );
269
+ const cumulative = {
270
+ ...analysis("rust-v0.5.0", "tool-surface review needed"),
271
+ is_adjacent_release: false,
272
+ };
273
+ const state = recordAnalysis(initial, {
274
+ analysis: cumulative,
275
+ outcome: "no_local_impact",
276
+ notes: "explicit cumulative replay",
277
+ });
278
+
279
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.1.0");
280
+ expect(
281
+ getCodexAuditCursorTag(
282
+ advanceCodexAuditCursor(
283
+ state,
284
+ "rust-v0.1.0",
285
+ "rust-v0.5.0",
286
+ false,
287
+ ),
288
+ ),
289
+ ).toBe("rust-v0.1.0");
290
+ });
291
+
292
+ test("advances across an already audited adjacent range", () => {
293
+ let state = upsertTrackerEntry(
294
+ emptyTrackerState(),
295
+ entry(1, "no_local_impact"),
296
+ );
297
+ state = upsertTrackerEntry(state, entry(3, "no_local_impact"));
298
+ state = upsertTrackerEntry(state, entry(2, "no_local_impact"));
299
+
300
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.2.0");
301
+ state = advanceCodexAuditCursor(
302
+ state,
303
+ "rust-v0.2.0",
304
+ "rust-v0.3.0",
305
+ true,
306
+ );
307
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.3.0");
308
+ });
309
+
310
+ test("retains the durable cursor entry when history is truncated", () => {
311
+ let state = upsertTrackerEntry(
312
+ emptyTrackerState(),
313
+ entry(100, "no_local_impact"),
314
+ );
315
+ for (let index = 1; index <= 60; index += 1) {
316
+ state = upsertTrackerEntry(state, entry(index, "no_local_impact"));
317
+ }
318
+
319
+ expect(state.processed).toHaveLength(50);
320
+ expect(state.processed.some(({ tag }) => tag === "rust-v0.100.0")).toBe(
321
+ true,
322
+ );
323
+ expect(getCodexAuditCursorTag(state)).toBe("rust-v0.100.0");
324
+ });
325
+
89
326
  test("keeps the last 50 processed releases in hidden state", () => {
90
327
  let state = emptyTrackerState();
91
328
  for (let i = 1; i <= 60; i++) {
@@ -26,6 +26,8 @@ export interface TrackerEntry {
26
26
  }
27
27
 
28
28
  export interface TrackerState {
29
+ audit_cursor_tag: string | null;
30
+ audit_cursor_validated: boolean;
29
31
  last_checked_tag: string | null;
30
32
  last_checked_at: string | null;
31
33
  processed: TrackerEntry[];
@@ -41,6 +43,8 @@ export interface RecordAnalysisOptions {
41
43
 
42
44
  export function emptyTrackerState(): TrackerState {
43
45
  return {
46
+ audit_cursor_tag: null,
47
+ audit_cursor_validated: true,
44
48
  last_checked_tag: null,
45
49
  last_checked_at: null,
46
50
  processed: [],
@@ -49,21 +53,81 @@ export function emptyTrackerState(): TrackerState {
49
53
 
50
54
  export function parseTrackerState(body: string): TrackerState {
51
55
  const start = body.indexOf(STATE_START);
52
- if (start === -1) return emptyTrackerState();
56
+ if (start === -1) throw new Error("Codex tracker hidden state is missing");
53
57
 
54
58
  const jsonStart = start + STATE_START.length;
55
59
  const end = body.indexOf(STATE_END, jsonStart);
56
- if (end === -1) return emptyTrackerState();
60
+ if (end === -1) throw new Error("Codex tracker hidden state is incomplete");
57
61
 
58
62
  try {
59
63
  return normalizeState(JSON.parse(body.slice(jsonStart, end).trim()));
60
- } catch {
61
- return emptyTrackerState();
64
+ } catch (error) {
65
+ throw new Error("Codex tracker hidden state is invalid", { cause: error });
62
66
  }
63
67
  }
64
68
 
65
- export function hasProcessedTag(state: TrackerState, tag: string): boolean {
66
- return state.processed.some((entry) => entry.tag === tag);
69
+ export function isTerminalOutcome(outcome: TrackerOutcome): boolean {
70
+ return outcome !== "error";
71
+ }
72
+
73
+ export function hasProcessedRange(
74
+ state: TrackerState,
75
+ previousTag: string,
76
+ currentTag: string,
77
+ ): boolean {
78
+ return state.processed.some(
79
+ (entry) =>
80
+ entry.previous_tag === previousTag &&
81
+ entry.tag === currentTag &&
82
+ isTerminalOutcome(entry.outcome),
83
+ );
84
+ }
85
+
86
+ export function getCodexAuditCursorTag(state: TrackerState): string | null {
87
+ return state.audit_cursor_tag;
88
+ }
89
+
90
+ export function validateLegacyCodexAuditCursor(
91
+ state: TrackerState,
92
+ stableTags: string[],
93
+ ): TrackerState {
94
+ if (state.audit_cursor_validated) return state;
95
+
96
+ let tag = state.audit_cursor_tag;
97
+ while (tag !== null) {
98
+ const entry = state.processed.find(
99
+ (candidate) =>
100
+ candidate.tag === tag && isTerminalOutcome(candidate.outcome),
101
+ );
102
+ if (!entry) break;
103
+ const currentIndex = stableTags.indexOf(entry.tag);
104
+ if (
105
+ currentIndex < 1 ||
106
+ stableTags[currentIndex - 1] !== entry.previous_tag
107
+ ) {
108
+ throw new Error(
109
+ `Legacy Codex tracker range is not adjacent: ${entry.previous_tag}...${entry.tag}`,
110
+ );
111
+ }
112
+ tag = entry.previous_tag;
113
+ }
114
+
115
+ return { ...state, audit_cursor_validated: true };
116
+ }
117
+
118
+ export function advanceCodexAuditCursor(
119
+ state: TrackerState,
120
+ previousTag: string,
121
+ currentTag: string,
122
+ isAdjacentRelease: boolean,
123
+ ): TrackerState {
124
+ if (!isAdjacentRelease || state.audit_cursor_tag !== previousTag) return state;
125
+ if (!hasProcessedRange(state, previousTag, currentTag)) {
126
+ throw new Error(
127
+ `Cannot advance Codex audit cursor without terminal ${previousTag}...${currentTag}`,
128
+ );
129
+ }
130
+ return { ...state, audit_cursor_tag: currentTag };
67
131
  }
68
132
 
69
133
  export function recordAnalysis(
@@ -81,19 +145,51 @@ export function recordAnalysis(
81
145
  processed_at: processedAt,
82
146
  compare_url: options.analysis.compare_url,
83
147
  workflow_run_url: options.analysis.workflow_run_url,
84
- });
148
+ }, options.analysis.is_adjacent_release);
85
149
  }
86
150
 
87
151
  export function upsertTrackerEntry(
88
152
  state: TrackerState,
89
153
  entry: TrackerEntry,
154
+ advanceAuditCursor = true,
90
155
  ): TrackerState {
91
- const processed = [
156
+ let auditCursorTag = state.audit_cursor_tag;
157
+ if (auditCursorTag === null && !advanceAuditCursor) {
158
+ auditCursorTag = entry.previous_tag;
159
+ } else if (
160
+ advanceAuditCursor &&
161
+ entry.outcome === "error" &&
162
+ auditCursorTag === null
163
+ ) {
164
+ auditCursorTag = entry.previous_tag;
165
+ } else if (
166
+ advanceAuditCursor &&
167
+ isTerminalOutcome(entry.outcome) &&
168
+ (auditCursorTag === null || entry.previous_tag === auditCursorTag)
169
+ ) {
170
+ auditCursorTag = entry.tag;
171
+ }
172
+
173
+ const candidates = [
92
174
  entry,
93
- ...state.processed.filter((existing) => existing.tag !== entry.tag),
94
- ].slice(0, HIDDEN_STATE_LIMIT);
175
+ ...state.processed.filter(
176
+ (existing) =>
177
+ existing.tag !== entry.tag ||
178
+ existing.previous_tag !== entry.previous_tag,
179
+ ),
180
+ ];
181
+ let processed = candidates.slice(0, HIDDEN_STATE_LIMIT);
182
+ if (auditCursorTag !== null && !isSupportedAuditCursor(processed, auditCursorTag)) {
183
+ const support = candidates.find((candidate) =>
184
+ isAuditCursorSupportEntry(candidate, auditCursorTag),
185
+ );
186
+ if (!support) throw new Error("Codex audit cursor has no supporting entry");
187
+ processed = [...processed.slice(0, HIDDEN_STATE_LIMIT - 1), support];
188
+ }
95
189
 
96
190
  return {
191
+ audit_cursor_tag: auditCursorTag,
192
+ audit_cursor_validated: state.audit_cursor_validated,
97
193
  last_checked_tag: entry.tag,
98
194
  last_checked_at: entry.processed_at,
99
195
  processed,
@@ -103,9 +199,7 @@ export function upsertTrackerEntry(
103
199
  export function renderTrackerBody(state: TrackerState): string {
104
200
  const normalized = normalizeState(state);
105
201
  const parts: string[] = [
106
- "Central tracker for the Amelia-driven Codex upstream drift watch experiment.",
107
- "",
108
- "The legacy per-release `codex-release-watch.yml` issue workflow is still enabled as the baseline while this tracker bakes off the new automation path.",
202
+ "Central tracker for Amelia-driven Codex upstream drift monitoring.",
109
203
  "",
110
204
  renderLastChecked(normalized),
111
205
  "",
@@ -181,28 +275,129 @@ function escapeTable(value: string): string {
181
275
  }
182
276
 
183
277
  function normalizeState(value: unknown): TrackerState {
184
- if (!isRecord(value)) return emptyTrackerState();
278
+ if (!isRecord(value)) throw new TypeError("tracker state must be an object");
279
+ if (!Array.isArray(value.processed) || !value.processed.every(isTrackerEntry)) {
280
+ throw new TypeError("tracker processed entries are invalid");
281
+ }
282
+ if (
283
+ value.last_checked_tag !== null &&
284
+ typeof value.last_checked_tag !== "string"
285
+ ) {
286
+ throw new TypeError("tracker last_checked_tag is invalid");
287
+ }
288
+ if (
289
+ value.last_checked_at !== null &&
290
+ typeof value.last_checked_at !== "string"
291
+ ) {
292
+ throw new TypeError("tracker last_checked_at is invalid");
293
+ }
185
294
 
186
- const processed = Array.isArray(value.processed)
187
- ? value.processed.filter(isTrackerEntry).slice(0, HIDDEN_STATE_LIMIT)
188
- : [];
295
+ const processed = value.processed.slice(
296
+ 0,
297
+ HIDDEN_STATE_LIMIT,
298
+ ) as TrackerEntry[];
299
+ const lastCheckedTag = value.last_checked_tag as string | null;
300
+ const lastChecked =
301
+ lastCheckedTag === null
302
+ ? null
303
+ : processed.find((entry) => entry.tag === lastCheckedTag);
304
+ if (lastCheckedTag === null ? processed.length > 0 : !lastChecked) {
305
+ throw new TypeError("tracker last_checked_tag is inconsistent");
306
+ }
307
+
308
+ let auditCursorTag: string | null;
309
+ let auditCursorValidated: boolean;
310
+ if (value.audit_cursor_tag === undefined) {
311
+ auditCursorTag = deriveLegacyAuditCursor(processed);
312
+ auditCursorValidated = false;
313
+ } else if (
314
+ (value.audit_cursor_tag === null ||
315
+ typeof value.audit_cursor_tag === "string") &&
316
+ value.audit_cursor_validated === true
317
+ ) {
318
+ auditCursorTag = value.audit_cursor_tag;
319
+ auditCursorValidated = true;
320
+ } else {
321
+ throw new TypeError("tracker audit cursor is invalid");
322
+ }
323
+ if (auditCursorTag !== null && !isStableTag(auditCursorTag)) {
324
+ throw new TypeError("tracker audit_cursor_tag is invalid");
325
+ }
326
+ if (auditCursorTag === null && processed.length > 0) {
327
+ throw new TypeError("tracker audit_cursor_tag is missing");
328
+ }
329
+ if (
330
+ auditCursorTag !== null &&
331
+ !isSupportedAuditCursor(processed, auditCursorTag)
332
+ ) {
333
+ throw new TypeError("tracker audit_cursor_tag is inconsistent");
334
+ }
189
335
 
190
336
  return {
191
- last_checked_tag:
192
- typeof value.last_checked_tag === "string"
193
- ? value.last_checked_tag
194
- : null,
195
- last_checked_at:
196
- typeof value.last_checked_at === "string" ? value.last_checked_at : null,
337
+ audit_cursor_tag: auditCursorTag,
338
+ audit_cursor_validated: auditCursorValidated,
339
+ last_checked_tag: lastCheckedTag,
340
+ last_checked_at: value.last_checked_at as string | null,
197
341
  processed,
198
342
  };
199
343
  }
200
344
 
345
+ function isSupportedAuditCursor(
346
+ processed: TrackerEntry[],
347
+ cursorTag: string,
348
+ ): boolean {
349
+ return processed.some((entry) =>
350
+ isAuditCursorSupportEntry(entry, cursorTag),
351
+ );
352
+ }
353
+
354
+ function isAuditCursorSupportEntry(
355
+ entry: TrackerEntry,
356
+ cursorTag: string,
357
+ ): boolean {
358
+ return (
359
+ (entry.tag === cursorTag && isTerminalOutcome(entry.outcome)) ||
360
+ entry.previous_tag === cursorTag
361
+ );
362
+ }
363
+
364
+ function deriveLegacyAuditCursor(processed: TrackerEntry[]): string | null {
365
+ const terminal = processed.filter((entry) =>
366
+ isTerminalOutcome(entry.outcome),
367
+ );
368
+ if (terminal.length === 0) {
369
+ const errorBaselines = [
370
+ ...new Set(
371
+ processed
372
+ .filter((entry) => entry.outcome === "error")
373
+ .map((entry) => entry.previous_tag),
374
+ ),
375
+ ];
376
+ if (errorBaselines.length > 1) {
377
+ throw new TypeError("legacy tracker error baselines are ambiguous");
378
+ }
379
+ return errorBaselines[0] ?? null;
380
+ }
381
+
382
+ const tags = terminal.map((entry) => entry.tag);
383
+ if (new Set(tags).size !== tags.length) {
384
+ throw new TypeError("legacy tracker terminal tags are duplicated");
385
+ }
386
+ const previousTags = new Set(terminal.map((entry) => entry.previous_tag));
387
+ const endpoints = tags.filter((tag) => !previousTags.has(tag));
388
+ if (endpoints.length !== 1) {
389
+ throw new TypeError("legacy tracker audit chain is ambiguous");
390
+ }
391
+ return endpoints[0] ?? null;
392
+ }
393
+
201
394
  function isTrackerEntry(value: unknown): value is TrackerEntry {
202
395
  if (!isRecord(value)) return false;
203
396
  return (
204
397
  typeof value.tag === "string" &&
398
+ isStableTag(value.tag) &&
205
399
  typeof value.previous_tag === "string" &&
400
+ isStableTag(value.previous_tag) &&
206
401
  isVerdict(value.verdict) &&
207
402
  isOutcome(value.outcome) &&
208
403
  (typeof value.pr_url === "string" || value.pr_url === null) &&
@@ -213,6 +408,10 @@ function isTrackerEntry(value: unknown): value is TrackerEntry {
213
408
  );
214
409
  }
215
410
 
411
+ function isStableTag(value: string): boolean {
412
+ return /^(?:rust-v|v)?\d+\.\d+\.\d+$/.test(value);
413
+ }
414
+
216
415
  function isVerdict(value: unknown): value is Verdict {
217
416
  return (
218
417
  value === "no-op" ||