@dsh-cc/advisor-watchdog 0.8.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.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Settings for the advisor watchdog (plan
3
+ * docs/plans/2026-09-23-advisor-watchdog.md §4.9), two halves — the turn-rules
4
+ * dual-half pattern (packages/interaction/turn-rules/src/settings.ts):
5
+ *
6
+ * 1. namespace registration via `@dsh-cc/settings-ns` (kebab keys, for /config
7
+ * UX and validation only);
8
+ * 2. a RAW user-layer read of `<dshHome>/settings.json` re-read per use, so a
9
+ * turn never depends on cascade timing.
10
+ *
11
+ * Schemastery has no `z.enum`; enum members are expressed as
12
+ * `z.union([z.const(...), ...])`.
13
+ *
14
+ * @module
15
+ */
16
+ import { readFileSync } from 'node:fs';
17
+ import { readFile } from 'node:fs/promises';
18
+ import { join } from 'node:path';
19
+ import z from '@deepseek-ai/schemastery';
20
+ import { registerNamespaceSafe } from '@dsh-cc/settings-ns';
21
+ /** The settings namespace carrying the advisor flags. */
22
+ export const SETTINGS_NAMESPACE = 'cc-advisor';
23
+ const opt = (t) => z.union([t, z.const(undefined)]);
24
+ const SeverityEnum = z.union([
25
+ z.const('nit'),
26
+ z.const('concern'),
27
+ z.const('blocker'),
28
+ ]);
29
+ /** Inner object shape (kebab keys). Absence resolves to defaults via schemastery. */
30
+ const SettingsObject = z.object({
31
+ enabled: z.boolean().default(false),
32
+ alias: z.string().default('haiku'),
33
+ // Schemastery's number schema has no .int; integrality is enforced in
34
+ // resolveSection (truncation) — the range bounds are the schema's job.
35
+ budget: z.number().min(1).max(8).default(2),
36
+ 'immune-turns': z.number().min(0).max(8).default(3),
37
+ 'session-cap': z.number().min(1).max(256).default(24),
38
+ severities: z.array(SeverityEnum).default(['nit', 'concern', 'blocker']),
39
+ subagents: z.union([z.const('off'), z.const('on'), z.string()]).default('off'),
40
+ });
41
+ /**
42
+ * Namespace schema. Wrapped in the z.const(undefined) union (turn-rules
43
+ * convention) so a genuinely absent namespace value stays absent instead of
44
+ * materializing defaults into the cascade.
45
+ */
46
+ export const SettingsSchema = opt(SettingsObject);
47
+ /** Ship-dark defaults (§4.8): enabled false. */
48
+ export const DEFAULT_ADVISOR_SETTINGS = {
49
+ enabled: false,
50
+ alias: 'haiku',
51
+ budget: 2,
52
+ immuneTurns: 3,
53
+ sessionCap: 24,
54
+ severities: ['nit', 'concern', 'blocker'],
55
+ subagents: 'off',
56
+ };
57
+ /**
58
+ * Register the settings namespace (for /config UX and validation only —
59
+ * the listener reads the raw user file). Returns the live reader, or
60
+ * `undefined` when the host has no settings provider.
61
+ */
62
+ export function registerSettings(ctx) {
63
+ const settings = ctx.get('settings');
64
+ if (settings === undefined)
65
+ return undefined;
66
+ const read = registerNamespaceSafe(ctx, SETTINGS_NAMESPACE, SettingsSchema);
67
+ return () => {
68
+ try {
69
+ const value = read();
70
+ if (value === undefined)
71
+ return DEFAULT_ADVISOR_SETTINGS;
72
+ return resolveSection(value);
73
+ }
74
+ catch {
75
+ // Malformed live scope → ship defaults; never throw into a hot path.
76
+ return DEFAULT_ADVISOR_SETTINGS;
77
+ }
78
+ };
79
+ }
80
+ /** Resolve one raw section into the settings shape with defaults. */
81
+ function resolveSection(section) {
82
+ const resolved = SettingsObject(section);
83
+ const asInt = (value, fallback) => {
84
+ const n = typeof value === 'number' && Number.isFinite(value) ? Math.trunc(value) : fallback;
85
+ return n;
86
+ };
87
+ return {
88
+ enabled: resolved.enabled,
89
+ alias: resolved.alias,
90
+ budget: asInt(resolved.budget, 2),
91
+ immuneTurns: asInt(resolved['immune-turns'], 3),
92
+ sessionCap: asInt(resolved['session-cap'], 24),
93
+ severities: resolved.severities ?? DEFAULT_ADVISOR_SETTINGS.severities,
94
+ subagents: resolved.subagents ?? 'off',
95
+ };
96
+ }
97
+ /**
98
+ * Read the settings DIRECTLY from `<dshHome>/settings.json`, bypassing the
99
+ * merged cascade. Fail-soft: absent file, parse error, or a malformed section
100
+ * yields the ship defaults. Project scope is never read — invisible, not refused.
101
+ */
102
+ export async function readUserSettings(dshHome) {
103
+ let text;
104
+ try {
105
+ text = await readFile(join(dshHome, 'settings.json'), 'utf8');
106
+ }
107
+ catch {
108
+ return DEFAULT_ADVISOR_SETTINGS;
109
+ }
110
+ let root;
111
+ try {
112
+ root = JSON.parse(text);
113
+ }
114
+ catch {
115
+ return DEFAULT_ADVISOR_SETTINGS;
116
+ }
117
+ if (typeof root !== 'object' || root === null)
118
+ return DEFAULT_ADVISOR_SETTINGS;
119
+ const section = root[SETTINGS_NAMESPACE];
120
+ if (typeof section !== 'object' || section === null)
121
+ return DEFAULT_ADVISOR_SETTINGS;
122
+ try {
123
+ return resolveSection(section);
124
+ }
125
+ catch {
126
+ return DEFAULT_ADVISOR_SETTINGS;
127
+ }
128
+ }
129
+ /**
130
+ * SYNCHRONOUS raw read of `<dshHome>/settings.json` — the trigger-side half
131
+ * of the dual-half pattern (§4.9): the `agent/turn-stopping` handler must run
132
+ * synchronously up to capture (a step can begin during the handler's
133
+ * microtasks, and an async read would let the next request's snapshot
134
+ * overwrite the one being reviewed). Same fail-soft semantics as
135
+ * {@link readUserSettings}.
136
+ */
137
+ export function readUserSettingsSync(dshHome) {
138
+ let text;
139
+ try {
140
+ text = readFileSync(join(dshHome, 'settings.json'), 'utf8');
141
+ }
142
+ catch {
143
+ return DEFAULT_ADVISOR_SETTINGS;
144
+ }
145
+ let root;
146
+ try {
147
+ root = JSON.parse(text);
148
+ }
149
+ catch {
150
+ return DEFAULT_ADVISOR_SETTINGS;
151
+ }
152
+ if (typeof root !== 'object' || root === null)
153
+ return DEFAULT_ADVISOR_SETTINGS;
154
+ const section = root[SETTINGS_NAMESPACE];
155
+ if (typeof section !== 'object' || section === null)
156
+ return DEFAULT_ADVISOR_SETTINGS;
157
+ try {
158
+ return resolveSection(section);
159
+ }
160
+ catch {
161
+ return DEFAULT_ADVISOR_SETTINGS;
162
+ }
163
+ }
164
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Live wiring (plan docs/plans/2026-09-23-advisor-watchdog.md §4.1/§4.4):
3
+ * the passive read-only `llm/stream` snapshot listener (per-session newest
4
+ * qualifying request messages) and the `agent/turn-stopping` trigger (gates,
5
+ * cursor protocol, immediate cursor advance, inFlight flag, detached
6
+ * side-query spawn, resolve-time inject). Every fault degrades to a no-op:
7
+ * the advisor is advisory enrichment and must never throw into a waterfall,
8
+ * block a request, or wake an idle driver.
9
+ *
10
+ * State lifetime: per-mount Maps keyed by session id — preset remount
11
+ * replaces the mount and with it the maps (§4.4 "re-arm next session"); there
12
+ * is no per-session dispose (turn-rules posture).
13
+ *
14
+ * @module
15
+ */
16
+ import type { Context } from '@deepseek-ai/cordis';
17
+ declare module '@deepseek-ai/dsh-llm' {
18
+ interface MessageSourceMap {
19
+ 'advisor': {
20
+ kind: 'advisor';
21
+ };
22
+ }
23
+ }
24
+ /**
25
+ * Register the snapshot + trigger listeners. Plain plugin — no Service, no
26
+ * isolate key. @param ctx - the plug context (needs `llm` for the side query).
27
+ */
28
+ export declare function registerListeners(ctx: Context): void;
29
+ declare module '@deepseek-ai/cordis' {
30
+ interface Context {
31
+ /** Harness-home path resolver, provided by @deepseek-ai/dsh-app-boot at boot. Optional in tests. */
32
+ dshHomePath?: (...segments: string[]) => string;
33
+ }
34
+ }
35
+ //# sourceMappingURL=wiring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../src/wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAuBlD,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,SAAS,EAAE;YAAE,IAAI,EAAE,SAAS,CAAA;SAAE,CAAA;KAC/B;CACF;AA0BD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAkCpD;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,oGAAoG;QACpG,WAAW,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,MAAM,CAAA;KAChD;CACF"}
package/lib/wiring.js ADDED
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Live wiring (plan docs/plans/2026-09-23-advisor-watchdog.md §4.1/§4.4):
3
+ * the passive read-only `llm/stream` snapshot listener (per-session newest
4
+ * qualifying request messages) and the `agent/turn-stopping` trigger (gates,
5
+ * cursor protocol, immediate cursor advance, inFlight flag, detached
6
+ * side-query spawn, resolve-time inject). Every fault degrades to a no-op:
7
+ * the advisor is advisory enrichment and must never throw into a waterfall,
8
+ * block a request, or wake an idle driver.
9
+ *
10
+ * State lifetime: per-mount Maps keyed by session id — preset remount
11
+ * replaces the mount and with it the maps (§4.4 "re-arm next session"); there
12
+ * is no per-session dispose (turn-rules posture).
13
+ *
14
+ * @module
15
+ */
16
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
17
+ import { resolveAlias } from '@dsh-cc/model-aliases';
18
+ import { ADVISOR_SOURCE_KIND, fullCursor, renderDelta, reviewWindow } from "./delta.js";
19
+ import { applyEmissionGuard, emptyDrops, emptyGuardState, rememberFingerprint } from "./guard.js";
20
+ import { parseAdvisorNotes, runAdvisor } from "./advise.js";
21
+ import { appendJournal } from "./journal.js";
22
+ import { readUserSettingsSync } from "./settings.js";
23
+ /** Top-level-only predicate (turn-rules wiring.ts:27-30 precedent). */
24
+ function isTopLevel(agent) {
25
+ const header = agent.session.header;
26
+ return header.origin !== 'subagent' && (header.delegationDepth ?? 0) <= 0;
27
+ }
28
+ /** Guarded dshHome read (turn-rules pattern): cordis throws on the property access itself. */
29
+ function dshHomeOf(ctx) {
30
+ try {
31
+ return ctx.dshHomePath?.();
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ /** Debug notice (fail-soft). */
38
+ function debug(ctx, message) {
39
+ try {
40
+ ctx.logger.debug(message);
41
+ }
42
+ catch {
43
+ // Never throw into a hot path.
44
+ }
45
+ }
46
+ /**
47
+ * Register the snapshot + trigger listeners. Plain plugin — no Service, no
48
+ * isolate key. @param ctx - the plug context (needs `llm` for the side query).
49
+ */
50
+ export function registerListeners(ctx) {
51
+ const states = new Map();
52
+ // Newest qualifying request's message array, per session (§4.1). Retained
53
+ // cost is one array reference per active session id; entries are dropped
54
+ // when a session becomes gated-out or disabled.
55
+ const snapshots = new Map();
56
+ // Read-only `llm/stream` listener (cache-health precedent): observe and
57
+ // pass through. Zero settings/IO work, never mutates `options`, never
58
+ // throws into the waterfall. A qualifying request keeps its message array:
59
+ // the loop stamps `sessionId` for request routing, so loop-built
60
+ // conversation requests qualify and every hand-built one-shot (our own
61
+ // runSideQuery included — it never sets `sessionId`) is excluded by
62
+ // construction; auxiliary purpose-tagged calls are skipped.
63
+ ctx.on('llm/stream', (options, next) => {
64
+ try {
65
+ if (options.sessionId !== undefined && options.purpose === undefined) {
66
+ snapshots.set(String(options.sessionId), options.messages);
67
+ }
68
+ }
69
+ catch {
70
+ // Never throw into the request path.
71
+ }
72
+ return next();
73
+ }, { global: true, prepend: true });
74
+ ctx.on('agent/turn-stopping', ({ agent }) => {
75
+ try {
76
+ // Fire-and-forget: capture/advance/spawn happen inside a detached
77
+ // promise — never awaited by the handler, never throwing into the event.
78
+ void onTurnStopping(ctx, snapshots, states, agent).catch(() => { });
79
+ }
80
+ catch {
81
+ // Never throw into the waterfall.
82
+ }
83
+ });
84
+ }
85
+ /** Ensure one session's state (per-mount map is the lifetime). */
86
+ function ensure(states, sessionId) {
87
+ let state = states.get(sessionId);
88
+ if (state === undefined) {
89
+ state = { cursor: undefined, turnCounter: 0, inFlight: false, guard: emptyGuardState(), drops: emptyDrops(), disabled: false };
90
+ states.set(sessionId, state);
91
+ }
92
+ return state;
93
+ }
94
+ /** The turn-stopping trigger (§4.1 steps 1-5), run detached. */
95
+ async function onTurnStopping(ctx, snapshots, states, agent) {
96
+ const home = dshHomeOf(ctx);
97
+ if (home === undefined)
98
+ return;
99
+ // Synchronous up to capture (§4.1 "single synchronous handler"): the raw
100
+ // dual-half read is a readFileSync — an async read here would let the next
101
+ // request's llm/stream overwrite the snapshot being reviewed.
102
+ const settings = readUserSettingsSync(home);
103
+ const sessionId = String(agent.session.header.id);
104
+ // Gate 1: settings `.enabled` (raw dual-half read, §4.9).
105
+ if (!settings.enabled) {
106
+ snapshots.delete(sessionId);
107
+ return;
108
+ }
109
+ // Gate 2: global subagent gate (§4.7) — settings-level only; 'off'
110
+ // restricts to top-level sessions; an alias STRING overrides the lane for
111
+ // subagent sessions ('on' keeps the session alias).
112
+ if (settings.subagents === 'off' && !isTopLevel(agent)) {
113
+ snapshots.delete(sessionId);
114
+ return;
115
+ }
116
+ const effectiveAlias = !isTopLevel(agent) && settings.subagents !== 'off' && settings.subagents !== 'on'
117
+ ? settings.subagents
118
+ : settings.alias;
119
+ const state = ensure(states, sessionId);
120
+ // Gate 3: session-disabled (cap or unrouted).
121
+ if (state.disabled) {
122
+ debug(ctx, 'advisor: session-disabled (cap or unrouted)');
123
+ snapshots.delete(sessionId);
124
+ return;
125
+ }
126
+ // Gate 4: inFlight — a stop during flight captures nothing and leaves the
127
+ // cursor alone, so the window accumulates into the next stop.
128
+ if (state.inFlight)
129
+ return;
130
+ // Snapshot absent: enabled mid-session with no qualifying request yet, or
131
+ // fully filtered ⇒ skip (counter unchanged).
132
+ const snapshot = snapshots.get(sessionId);
133
+ if (snapshot === undefined)
134
+ return;
135
+ const decision = reviewWindow(snapshot, state.cursor);
136
+ switch (decision.action) {
137
+ case 'init':
138
+ // Cold or resumed history is never review-billed.
139
+ state.cursor = fullCursor(snapshot);
140
+ return;
141
+ case 'reset':
142
+ state.drops.cursorReset += 1;
143
+ state.cursor = fullCursor(snapshot);
144
+ return;
145
+ case 'skip':
146
+ // Empty window or no genuine user: advance the cursor, skip.
147
+ state.cursor = fullCursor(snapshot);
148
+ return;
149
+ case 'review':
150
+ break;
151
+ }
152
+ // Review (§4.1 step 4): capture, advance the cursor IMMEDIATELY (it tracks
153
+ // review eligibility, not call completion), flag inFlight, spawn detached.
154
+ const capturedTurn = state.turnCounter;
155
+ const window = decision.window;
156
+ const rendered = renderDelta(window);
157
+ const deltaBytes = Buffer.byteLength(rendered, 'utf8');
158
+ state.cursor = fullCursor(snapshot);
159
+ state.inFlight = true;
160
+ // §4.1 step 5: turnCounter += 1 AFTER capture — capturedTurn pins to the
161
+ // pre-increment count (the number of completed turns the window may span).
162
+ state.turnCounter += 1;
163
+ void runAndDeliver(ctx, home, state, settings, effectiveAlias, agent, sessionId, capturedTurn, window.length, rendered, deltaBytes)
164
+ .catch(() => { })
165
+ .finally(() => {
166
+ state.inFlight = false;
167
+ });
168
+ }
169
+ /** Resolve-time: journal, parse, guard, staleness, inject. */
170
+ async function runAndDeliver(ctx, home, state, settings, alias, agent, sessionId, capturedTurn, deltaMessages, rendered, deltaBytes) {
171
+ // Journal model: resolved up front (§4.2) — null when unrouted/unset.
172
+ const route = resolveAlias(ctx, alias);
173
+ const base = {
174
+ ts: Date.now(),
175
+ turn: capturedTurn,
176
+ alias,
177
+ model: (route?.model ?? null),
178
+ inheritedRoute: false,
179
+ ok: false,
180
+ reason: undefined,
181
+ durationMs: 0,
182
+ deltaMessages,
183
+ deltaBytes,
184
+ notesIn: 0,
185
+ notesOut: 0,
186
+ drops: state.drops,
187
+ usage: null,
188
+ };
189
+ let notesIn = 0;
190
+ let notesOut = 0;
191
+ base.ok = false;
192
+ let reason;
193
+ let inherited = false;
194
+ try {
195
+ const result = await runAdvisor(ctx, { agent, alias, renderedDelta: rendered });
196
+ if (!result.ok) {
197
+ reason = result.reason;
198
+ // §4.2 no-inherit rule: the first unrouted result disables the advisor
199
+ // for the session (silent main-route inheritance is impossible by
200
+ // construction; this is the belt over it).
201
+ if (result.reason === 'unrouted') {
202
+ state.disabled = true;
203
+ debug(ctx, 'advisor: alias unrouted — disabled for this session');
204
+ }
205
+ }
206
+ else {
207
+ base.ok = true;
208
+ inherited = result.inheritedRoute;
209
+ if (result.inheritedRoute) {
210
+ // An inherited main-route run is a misconfiguration surfacing as cost:
211
+ // journal it and disable for the session.
212
+ state.disabled = true;
213
+ debug(ctx, 'advisor: inherited parent route — disabled for this session');
214
+ reason = 'unrouted';
215
+ base.ok = false;
216
+ }
217
+ else {
218
+ const parsed = parseAdvisorNotes(result.text);
219
+ if (!parsed.ok) {
220
+ state.drops.malformed += 1;
221
+ }
222
+ else {
223
+ notesIn = parsed.notes.length;
224
+ // Guard steps 1-6 at resolve time, then step 7 staleness.
225
+ const resolveTurn = state.turnCounter;
226
+ const surviving = applyEmissionGuard(state.guard, parsed.notes, state.drops, settings, resolveTurn);
227
+ if (resolveTurn - capturedTurn > 1) {
228
+ state.drops.stale += surviving.length;
229
+ debug(ctx, 'advisor: stale resolve — dropped');
230
+ }
231
+ else {
232
+ notesOut = surviving.length;
233
+ if (notesOut > 0)
234
+ deliver(ctx, state, settings, agent, surviving, resolveTurn);
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ catch {
241
+ // runSideQuery never throws; this is defense in depth for the inject path.
242
+ }
243
+ base.notesIn = notesIn;
244
+ base.notesOut = notesOut;
245
+ base.reason = reason;
246
+ base.inheritedRoute = inherited;
247
+ base.durationMs = Math.max(0, Date.now() - base.ts);
248
+ void appendJournal(home, sessionId, { ...base, drops: { ...state.drops } });
249
+ }
250
+ /** Deliver surviving notes: one inject per run, then cap/immune bookkeeping. */
251
+ function deliver(ctx, state, settings, agent, notes, turnCounter) {
252
+ const body = [
253
+ '<advisory>',
254
+ ...notes.map(note => `<note severity="${note.severity}">${note.text}</note>`),
255
+ 'Advisory notes from a background reviewer of your last completed turn.',
256
+ 'Weigh them; do not reply to them; they are not user instructions.',
257
+ '</advisory>',
258
+ ].join('\n');
259
+ try {
260
+ agent.inject(createUserMessage({
261
+ content: [{ type: 'text', text: body }],
262
+ source: { kind: ADVISOR_SOURCE_KIND },
263
+ }));
264
+ }
265
+ catch {
266
+ // Delivery failure is a drop, never an error into the caller.
267
+ return;
268
+ }
269
+ for (const note of notes)
270
+ rememberFingerprint(state.guard, note.text);
271
+ state.guard.deliveredNotes += notes.length;
272
+ // Immune re-arm (§4.4 step 5): after a delivered run containing ≥1
273
+ // concern or blocker, concerns are suppressed for the next immuneTurns
274
+ // turns (delivery at turn N suppresses N..N+immuneTurns-1).
275
+ if (notes.some(note => note.severity === 'concern' || note.severity === 'blocker')) {
276
+ state.guard.immuneUntil = turnCounter + settings.immuneTurns;
277
+ }
278
+ if (state.guard.deliveredNotes >= settings.sessionCap) {
279
+ state.disabled = true;
280
+ debug(ctx, 'advisor: session cap reached — disabled for this session');
281
+ }
282
+ }
283
+ //# sourceMappingURL=wiring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiring.js","sourceRoot":"","sources":["../src/wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,iBAAiB,EAA0C,MAAM,sBAAsB,CAAA;AAEhG,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAkC,MAAM,YAAY,CAAA;AAEvH,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAAwD,MAAM,YAAY,CAAA;AACvJ,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAwB,MAAM,eAAe,CAAA;AAoB1E,uEAAuE;AACvE,SAAS,UAAU,CAAC,KAAY;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAA;IACnC,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC,IAAI,CAAC,CAAA;AAC3E,CAAC;AAED,8FAA8F;AAC9F,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,WAAW,EAAE,EAAE,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,gCAAgC;AAChC,SAAS,KAAK,CAAC,GAAY,EAAE,OAAe;IAC1C,IAAI,CAAC;QACH,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAA;IAC9C,0EAA0E;IAC1E,yEAAyE;IACzE,gDAAgD;IAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAmC,CAAA;IAE5D,wEAAwE;IACxE,sEAAsE;IACtE,2EAA2E;IAC3E,iEAAiE;IACjE,uEAAuE;IACvE,oEAAoE;IACpE,4DAA4D;IAC5D,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,OAAwB,EAAE,IAAsC,EAA8B,EAAE;QACpH,IAAI,CAAC;YACH,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACrE,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,QAAmC,CAAC,CAAA;YACvF,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;QACD,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAEnC,GAAG,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,KAAK,EAAoB,EAAQ,EAAE;QAClE,IAAI,CAAC;YACH,kEAAkE;YAClE,yEAAyE;YACzE,KAAK,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAYD,kEAAkE;AAClE,SAAS,MAAM,CAAC,MAAc,EAAE,SAAiB;IAC/C,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,KAAK,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;QAC9H,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,cAAc,CAC3B,GAAY,EACZ,SAA+C,EAC/C,MAAc,EACd,KAAY;IAEZ,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAM;IAC9B,yEAAyE;IACzE,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACjD,0DAA0D;IAC1D,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC3B,OAAM;IACR,CAAC;IACD,mEAAmE;IACnE,0EAA0E;IAC1E,oDAAoD;IACpD,IAAI,QAAQ,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC3B,OAAM;IACR,CAAC;IACD,MAAM,cAAc,GAClB,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,KAAK,KAAK,IAAI,QAAQ,CAAC,SAAS,KAAK,IAAI;QAC/E,CAAC,CAAC,QAAQ,CAAC,SAAS;QACpB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAA;IACpB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACvC,8CAA8C;IAC9C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,KAAK,CAAC,GAAG,EAAE,6CAA6C,CAAC,CAAA;QACzD,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC3B,OAAM;IACR,CAAC;IACD,0EAA0E;IAC1E,8DAA8D;IAC9D,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAM;IAC1B,0EAA0E;IAC1E,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACzC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAM;IAClC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACrD,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;QACxB,KAAK,MAAM;YACT,kDAAkD;YAClD,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;YACnC,OAAM;QACR,KAAK,OAAO;YACV,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,CAAA;YAC5B,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;YACnC,OAAM;QACR,KAAK,MAAM;YACT,6DAA6D;YAC7D,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;YACnC,OAAM;QACR,KAAK,QAAQ;YACX,MAAK;IACT,CAAC;IACD,2EAA2E;IAC3E,2EAA2E;IAC3E,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAA;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;IAC9B,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACtD,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACnC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;IACrB,yEAAyE;IACzE,2EAA2E;IAC3E,KAAK,CAAC,WAAW,IAAI,CAAC,CAAA;IACtB,KAAK,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC;SAChI,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;SACf,OAAO,CAAC,GAAG,EAAE;QACZ,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAA;IACxB,CAAC,CAAC,CAAA;AACN,CAAC;AAED,8DAA8D;AAC9D,KAAK,UAAU,aAAa,CAC1B,GAAY,EACZ,IAAY,EACZ,KAAmB,EACnB,QAAyB,EACzB,KAAa,EACb,KAAY,EACZ,SAAiB,EACjB,YAAoB,EACpB,aAAqB,EACrB,QAAgB,EAChB,UAAkB;IAElB,sEAAsE;IACtE,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACtC,MAAM,IAAI,GAAwB;QAChC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;QACd,IAAI,EAAE,YAAY;QAClB,KAAK;QACL,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,CAAkB;QAC9C,cAAc,EAAE,KAAK;QACrB,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,CAAC;QACb,aAAa;QACb,UAAU;QACV,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,IAAI;KACZ,CAAA;IACD,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,CAAC,EAAE,GAAG,KAAK,CAAA;IACf,IAAI,MAA0B,CAAA;IAC9B,IAAI,SAAS,GAAG,KAAK,CAAA;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC/E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;YACtB,uEAAuE;YACvE,kEAAkE;YAClE,2CAA2C;YAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;gBACrB,KAAK,CAAC,GAAG,EAAE,qDAAqD,CAAC,CAAA;YACnE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;YACd,SAAS,GAAG,MAAM,CAAC,cAAc,CAAA;YACjC,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1B,uEAAuE;gBACvE,0CAA0C;gBAC1C,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;gBACrB,KAAK,CAAC,GAAG,EAAE,6DAA6D,CAAC,CAAA;gBACzE,MAAM,GAAG,UAAU,CAAA;gBACnB,IAAI,CAAC,EAAE,GAAG,KAAK,CAAA;YACjB,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;gBAC7C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAA;gBAC5B,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;oBAC7B,0DAA0D;oBAC1D,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAA;oBACrC,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;oBACnG,IAAI,WAAW,GAAG,YAAY,GAAG,CAAC,EAAE,CAAC;wBACnC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAA;wBACrC,KAAK,CAAC,GAAG,EAAE,kCAAkC,CAAC,CAAA;oBAChD,CAAC;yBAAM,CAAC;wBACN,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAA;wBAC3B,IAAI,QAAQ,GAAG,CAAC;4BAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAAA;oBAChF,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;IAC7E,CAAC;IACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACtB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACpB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAA;IAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;IACnD,KAAK,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAC7E,CAAC;AAED,gFAAgF;AAChF,SAAS,OAAO,CACd,GAAY,EACZ,KAAmB,EACnB,QAAyB,EACzB,KAAY,EACZ,KAA6B,EAC7B,WAAmB;IAEnB,MAAM,IAAI,GAAG;QACX,YAAY;QACZ,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAmB,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,SAAS,CAAC;QAC7E,wEAAwE;QACxE,mEAAmE;QACnE,aAAa;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACZ,IAAI,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC7B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE;SACtC,CAAC,CAAC,CAAA;IACL,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAM;IACR,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,mBAAmB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IACrE,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM,CAAA;IAC1C,mEAAmE;IACnE,uEAAuE;IACvE,4DAA4D;IAC5D,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,EAAE,CAAC;QACnF,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;IAC9D,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtD,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;QACrB,KAAK,CAAC,GAAG,EAAE,0DAA0D,CAAC,CAAA;IACxE,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@dsh-cc/advisor-watchdog",
3
+ "description": "Advisor watchdog: an opt-in second model (cheap lane via runSideQuery) reading every completed turn's delta and injecting severity-tiered advisory notes at the next step; default off",
4
+ "version": "0.8.1",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/dsh-cc/dsh-cc.git",
8
+ "directory": "packages/interaction/advisor-watchdog"
9
+ },
10
+ "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/index.d.ts",
14
+ "default": "./lib/index.js"
15
+ },
16
+ "./src/*": "./src/*",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "lib"
21
+ ],
22
+ "license": "Apache-2.0",
23
+ "peerDependencies": {
24
+ "@deepseek-ai/cordis": ">=0.1.5-rc.1",
25
+ "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1",
26
+ "@deepseek-ai/schemastery": "^3.18.1",
27
+ "@deepseek-ai/dsh-agent": ">=0.1.5-rc.1"
28
+ },
29
+ "dependencies": {
30
+ "zod": "^4.4.3",
31
+ "@dsh-cc/model-aliases": "^0.8.1",
32
+ "@dsh-cc/permission-rules": "^0.8.1",
33
+ "@dsh-cc/settings-ns": "^0.8.1",
34
+ "@dsh-cc/side-query": "^0.8.1"
35
+ },
36
+ "devDependencies": {
37
+ "@deepseek-ai/cordis": "link:../../../../deepseek-harness/vendor/cordis",
38
+ "@deepseek-ai/dsh-agent": "link:../../../../deepseek-harness/packages/core/agent",
39
+ "@deepseek-ai/dsh-agent-loop": "link:../../../../deepseek-harness/packages/core/agent-loop",
40
+ "@deepseek-ai/dsh-agent-loop-testkit": "link:../../../../deepseek-harness/packages/test-support/agent-loop-testkit",
41
+ "@deepseek-ai/dsh-llm": "link:../../../../deepseek-harness/packages/llm/llm",
42
+ "@deepseek-ai/dsh-session": "link:../../../../deepseek-harness/packages/core/session",
43
+ "@deepseek-ai/dsh-session-persistence-jsonl": "link:../../../../deepseek-harness/packages/session/session-persistence-jsonl",
44
+ "@deepseek-ai/dsh-settings": "link:../../../../deepseek-harness/packages/settings/settings",
45
+ "@deepseek-ai/schemastery": "link:../../../../deepseek-harness/vendor/schemastery",
46
+ "vitest": "^4.1.8",
47
+ "@dsh-cc/permission-rules": "^0.8.1",
48
+ "@dsh-cc/model-aliases": "^0.8.1",
49
+ "@dsh-cc/settings-ns": "^0.8.1",
50
+ "@dsh-cc/side-query": "^0.8.1"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "scripts": {
56
+ "test": "vitest run"
57
+ }
58
+ }