instar 1.2.37 → 1.2.39
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 +19 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/TopicIntent.d.ts +162 -0
- package/dist/core/TopicIntent.d.ts.map +1 -0
- package/dist/core/TopicIntent.js +355 -0
- package/dist/core/TopicIntent.js.map +1 -0
- package/dist/core/TopicIntentArcCheck.d.ts +101 -0
- package/dist/core/TopicIntentArcCheck.d.ts.map +1 -0
- package/dist/core/TopicIntentArcCheck.js +146 -0
- package/dist/core/TopicIntentArcCheck.js.map +1 -0
- package/dist/core/TopicIntentBriefing.d.ts +44 -0
- package/dist/core/TopicIntentBriefing.d.ts.map +1 -0
- package/dist/core/TopicIntentBriefing.js +88 -0
- package/dist/core/TopicIntentBriefing.js.map +1 -0
- package/dist/core/TopicIntentExtractor.d.ts +90 -0
- package/dist/core/TopicIntentExtractor.d.ts.map +1 -0
- package/dist/core/TopicIntentExtractor.js +153 -0
- package/dist/core/TopicIntentExtractor.js.map +1 -0
- package/dist/core/TopicIntentPendingConfirm.d.ts +96 -0
- package/dist/core/TopicIntentPendingConfirm.d.ts.map +1 -0
- package/dist/core/TopicIntentPendingConfirm.js +223 -0
- package/dist/core/TopicIntentPendingConfirm.js.map +1 -0
- package/dist/messaging/TelegramAdapter.d.ts +45 -0
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +52 -0
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/server/AgentServer.d.ts +3 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +10 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/topicIntentRoutes.d.ts +27 -0
- package/dist/server/topicIntentRoutes.d.ts.map +1 -0
- package/dist/server/topicIntentRoutes.js +189 -0
- package/dist/server/topicIntentRoutes.js.map +1 -0
- package/dist/tunnel/TunnelManager.d.ts +32 -1
- package/dist/tunnel/TunnelManager.d.ts.map +1 -1
- package/dist/tunnel/TunnelManager.js +36 -0
- package/dist/tunnel/TunnelManager.js.map +1 -1
- package/dist/tunnel/TunnelNotifier.d.ts +28 -0
- package/dist/tunnel/TunnelNotifier.d.ts.map +1 -1
- package/dist/tunnel/TunnelNotifier.js +38 -4
- package/dist/tunnel/TunnelNotifier.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +4 -4
- package/src/templates/hooks/telegram-topic-context.sh +19 -0
- package/upgrades/1.2.38.md +103 -0
- package/upgrades/1.2.39.md +54 -0
- package/upgrades/side-effects/owner-dm-channel.md +152 -0
- package/upgrades/side-effects/topic-intent-layer.md +86 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TopicIntent — per-topic semantic state tracking via continuous confidence.
|
|
3
|
+
*
|
|
4
|
+
* Layer 1 of the Topic Intent Layer spec (v14 CLEAN, approved 2026-05-22).
|
|
5
|
+
* See docs/specs/topic-intent-layer.md.
|
|
6
|
+
*
|
|
7
|
+
* Tracks candidate facts and decisions extracted from conversation. Each
|
|
8
|
+
* EstablishedRef accumulates evidence over multi-turn exchange; confidence
|
|
9
|
+
* is computed on read as a deterministic projection over the append-only
|
|
10
|
+
* event log.
|
|
11
|
+
*
|
|
12
|
+
* Framework-agnostic: pure JSON persistence, pure math projection. Reachable
|
|
13
|
+
* from Claude Code and Codex sessions alike.
|
|
14
|
+
*
|
|
15
|
+
* Storage: {stateDir}/topic-intent/<topicId>.json
|
|
16
|
+
*/
|
|
17
|
+
export type RefKind = 'fact' | 'decision';
|
|
18
|
+
export type RefStatus = 'live' | 'conflicted';
|
|
19
|
+
export type EvidenceKind = 'extract-user' | 'extract-agent' | 'user-reref' | 'agent-reref' | 'user-affirm' | 'pending-confirm-positive' | 'pending-confirm-negative' | 'contradiction' | 'conflict-mark' | 'sharpen-retry-issued';
|
|
20
|
+
export interface EvidenceEvent {
|
|
21
|
+
eventId: string;
|
|
22
|
+
refId: string;
|
|
23
|
+
kind: EvidenceKind;
|
|
24
|
+
sourceMessageId: string;
|
|
25
|
+
userAuthored: boolean;
|
|
26
|
+
at: string;
|
|
27
|
+
delta: number;
|
|
28
|
+
meta?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export interface EstablishedRef {
|
|
31
|
+
refId: string;
|
|
32
|
+
arcId: string;
|
|
33
|
+
topicId: number;
|
|
34
|
+
kind: RefKind;
|
|
35
|
+
text: string;
|
|
36
|
+
confidence: number;
|
|
37
|
+
evidence: EvidenceEvent[];
|
|
38
|
+
lastReinforcedAt: string;
|
|
39
|
+
status: RefStatus;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
updatedAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface PendingConfirmation {
|
|
44
|
+
pendingId: string;
|
|
45
|
+
topicId: number;
|
|
46
|
+
arcId: string;
|
|
47
|
+
refId: string;
|
|
48
|
+
propositionText: string;
|
|
49
|
+
questionText: string;
|
|
50
|
+
sentAtTurn: number;
|
|
51
|
+
sentAtTime: string;
|
|
52
|
+
ttl: {
|
|
53
|
+
turns: number;
|
|
54
|
+
hours: number;
|
|
55
|
+
};
|
|
56
|
+
retries: number;
|
|
57
|
+
maxRetries: number;
|
|
58
|
+
status: 'pending' | 'answered' | 'expired' | 'abandoned';
|
|
59
|
+
queuedAtTime?: string;
|
|
60
|
+
dequeuedAtTime?: string;
|
|
61
|
+
answeredAtTime?: string;
|
|
62
|
+
answerVerdict?: 'positive' | 'negative' | 'ambiguous' | 'non-responsive';
|
|
63
|
+
}
|
|
64
|
+
export interface TopicIntentFile {
|
|
65
|
+
topicId: number;
|
|
66
|
+
refs: Record<string, EstablishedRef>;
|
|
67
|
+
pending: {
|
|
68
|
+
outstanding: PendingConfirmation | null;
|
|
69
|
+
queue: PendingConfirmation[];
|
|
70
|
+
};
|
|
71
|
+
telemetry: TelemetryCounters;
|
|
72
|
+
schemaVersion: 1;
|
|
73
|
+
}
|
|
74
|
+
export interface TelemetryCounters {
|
|
75
|
+
extraction_total: Record<string, number>;
|
|
76
|
+
evidence_event_total: Record<string, number>;
|
|
77
|
+
confidence_clamp_authority_total: number;
|
|
78
|
+
pending_confirm_created_total: number;
|
|
79
|
+
pending_confirm_queue_dropped_total: number;
|
|
80
|
+
pending_confirm_abandoned_total: number;
|
|
81
|
+
pending_confirm_expired_total: number;
|
|
82
|
+
pending_confirm_answered_total: Record<string, number>;
|
|
83
|
+
}
|
|
84
|
+
export declare const SIGNAL_DELTA: Record<EvidenceKind, number>;
|
|
85
|
+
export declare const USER_AUTHORED_BY_DEFAULT: Record<EvidenceKind, boolean>;
|
|
86
|
+
export interface ProjectionResult {
|
|
87
|
+
confidence: number;
|
|
88
|
+
tier: 'observation' | 'tentative' | 'authoritative';
|
|
89
|
+
authorityClampApplied: boolean;
|
|
90
|
+
decayApplied: number;
|
|
91
|
+
evidenceCount: number;
|
|
92
|
+
userAuthoredEpisodes: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Compute the confidence projection for a single EstablishedRef from its
|
|
96
|
+
* evidence array. Pure function — no I/O, no state, fully deterministic.
|
|
97
|
+
*
|
|
98
|
+
* Order of operations:
|
|
99
|
+
* 1. Per-message dedup by (refId, sourceMessageId): on collision, keep the
|
|
100
|
+
* single largest applicable delta. (Multiple signals from the same user
|
|
101
|
+
* message about the same refId count as ONE episode.)
|
|
102
|
+
* 2. Apply signal-specific caps (user-reref cumulative <= +0.30, etc.)
|
|
103
|
+
* 3. Apply affirmation caps (per-refId per 24h, per single user message).
|
|
104
|
+
* 4. Sum applicable deltas (with caps).
|
|
105
|
+
* 5. Apply time decay if (now - lastReinforcedAt) > 30 days.
|
|
106
|
+
* 6. Authority hard clamp: if would-be >= 0.7 and no qualifying
|
|
107
|
+
* user-authored episode exists, clamp at 0.69.
|
|
108
|
+
* 7. Clamp final to [0.0, 1.0].
|
|
109
|
+
*/
|
|
110
|
+
export declare function projectConfidence(evidence: EvidenceEvent[], lastReinforcedAt: string, nowMs?: number): ProjectionResult;
|
|
111
|
+
/**
|
|
112
|
+
* Which evidence kinds count as user-authored EPISODES that qualify for
|
|
113
|
+
* authority? (Distinct from the userAuthored boolean, which is broader.)
|
|
114
|
+
*
|
|
115
|
+
* Per spec: "user-authored episodes are the unit of evidence." Only
|
|
116
|
+
* specific kinds qualify — extraction from user, user re-reference,
|
|
117
|
+
* anchored affirmation, positive pending-confirm answer, contradiction
|
|
118
|
+
* (which is also a user-authored episode in the negative direction).
|
|
119
|
+
*/
|
|
120
|
+
export declare function qualifiesAsUserAuthoredEpisode(kind: EvidenceKind): boolean;
|
|
121
|
+
export declare function buildEvent(refId: string, kind: EvidenceKind, sourceMessageId: string, opts?: {
|
|
122
|
+
at?: string;
|
|
123
|
+
userAuthored?: boolean;
|
|
124
|
+
delta?: number;
|
|
125
|
+
meta?: Record<string, unknown>;
|
|
126
|
+
}): EvidenceEvent;
|
|
127
|
+
export declare class TopicIntentStore {
|
|
128
|
+
private dir;
|
|
129
|
+
constructor(stateDir: string);
|
|
130
|
+
private filePath;
|
|
131
|
+
/** Load a topic's intent file, returning an empty skeleton if missing or corrupt. */
|
|
132
|
+
load(topicId: number): TopicIntentFile;
|
|
133
|
+
/** Persist the topic's intent file. */
|
|
134
|
+
save(file: TopicIntentFile): void;
|
|
135
|
+
/**
|
|
136
|
+
* Append an evidence event to a refId. Creates the ref if it doesn't exist.
|
|
137
|
+
* Updates lastReinforcedAt if the event has positive delta.
|
|
138
|
+
* Updates telemetry counters.
|
|
139
|
+
*/
|
|
140
|
+
appendEvidence(topicId: number, refId: string, ev: EvidenceEvent, refInit?: Partial<EstablishedRef>): TopicIntentFile;
|
|
141
|
+
/** Get the live projection for a refId (recomputed from evidence). */
|
|
142
|
+
getProjection(topicId: number, refId: string, nowMs?: number): ProjectionResult | null;
|
|
143
|
+
/** Get all refs for a topic at current tier or above. */
|
|
144
|
+
getRefsAtOrAbove(topicId: number, minTier: 'observation' | 'tentative' | 'authoritative', nowMs?: number): Array<EstablishedRef & {
|
|
145
|
+
projection: ProjectionResult;
|
|
146
|
+
}>;
|
|
147
|
+
/** Full read of a topic's file (for diagnostics endpoint). */
|
|
148
|
+
read(topicId: number): TopicIntentFile;
|
|
149
|
+
}
|
|
150
|
+
export declare const TOPIC_INTENT_CONSTANTS: {
|
|
151
|
+
DECAY_HALF_LIFE_DAYS: number;
|
|
152
|
+
DECAY_GRACE_DAYS: number;
|
|
153
|
+
DECAY_LAMBDA: number;
|
|
154
|
+
AUTHORITY_THRESHOLD: number;
|
|
155
|
+
AUTHORITY_CLAMP: number;
|
|
156
|
+
TENTATIVE_THRESHOLD: number;
|
|
157
|
+
SIGNAL_CAPS: Partial<Record<EvidenceKind, number>>;
|
|
158
|
+
AFFIRM_PER_REF_PER_24H_LIMIT: number;
|
|
159
|
+
AFFIRM_PER_MESSAGE_REF_LIMIT: number;
|
|
160
|
+
MS_PER_DAY: number;
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=TopicIntent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TopicIntent.d.ts","sourceRoot":"","sources":["../../src/core/TopicIntent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TopicIntent — per-topic semantic state tracking via continuous confidence.
|
|
3
|
+
*
|
|
4
|
+
* Layer 1 of the Topic Intent Layer spec (v14 CLEAN, approved 2026-05-22).
|
|
5
|
+
* See docs/specs/topic-intent-layer.md.
|
|
6
|
+
*
|
|
7
|
+
* Tracks candidate facts and decisions extracted from conversation. Each
|
|
8
|
+
* EstablishedRef accumulates evidence over multi-turn exchange; confidence
|
|
9
|
+
* is computed on read as a deterministic projection over the append-only
|
|
10
|
+
* event log.
|
|
11
|
+
*
|
|
12
|
+
* Framework-agnostic: pure JSON persistence, pure math projection. Reachable
|
|
13
|
+
* from Claude Code and Codex sessions alike.
|
|
14
|
+
*
|
|
15
|
+
* Storage: {stateDir}/topic-intent/<topicId>.json
|
|
16
|
+
*/
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { randomUUID } from 'node:crypto';
|
|
20
|
+
// ── Constants from spec ──────────────────────────────────────────────────
|
|
21
|
+
const DECAY_HALF_LIFE_DAYS = 180;
|
|
22
|
+
const DECAY_GRACE_DAYS = 30;
|
|
23
|
+
const DECAY_LAMBDA = Math.log(2) / DECAY_HALF_LIFE_DAYS;
|
|
24
|
+
const AUTHORITY_THRESHOLD = 0.7;
|
|
25
|
+
const AUTHORITY_CLAMP = 0.69;
|
|
26
|
+
const TENTATIVE_THRESHOLD = 0.3;
|
|
27
|
+
/** Signal-specific caps. Numeric = max cumulative contribution from that kind. */
|
|
28
|
+
const SIGNAL_CAPS = {
|
|
29
|
+
'user-reref': 0.30,
|
|
30
|
+
'agent-reref': 0.05,
|
|
31
|
+
'extract-agent': 0.10, // initial agent-origin extraction capped at single occurrence value
|
|
32
|
+
};
|
|
33
|
+
/** Affirmation safety: per-refId per 24h cap. */
|
|
34
|
+
const AFFIRM_PER_REF_PER_24H_LIMIT = 1;
|
|
35
|
+
/** Per single user message, max number of distinct refIds that may receive affirmation bonus. */
|
|
36
|
+
const AFFIRM_PER_MESSAGE_REF_LIMIT = 3;
|
|
37
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
38
|
+
// ── Default signal deltas (used by helpers; raw spec values) ─────────────
|
|
39
|
+
export const SIGNAL_DELTA = {
|
|
40
|
+
'extract-user': 0.40,
|
|
41
|
+
'extract-agent': 0.10,
|
|
42
|
+
'user-reref': 0.10,
|
|
43
|
+
'agent-reref': 0.01,
|
|
44
|
+
'user-affirm': 0.30,
|
|
45
|
+
'pending-confirm-positive': 0.50,
|
|
46
|
+
'pending-confirm-negative': -0.70,
|
|
47
|
+
'contradiction': -0.60,
|
|
48
|
+
'conflict-mark': 0, // marker-only, no delta
|
|
49
|
+
'sharpen-retry-issued': 0, // bookkeeping, no delta
|
|
50
|
+
};
|
|
51
|
+
export const USER_AUTHORED_BY_DEFAULT = {
|
|
52
|
+
'extract-user': true,
|
|
53
|
+
'extract-agent': false,
|
|
54
|
+
'user-reref': true,
|
|
55
|
+
'agent-reref': false,
|
|
56
|
+
'user-affirm': true,
|
|
57
|
+
'pending-confirm-positive': true,
|
|
58
|
+
'pending-confirm-negative': true,
|
|
59
|
+
'contradiction': true,
|
|
60
|
+
'conflict-mark': false,
|
|
61
|
+
'sharpen-retry-issued': false,
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Compute the confidence projection for a single EstablishedRef from its
|
|
65
|
+
* evidence array. Pure function — no I/O, no state, fully deterministic.
|
|
66
|
+
*
|
|
67
|
+
* Order of operations:
|
|
68
|
+
* 1. Per-message dedup by (refId, sourceMessageId): on collision, keep the
|
|
69
|
+
* single largest applicable delta. (Multiple signals from the same user
|
|
70
|
+
* message about the same refId count as ONE episode.)
|
|
71
|
+
* 2. Apply signal-specific caps (user-reref cumulative <= +0.30, etc.)
|
|
72
|
+
* 3. Apply affirmation caps (per-refId per 24h, per single user message).
|
|
73
|
+
* 4. Sum applicable deltas (with caps).
|
|
74
|
+
* 5. Apply time decay if (now - lastReinforcedAt) > 30 days.
|
|
75
|
+
* 6. Authority hard clamp: if would-be >= 0.7 and no qualifying
|
|
76
|
+
* user-authored episode exists, clamp at 0.69.
|
|
77
|
+
* 7. Clamp final to [0.0, 1.0].
|
|
78
|
+
*/
|
|
79
|
+
export function projectConfidence(evidence, lastReinforcedAt, nowMs = Date.now()) {
|
|
80
|
+
// Step 1: per-message dedup — keep largest applicable delta per (refId, sourceMessageId)
|
|
81
|
+
const dedupedByMsg = new Map();
|
|
82
|
+
for (const ev of evidence) {
|
|
83
|
+
const key = `${ev.refId}::${ev.sourceMessageId}`;
|
|
84
|
+
const existing = dedupedByMsg.get(key);
|
|
85
|
+
if (!existing || Math.abs(ev.delta) > Math.abs(existing.delta)) {
|
|
86
|
+
dedupedByMsg.set(key, ev);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const deduped = Array.from(dedupedByMsg.values());
|
|
90
|
+
// Step 2-3: bucket by kind, apply caps
|
|
91
|
+
const bucketedByKind = new Map();
|
|
92
|
+
for (const ev of deduped) {
|
|
93
|
+
if (!bucketedByKind.has(ev.kind))
|
|
94
|
+
bucketedByKind.set(ev.kind, []);
|
|
95
|
+
bucketedByKind.get(ev.kind).push(ev);
|
|
96
|
+
}
|
|
97
|
+
let runningSum = 0;
|
|
98
|
+
let userAuthoredEpisodes = 0;
|
|
99
|
+
for (const [kind, events] of bucketedByKind) {
|
|
100
|
+
const cap = SIGNAL_CAPS[kind];
|
|
101
|
+
if (cap !== undefined && events.length > 0 && events[0].delta > 0) {
|
|
102
|
+
// Positive-delta capped signal: sum and clamp at cap
|
|
103
|
+
const raw = events.reduce((s, e) => s + e.delta, 0);
|
|
104
|
+
runningSum += Math.min(raw, cap);
|
|
105
|
+
}
|
|
106
|
+
else if (kind === 'user-affirm') {
|
|
107
|
+
// Affirm safety: enforce per-refId per 24h limit
|
|
108
|
+
// and per single source-message limit of distinct refIds (handled at INSERT time,
|
|
109
|
+
// but defensive in projection too)
|
|
110
|
+
const affirmsByDay = new Map();
|
|
111
|
+
for (const ev of events) {
|
|
112
|
+
const dayKey = ev.at.slice(0, 10); // YYYY-MM-DD coarse bucket
|
|
113
|
+
if (!affirmsByDay.has(dayKey))
|
|
114
|
+
affirmsByDay.set(dayKey, []);
|
|
115
|
+
affirmsByDay.get(dayKey).push(ev);
|
|
116
|
+
}
|
|
117
|
+
let appliedAffirms = 0;
|
|
118
|
+
for (const dayEvents of affirmsByDay.values()) {
|
|
119
|
+
// Sort by time and take only the first AFFIRM_PER_REF_PER_24H_LIMIT
|
|
120
|
+
dayEvents.sort((a, b) => a.at.localeCompare(b.at));
|
|
121
|
+
const allowed = dayEvents.slice(0, AFFIRM_PER_REF_PER_24H_LIMIT);
|
|
122
|
+
appliedAffirms += allowed.reduce((s, e) => s + e.delta, 0);
|
|
123
|
+
}
|
|
124
|
+
runningSum += appliedAffirms;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Uncapped signal: just sum
|
|
128
|
+
runningSum += events.reduce((s, e) => s + e.delta, 0);
|
|
129
|
+
}
|
|
130
|
+
// Count user-authored episodes (those that qualify for authority)
|
|
131
|
+
for (const ev of events) {
|
|
132
|
+
if (ev.userAuthored && qualifiesAsUserAuthoredEpisode(ev.kind)) {
|
|
133
|
+
userAuthoredEpisodes++;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Step 5: time decay
|
|
138
|
+
let preDecaySum = Math.max(0, Math.min(1, runningSum));
|
|
139
|
+
const daysSince = Math.max(0, (nowMs - new Date(lastReinforcedAt).getTime()) / MS_PER_DAY);
|
|
140
|
+
let decayApplied = 0;
|
|
141
|
+
if (daysSince > DECAY_GRACE_DAYS) {
|
|
142
|
+
const decayDays = daysSince - DECAY_GRACE_DAYS;
|
|
143
|
+
const decayed = preDecaySum * Math.exp(-DECAY_LAMBDA * decayDays);
|
|
144
|
+
decayApplied = preDecaySum - decayed;
|
|
145
|
+
preDecaySum = decayed;
|
|
146
|
+
}
|
|
147
|
+
// Step 6: authority hard clamp
|
|
148
|
+
let authorityClampApplied = false;
|
|
149
|
+
let finalConf = preDecaySum;
|
|
150
|
+
if (finalConf >= AUTHORITY_THRESHOLD && userAuthoredEpisodes === 0) {
|
|
151
|
+
finalConf = AUTHORITY_CLAMP;
|
|
152
|
+
authorityClampApplied = true;
|
|
153
|
+
}
|
|
154
|
+
// Step 7: final clamp
|
|
155
|
+
finalConf = Math.max(0, Math.min(1, finalConf));
|
|
156
|
+
// Tier classification (emergent)
|
|
157
|
+
let tier;
|
|
158
|
+
if (finalConf < TENTATIVE_THRESHOLD)
|
|
159
|
+
tier = 'observation';
|
|
160
|
+
else if (finalConf < AUTHORITY_THRESHOLD)
|
|
161
|
+
tier = 'tentative';
|
|
162
|
+
else
|
|
163
|
+
tier = 'authoritative';
|
|
164
|
+
return {
|
|
165
|
+
confidence: finalConf,
|
|
166
|
+
tier,
|
|
167
|
+
authorityClampApplied,
|
|
168
|
+
decayApplied,
|
|
169
|
+
evidenceCount: deduped.length,
|
|
170
|
+
userAuthoredEpisodes,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Which evidence kinds count as user-authored EPISODES that qualify for
|
|
175
|
+
* authority? (Distinct from the userAuthored boolean, which is broader.)
|
|
176
|
+
*
|
|
177
|
+
* Per spec: "user-authored episodes are the unit of evidence." Only
|
|
178
|
+
* specific kinds qualify — extraction from user, user re-reference,
|
|
179
|
+
* anchored affirmation, positive pending-confirm answer, contradiction
|
|
180
|
+
* (which is also a user-authored episode in the negative direction).
|
|
181
|
+
*/
|
|
182
|
+
export function qualifiesAsUserAuthoredEpisode(kind) {
|
|
183
|
+
return (kind === 'extract-user' ||
|
|
184
|
+
kind === 'user-reref' ||
|
|
185
|
+
kind === 'user-affirm' ||
|
|
186
|
+
kind === 'pending-confirm-positive' ||
|
|
187
|
+
kind === 'pending-confirm-negative' ||
|
|
188
|
+
kind === 'contradiction');
|
|
189
|
+
}
|
|
190
|
+
// ── Helpers for building events ──────────────────────────────────────────
|
|
191
|
+
export function buildEvent(refId, kind, sourceMessageId, opts) {
|
|
192
|
+
return {
|
|
193
|
+
eventId: randomUUID(),
|
|
194
|
+
refId,
|
|
195
|
+
kind,
|
|
196
|
+
sourceMessageId,
|
|
197
|
+
userAuthored: opts?.userAuthored ?? USER_AUTHORED_BY_DEFAULT[kind],
|
|
198
|
+
at: opts?.at ?? new Date().toISOString(),
|
|
199
|
+
delta: opts?.delta ?? SIGNAL_DELTA[kind],
|
|
200
|
+
meta: opts?.meta,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
// ── Store (file-based, framework-agnostic) ───────────────────────────────
|
|
204
|
+
export class TopicIntentStore {
|
|
205
|
+
dir;
|
|
206
|
+
constructor(stateDir) {
|
|
207
|
+
this.dir = path.join(stateDir, 'topic-intent');
|
|
208
|
+
try {
|
|
209
|
+
fs.mkdirSync(this.dir, { recursive: true });
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
console.error(`[TopicIntentStore] Failed to create dir ${this.dir}: ${err}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
filePath(topicId) {
|
|
216
|
+
return path.join(this.dir, `${topicId}.json`);
|
|
217
|
+
}
|
|
218
|
+
/** Load a topic's intent file, returning an empty skeleton if missing or corrupt. */
|
|
219
|
+
load(topicId) {
|
|
220
|
+
const fp = this.filePath(topicId);
|
|
221
|
+
try {
|
|
222
|
+
if (fs.existsSync(fp)) {
|
|
223
|
+
const parsed = JSON.parse(fs.readFileSync(fp, 'utf-8'));
|
|
224
|
+
// Ensure required fields exist (defensive for older files)
|
|
225
|
+
if (!parsed.refs)
|
|
226
|
+
parsed.refs = {};
|
|
227
|
+
if (!parsed.pending)
|
|
228
|
+
parsed.pending = { outstanding: null, queue: [] };
|
|
229
|
+
if (!parsed.telemetry)
|
|
230
|
+
parsed.telemetry = emptyTelemetry();
|
|
231
|
+
if (parsed.schemaVersion === undefined)
|
|
232
|
+
parsed.schemaVersion = 1;
|
|
233
|
+
return parsed;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
console.error(`[TopicIntentStore] Corrupt file ${fp}, starting fresh: ${err}`);
|
|
238
|
+
}
|
|
239
|
+
return emptyFile(topicId);
|
|
240
|
+
}
|
|
241
|
+
/** Persist the topic's intent file. */
|
|
242
|
+
save(file) {
|
|
243
|
+
const fp = this.filePath(file.topicId);
|
|
244
|
+
try {
|
|
245
|
+
fs.writeFileSync(fp, JSON.stringify(file, null, 2));
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
console.error(`[TopicIntentStore] Failed to save ${fp}: ${err}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Append an evidence event to a refId. Creates the ref if it doesn't exist.
|
|
253
|
+
* Updates lastReinforcedAt if the event has positive delta.
|
|
254
|
+
* Updates telemetry counters.
|
|
255
|
+
*/
|
|
256
|
+
appendEvidence(topicId, refId, ev, refInit) {
|
|
257
|
+
const file = this.load(topicId);
|
|
258
|
+
let ref = file.refs[refId];
|
|
259
|
+
if (!ref) {
|
|
260
|
+
ref = {
|
|
261
|
+
refId,
|
|
262
|
+
arcId: refInit?.arcId ?? `arc-${topicId}`,
|
|
263
|
+
topicId,
|
|
264
|
+
kind: refInit?.kind ?? 'fact',
|
|
265
|
+
text: refInit?.text ?? '',
|
|
266
|
+
confidence: 0,
|
|
267
|
+
evidence: [],
|
|
268
|
+
lastReinforcedAt: ev.at,
|
|
269
|
+
status: 'live',
|
|
270
|
+
createdAt: ev.at,
|
|
271
|
+
updatedAt: ev.at,
|
|
272
|
+
};
|
|
273
|
+
file.refs[refId] = ref;
|
|
274
|
+
}
|
|
275
|
+
ref.evidence.push(ev);
|
|
276
|
+
if (ev.delta > 0) {
|
|
277
|
+
ref.lastReinforcedAt = ev.at;
|
|
278
|
+
}
|
|
279
|
+
ref.updatedAt = ev.at;
|
|
280
|
+
// Recompute confidence + tier snapshot for visibility (projection runs on read regardless)
|
|
281
|
+
const proj = projectConfidence(ref.evidence, ref.lastReinforcedAt);
|
|
282
|
+
ref.confidence = proj.confidence;
|
|
283
|
+
// Telemetry
|
|
284
|
+
const extractKey = `${ev.kind}:${ev.userAuthored}`;
|
|
285
|
+
file.telemetry.extraction_total[extractKey] = (file.telemetry.extraction_total[extractKey] ?? 0) + 1;
|
|
286
|
+
file.telemetry.evidence_event_total[ev.kind] = (file.telemetry.evidence_event_total[ev.kind] ?? 0) + 1;
|
|
287
|
+
if (proj.authorityClampApplied) {
|
|
288
|
+
file.telemetry.confidence_clamp_authority_total++;
|
|
289
|
+
}
|
|
290
|
+
this.save(file);
|
|
291
|
+
return file;
|
|
292
|
+
}
|
|
293
|
+
/** Get the live projection for a refId (recomputed from evidence). */
|
|
294
|
+
getProjection(topicId, refId, nowMs) {
|
|
295
|
+
const file = this.load(topicId);
|
|
296
|
+
const ref = file.refs[refId];
|
|
297
|
+
if (!ref)
|
|
298
|
+
return null;
|
|
299
|
+
return projectConfidence(ref.evidence, ref.lastReinforcedAt, nowMs);
|
|
300
|
+
}
|
|
301
|
+
/** Get all refs for a topic at current tier or above. */
|
|
302
|
+
getRefsAtOrAbove(topicId, minTier, nowMs) {
|
|
303
|
+
const file = this.load(topicId);
|
|
304
|
+
const tierOrder = { observation: 0, tentative: 1, authoritative: 2 };
|
|
305
|
+
const minRank = tierOrder[minTier];
|
|
306
|
+
const out = [];
|
|
307
|
+
for (const ref of Object.values(file.refs)) {
|
|
308
|
+
const proj = projectConfidence(ref.evidence, ref.lastReinforcedAt, nowMs);
|
|
309
|
+
if (tierOrder[proj.tier] >= minRank) {
|
|
310
|
+
out.push({ ...ref, projection: proj });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
}
|
|
315
|
+
/** Full read of a topic's file (for diagnostics endpoint). */
|
|
316
|
+
read(topicId) {
|
|
317
|
+
return this.load(topicId);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// ── Helpers for empty state ──────────────────────────────────────────────
|
|
321
|
+
function emptyTelemetry() {
|
|
322
|
+
return {
|
|
323
|
+
extraction_total: {},
|
|
324
|
+
evidence_event_total: {},
|
|
325
|
+
confidence_clamp_authority_total: 0,
|
|
326
|
+
pending_confirm_created_total: 0,
|
|
327
|
+
pending_confirm_queue_dropped_total: 0,
|
|
328
|
+
pending_confirm_abandoned_total: 0,
|
|
329
|
+
pending_confirm_expired_total: 0,
|
|
330
|
+
pending_confirm_answered_total: {},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function emptyFile(topicId) {
|
|
334
|
+
return {
|
|
335
|
+
topicId,
|
|
336
|
+
refs: {},
|
|
337
|
+
pending: { outstanding: null, queue: [] },
|
|
338
|
+
telemetry: emptyTelemetry(),
|
|
339
|
+
schemaVersion: 1,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
// ── Re-exports for convenience ───────────────────────────────────────────
|
|
343
|
+
export const TOPIC_INTENT_CONSTANTS = {
|
|
344
|
+
DECAY_HALF_LIFE_DAYS,
|
|
345
|
+
DECAY_GRACE_DAYS,
|
|
346
|
+
DECAY_LAMBDA,
|
|
347
|
+
AUTHORITY_THRESHOLD,
|
|
348
|
+
AUTHORITY_CLAMP,
|
|
349
|
+
TENTATIVE_THRESHOLD,
|
|
350
|
+
SIGNAL_CAPS,
|
|
351
|
+
AFFIRM_PER_REF_PER_24H_LIMIT,
|
|
352
|
+
AFFIRM_PER_MESSAGE_REF_LIMIT,
|
|
353
|
+
MS_PER_DAY,
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=TopicIntent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TopicIntent.js","sourceRoot":"","sources":["../../src/core/TopicIntent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TopicIntentArcCheck — Layer 3 of the Topic Intent Layer.
|
|
3
|
+
*
|
|
4
|
+
* Pre-send classifier that scans an agent's draft reply against the
|
|
5
|
+
* topic's current tentative + settled items. Fires signals (not blocks)
|
|
6
|
+
* when the draft would:
|
|
7
|
+
* - Act on a tentative item without conversational confirmation
|
|
8
|
+
* - Contradict an item already at authoritative tier
|
|
9
|
+
*
|
|
10
|
+
* Per spec v14 sections "How the agent asks for confirmation" and
|
|
11
|
+
* "Authority on send" — ArcCheck is SIGNAL-only. The existing outbound
|
|
12
|
+
* gate retains authority. The fired signal includes a suggested rewrite
|
|
13
|
+
* hint, but never blocks. The agent itself decides whether to redraft.
|
|
14
|
+
*
|
|
15
|
+
* Per `feedback_gate_latency_vs_client_timeout`: ArcCheck is designed
|
|
16
|
+
* to run concurrent with send-prep, not as a serial second gate. The
|
|
17
|
+
* timeout is enforced at the HTTP route layer (route caller sets the
|
|
18
|
+
* deadline; classifier itself is pure async).
|
|
19
|
+
*
|
|
20
|
+
* Per `feedback_signal_vs_authority`: ArcCheck is the brittle/low-context
|
|
21
|
+
* filter that detects and emits a signal. The higher-level outbound gate
|
|
22
|
+
* (tone-gate, response-review) has blocking authority. Two-layer split.
|
|
23
|
+
*
|
|
24
|
+
* Framework-agnostic: the LLM call is injected. Production wires it to
|
|
25
|
+
* Instar's LlmQueue + IntelligenceProvider; tests stub it.
|
|
26
|
+
*/
|
|
27
|
+
import { TopicIntentStore, type EstablishedRef, type ProjectionResult } from './TopicIntent.js';
|
|
28
|
+
export interface ArcCheckInput {
|
|
29
|
+
topicId: number;
|
|
30
|
+
draftText: string;
|
|
31
|
+
/** Optional: which user turn this draft is in reply to (for record-keeping). */
|
|
32
|
+
forUserTurn?: number;
|
|
33
|
+
}
|
|
34
|
+
export type ArcCheckVerdict = {
|
|
35
|
+
fire: false;
|
|
36
|
+
} | {
|
|
37
|
+
fire: true;
|
|
38
|
+
kind: 'acting-on-tentative' | 'contradicts-settled';
|
|
39
|
+
refId: string;
|
|
40
|
+
refText: string;
|
|
41
|
+
currentTier: 'tentative' | 'authoritative';
|
|
42
|
+
currentConfidence: number;
|
|
43
|
+
reason: string;
|
|
44
|
+
/** Suggested rewrite hint the agent can include in its redraft. */
|
|
45
|
+
suggestedRewriteHint: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The injectable LLM step. Receives the draft + tracked refs and returns
|
|
49
|
+
* a structured classification. Production wires this to a Haiku-class
|
|
50
|
+
* call via LlmQueue; tests stub it.
|
|
51
|
+
*
|
|
52
|
+
* Return value shape: which refs (if any) the draft engages with, and
|
|
53
|
+
* whether the engagement is "act on it" or "contradict it."
|
|
54
|
+
*/
|
|
55
|
+
export interface ArcCheckClassification {
|
|
56
|
+
/** refIds the draft appears to ACT ON (decisions baked in, facts assumed). */
|
|
57
|
+
actsOn: string[];
|
|
58
|
+
/** refIds the draft appears to CONTRADICT. */
|
|
59
|
+
contradicts: string[];
|
|
60
|
+
}
|
|
61
|
+
export type ArcCheckClassifyFn = (draftText: string, refs: Array<EstablishedRef & {
|
|
62
|
+
projection: ProjectionResult;
|
|
63
|
+
}>) => Promise<ArcCheckClassification>;
|
|
64
|
+
export declare class ArcCheck {
|
|
65
|
+
private store;
|
|
66
|
+
private classifyFn;
|
|
67
|
+
constructor(store: TopicIntentStore, classifyFn: ArcCheckClassifyFn);
|
|
68
|
+
/**
|
|
69
|
+
* Run ArcCheck on a draft. Returns a verdict object suitable for direct
|
|
70
|
+
* return from an HTTP route or consumption by a hook.
|
|
71
|
+
*
|
|
72
|
+
* Verdict priority (when multiple conditions fire):
|
|
73
|
+
* 1. contradicts-settled (highest — wrong direction on a decided item)
|
|
74
|
+
* 2. acting-on-tentative (lower — uncertain, but not wrong)
|
|
75
|
+
*
|
|
76
|
+
* If the draft engages multiple refs, the first matching one of the
|
|
77
|
+
* highest-priority kind wins. Subsequent fires are deferred to a
|
|
78
|
+
* future ArcCheck call after the agent's redraft.
|
|
79
|
+
*/
|
|
80
|
+
check(input: ArcCheckInput): Promise<ArcCheckVerdict>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build the ArcCheck prompt for production use. Separated so prompt
|
|
84
|
+
* tuning can iterate without touching the classifier logic.
|
|
85
|
+
*
|
|
86
|
+
* The actual LLM provider call is wired in by the caller; this returns
|
|
87
|
+
* the prompt string + structured response schema description.
|
|
88
|
+
*/
|
|
89
|
+
export declare function buildArcCheckPrompt(draftText: string, refs: Array<EstablishedRef & {
|
|
90
|
+
projection: ProjectionResult;
|
|
91
|
+
}>): {
|
|
92
|
+
systemPrompt: string;
|
|
93
|
+
userPrompt: string;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Parse the LLM's response into an ArcCheckClassification. Tolerates
|
|
97
|
+
* code fences and prose preamble; degrades to empty arrays on parse
|
|
98
|
+
* failure so a busted LLM response never falsely fires ArcCheck.
|
|
99
|
+
*/
|
|
100
|
+
export declare function parseArcCheckResponse(raw: string): ArcCheckClassification;
|
|
101
|
+
//# sourceMappingURL=TopicIntentArcCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TopicIntentArcCheck.d.ts","sourceRoot":"","sources":["../../src/core/TopicIntentArcCheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IACE,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,qBAAqB,GAAG,qBAAqB,CAAC;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,GAAG,eAAe,CAAC;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,KAAK,CAAC,cAAc,GAAG;IAAE,UAAU,EAAE,gBAAgB,CAAA;CAAE,CAAC,KAC3D,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAErC,qBAAa,QAAQ;IAEjB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,UAAU;gBADV,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,kBAAkB;IAGxC;;;;;;;;;;;OAWG;IACG,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC;CAgD5D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,KAAK,CAAC,cAAc,GAAG;IAAE,UAAU,EAAE,gBAAgB,CAAA;CAAE,CAAC,GAC7D;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA2B9C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAiBzE"}
|