instar 1.3.131 → 1.3.133
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +92 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +10 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +35 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +12 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts +103 -0
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -0
- package/dist/monitoring/AgentWorktreeReaper.js +159 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -0
- package/dist/monitoring/CiFailurePoller.d.ts +1 -7
- package/dist/monitoring/CiFailurePoller.d.ts.map +1 -1
- package/dist/monitoring/CiFailurePoller.js +5 -12
- package/dist/monitoring/CiFailurePoller.js.map +1 -1
- package/dist/monitoring/CorrectionAnalyzer.d.ts +65 -0
- package/dist/monitoring/CorrectionAnalyzer.d.ts.map +1 -0
- package/dist/monitoring/CorrectionAnalyzer.js +78 -0
- package/dist/monitoring/CorrectionAnalyzer.js.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts +130 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.js +249 -0
- package/dist/monitoring/CorrectionCaptureLoop.js.map +1 -0
- package/dist/monitoring/CorrectionLedger.d.ts +149 -0
- package/dist/monitoring/CorrectionLedger.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLedger.js +386 -0
- package/dist/monitoring/CorrectionLedger.js.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts +135 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.js +185 -0
- package/dist/monitoring/CorrectionLoopDriver.js.map +1 -0
- package/dist/monitoring/HumanAsDetectorLog.d.ts +31 -1
- package/dist/monitoring/HumanAsDetectorLog.d.ts.map +1 -1
- package/dist/monitoring/HumanAsDetectorLog.js +70 -0
- package/dist/monitoring/HumanAsDetectorLog.js.map +1 -1
- package/dist/monitoring/agentWorktreeGit.d.ts +43 -0
- package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -0
- package/dist/monitoring/agentWorktreeGit.js +194 -0
- package/dist/monitoring/agentWorktreeGit.js.map +1 -0
- package/dist/monitoring/scrubSecrets.d.ts +23 -0
- package/dist/monitoring/scrubSecrets.d.ts.map +1 -0
- package/dist/monitoring/scrubSecrets.js +41 -0
- package/dist/monitoring/scrubSecrets.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +20 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +8 -3
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +7 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +213 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates/jobs/instar/correction-analyzer.md +32 -0
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.132.md +42 -0
- package/upgrades/1.3.133.md +70 -0
- package/upgrades/side-effects/agent-worktree-reaper.md +96 -0
- package/upgrades/side-effects/correction-preference-learning-sentinel-slice1b.md +79 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CorrectionLoopDriver — the closed self-improvement loop for corrections (spec §3.6/§3.7/§3.8).
|
|
3
|
+
*
|
|
4
|
+
* detect (Layer 0) → capture+distill → CorrectionLedger →
|
|
5
|
+
* gate (CorrectionAnalyzer) → ROUTE (this) → VERIFY (this).
|
|
6
|
+
*
|
|
7
|
+
* The headline safety property — "the loop can never change the agent's policy
|
|
8
|
+
* or mint a proposal on its own" — is enforced BY CONSTRUCTION (spec §3.8). The
|
|
9
|
+
* driver's injected capabilities are EXACTLY:
|
|
10
|
+
* - addAction (open an Evolution Action — a tracked to-do)
|
|
11
|
+
* - createInitiative (open a draft Initiative in needs-user)
|
|
12
|
+
* - feedbackLoopbackPost (POST the agent's OWN /feedback route — traverses
|
|
13
|
+
* anomaly/quality/length guards; never FeedbackManager.submit)
|
|
14
|
+
* - recordPreference (write .instar/preferences.json — explicit-preference
|
|
15
|
+
* + gate-passed + policy-keyword-clean records ONLY)
|
|
16
|
+
* - attentionRoute (route a candidate to the Attention queue for human
|
|
17
|
+
* disposition — inferred prefs + policy-keyword matches)
|
|
18
|
+
*
|
|
19
|
+
* It is given NO ability to mint an EvolutionProposal (the ONLY thing the
|
|
20
|
+
* autonomous auto-implement evaluator acts on) and NO direct write to MEMORY.md
|
|
21
|
+
* / CLAUDE.md / feedback_*.md. So an auto-implemented policy change is
|
|
22
|
+
* unreachable for anything this loop produces, regardless of
|
|
23
|
+
* evolutionApprovalMode. A by-construction test pins ZERO proposals + ZERO
|
|
24
|
+
* memory writes under autonomy ON.
|
|
25
|
+
*
|
|
26
|
+
* `kind` is signal, never authority — it routes a proposal / preferences write /
|
|
27
|
+
* Attention item, never blocks or mutates on its own.
|
|
28
|
+
*/
|
|
29
|
+
import type { CorrectionLedger, CorrectionRecord } from './CorrectionLedger.js';
|
|
30
|
+
import type { CorrectionAnalyzer } from './CorrectionAnalyzer.js';
|
|
31
|
+
export declare function matchesPolicyRelaxation(learning: string): boolean;
|
|
32
|
+
/** The ONLY mutation capabilities the loop is given. Deliberately excludes any
|
|
33
|
+
* proposal-creation path AND any direct memory-file write (the by-construction
|
|
34
|
+
* authority guard, spec §3.8). */
|
|
35
|
+
export interface CorrectionLoopDeps {
|
|
36
|
+
/** Open an Evolution Action (tracked self-improvement to-do). */
|
|
37
|
+
addAction: (opts: {
|
|
38
|
+
title: string;
|
|
39
|
+
description: string;
|
|
40
|
+
priority?: 'critical' | 'high' | 'medium' | 'low';
|
|
41
|
+
source?: string;
|
|
42
|
+
tags?: string[];
|
|
43
|
+
}) => {
|
|
44
|
+
id: string;
|
|
45
|
+
};
|
|
46
|
+
/** Open a draft Initiative in needs-user (a human approves turning it real). */
|
|
47
|
+
createInitiative: (input: {
|
|
48
|
+
id: string;
|
|
49
|
+
title: string;
|
|
50
|
+
description: string;
|
|
51
|
+
phases: {
|
|
52
|
+
name: string;
|
|
53
|
+
status: string;
|
|
54
|
+
}[];
|
|
55
|
+
needsUser: boolean;
|
|
56
|
+
needsUserReason?: string;
|
|
57
|
+
}) => Promise<{
|
|
58
|
+
id: string;
|
|
59
|
+
}>;
|
|
60
|
+
/** POST the agent's OWN /feedback route. Resolves to true when the route
|
|
61
|
+
* accepted (201); false otherwise — including a guard rejection (which is the
|
|
62
|
+
* guard doing its job). NEVER FeedbackManager.submit() directly. */
|
|
63
|
+
feedbackLoopbackPost: (payload: {
|
|
64
|
+
type: string;
|
|
65
|
+
title: string;
|
|
66
|
+
description: string;
|
|
67
|
+
}) => Promise<boolean>;
|
|
68
|
+
/** Write an explicit, gate-passed, policy-keyword-clean preference. */
|
|
69
|
+
recordPreference: (payload: {
|
|
70
|
+
learning: string;
|
|
71
|
+
dedupeKey: string;
|
|
72
|
+
confidence?: number;
|
|
73
|
+
}) => void;
|
|
74
|
+
/** Route a candidate to the Attention queue for human disposition. Resolves to
|
|
75
|
+
* true on delivery. */
|
|
76
|
+
attentionRoute: (item: {
|
|
77
|
+
id: string;
|
|
78
|
+
title: string;
|
|
79
|
+
summary: string;
|
|
80
|
+
priority?: string;
|
|
81
|
+
}) => Promise<boolean>;
|
|
82
|
+
now?: () => number;
|
|
83
|
+
/** Verify-window (preference path), default 7 days. */
|
|
84
|
+
verifyWindowDaysPreference?: number;
|
|
85
|
+
/** Verify-window (infra-gap path), default 14 days. */
|
|
86
|
+
verifyWindowDaysInfraGap?: number;
|
|
87
|
+
/** Max reopens before terminal `inconclusive` (default 2). */
|
|
88
|
+
maxReopens?: number;
|
|
89
|
+
/** Whether to actually POST infra-gap learnings to /feedback (default false —
|
|
90
|
+
* propose-only: queue a tracked Action + the human posts it). */
|
|
91
|
+
autoFeedback?: boolean;
|
|
92
|
+
/** Probe whether the loop-written preference entry still exists on disk
|
|
93
|
+
* (silence ≠ effective; verified requires the application persisted). */
|
|
94
|
+
preferenceStillPresent?: (dedupeKey: string) => boolean;
|
|
95
|
+
}
|
|
96
|
+
export interface RouteResult {
|
|
97
|
+
routed: CorrectionRecord[];
|
|
98
|
+
toFeedback: number;
|
|
99
|
+
toPreferences: number;
|
|
100
|
+
toAttention: number;
|
|
101
|
+
}
|
|
102
|
+
export interface VerifyResult {
|
|
103
|
+
evaluated: CorrectionRecord[];
|
|
104
|
+
}
|
|
105
|
+
export declare class CorrectionLoopDriver {
|
|
106
|
+
private readonly ledger;
|
|
107
|
+
private readonly analyzer;
|
|
108
|
+
private readonly deps;
|
|
109
|
+
constructor(ledger: CorrectionLedger, analyzer: CorrectionAnalyzer, deps: CorrectionLoopDeps);
|
|
110
|
+
private now;
|
|
111
|
+
/**
|
|
112
|
+
* ROUTE step (spec §3.6): for each gate-crossing record, route it by kind:
|
|
113
|
+
* user-preference + policy-keyword-clean → recordPreference()
|
|
114
|
+
* user-preference + policy-keyword-match → Attention (human disposes)
|
|
115
|
+
* infra-gap (autoFeedback ON) → feedbackLoopbackPost()
|
|
116
|
+
* infra-gap (autoFeedback OFF, default) → tracked Action + draft Initiative (propose-only)
|
|
117
|
+
* Then open a verify window + move the record to acted-on. Idempotent: an
|
|
118
|
+
* insight already past `open` is skipped by the analyzer's status:'open' filter.
|
|
119
|
+
*/
|
|
120
|
+
route(): Promise<RouteResult>;
|
|
121
|
+
/**
|
|
122
|
+
* VERIFY step (spec §3.7): for each `acted-on` record whose window has elapsed,
|
|
123
|
+
* decide the outcome keyed on the SAME dedupeKey:
|
|
124
|
+
* - recurrence-after on the SAME dedupeKey → reopen (capped at maxReopens →
|
|
125
|
+
* inconclusive). Keying on dedupeKey (not the coarse kind) prevents a
|
|
126
|
+
* false-reopen from an unrelated learning in the same regex bucket.
|
|
127
|
+
* - SILENCE alone ≠ effective. A preference is `verified` only when (a) the
|
|
128
|
+
* dedupeKey did not recur in the window AND (b) the loop-written preference
|
|
129
|
+
* entry is still present (not human-deleted as wrong). Otherwise inconclusive.
|
|
130
|
+
*/
|
|
131
|
+
runVerification(): VerifyResult;
|
|
132
|
+
/** Whether the dedupeKey logged any occurrence at/after a timestamp (recurrence). */
|
|
133
|
+
private recurredSince;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=CorrectionLoopDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CorrectionLoopDriver.d.ts","sourceRoot":"","sources":["../../src/monitoring/CorrectionLoopDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic policy-keyword filter (spec §3.6, NEW-A / P2). A learning that
|
|
3
|
+
* tries to relax a safety/policy guard does NOT get silently vetoed (a regex
|
|
4
|
+
* never wields blocking authority on its own); it is DOWNGRADED to the Attention
|
|
5
|
+
* queue for one-tap human disposition. Returns true when the learning matches a
|
|
6
|
+
* policy-relaxation pattern.
|
|
7
|
+
*/
|
|
8
|
+
const POLICY_VERB = /\b(ignore|skip|bypass|disable|always allow|pre-?authorize|pre-?approved|no need to confirm|never (ask|prompt|gate|confirm|block))\b/i;
|
|
9
|
+
const POLICY_NOUN = /\b(guard|gate|confirm(ation)?|safety|coherence|block|approval|permission|authoriz)\b/i;
|
|
10
|
+
export function matchesPolicyRelaxation(learning) {
|
|
11
|
+
const s = String(learning);
|
|
12
|
+
return POLICY_VERB.test(s) && POLICY_NOUN.test(s);
|
|
13
|
+
}
|
|
14
|
+
export class CorrectionLoopDriver {
|
|
15
|
+
ledger;
|
|
16
|
+
analyzer;
|
|
17
|
+
deps;
|
|
18
|
+
constructor(ledger, analyzer, deps) {
|
|
19
|
+
this.ledger = ledger;
|
|
20
|
+
this.analyzer = analyzer;
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
}
|
|
23
|
+
now() { return this.deps.now ? this.deps.now() : Date.now(); }
|
|
24
|
+
/**
|
|
25
|
+
* ROUTE step (spec §3.6): for each gate-crossing record, route it by kind:
|
|
26
|
+
* user-preference + policy-keyword-clean → recordPreference()
|
|
27
|
+
* user-preference + policy-keyword-match → Attention (human disposes)
|
|
28
|
+
* infra-gap (autoFeedback ON) → feedbackLoopbackPost()
|
|
29
|
+
* infra-gap (autoFeedback OFF, default) → tracked Action + draft Initiative (propose-only)
|
|
30
|
+
* Then open a verify window + move the record to acted-on. Idempotent: an
|
|
31
|
+
* insight already past `open` is skipped by the analyzer's status:'open' filter.
|
|
32
|
+
*/
|
|
33
|
+
async route() {
|
|
34
|
+
const result = { routed: [], toFeedback: 0, toPreferences: 0, toAttention: 0 };
|
|
35
|
+
const { crossed } = this.analyzer.analyze();
|
|
36
|
+
for (const verdict of crossed) {
|
|
37
|
+
const rec = verdict.record;
|
|
38
|
+
let routedVia = null;
|
|
39
|
+
if (rec.kind === 'user-preference') {
|
|
40
|
+
if (matchesPolicyRelaxation(rec.learning)) {
|
|
41
|
+
// P2: a policy-relaxation learning NEVER auto-records — route to a human.
|
|
42
|
+
const ok = await this.deps.attentionRoute({
|
|
43
|
+
id: `correction-policy:${rec.dedupeKey.slice(0, 40)}`,
|
|
44
|
+
title: 'Learned preference needs your approval (policy-relaxation)',
|
|
45
|
+
summary: rec.scrubbedSummary,
|
|
46
|
+
priority: 'medium',
|
|
47
|
+
});
|
|
48
|
+
routedVia = 'attention';
|
|
49
|
+
if (ok)
|
|
50
|
+
result.toAttention++;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.deps.recordPreference({
|
|
54
|
+
learning: rec.learning,
|
|
55
|
+
dedupeKey: rec.dedupeKey,
|
|
56
|
+
confidence: rec.llmConfidence,
|
|
57
|
+
});
|
|
58
|
+
routedVia = 'recordPreference';
|
|
59
|
+
result.toPreferences++;
|
|
60
|
+
// Parallel /learn proposal is queued as a tracked Action (documentation,
|
|
61
|
+
// not the closing link). Bounded — no proposal minted.
|
|
62
|
+
this.deps.addAction({
|
|
63
|
+
title: `Durable-memory candidate: ${rec.scrubbedSummary}`,
|
|
64
|
+
description: `The correction loop recorded this as a preference (${rec.dedupeKey}). Consider converting to a durable feedback_* memory entry. This is documentation only — the preferences write already closed the loop.`,
|
|
65
|
+
priority: 'low',
|
|
66
|
+
source: 'correction-preference-loop',
|
|
67
|
+
tags: ['correction-learning', 'preference'],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (rec.kind === 'infra-gap') {
|
|
72
|
+
if (this.deps.autoFeedback) {
|
|
73
|
+
// Loopback POST through the real route guards (anomaly/quality/length).
|
|
74
|
+
// The description carries ONLY the scrubbed summary, never raw learning.
|
|
75
|
+
const ok = await this.deps.feedbackLoopbackPost({
|
|
76
|
+
type: 'improvement',
|
|
77
|
+
title: `Recurring friction: ${rec.scrubbedSummary.slice(0, 120)}`,
|
|
78
|
+
description: rec.scrubbedSummary,
|
|
79
|
+
});
|
|
80
|
+
routedVia = 'feedback';
|
|
81
|
+
if (ok)
|
|
82
|
+
result.toFeedback++;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Propose-only default: a tracked Action + a draft Initiative; the
|
|
86
|
+
// human posts the feedback. No proposal minted.
|
|
87
|
+
const slug = rec.dedupeKey.replace(/[^a-z0-9]+/gi, '-').toLowerCase().slice(0, 50);
|
|
88
|
+
this.deps.addAction({
|
|
89
|
+
title: `Infra-gap proposal: ${rec.scrubbedSummary}`,
|
|
90
|
+
description: `Recurring friction (${verdict.qualifyingOccurrences} support / ${verdict.distinctDays} days). Consider filing /feedback so Dawn can close the gap fleet-wide. Record ${rec.id}.`,
|
|
91
|
+
priority: 'medium',
|
|
92
|
+
source: 'correction-preference-loop',
|
|
93
|
+
tags: ['correction-learning', 'infra-gap'],
|
|
94
|
+
});
|
|
95
|
+
await this.deps.createInitiative({
|
|
96
|
+
id: `correction-infra-gap-${slug}`,
|
|
97
|
+
title: `Infra-gap: ${rec.scrubbedSummary.slice(0, 80)}`,
|
|
98
|
+
description: `The Correction & Preference Learning Sentinel detected a recurring infra-gap (record ${rec.id}). Approve to file /feedback (Rising Tide) so it helps every agent.`,
|
|
99
|
+
phases: [{ name: 'Approve + file /feedback', status: 'pending' }],
|
|
100
|
+
needsUser: true,
|
|
101
|
+
needsUserReason: 'Recurring infra-gap correction; human approval required before fleet-wide feedback.',
|
|
102
|
+
});
|
|
103
|
+
routedVia = 'feedback';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!routedVia)
|
|
107
|
+
continue;
|
|
108
|
+
// Open the verify window + move to acted-on.
|
|
109
|
+
const windowDays = rec.kind === 'user-preference'
|
|
110
|
+
? (this.deps.verifyWindowDaysPreference ?? 7)
|
|
111
|
+
: (this.deps.verifyWindowDaysInfraGap ?? 14);
|
|
112
|
+
const start = new Date(this.now()).toISOString();
|
|
113
|
+
const end = new Date(this.now() + windowDays * 86400_000).toISOString();
|
|
114
|
+
const res = this.ledger.update(rec.id, { status: 'acted-on', routedVia, verifyWindowStart: start, verifyWindowEnd: end }, rec.version);
|
|
115
|
+
if (res.ok)
|
|
116
|
+
result.routed.push(res.record);
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* VERIFY step (spec §3.7): for each `acted-on` record whose window has elapsed,
|
|
122
|
+
* decide the outcome keyed on the SAME dedupeKey:
|
|
123
|
+
* - recurrence-after on the SAME dedupeKey → reopen (capped at maxReopens →
|
|
124
|
+
* inconclusive). Keying on dedupeKey (not the coarse kind) prevents a
|
|
125
|
+
* false-reopen from an unrelated learning in the same regex bucket.
|
|
126
|
+
* - SILENCE alone ≠ effective. A preference is `verified` only when (a) the
|
|
127
|
+
* dedupeKey did not recur in the window AND (b) the loop-written preference
|
|
128
|
+
* entry is still present (not human-deleted as wrong). Otherwise inconclusive.
|
|
129
|
+
*/
|
|
130
|
+
runVerification() {
|
|
131
|
+
const evaluated = [];
|
|
132
|
+
const maxReopens = this.deps.maxReopens ?? 2;
|
|
133
|
+
for (const rec of this.ledger.list({ status: 'acted-on', limit: 1000 })) {
|
|
134
|
+
if (!rec.verifyWindowEnd || this.now() < Date.parse(rec.verifyWindowEnd))
|
|
135
|
+
continue;
|
|
136
|
+
if (!rec.verifyWindowStart)
|
|
137
|
+
continue;
|
|
138
|
+
// Did the dedupeKey recur within the verify window? A recurrence shows up
|
|
139
|
+
// as occurrences logged after the window opened.
|
|
140
|
+
const windowStartMs = Date.parse(rec.verifyWindowStart);
|
|
141
|
+
const recurred = this.recurredSince(rec.dedupeKey, windowStartMs);
|
|
142
|
+
let next;
|
|
143
|
+
if (recurred) {
|
|
144
|
+
if (rec.reopenCount >= maxReopens) {
|
|
145
|
+
next = { status: 'inconclusive' };
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const windowDays = rec.kind === 'user-preference'
|
|
149
|
+
? (this.deps.verifyWindowDaysPreference ?? 7)
|
|
150
|
+
: (this.deps.verifyWindowDaysInfraGap ?? 14);
|
|
151
|
+
const end = new Date(this.now() + windowDays * 86400_000).toISOString();
|
|
152
|
+
next = { status: 'reopened', reopenCount: rec.reopenCount + 1, verifyWindowEnd: end };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else if (rec.kind === 'user-preference') {
|
|
156
|
+
// Silence ≠ effective. Verified ONLY if the application persisted.
|
|
157
|
+
const persisted = this.deps.preferenceStillPresent
|
|
158
|
+
? this.deps.preferenceStillPresent(rec.dedupeKey)
|
|
159
|
+
: false;
|
|
160
|
+
next = persisted ? { status: 'verified' } : { status: 'inconclusive' };
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// infra-gap fix is cross-org (Dawn ships it). Slice 1 marks silence-only
|
|
164
|
+
// as inconclusive — the verified correlation lands in Slice 2.
|
|
165
|
+
next = { status: 'inconclusive' };
|
|
166
|
+
}
|
|
167
|
+
const res = this.ledger.update(rec.id, next, rec.version);
|
|
168
|
+
if (res.ok)
|
|
169
|
+
evaluated.push(res.record);
|
|
170
|
+
}
|
|
171
|
+
return { evaluated };
|
|
172
|
+
}
|
|
173
|
+
/** Whether the dedupeKey logged any occurrence at/after a timestamp (recurrence). */
|
|
174
|
+
recurredSince(dedupeKey, sinceMs) {
|
|
175
|
+
// The ledger only exposes day-bucketed distinct counts + the record's own
|
|
176
|
+
// detectedAt. A recurrence advances the record's detected_at (the upsert sets
|
|
177
|
+
// detected_at = excluded.detected_at), so a recurrence-after-window-open is
|
|
178
|
+
// detectable as the record's current detectedAt being >= window start.
|
|
179
|
+
const rec = this.ledger.getByDedupeKey(dedupeKey);
|
|
180
|
+
if (!rec)
|
|
181
|
+
return false;
|
|
182
|
+
return Date.parse(rec.detectedAt) >= sinceMs && rec.occurrenceCount > 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=CorrectionLoopDriver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CorrectionLoopDriver.js","sourceRoot":"","sources":["../../src/monitoring/CorrectionLoopDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,7 +46,19 @@ export interface HumanDetectorSignal {
|
|
|
46
46
|
/** Short preview of the human's message (truncated) */
|
|
47
47
|
messagePreview: string;
|
|
48
48
|
}
|
|
49
|
-
export type HumanDetectorCategory = 'factual-correction' | 'staleness' | 'contradiction' | 'source-of-truth-drift' | 'repeat-ask' | 'meta-failure';
|
|
49
|
+
export type HumanDetectorCategory = 'factual-correction' | 'staleness' | 'contradiction' | 'source-of-truth-drift' | 'repeat-ask' | 'meta-failure' | 'preference' | 'frustration';
|
|
50
|
+
/**
|
|
51
|
+
* Categories that feed the Correction & Preference Learning Sentinel rather
|
|
52
|
+
* than the guardian-failure heat map. They are tagged here (single source of
|
|
53
|
+
* truth) and excluded from {@link HumanAsDetectorLog.summarizeByLayer}. The
|
|
54
|
+
* correction loop keys on these to decide whether a message is a learning
|
|
55
|
+
* candidate. Spec §3.2.
|
|
56
|
+
*/
|
|
57
|
+
export declare const LEARNING_ONLY_CATEGORIES: ReadonlySet<HumanDetectorCategory>;
|
|
58
|
+
/** Deterministic-weight at/above which a learning signal is "full confidence"
|
|
59
|
+
* for the analyzer's code-determined provenance filter (spec §3.5). A lone
|
|
60
|
+
* weak rule (weight < this) surfaces but never alone admits a record. */
|
|
61
|
+
export declare const LEARNING_DETERMINISTIC_THRESHOLD = 3;
|
|
50
62
|
export declare class HumanAsDetectorLog {
|
|
51
63
|
private static instance;
|
|
52
64
|
private stateDir;
|
|
@@ -72,6 +84,13 @@ export declare class HumanAsDetectorLog {
|
|
|
72
84
|
suspectedFailedLayer: string;
|
|
73
85
|
confidence: 'low' | 'medium' | 'high';
|
|
74
86
|
matchedSignals: string[];
|
|
87
|
+
/** Total Layer-0 weight — the CODE-determined provenance the correction
|
|
88
|
+
* analyzer keys on (spec §3.5). Stable across phrasings of the same rule. */
|
|
89
|
+
deterministicWeight: number;
|
|
90
|
+
/** When the top signal is a learning-only family (preference|frustration),
|
|
91
|
+
* this is that category; null otherwise. The correction loop reads this to
|
|
92
|
+
* decide whether a message is a learning candidate (spec §3.2). */
|
|
93
|
+
learningKind: 'preference' | 'frustration' | null;
|
|
75
94
|
} | null;
|
|
76
95
|
/**
|
|
77
96
|
* Observe an inbound human message. If it looks like a coherence-break
|
|
@@ -86,6 +105,17 @@ export declare class HumanAsDetectorLog {
|
|
|
86
105
|
}): HumanDetectorSignal | null;
|
|
87
106
|
/** Recent in-memory signals (for health checks / summary endpoint). */
|
|
88
107
|
getRecent(): HumanDetectorSignal[];
|
|
108
|
+
private driftSampled;
|
|
109
|
+
private driftMismatches;
|
|
110
|
+
/** Record one drift-canary sample outcome. `mismatch` = the LLM judged the
|
|
111
|
+
* un-classified message to actually be a correction (a regex miss). */
|
|
112
|
+
recordDriftSample(mismatch: boolean): void;
|
|
113
|
+
/** Drift-canary counters (sampled / mismatches / miss-rate). Read-only. */
|
|
114
|
+
getDriftCanary(): {
|
|
115
|
+
sampled: number;
|
|
116
|
+
mismatches: number;
|
|
117
|
+
missRate: number;
|
|
118
|
+
};
|
|
89
119
|
/**
|
|
90
120
|
* Summarize signals grouped by suspected failed layer — the heat map of
|
|
91
121
|
* "where the human is doing the system's job."
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HumanAsDetectorLog.d.ts","sourceRoot":"","sources":["../../src/monitoring/HumanAsDetectorLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,qEAAqE;IACrE,QAAQ,EAAE,qBAAqB,CAAC;IAChC,oEAAoE;IACpE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,+DAA+D;IAC/D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,qBAAqB,GAC7B,oBAAoB,GACpB,WAAW,GACX,eAAe,GACf,uBAAuB,GACvB,YAAY,GACZ,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"HumanAsDetectorLog.d.ts","sourceRoot":"","sources":["../../src/monitoring/HumanAsDetectorLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,19 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import fs from 'node:fs';
|
|
29
29
|
import path from 'node:path';
|
|
30
|
+
/**
|
|
31
|
+
* Categories that feed the Correction & Preference Learning Sentinel rather
|
|
32
|
+
* than the guardian-failure heat map. They are tagged here (single source of
|
|
33
|
+
* truth) and excluded from {@link HumanAsDetectorLog.summarizeByLayer}. The
|
|
34
|
+
* correction loop keys on these to decide whether a message is a learning
|
|
35
|
+
* candidate. Spec §3.2.
|
|
36
|
+
*/
|
|
37
|
+
export const LEARNING_ONLY_CATEGORIES = new Set([
|
|
38
|
+
'preference',
|
|
39
|
+
'frustration',
|
|
40
|
+
]);
|
|
41
|
+
/** Suspected-layer sentinel value for learning-only signals (never a real guardian). */
|
|
42
|
+
const LEARNING_ONLY_LAYER = 'n/a (correction-learning signal — not a guardian failure)';
|
|
30
43
|
// Conservative signal set — biased toward precision over recall. A missed
|
|
31
44
|
// signal is a lost data point; a false positive pollutes the heat map.
|
|
32
45
|
const SIGNAL_RULES = [
|
|
@@ -40,7 +53,32 @@ const SIGNAL_RULES = [
|
|
|
40
53
|
{ pattern: /\bwhy (didn'?t|did no|wasn'?t).*(catch|caught|detect|flag|notice)\b/, category: 'meta-failure', suspectedLayer: 'guardian coverage (no owner)', weight: 3, label: 'why not caught' },
|
|
41
54
|
{ pattern: /\bactually,?\s/, category: 'factual-correction', suspectedLayer: 'CoherenceGate / output-sanity', weight: 1, label: 'actually,' },
|
|
42
55
|
{ pattern: /\bthat'?s not (what|how)\b/, category: 'factual-correction', suspectedLayer: 'CoherenceGate / output-sanity', weight: 2, label: "that's not what/how" },
|
|
56
|
+
// ── Correction & Preference Learning Sentinel (Slice 1b, spec §3.2) ──
|
|
57
|
+
// Distinctly-tagged signal families. suspectedLayer is the LEARNING_ONLY
|
|
58
|
+
// sentinel so summarizeByLayer() (the guardian-failure heat map) excludes
|
|
59
|
+
// them. Strong (weight ≥3) phrasings cross the deterministic-provenance
|
|
60
|
+
// threshold the analyzer keys on; weak ones still surface to the loop but
|
|
61
|
+
// never alone admit a record to the recurrence gate.
|
|
62
|
+
// preference family:
|
|
63
|
+
{ pattern: /\bfrom now on\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'from now on' },
|
|
64
|
+
{ pattern: /\b(please )?always\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 2, label: 'always' },
|
|
65
|
+
// "i prefer", "i'd rather", "i would rather" — note "i'd" has no space.
|
|
66
|
+
{ pattern: /\b(i prefer|i'?d rather|i would rather)\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'I prefer / I’d rather' },
|
|
67
|
+
{ pattern: /\bdon'?t (use|ask|do|send|give)\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 2, label: "don't X" },
|
|
68
|
+
{ pattern: /\b(please )?(just )?keep it\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 2, label: 'keep it' },
|
|
69
|
+
{ pattern: /\bno (need to|more)\b/, category: 'preference', suspectedLayer: LEARNING_ONLY_LAYER, weight: 1, label: 'no need to / no more' },
|
|
70
|
+
// frustration family — "you keep" requires a following gerund/verb so a
|
|
71
|
+
// benign "you keep it plain" is NOT misread as frustration.
|
|
72
|
+
{ pattern: /\byou keep (asking|doing|saying|telling|sending|giving|making|getting|\w+ing)\b/, category: 'frustration', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'you keep …ing' },
|
|
73
|
+
{ pattern: /\bevery (time|session)\b/, category: 'frustration', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'every time/session' },
|
|
74
|
+
{ pattern: /\bi keep having to\b/, category: 'frustration', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'I keep having to' },
|
|
75
|
+
{ pattern: /\bstop asking me\b/, category: 'frustration', suspectedLayer: LEARNING_ONLY_LAYER, weight: 3, label: 'stop asking me' },
|
|
76
|
+
{ pattern: /\bagain\?(\s|$)/, category: 'frustration', suspectedLayer: LEARNING_ONLY_LAYER, weight: 2, label: 'again?' },
|
|
43
77
|
];
|
|
78
|
+
/** Deterministic-weight at/above which a learning signal is "full confidence"
|
|
79
|
+
* for the analyzer's code-determined provenance filter (spec §3.5). A lone
|
|
80
|
+
* weak rule (weight < this) surfaces but never alone admits a record. */
|
|
81
|
+
export const LEARNING_DETERMINISTIC_THRESHOLD = 3;
|
|
44
82
|
const PREVIEW_MAX = 220;
|
|
45
83
|
export class HumanAsDetectorLog {
|
|
46
84
|
static instance = null;
|
|
@@ -91,11 +129,14 @@ export class HumanAsDetectorLog {
|
|
|
91
129
|
if (totalWeight < 2)
|
|
92
130
|
return null;
|
|
93
131
|
const confidence = totalWeight >= 5 ? 'high' : totalWeight >= 3 ? 'medium' : 'low';
|
|
132
|
+
const learningKind = top.category === 'preference' || top.category === 'frustration' ? top.category : null;
|
|
94
133
|
return {
|
|
95
134
|
category: top.category,
|
|
96
135
|
suspectedFailedLayer: top.suspectedLayer,
|
|
97
136
|
confidence,
|
|
98
137
|
matchedSignals: matched.map((r) => r.label),
|
|
138
|
+
deterministicWeight: totalWeight,
|
|
139
|
+
learningKind,
|
|
99
140
|
};
|
|
100
141
|
}
|
|
101
142
|
/**
|
|
@@ -137,6 +178,29 @@ export class HumanAsDetectorLog {
|
|
|
137
178
|
getRecent() {
|
|
138
179
|
return [...this.recent];
|
|
139
180
|
}
|
|
181
|
+
// ── Drift canary (spec §3.2) ───────────────────────────────────────
|
|
182
|
+
// A small in-memory counter: when the correction loop's drift canary samples
|
|
183
|
+
// an UN-classified message through the LLM and the LLM thinks it WAS a
|
|
184
|
+
// correction, that is a regex-recall miss — recorded here so the broadened
|
|
185
|
+
// Layer-0 rule set's recall drift is observable over time without persisting
|
|
186
|
+
// any raw text. Metadata-only; never serialized into /health by default.
|
|
187
|
+
driftSampled = 0;
|
|
188
|
+
driftMismatches = 0;
|
|
189
|
+
/** Record one drift-canary sample outcome. `mismatch` = the LLM judged the
|
|
190
|
+
* un-classified message to actually be a correction (a regex miss). */
|
|
191
|
+
recordDriftSample(mismatch) {
|
|
192
|
+
this.driftSampled += 1;
|
|
193
|
+
if (mismatch)
|
|
194
|
+
this.driftMismatches += 1;
|
|
195
|
+
}
|
|
196
|
+
/** Drift-canary counters (sampled / mismatches / miss-rate). Read-only. */
|
|
197
|
+
getDriftCanary() {
|
|
198
|
+
return {
|
|
199
|
+
sampled: this.driftSampled,
|
|
200
|
+
mismatches: this.driftMismatches,
|
|
201
|
+
missRate: this.driftSampled > 0 ? this.driftMismatches / this.driftSampled : 0,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
140
204
|
/**
|
|
141
205
|
* Summarize signals grouped by suspected failed layer — the heat map of
|
|
142
206
|
* "where the human is doing the system's job."
|
|
@@ -144,6 +208,12 @@ export class HumanAsDetectorLog {
|
|
|
144
208
|
summarizeByLayer() {
|
|
145
209
|
const byLayer = new Map();
|
|
146
210
|
for (const s of this.recent) {
|
|
211
|
+
// Correction & Preference Learning Sentinel (spec §3.2): preference /
|
|
212
|
+
// frustration signals feed the correction loop, NOT the guardian-failure
|
|
213
|
+
// heat map. Excluding them here keeps the heat map's precision contract
|
|
214
|
+
// intact (a unit test pins that they don't change these counts).
|
|
215
|
+
if (LEARNING_ONLY_CATEGORIES.has(s.category))
|
|
216
|
+
continue;
|
|
147
217
|
const entry = byLayer.get(s.suspectedFailedLayer) ?? { count: 0, categories: new Set() };
|
|
148
218
|
entry.count++;
|
|
149
219
|
entry.categories.add(s.category);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HumanAsDetectorLog.js","sourceRoot":"","sources":["../../src/monitoring/HumanAsDetectorLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"HumanAsDetectorLog.js","sourceRoot":"","sources":["../../src/monitoring/HumanAsDetectorLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-backed signal sources for the AgentWorktreeReaper. Kept separate from the
|
|
3
|
+
* classifier so the reaper stays unit-testable with fakes; the merged-detection
|
|
4
|
+
* is itself a standalone, fake-git-testable function.
|
|
5
|
+
*
|
|
6
|
+
* All queries are read-only (SafeGitExecutor.readSync). The single destructive
|
|
7
|
+
* op — `git worktree remove` — goes through SafeGitExecutor.execSync.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentWorktreeReaperDeps } from './AgentWorktreeReaper.js';
|
|
10
|
+
/** Read-only git executor signature (injected so this module is testable). */
|
|
11
|
+
export type ReadGit = (args: string[], cwd: string) => string;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the canonical default branch ref that exists locally, preferring the
|
|
14
|
+
* upstream remote. Returns null when none resolve (→ callers treat merged as
|
|
15
|
+
* unknown and KEEP).
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveBaseRef(readGit: ReadGit, repo: string): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* True when EVERY commit unique to `branchSha` already has an equivalent patch
|
|
20
|
+
* in `baseRef` — i.e. the branch's content is in the default branch. Uses
|
|
21
|
+
* `git cherry` (patch-id equivalence), which catches fast-forward, merge-commit,
|
|
22
|
+
* rebased, and single-commit-squash merges. A multi-commit squash-merge is NOT
|
|
23
|
+
* detected (its commits' individual patch-ids differ from the squashed commit) →
|
|
24
|
+
* reported NOT merged → KEPT. Conservative by design: it never false-positives
|
|
25
|
+
* "merged", so the reaper never deletes unmerged work.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isBranchMerged(readGit: ReadGit, repo: string, baseRef: string, branchSha: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Build the production git/fs-backed deps for the AgentWorktreeReaper.
|
|
30
|
+
* `worktreesDir` bounds which `git worktree list` entries are considered (the
|
|
31
|
+
* agent's `.worktrees/`); the main checkout and any out-of-tree worktrees are
|
|
32
|
+
* excluded.
|
|
33
|
+
*/
|
|
34
|
+
export declare function makeAgentWorktreeReaperDeps(opts: {
|
|
35
|
+
instarRepo: string;
|
|
36
|
+
worktreesDir: string;
|
|
37
|
+
readGit?: ReadGit;
|
|
38
|
+
/** Override the process-cwd scanner (testing). Returns the set of worktree
|
|
39
|
+
* ROOT paths that currently have a live process cwd inside them. */
|
|
40
|
+
cwdRoots?: () => Set<string>;
|
|
41
|
+
now?: () => number;
|
|
42
|
+
}): AgentWorktreeReaperDeps;
|
|
43
|
+
//# sourceMappingURL=agentWorktreeGit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentWorktreeGit.d.ts","sourceRoot":"","sources":["../../src/monitoring/agentWorktreeGit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,uBAAuB,EAAgB,MAAM,0BAA0B,CAAC;AAEtF,8EAA8E;AAC9E,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAK9D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAU1G;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;yEACqE;IACrE,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,uBAAuB,CAoG1B"}
|