instar 1.3.484 → 1.3.486

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dashboard/index.html +4 -1
  2. package/dist/core/MessagingToneGate.d.ts +23 -2
  3. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  4. package/dist/core/MessagingToneGate.js +15 -1
  5. package/dist/core/MessagingToneGate.js.map +1 -1
  6. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  7. package/dist/core/PostUpdateMigrator.js +21 -0
  8. package/dist/core/PostUpdateMigrator.js.map +1 -1
  9. package/dist/core/SessionManager.d.ts.map +1 -1
  10. package/dist/core/SessionManager.js +22 -0
  11. package/dist/core/SessionManager.js.map +1 -1
  12. package/dist/core/TelegramRelay.d.ts +1 -0
  13. package/dist/core/TelegramRelay.d.ts.map +1 -1
  14. package/dist/core/TelegramRelay.js +9 -1
  15. package/dist/core/TelegramRelay.js.map +1 -1
  16. package/dist/core/raw-file-path.d.ts +33 -0
  17. package/dist/core/raw-file-path.d.ts.map +1 -0
  18. package/dist/core/raw-file-path.js +105 -0
  19. package/dist/core/raw-file-path.js.map +1 -0
  20. package/dist/messaging/OutboundAdvisory.d.ts +152 -0
  21. package/dist/messaging/OutboundAdvisory.d.ts.map +1 -0
  22. package/dist/messaging/OutboundAdvisory.js +453 -0
  23. package/dist/messaging/OutboundAdvisory.js.map +1 -0
  24. package/dist/messaging/TelegramAdapter.d.ts +6 -0
  25. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  26. package/dist/messaging/TelegramAdapter.js +4 -1
  27. package/dist/messaging/TelegramAdapter.js.map +1 -1
  28. package/dist/messaging/pending-relay-store.d.ts +7 -0
  29. package/dist/messaging/pending-relay-store.d.ts.map +1 -1
  30. package/dist/messaging/pending-relay-store.js +9 -3
  31. package/dist/messaging/pending-relay-store.js.map +1 -1
  32. package/dist/monitoring/delivery-failure-sentinel.d.ts +6 -1
  33. package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -1
  34. package/dist/monitoring/delivery-failure-sentinel.js +15 -3
  35. package/dist/monitoring/delivery-failure-sentinel.js.map +1 -1
  36. package/dist/scaffold/templates.d.ts.map +1 -1
  37. package/dist/scaffold/templates.js +7 -1
  38. package/dist/scaffold/templates.js.map +1 -1
  39. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  40. package/dist/scheduler/JobScheduler.js +8 -0
  41. package/dist/scheduler/JobScheduler.js.map +1 -1
  42. package/dist/server/AgentServer.d.ts +1 -0
  43. package/dist/server/AgentServer.d.ts.map +1 -1
  44. package/dist/server/AgentServer.js +22 -0
  45. package/dist/server/AgentServer.js.map +1 -1
  46. package/dist/server/PeerStreamProxy.d.ts +7 -0
  47. package/dist/server/PeerStreamProxy.d.ts.map +1 -1
  48. package/dist/server/PeerStreamProxy.js +11 -2
  49. package/dist/server/PeerStreamProxy.js.map +1 -1
  50. package/dist/server/WebSocketManager.d.ts +10 -1
  51. package/dist/server/WebSocketManager.d.ts.map +1 -1
  52. package/dist/server/WebSocketManager.js +27 -3
  53. package/dist/server/WebSocketManager.js.map +1 -1
  54. package/dist/server/routes.d.ts +12 -0
  55. package/dist/server/routes.d.ts.map +1 -1
  56. package/dist/server/routes.js +216 -3
  57. package/dist/server/routes.js.map +1 -1
  58. package/package.json +1 -1
  59. package/src/data/builtin-manifest.json +67 -67
  60. package/src/scaffold/templates.ts +7 -1
  61. package/src/templates/scripts/telegram-reply.sh +202 -10
  62. package/upgrades/1.3.485.md +31 -0
  63. package/upgrades/1.3.486.md +38 -0
  64. package/upgrades/side-effects/outbound-advisory-inform-only.md +252 -0
  65. package/upgrades/side-effects/pool-stream-cross-machine-fix.md +94 -0
@@ -48,5 +48,6 @@ export interface RelayDeps {
48
48
  */
49
49
  export declare function relayOutbound(topicId: number, text: string, opts: {
50
50
  silent?: boolean;
51
+ kindMetadata?: Record<string, unknown>;
51
52
  } | undefined, deps: RelayDeps): Promise<RelayResult | null>;
52
53
  //# sourceMappingURL=TelegramRelay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TelegramRelay.d.ts","sourceRoot":"","sources":["../../src/core/TelegramRelay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,iFAAiF;IACjF,WAAW,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACjC,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,iEAAiE;IACjE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EACtC,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAiD7B"}
1
+ {"version":3,"file":"TelegramRelay.d.ts","sourceRoot":"","sources":["../../src/core/TelegramRelay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,iFAAiF;IACjF,WAAW,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACjC,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,iEAAiE;IACjE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,SAAS,EAC9E,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAyD7B"}
@@ -44,7 +44,15 @@ export async function relayOutbound(topicId, text, opts, deps) {
44
44
  const resp = await fetchImpl(`${url}/telegram/reply/${topicId}`, {
45
45
  method: 'POST',
46
46
  headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${deps.authToken}` },
47
- body: JSON.stringify({ text, ...(opts?.silent ? { silent: true } : {}) }),
47
+ // Forward the kind metadata so an automated send keeps its kind across
48
+ // the hop and the HOLDER's gate/audit see accurate context (spec
49
+ // outbound-jargon-filepath-gap §2.5). The preflight already ran on the
50
+ // ORIGINATING machine — it never re-runs here.
51
+ body: JSON.stringify({
52
+ text,
53
+ ...(opts?.silent ? { silent: true } : {}),
54
+ ...(opts?.kindMetadata ? { metadata: opts.kindMetadata } : {}),
55
+ }),
48
56
  signal: ac.signal,
49
57
  });
50
58
  if (!resp.ok) {
@@ -1 +1 @@
1
- {"version":3,"file":"TelegramRelay.js","sourceRoot":"","sources":["../../src/core/TelegramRelay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TelegramRelay.js","sourceRoot":"","sources":["../../src/core/TelegramRelay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * raw-file-path — deterministic detector for literal filesystem paths in
3
+ * user-facing messages.
4
+ *
5
+ * Sibling of `localhost-link.ts`, held to the same linear-regex discipline —
6
+ * but unlike the localhost guard this is a pure SIGNAL, never a block
7
+ * (spec: docs/specs/outbound-jargon-filepath-gap.md §2.3). A literal repo
8
+ * path shown to a user ("/Users/justin/...", ".instar/config.json",
9
+ * "src/core/Foo.ts") is something the user usually can't act on; the
10
+ * existing B2_FILE_PATH judgment belongs to the LLM authority, and on
11
+ * automated sends the preflight advisory informs the SENDER. This detector
12
+ * only surfaces the observation.
13
+ *
14
+ * Hard requirements (r2 convergence):
15
+ * - ReDoS-safe: linear, non-backtracking patterns; bounded segment count
16
+ * and length; an indexOf prescreen so the regex only runs when a path is
17
+ * plausibly present.
18
+ * - Never matches inside an `http(s)://` URL — URLs containing paths are
19
+ * the legitimate form to preserve.
20
+ * - Bounded match echo: the returned match is the regex token (whose char
21
+ * class already stops at whitespace/quote/`?`/`#`/`)`), truncated to
22
+ * 120 chars, so a secret adjacent to a path can never ride into
23
+ * logs/advisories/transcripts.
24
+ * - Callers wrap every call fail-OPEN: a throw skips the signal, never
25
+ * withholds a message and never 500s a route.
26
+ */
27
+ export interface RawFilePathResult {
28
+ detected: boolean;
29
+ /** First offending path, bounded to 120 chars — safe to echo in advisories/audits. */
30
+ match?: string;
31
+ }
32
+ export declare function detectRawFilePath(text: string): RawFilePathResult;
33
+ //# sourceMappingURL=raw-file-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-file-path.d.ts","sourceRoot":"","sources":["../../src/core/raw-file-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAmCH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAsBjE"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * raw-file-path — deterministic detector for literal filesystem paths in
3
+ * user-facing messages.
4
+ *
5
+ * Sibling of `localhost-link.ts`, held to the same linear-regex discipline —
6
+ * but unlike the localhost guard this is a pure SIGNAL, never a block
7
+ * (spec: docs/specs/outbound-jargon-filepath-gap.md §2.3). A literal repo
8
+ * path shown to a user ("/Users/justin/...", ".instar/config.json",
9
+ * "src/core/Foo.ts") is something the user usually can't act on; the
10
+ * existing B2_FILE_PATH judgment belongs to the LLM authority, and on
11
+ * automated sends the preflight advisory informs the SENDER. This detector
12
+ * only surfaces the observation.
13
+ *
14
+ * Hard requirements (r2 convergence):
15
+ * - ReDoS-safe: linear, non-backtracking patterns; bounded segment count
16
+ * and length; an indexOf prescreen so the regex only runs when a path is
17
+ * plausibly present.
18
+ * - Never matches inside an `http(s)://` URL — URLs containing paths are
19
+ * the legitimate form to preserve.
20
+ * - Bounded match echo: the returned match is the regex token (whose char
21
+ * class already stops at whitespace/quote/`?`/`#`/`)`), truncated to
22
+ * 120 chars, so a secret adjacent to a path can never ride into
23
+ * logs/advisories/transcripts.
24
+ * - Callers wrap every call fail-OPEN: a throw skips the signal, never
25
+ * withholds a message and never 500s a route.
26
+ */
27
+ /** Truncation cap for the echoed match (privacy bound on adjacent content). */
28
+ const MATCH_ECHO_MAX = 120;
29
+ /** Defensive input cap — callers already cap analyzed text (64KB at the
30
+ * preflight route); this keeps the detector itself bounded regardless. */
31
+ const INPUT_MAX = 64 * 1024;
32
+ /**
33
+ * Path-segment char class: stops at whitespace, quotes, `?`, `#`, `)`,
34
+ * backticks and other prose punctuation by construction. Bounded segment
35
+ * length (1–64) and bounded segment count keep the scan linear.
36
+ *
37
+ * Three alternatives, all anchored on a real separator so prose like
38
+ * "and/or" or "TCP/IP" cannot match:
39
+ * A) absolute or home paths with at least two segments: /Users/justin/x, ~/.config/foo
40
+ * B) dot-directory relative paths: .instar/config.json, .claude/hooks/x
41
+ * C) repo-relative paths under well-known dirs: src/core/Foo.ts, logs/server.log
42
+ */
43
+ const SEG = '[A-Za-z0-9._-]{1,64}';
44
+ const RAW_FILE_PATH_RE = new RegExp(
45
+ // A: "/seg/seg..." or "~/seg/seg..." (>= 2 segments so "/tmp" alone or a
46
+ // lone slash in prose stays legal)
47
+ `(?:(?:~)?/${SEG}(?:/${SEG}){1,12}` +
48
+ // B: ".instar/...", ".claude/...", ".github/...", ".husky/..." (single
49
+ // segment after the dot-dir is enough — ".instar/config.json")
50
+ `|\\.(?:instar|claude|github|husky|vscode|config)/${SEG}(?:/${SEG}){0,12}` +
51
+ // C: repo-relative under well-known top-level dirs; require the word
52
+ // boundary via a non-path char or string start (handled in code, not
53
+ // lookbehind, to keep the pattern simple and linear)
54
+ `|(?:src|docs|tests|scripts|logs|state|upgrades|dist|node_modules)/${SEG}(?:/${SEG}){0,12})`, 'g');
55
+ /**
56
+ * True when `index` sits inside a scheme-bearing URL token: the
57
+ * whitespace-delimited token containing the match start carries "://"
58
+ * before the match. Linear scan-back, bounded by the token itself.
59
+ */
60
+ function insideUrl(text, index) {
61
+ let start = index;
62
+ while (start > 0 && !/\s/.test(text[start - 1]))
63
+ start--;
64
+ const prefix = text.slice(start, index);
65
+ // `://` fully before the match, OR the match starts at the second slash of
66
+ // a scheme separator (prefix ends with `:/` — e.g. match begins at
67
+ // "/example.com/…" inside "https://example.com/…").
68
+ return prefix.includes('://') || /:\/$/.test(prefix);
69
+ }
70
+ /**
71
+ * For alternative C (bare repo-relative prefixes like "src/"), require a
72
+ * word boundary on the left so "missrc/foo" or "RandomLogs/x" can't match.
73
+ * Alternatives A/B self-anchor on '/', '~' or '.'.
74
+ */
75
+ function hasWordBoundaryLeft(text, index) {
76
+ if (index === 0)
77
+ return true;
78
+ return !/[A-Za-z0-9._\-/]/.test(text[index - 1]);
79
+ }
80
+ export function detectRawFilePath(text) {
81
+ if (typeof text !== 'string' || text.length === 0)
82
+ return { detected: false };
83
+ const input = text.length > INPUT_MAX ? text.slice(0, INPUT_MAX) : text;
84
+ // indexOf prescreen — the regex only runs when a path separator exists.
85
+ if (!input.includes('/'))
86
+ return { detected: false };
87
+ RAW_FILE_PATH_RE.lastIndex = 0;
88
+ let m;
89
+ while ((m = RAW_FILE_PATH_RE.exec(input)) !== null) {
90
+ const token = m[0];
91
+ const at = m.index;
92
+ // Never flag a path that lives inside an http(s):// URL.
93
+ if (insideUrl(input, at))
94
+ continue;
95
+ // Bare repo-relative alternative needs a real word boundary.
96
+ const firstChar = token[0];
97
+ if (firstChar !== '/' && firstChar !== '~' && firstChar !== '.') {
98
+ if (!hasWordBoundaryLeft(input, at))
99
+ continue;
100
+ }
101
+ return { detected: true, match: token.slice(0, MATCH_ECHO_MAX) };
102
+ }
103
+ return { detected: false };
104
+ }
105
+ //# sourceMappingURL=raw-file-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-file-path.js","sourceRoot":"","sources":["../../src/core/raw-file-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * OutboundAdvisory — the inform-only preflight surface for automated senders.
3
+ *
4
+ * Spec: docs/specs/outbound-jargon-filepath-gap.md (§2.4, §2.4(5), §2.4(6)).
5
+ *
6
+ * Three responsibilities, all strictly non-blocking:
7
+ *
8
+ * 1. **Advisory composition** (`composeAdvisories`) — run the deterministic
9
+ * detectors (jargon, raw-file-path, localhost-link) over a candidate text
10
+ * and return static-guidance advisories. No LLM call, fail-OPEN per
11
+ * detector, guidance keyed by code (never derived from message content —
12
+ * injection-pinned), detector match rendered only as an inert bounded
13
+ * token by the consumer.
14
+ *
15
+ * 2. **Audit** (`recordPreflight` / `recordAck`) — the SERVER is the single
16
+ * writer of `logs/outbound-advisory.jsonl`: one O_APPEND write per line,
17
+ * `{ts, topicId, jobSlug, kind, textHash, advisories, action}` with
18
+ * action `clean | advised | acked`. Size-rotated (single rollover to
19
+ * `.1` at the byte cap). The script writes NOTHING here.
20
+ *
21
+ * 3. **Repeated-ignore escalation** — the load-bearing bound on the design's
22
+ * worst failure mode (a sender silently dropping its own flagged
23
+ * message). Fed by an in-memory write-time index (no poller, no file
24
+ * scan; resets on restart are accepted best-effort observability):
25
+ * - per-SIGNATURE (jobSlug, topicId, sorted code set) unresolved-advised
26
+ * count in a rolling window, NOT reset by interleaved clean rows for
27
+ * other messages (the reset-gaming case);
28
+ * - a signature resolves on an `acked` with the same codes, or a `clean`
29
+ * preflight of the same message — "same message" judged by token-set
30
+ * similarity (the fix re-send is near-identical), never by exact hash
31
+ * alone;
32
+ * - a per-jobSlug AGGREGATE (across topics, higher threshold) covers
33
+ * one-shot senders whose topics vary;
34
+ * - a preemptive-ack consumer: N consecutive acked-with-NONEMPTY
35
+ * advisories per signature raises too (a job habitually overriding
36
+ * instead of fixing is operator-relevant).
37
+ * Escalation INFORMS THE OPERATOR (one deduped Attention item with the
38
+ * FIXED sourceContext 'outbound-advisory-escalation' so the per-source
39
+ * topic budget genuinely binds — P17). It never gates the sender.
40
+ */
41
+ export type AdvisoryCode = 'JARGON' | 'RAW_FILE_PATH' | 'LOCALHOST_LINK';
42
+ export interface Advisory {
43
+ code: AdvisoryCode;
44
+ /** Bounded inert detector match (≤120 chars) — data, never instructions. */
45
+ match?: string;
46
+ /** STATIC guidance keyed by code — never derived from message content. */
47
+ guidance: string;
48
+ }
49
+ /** Analyzed-text cap (consistent with the pipeline's downstream rejects). */
50
+ export declare const PREFLIGHT_TEXT_CAP: number;
51
+ /**
52
+ * Run the deterministic detectors over a candidate text. Each detector is
53
+ * individually fail-OPEN: a throw skips that signal and never withholds.
54
+ */
55
+ export declare function composeAdvisories(text: string): Advisory[];
56
+ export type AdvisoryAction = 'clean' | 'advised' | 'acked';
57
+ export interface AdvisoryAuditEntry {
58
+ ts: string;
59
+ topicId: number;
60
+ jobSlug: string;
61
+ kind: string;
62
+ textHash: string;
63
+ advisories: string[];
64
+ action: AdvisoryAction;
65
+ }
66
+ export interface AttentionRaiser {
67
+ (item: {
68
+ id: string;
69
+ title: string;
70
+ summary: string;
71
+ category: string;
72
+ priority: 'HIGH' | 'NORMAL' | 'LOW';
73
+ description?: string;
74
+ sourceContext?: string;
75
+ }): Promise<unknown> | unknown;
76
+ }
77
+ export interface OutboundAdvisoryAuditOptions {
78
+ /** Absolute path of the JSONL audit file (e.g. <root>/logs/outbound-advisory.jsonl). */
79
+ logPath: string;
80
+ /** Size-rotation cap in bytes (single rollover to `.1`). Default 10MB. */
81
+ maxLogBytes?: number;
82
+ /** Per-signature unresolved-advised threshold (live-read). Default 3. */
83
+ getIgnoreThreshold?: () => number;
84
+ /** Per-jobSlug aggregate threshold (live-read). Default 5. */
85
+ getSlugThreshold?: () => number;
86
+ /** Operator-inform surface. Absent → escalation is a no-op (audit still writes). */
87
+ raiseAttention?: AttentionRaiser;
88
+ }
89
+ /** Fixed sourceContext — P17: the per-source topic budget must genuinely bind. */
90
+ export declare const ADVISORY_ESCALATION_SOURCE = "outbound-advisory-escalation";
91
+ export declare function sha256Hex(text: string): string;
92
+ export declare class OutboundAdvisoryAudit {
93
+ private logPath;
94
+ private maxLogBytes;
95
+ private getIgnoreThreshold;
96
+ private getSlugThreshold;
97
+ private raiseAttention;
98
+ /** Write-time index — per-signature state (key: slug|topic|codes). */
99
+ private signatures;
100
+ /** Recent PREFLIGHT-written rows (clean/advised) for §2.1 spoof correlation.
101
+ * Keyed slug|topic → last preflight ts. Acked rows never land here —
102
+ * a send's own ack must not self-license it. */
103
+ private recentPreflights;
104
+ /** Per-slug escalation dedup for the aggregate bound. */
105
+ private escalatedSlugs;
106
+ constructor(opts: OutboundAdvisoryAuditOptions);
107
+ /**
108
+ * Record a PREFLIGHT outcome (the preflight route is the caller).
109
+ * action is derived: advisories present → 'advised', none → 'clean'.
110
+ * Never throws — audit failure must never affect delivery.
111
+ */
112
+ recordPreflight(entry: {
113
+ topicId: number;
114
+ jobSlug: string;
115
+ kind: string;
116
+ text: string;
117
+ advisories: string[];
118
+ }): AdvisoryAction;
119
+ /**
120
+ * Record an ACK (the /telegram/reply route is the single writer of 'acked'
121
+ * — it fires when a send carries metadata.advisoryAck). Resolves the
122
+ * signature's unresolved episodes when the codes match; counts consecutive
123
+ * non-empty-advisory acks for the preemptive-ack consumer.
124
+ */
125
+ recordAck(entry: {
126
+ topicId: number;
127
+ jobSlug: string;
128
+ kind: string;
129
+ text: string;
130
+ advisories: string[];
131
+ }): void;
132
+ /**
133
+ * §2.1 spoof correlation: was there a PREFLIGHT-written (clean/advised)
134
+ * row for this slug+topic recently? Acked rows deliberately don't count.
135
+ */
136
+ hasRecentPreflight(jobSlug: string, topicId: number, windowMs?: number): boolean;
137
+ /**
138
+ * Bounded tail read for GET /messaging/advisory-log — reads the last
139
+ * `maxBytes` of the file (default 256KB), NEVER the whole file, and
140
+ * returns up to `limit` newest parsed entries.
141
+ */
142
+ readTail(limit?: number, maxBytes?: number): AdvisoryAuditEntry[];
143
+ private signature;
144
+ private pruneEpisodes;
145
+ private prunePreflights;
146
+ private resolveNearIdentical;
147
+ private maybeEscalateIgnore;
148
+ private maybeEscalatePreemptiveAck;
149
+ private appendLine;
150
+ private rotateIfNeeded;
151
+ }
152
+ //# sourceMappingURL=OutboundAdvisory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OutboundAdvisory.d.ts","sourceRoot":"","sources":["../../src/messaging/OutboundAdvisory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAWH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgBD,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CA6C1D;AAID,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,IAAI,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;QACpC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,wFAAwF;IACxF,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAClC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,oFAAoF;IACpF,cAAc,CAAC,EAAE,eAAe,CAAC;CAClC;AAED,kFAAkF;AAClF,eAAO,MAAM,0BAA0B,iCAAiC,CAAC;AAqDzE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAe;IACzC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,cAAc,CAAyB;IAE/C,sEAAsE;IACtE,OAAO,CAAC,UAAU,CAAqC;IACvD;;qDAEiD;IACjD,OAAO,CAAC,gBAAgB,CAA6B;IACrD,yDAAyD;IACzD,OAAO,CAAC,cAAc,CAAqB;gBAE/B,IAAI,EAAE,4BAA4B;IAQ9C;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,GAAG,cAAc;IAyClB;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,GAAG,IAAI;IA6BR;;;OAGG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,SAA6B,GAAG,OAAO;IAKpG;;;;OAIG;IACH,QAAQ,CAAC,KAAK,SAAK,EAAE,QAAQ,SAAa,GAAG,kBAAkB,EAAE;IA+BjE,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,mBAAmB;IA+D3B,OAAO,CAAC,0BAA0B;IAuBlC,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,cAAc;CAUvB"}