instar 1.3.40 → 1.3.42
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/dist/core/PostUpdateMigrator.d.ts +27 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +137 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/scheduler/OutstandingPromptTracker.d.ts +82 -0
- package/dist/scheduler/OutstandingPromptTracker.d.ts.map +1 -0
- package/dist/scheduler/OutstandingPromptTracker.js +136 -0
- package/dist/scheduler/OutstandingPromptTracker.js.map +1 -0
- package/dist/server/AgentServer.d.ts +22 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +131 -5
- package/dist/server/AgentServer.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.41.md +43 -0
- package/upgrades/1.3.42.md +39 -0
- package/upgrades/side-effects/mentor-consumer-receiver-wire.md +89 -0
- package/upgrades/side-effects/mentor-retire-migrations.md +73 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutstandingPromptTracker — anti-ping-pong invariant for the mentor live loop.
|
|
3
|
+
*
|
|
4
|
+
* Spec: MENTOR-LIVE-READINESS §Fix 2b "Implementation surface" item 4 + Justin's original
|
|
5
|
+
* concern (the rebuilt-slow ping-pong: a 15-min mentor tick + a Codey reply that takes
|
|
6
|
+
* 16+ min = naive next-tick re-sends while the prior is in flight → loop).
|
|
7
|
+
*
|
|
8
|
+
* Justin's user-fidelity correction made this THE real cadence gate (Fix 1 idle-probe
|
|
9
|
+
* was removed; users don't probe). The mentor refuses to send a new prompt while any
|
|
10
|
+
* prior prompt is outstanding within `replyTimeoutMs`. On timeout expiry without a reply
|
|
11
|
+
* → degradation event + Attention entry (silent reply-loss is observable).
|
|
12
|
+
*
|
|
13
|
+
* Pure in-memory + a small persistence shim so a server restart doesn't lose the "I'm
|
|
14
|
+
* waiting on a reply" state (would otherwise re-send + double-prompt Codey).
|
|
15
|
+
*
|
|
16
|
+
* Keyed per-mentee. The same `corr` round-trips: mark on send, clear on matching reply.
|
|
17
|
+
*/
|
|
18
|
+
export interface OutstandingPromptTrackerOptions {
|
|
19
|
+
/** Absolute path to the JSON file backing the tracker (per-mentee state). */
|
|
20
|
+
filePath: string;
|
|
21
|
+
/** A reply that doesn't arrive within this window is treated as orphaned. */
|
|
22
|
+
replyTimeoutMs?: number;
|
|
23
|
+
/** Injected for testability. */
|
|
24
|
+
now?: () => number;
|
|
25
|
+
}
|
|
26
|
+
export type CheckResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
} | {
|
|
29
|
+
ok: false;
|
|
30
|
+
reason: 'prior-prompt-in-flight';
|
|
31
|
+
outstandingCorr: string;
|
|
32
|
+
sentAt: number;
|
|
33
|
+
};
|
|
34
|
+
export declare class OutstandingPromptTracker {
|
|
35
|
+
private readonly filePath;
|
|
36
|
+
private readonly replyTimeoutMs;
|
|
37
|
+
private readonly now;
|
|
38
|
+
private entries;
|
|
39
|
+
/** Per-(reason,day) dedup for the orphan-degradation notification. */
|
|
40
|
+
private orphanedNotifiedFor;
|
|
41
|
+
constructor(opts: OutstandingPromptTrackerOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Returns `{ok: true}` if the mentor can send a new prompt to this mentee; otherwise
|
|
44
|
+
* `{ok: false, reason: 'prior-prompt-in-flight'}` (the tick must refuse the send). An
|
|
45
|
+
* EXPIRED outstanding (past replyTimeoutMs) is automatically swept here and does NOT
|
|
46
|
+
* block — the caller can also call sweepExpired() explicitly to surface orphans.
|
|
47
|
+
*/
|
|
48
|
+
canSendTo(mentee: string): CheckResult;
|
|
49
|
+
/** Record that a prompt with this `corr` was sent to this mentee at now(). */
|
|
50
|
+
markSent(corr: string, mentee: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Clear an outstanding prompt by `corr` (called when the matching reply arrives).
|
|
53
|
+
* Returns true if an outstanding entry existed (legitimate reply); false if not
|
|
54
|
+
* (a reply with no outstanding match — possibly a late reply after orphan-sweep,
|
|
55
|
+
* or a spurious reply; the caller may want to log this).
|
|
56
|
+
*/
|
|
57
|
+
clearByCorr(corr: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Find + remove orphans (sentAt + replyTimeoutMs < now). Returns the list. Caller
|
|
60
|
+
* decides whether to fire DegradationReporter / Attention. The dedup field stays
|
|
61
|
+
* across calls so the same orphan-episode doesn't re-fire repeatedly.
|
|
62
|
+
*/
|
|
63
|
+
sweepExpired(): Array<{
|
|
64
|
+
corr: string;
|
|
65
|
+
mentee: string;
|
|
66
|
+
sentAt: number;
|
|
67
|
+
ageMs: number;
|
|
68
|
+
}>;
|
|
69
|
+
/** Idempotent: once an orphan-notify has fired for a (corr), don't re-fire. */
|
|
70
|
+
recordOrphanNotified(corr: string): boolean;
|
|
71
|
+
/** Test helper. */
|
|
72
|
+
size(): number;
|
|
73
|
+
/** Test helper. */
|
|
74
|
+
list(): Array<{
|
|
75
|
+
corr: string;
|
|
76
|
+
mentee: string;
|
|
77
|
+
sentAt: number;
|
|
78
|
+
}>;
|
|
79
|
+
private load;
|
|
80
|
+
private persist;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=OutstandingPromptTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OutstandingPromptTracker.d.ts","sourceRoot":"","sources":["../../src/scheduler/OutstandingPromptTracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,MAAM,WAAW,+BAA+B;IAC9C,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAiBD,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,wBAAwB,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,OAAO,CAAiC;IAChD,sEAAsE;IACtE,OAAO,CAAC,mBAAmB,CAAc;gBAE7B,IAAI,EAAE,+BAA+B;IASjD;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAUtC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAK5C;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMlC;;;;OAIG;IACH,YAAY,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAatF,+EAA+E;IAC/E,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAM3C,mBAAmB;IACnB,IAAI,IAAI,MAAM;IAId,mBAAmB;IACnB,IAAI,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAI/D,OAAO,CAAC,IAAI;IAkBZ,OAAO,CAAC,OAAO;CAahB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutstandingPromptTracker — anti-ping-pong invariant for the mentor live loop.
|
|
3
|
+
*
|
|
4
|
+
* Spec: MENTOR-LIVE-READINESS §Fix 2b "Implementation surface" item 4 + Justin's original
|
|
5
|
+
* concern (the rebuilt-slow ping-pong: a 15-min mentor tick + a Codey reply that takes
|
|
6
|
+
* 16+ min = naive next-tick re-sends while the prior is in flight → loop).
|
|
7
|
+
*
|
|
8
|
+
* Justin's user-fidelity correction made this THE real cadence gate (Fix 1 idle-probe
|
|
9
|
+
* was removed; users don't probe). The mentor refuses to send a new prompt while any
|
|
10
|
+
* prior prompt is outstanding within `replyTimeoutMs`. On timeout expiry without a reply
|
|
11
|
+
* → degradation event + Attention entry (silent reply-loss is observable).
|
|
12
|
+
*
|
|
13
|
+
* Pure in-memory + a small persistence shim so a server restart doesn't lose the "I'm
|
|
14
|
+
* waiting on a reply" state (would otherwise re-send + double-prompt Codey).
|
|
15
|
+
*
|
|
16
|
+
* Keyed per-mentee. The same `corr` round-trips: mark on send, clear on matching reply.
|
|
17
|
+
*/
|
|
18
|
+
import fs from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { SafeFsExecutor } from '../core/SafeFsExecutor.js';
|
|
21
|
+
const DEFAULT_REPLY_TIMEOUT_MS = 20 * 60 * 1000; // 20 min — > the 15-min tick interval.
|
|
22
|
+
export class OutstandingPromptTracker {
|
|
23
|
+
filePath;
|
|
24
|
+
replyTimeoutMs;
|
|
25
|
+
now;
|
|
26
|
+
entries;
|
|
27
|
+
/** Per-(reason,day) dedup for the orphan-degradation notification. */
|
|
28
|
+
orphanedNotifiedFor;
|
|
29
|
+
constructor(opts) {
|
|
30
|
+
this.filePath = opts.filePath;
|
|
31
|
+
this.replyTimeoutMs = opts.replyTimeoutMs ?? DEFAULT_REPLY_TIMEOUT_MS;
|
|
32
|
+
this.now = opts.now ?? Date.now;
|
|
33
|
+
this.entries = new Map();
|
|
34
|
+
this.orphanedNotifiedFor = new Set();
|
|
35
|
+
this.load();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns `{ok: true}` if the mentor can send a new prompt to this mentee; otherwise
|
|
39
|
+
* `{ok: false, reason: 'prior-prompt-in-flight'}` (the tick must refuse the send). An
|
|
40
|
+
* EXPIRED outstanding (past replyTimeoutMs) is automatically swept here and does NOT
|
|
41
|
+
* block — the caller can also call sweepExpired() explicitly to surface orphans.
|
|
42
|
+
*/
|
|
43
|
+
canSendTo(mentee) {
|
|
44
|
+
this.sweepExpired();
|
|
45
|
+
for (const [corr, p] of this.entries) {
|
|
46
|
+
if (p.mentee === mentee) {
|
|
47
|
+
return { ok: false, reason: 'prior-prompt-in-flight', outstandingCorr: corr, sentAt: p.sentAt };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { ok: true };
|
|
51
|
+
}
|
|
52
|
+
/** Record that a prompt with this `corr` was sent to this mentee at now(). */
|
|
53
|
+
markSent(corr, mentee) {
|
|
54
|
+
this.entries.set(corr, { sentAt: this.now(), mentee });
|
|
55
|
+
this.persist();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Clear an outstanding prompt by `corr` (called when the matching reply arrives).
|
|
59
|
+
* Returns true if an outstanding entry existed (legitimate reply); false if not
|
|
60
|
+
* (a reply with no outstanding match — possibly a late reply after orphan-sweep,
|
|
61
|
+
* or a spurious reply; the caller may want to log this).
|
|
62
|
+
*/
|
|
63
|
+
clearByCorr(corr) {
|
|
64
|
+
const had = this.entries.delete(corr);
|
|
65
|
+
if (had)
|
|
66
|
+
this.persist();
|
|
67
|
+
return had;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Find + remove orphans (sentAt + replyTimeoutMs < now). Returns the list. Caller
|
|
71
|
+
* decides whether to fire DegradationReporter / Attention. The dedup field stays
|
|
72
|
+
* across calls so the same orphan-episode doesn't re-fire repeatedly.
|
|
73
|
+
*/
|
|
74
|
+
sweepExpired() {
|
|
75
|
+
const cutoff = this.now() - this.replyTimeoutMs;
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const [corr, p] of this.entries) {
|
|
78
|
+
if (p.sentAt < cutoff) {
|
|
79
|
+
out.push({ corr, mentee: p.mentee, sentAt: p.sentAt, ageMs: this.now() - p.sentAt });
|
|
80
|
+
this.entries.delete(corr);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (out.length > 0)
|
|
84
|
+
this.persist();
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/** Idempotent: once an orphan-notify has fired for a (corr), don't re-fire. */
|
|
88
|
+
recordOrphanNotified(corr) {
|
|
89
|
+
if (this.orphanedNotifiedFor.has(corr))
|
|
90
|
+
return false;
|
|
91
|
+
this.orphanedNotifiedFor.add(corr);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/** Test helper. */
|
|
95
|
+
size() {
|
|
96
|
+
return this.entries.size;
|
|
97
|
+
}
|
|
98
|
+
/** Test helper. */
|
|
99
|
+
list() {
|
|
100
|
+
return [...this.entries].map(([corr, p]) => ({ corr, mentee: p.mentee, sentAt: p.sentAt }));
|
|
101
|
+
}
|
|
102
|
+
load() {
|
|
103
|
+
if (!fs.existsSync(this.filePath))
|
|
104
|
+
return;
|
|
105
|
+
try {
|
|
106
|
+
const raw = fs.readFileSync(this.filePath, 'utf-8');
|
|
107
|
+
const parsed = JSON.parse(raw);
|
|
108
|
+
if (parsed && parsed.v === 1 && parsed.entries && typeof parsed.entries === 'object') {
|
|
109
|
+
for (const [corr, p] of Object.entries(parsed.entries)) {
|
|
110
|
+
if (p && typeof p.sentAt === 'number' && typeof p.mentee === 'string') {
|
|
111
|
+
this.entries.set(corr, { sentAt: p.sentAt, mentee: p.mentee });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Corrupted state → start fresh; better than crashing the mentor on a bad file.
|
|
118
|
+
this.entries = new Map();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
persist() {
|
|
122
|
+
const file = {
|
|
123
|
+
v: 1,
|
|
124
|
+
entries: Object.fromEntries(this.entries),
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
|
|
128
|
+
SafeFsExecutor.atomicWriteJsonSync(this.filePath, file, { operation: 'OutstandingPromptTracker.persist' });
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// eslint-disable-next-line no-console
|
|
132
|
+
console.warn(`[mentor] OutstandingPromptTracker persist failed (non-fatal) at ${this.filePath}:`, err instanceof Error ? err.message : String(err));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=OutstandingPromptTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OutstandingPromptTracker.js","sourceRoot":"","sources":["../../src/scheduler/OutstandingPromptTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,6 +61,12 @@ export declare class AgentServer {
|
|
|
61
61
|
private mentorBotAdapterToken;
|
|
62
62
|
/** Lazily-constructed a2a audit ledger (shared across mentor sends/recvs). */
|
|
63
63
|
private a2aLedger;
|
|
64
|
+
/** Lazily-constructed processed-id store (idempotency for inbound mentor-reply). */
|
|
65
|
+
private a2aProcessedIds;
|
|
66
|
+
/** Lazily-constructed outstanding-prompt tracker (anti-ping-pong). */
|
|
67
|
+
private mentorOutstanding;
|
|
68
|
+
/** Reply-jsonl path (Codey's reply persisted here for Stage-B forensics). */
|
|
69
|
+
private mentorReplyJsonlPath;
|
|
64
70
|
private failureLedger;
|
|
65
71
|
private failureAttributionEngine;
|
|
66
72
|
private burnDetector;
|
|
@@ -246,6 +252,22 @@ export declare class AgentServer {
|
|
|
246
252
|
private getOrCreateMentorBot;
|
|
247
253
|
/** Lazily construct + cache the a2a audit ledger. Paths default under stateDir. */
|
|
248
254
|
private getOrCreateA2aLedger;
|
|
255
|
+
/** Lazily construct + cache the processed-id store (idempotency for inbound replies). */
|
|
256
|
+
private getOrCreateA2aProcessedIds;
|
|
257
|
+
/** Lazily construct + cache the outstanding-prompt tracker (anti-ping-pong). */
|
|
258
|
+
private getOrCreateMentorOutstanding;
|
|
259
|
+
/**
|
|
260
|
+
* Install the mentor-reply recipient hook on the mentor-bot adapter. Called from
|
|
261
|
+
* getOrCreateMentorBot once the adapter is up. The hook routes role=`mentor-reply`
|
|
262
|
+
* from Codey to a handler that (1) clears the outstanding-prompt entry by `corr`
|
|
263
|
+
* (so the next mentor tick can send again), and (2) persists the reply to a
|
|
264
|
+
* jsonl file Stage-B forensics reads. This is the capability-handle invariant from
|
|
265
|
+
* the spec: the reply-ingestion path CANNOT call spawnStageA / deliverToMentee /
|
|
266
|
+
* scheduler / Threadline — it only writes the reply + clears tracking.
|
|
267
|
+
*/
|
|
268
|
+
private installMentorReceiverHook;
|
|
269
|
+
/** Snapshot of mentor config for use outside the runner's getConfig closure. */
|
|
270
|
+
private getMentorConfigSnapshot;
|
|
249
271
|
private buildMentorRunner;
|
|
250
272
|
/**
|
|
251
273
|
* Start the HTTP server.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentServer.d.ts","sourceRoot":"","sources":["../../src/server/AgentServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAgB,EAAE,KAAK,OAAO,EAA+B,MAAM,SAAS,CAAC;AAM7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAcxF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"AgentServer.d.ts","sourceRoot":"","sources":["../../src/server/AgentServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,8 +38,11 @@ import { MentorOnboardingRunner, DEFAULT_MENTOR_CONFIG } from '../scheduler/Ment
|
|
|
38
38
|
import { STAGE_A_ALLOWED_TOOLS } from '../monitoring/MentorStageA.js';
|
|
39
39
|
import { analyzeForensics } from '../scheduler/MentorStageBForensics.js';
|
|
40
40
|
import { TelegramAdapter as MentorTelegramAdapter } from '../messaging/TelegramAdapter.js';
|
|
41
|
-
import { sendAgentMessage } from '../messaging/AgentTelegramComms.js';
|
|
41
|
+
import { sendAgentMessage, A2A_VERSION } from '../messaging/AgentTelegramComms.js';
|
|
42
42
|
import { AgentTelegramLedger, defaultLedgerPaths as defaultA2aLedgerPaths } from '../messaging/AgentTelegramLedger.js';
|
|
43
|
+
import { ProcessedIdStore } from '../messaging/ProcessedIdStore.js';
|
|
44
|
+
import { buildAgentMessageHook } from '../messaging/installAgentMessageHook.js';
|
|
45
|
+
import { OutstandingPromptTracker } from '../scheduler/OutstandingPromptTracker.js';
|
|
43
46
|
import { parseCodexRollout } from '../monitoring/CodexRolloutParser.js';
|
|
44
47
|
import { BurnDetector } from '../monitoring/BurnDetector.js';
|
|
45
48
|
import { BurnThrottleRunbook } from '../monitoring/BurnThrottleRunbook.js';
|
|
@@ -78,6 +81,12 @@ export class AgentServer {
|
|
|
78
81
|
mentorBotAdapterToken = null;
|
|
79
82
|
/** Lazily-constructed a2a audit ledger (shared across mentor sends/recvs). */
|
|
80
83
|
a2aLedger = null;
|
|
84
|
+
/** Lazily-constructed processed-id store (idempotency for inbound mentor-reply). */
|
|
85
|
+
a2aProcessedIds = null;
|
|
86
|
+
/** Lazily-constructed outstanding-prompt tracker (anti-ping-pong). */
|
|
87
|
+
mentorOutstanding = null;
|
|
88
|
+
/** Reply-jsonl path (Codey's reply persisted here for Stage-B forensics). */
|
|
89
|
+
mentorReplyJsonlPath = null;
|
|
81
90
|
failureLedger = null;
|
|
82
91
|
failureAttributionEngine = null;
|
|
83
92
|
// Burn-detection-and-self-heal system (six-phase umbrella spec at
|
|
@@ -591,6 +600,10 @@ export class AgentServer {
|
|
|
591
600
|
try {
|
|
592
601
|
this.mentorBotAdapter = new MentorTelegramAdapter({ token: botToken, chatId: menteeChatId }, this.config.stateDir, { subDir: 'agent-telegram/mentor-bot', suppressLifelineAutoCreate: true });
|
|
593
602
|
this.mentorBotAdapterToken = botToken;
|
|
603
|
+
// Install the mentor-reply recipient hook now that the adapter is up. The handler
|
|
604
|
+
// clears the outstanding-prompt by corr + persists the reply for Stage-B.
|
|
605
|
+
const mentorBotId = botToken.split(':')[0];
|
|
606
|
+
this.installMentorReceiverHook(this.mentorBotAdapter, mentorBotId);
|
|
594
607
|
return this.mentorBotAdapter;
|
|
595
608
|
}
|
|
596
609
|
catch (err) {
|
|
@@ -607,6 +620,87 @@ export class AgentServer {
|
|
|
607
620
|
}
|
|
608
621
|
return this.a2aLedger;
|
|
609
622
|
}
|
|
623
|
+
/** Lazily construct + cache the processed-id store (idempotency for inbound replies). */
|
|
624
|
+
getOrCreateA2aProcessedIds() {
|
|
625
|
+
if (!this.a2aProcessedIds) {
|
|
626
|
+
this.a2aProcessedIds = new ProcessedIdStore({
|
|
627
|
+
filePath: path.join(this.config.stateDir, 'a2a-processed-ids.json'),
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
return this.a2aProcessedIds;
|
|
631
|
+
}
|
|
632
|
+
/** Lazily construct + cache the outstanding-prompt tracker (anti-ping-pong). */
|
|
633
|
+
getOrCreateMentorOutstanding() {
|
|
634
|
+
if (!this.mentorOutstanding) {
|
|
635
|
+
this.mentorOutstanding = new OutstandingPromptTracker({
|
|
636
|
+
filePath: path.join(this.config.stateDir, 'mentor-outstanding-prompts.json'),
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
return this.mentorOutstanding;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Install the mentor-reply recipient hook on the mentor-bot adapter. Called from
|
|
643
|
+
* getOrCreateMentorBot once the adapter is up. The hook routes role=`mentor-reply`
|
|
644
|
+
* from Codey to a handler that (1) clears the outstanding-prompt entry by `corr`
|
|
645
|
+
* (so the next mentor tick can send again), and (2) persists the reply to a
|
|
646
|
+
* jsonl file Stage-B forensics reads. This is the capability-handle invariant from
|
|
647
|
+
* the spec: the reply-ingestion path CANNOT call spawnStageA / deliverToMentee /
|
|
648
|
+
* scheduler / Threadline — it only writes the reply + clears tracking.
|
|
649
|
+
*/
|
|
650
|
+
installMentorReceiverHook(bot, mentorBotId) {
|
|
651
|
+
const cfg = this.getMentorConfigSnapshot();
|
|
652
|
+
if (!cfg.menteeBotId)
|
|
653
|
+
return;
|
|
654
|
+
const recipientCfg = {
|
|
655
|
+
localAgent: 'echo',
|
|
656
|
+
knownAgents: { [`instar-${cfg.menteeFramework}`]: { botId: cfg.menteeBotId } },
|
|
657
|
+
acceptRoles: { [`instar-${cfg.menteeFramework}`]: ['mentor-reply'] },
|
|
658
|
+
skewWindowMs: 24 * 60 * 60 * 1000,
|
|
659
|
+
maxVersion: A2A_VERSION,
|
|
660
|
+
};
|
|
661
|
+
const outstanding = this.getOrCreateMentorOutstanding();
|
|
662
|
+
const replyJsonl = path.join(this.config.stateDir, 'mentor-replies.jsonl');
|
|
663
|
+
this.mentorReplyJsonlPath = replyJsonl;
|
|
664
|
+
const mentorReplyHandler = async (msg, ctx) => {
|
|
665
|
+
// (1) Clear the outstanding-prompt by corr (the next tick can send again).
|
|
666
|
+
const had = outstanding.clearByCorr(msg.corr);
|
|
667
|
+
if (!had) {
|
|
668
|
+
// Spurious / late reply (no outstanding match). Still persist it for forensics.
|
|
669
|
+
console.warn(`[mentor] mentor-reply for unknown corr=${msg.corr} (late after orphan-sweep?); persisting anyway`);
|
|
670
|
+
}
|
|
671
|
+
// (2) Persist the reply for Stage-B (append-only JSONL). Capability-handle
|
|
672
|
+
// invariant: this is the ONLY outbound effect; no spawn/deliver/schedule.
|
|
673
|
+
try {
|
|
674
|
+
fs.mkdirSync(path.dirname(replyJsonl), { recursive: true });
|
|
675
|
+
const row = {
|
|
676
|
+
ts: Date.now(),
|
|
677
|
+
fromAgent: msg.from,
|
|
678
|
+
corr: msg.corr,
|
|
679
|
+
replyId: msg.id,
|
|
680
|
+
topicId: ctx.topicId,
|
|
681
|
+
message: msg.body,
|
|
682
|
+
};
|
|
683
|
+
fs.appendFileSync(replyJsonl, JSON.stringify(row) + '\n', 'utf-8');
|
|
684
|
+
}
|
|
685
|
+
catch (err) {
|
|
686
|
+
console.warn('[mentor] mentor-reply persist failed (non-fatal):', err instanceof Error ? err.message : String(err));
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
const hook = buildAgentMessageHook({
|
|
690
|
+
config: recipientCfg,
|
|
691
|
+
ledger: this.getOrCreateA2aLedger(),
|
|
692
|
+
processedIds: this.getOrCreateA2aProcessedIds(),
|
|
693
|
+
roleHandlers: new Map([['mentor-reply', mentorReplyHandler]]),
|
|
694
|
+
});
|
|
695
|
+
bot.setAgentMessageHook(hook);
|
|
696
|
+
}
|
|
697
|
+
/** Snapshot of mentor config for use outside the runner's getConfig closure. */
|
|
698
|
+
getMentorConfigSnapshot() {
|
|
699
|
+
return {
|
|
700
|
+
...DEFAULT_MENTOR_CONFIG,
|
|
701
|
+
...(this.config.mentor ?? {}),
|
|
702
|
+
};
|
|
703
|
+
}
|
|
610
704
|
buildMentorRunner(ledger, options, serverDataDir) {
|
|
611
705
|
const getConfig = () => ({
|
|
612
706
|
...DEFAULT_MENTOR_CONFIG,
|
|
@@ -723,17 +817,45 @@ export class AgentServer {
|
|
|
723
817
|
console.warn(`[mentor] deliverToMentee skipped — mentor-bot config incomplete (need mentor.botToken + menteeBotId + menteeChatId + menteeTopicId; framework=${framework})`);
|
|
724
818
|
return;
|
|
725
819
|
}
|
|
820
|
+
const menteeAgent = `instar-${framework}`;
|
|
821
|
+
// Anti-ping-pong (spec §Fix 2b item 4 + Justin's original concern). Refuse to
|
|
822
|
+
// send a new prompt while a prior one is unanswered within replyTimeoutMs.
|
|
823
|
+
const outstanding = self.getOrCreateMentorOutstanding();
|
|
824
|
+
const orphans = outstanding.sweepExpired();
|
|
825
|
+
for (const orphan of orphans) {
|
|
826
|
+
if (outstanding.recordOrphanNotified(orphan.corr)) {
|
|
827
|
+
console.warn(`[mentor] orphaned prompt — no reply within ${orphan.ageMs}ms (corr=${orphan.corr}, mentee=${orphan.mentee})`);
|
|
828
|
+
try {
|
|
829
|
+
DegradationReporter.getInstance().report({
|
|
830
|
+
feature: 'mentor.reply-orphaned',
|
|
831
|
+
primary: 'mentor receives Codey reply within replyTimeoutMs',
|
|
832
|
+
fallback: 'tick continues; no auto-resend; Stage-B sees the routed-sent row + no matching reply row',
|
|
833
|
+
reason: `outstanding prompt corr=${orphan.corr} aged ${orphan.ageMs}ms without a mentor-reply`,
|
|
834
|
+
impact: 'mentor cycle silently lost a reply; next tick allowed to retry',
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
catch { /* best-effort */ }
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
const check = outstanding.canSendTo(menteeAgent);
|
|
841
|
+
if (!check.ok) {
|
|
842
|
+
console.warn(`[mentor] deliverToMentee deferred — prior-prompt-in-flight (corr=${check.outstandingCorr}, sentAt=${check.sentAt})`);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
726
845
|
const bot = self.getOrCreateMentorBot(cfg.botToken, cfg.menteeChatId);
|
|
727
846
|
if (!bot)
|
|
728
847
|
return;
|
|
729
848
|
const ledger = self.getOrCreateA2aLedger();
|
|
849
|
+
const corr = `mp-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
730
850
|
try {
|
|
731
|
-
await sendAgentMessage({
|
|
851
|
+
const result = await sendAgentMessage({
|
|
732
852
|
fromAgent: 'echo',
|
|
733
|
-
toAgent:
|
|
853
|
+
toAgent: menteeAgent,
|
|
734
854
|
role: 'mentor',
|
|
735
855
|
toTopicId: cfg.menteeTopicId,
|
|
736
856
|
message,
|
|
857
|
+
id: corr,
|
|
858
|
+
correlationId: corr,
|
|
737
859
|
}, {
|
|
738
860
|
send: async (topicId, text) => {
|
|
739
861
|
try {
|
|
@@ -746,12 +868,16 @@ export class AgentServer {
|
|
|
746
868
|
},
|
|
747
869
|
appendAudit: (row) => ledger.appendSent(row),
|
|
748
870
|
now: () => Date.now(),
|
|
749
|
-
mintId: () =>
|
|
871
|
+
mintId: () => corr,
|
|
750
872
|
allowedRoles: new Set(['mentor']),
|
|
751
873
|
botToken: cfg.botToken,
|
|
752
|
-
fromBotId: cfg.botToken.split(':')[0],
|
|
874
|
+
fromBotId: cfg.botToken.split(':')[0],
|
|
753
875
|
toBotId: cfg.menteeBotId,
|
|
754
876
|
});
|
|
877
|
+
if (result.ok) {
|
|
878
|
+
// Mark only on successful send — a failed send doesn't owe a reply.
|
|
879
|
+
outstanding.markSent(corr, menteeAgent);
|
|
880
|
+
}
|
|
755
881
|
}
|
|
756
882
|
catch (err) {
|
|
757
883
|
console.warn('[mentor] deliverToMentee send failed (non-fatal):', err instanceof Error ? err.message : String(err));
|