@rocketlang/chitta-detect 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -181,3 +181,66 @@ AGPL-3.0-only. The full chitta-guard service is BSL-1.1 (converts to AGPL-3.0 af
181
181
  See [LICENSE](LICENSE) for the AGPL-3.0 terms. Any modified version run as a network service must publish source per AGPL clause 13.
182
182
 
183
183
  For commercial dual-licensing or EE-tier access: [captain@ankr.in](mailto:captain@ankr.in).
184
+
185
+ ---
186
+
187
+ ## v0.2.0 — Opt-in Agentic Control Center (ACC) event bus
188
+
189
+ Added 2026-05-17. `scan.evaluate()` now emits an `AccReceipt` on every
190
+ scan, **but only when you wire a bus**. Without `setEventBus`, v0.2.0
191
+ behaves identically to v0.1.0 — no emission, no state, no side effect.
192
+
193
+ ### Wire it in 3 lines
194
+
195
+ ```typescript
196
+ import { setEventBus, type EventBus, type AccReceipt } from '@rocketlang/chitta-detect';
197
+
198
+ const myBus: EventBus = {
199
+ emit: (r: AccReceipt) => console.log(`[ACC] ${r.event_type} ${r.verdict} ${r.summary}`),
200
+ };
201
+ setEventBus(myBus);
202
+ ```
203
+
204
+ ### Receipt events emitted
205
+
206
+ | Primitive | event_type | verdict |
207
+ |---|---|---|
208
+ | `scan.evaluate` | `scan.evaluated` | PASS / ADVISORY / INJECT_SUSPECT / BLOCK |
209
+
210
+ ### Receipt shape
211
+
212
+ ```typescript
213
+ interface AccReceipt {
214
+ receipt_id: string; // primitive-prefixed (cg-scan-{ts}-{counter})
215
+ primitive: string; // always 'chitta-detect'
216
+ event_type: string; // 'scan.evaluated'
217
+ emitted_at: string; // ISO 8601
218
+ agent_id?: string; // copied from agentContext.agent_id
219
+ verdict?: string; // PASS | ADVISORY | INJECT_SUSPECT | BLOCK
220
+ rules_fired?: string[]; // e.g. ['CG-006', 'CG-003', 'INF-CG-002']
221
+ summary?: string; // "{scan_type} → {verdict} (confidence=X, action=Y)"
222
+ payload?: Record<string, unknown>; // scan_type, posture, confidence, fingerprint_matched, tool_output_classification
223
+ }
224
+ ```
225
+
226
+ Strict subset of EE PRAMANA receipt format — EE consumers ingest without translation.
227
+
228
+ ### Phase-1 limits (v0.2.0)
229
+
230
+ - **Only `scan.evaluate` emits** — the orchestrator that combines all
231
+ detectors. Individual detector primitives (`fingerprint.scan`,
232
+ `imperative.scan`, `trust.resolve`, `toolOutput.classify`,
233
+ `capabilityExpansion.scan`, `rateLimit.check`, `retrospective.audit`)
234
+ do NOT emit independently. Reasoning: emitting from every detector
235
+ would flood the bus (a single `scan.evaluate` call runs 4+ detectors).
236
+ If you call detectors directly outside `scan.evaluate`, no event is
237
+ emitted — that's a Phase-1 limit.
238
+ - **Default bus is in-process only.** Multi-process buses (Redis-backed,
239
+ etc.) are a consumer choice.
240
+
241
+ ### Use with `@rocketlang/aegis-suite`
242
+
243
+ ```typescript
244
+ import { wireAllToBus } from '@rocketlang/aegis-suite'; // suite v0.2.0+
245
+ wireAllToBus(); // wires aegis-guard + chitta-detect + lakshmanrekha + hanumang-mandate at once
246
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rocketlang/chitta-detect",
3
- "version": "0.1.0",
4
- "description": "Memory poisoning detection primitives for AI agents — pure pattern matchers (RAG trust, agent-role imperatives, tool-output poisoning, capability expansion, injection fingerprints). Extracted from chitta-guard.",
3
+ "version": "0.2.0",
4
+ "description": "Memory poisoning detection primitives for AI agents — pure pattern matchers (RAG trust, agent-role imperatives, tool-output poisoning, capability expansion, injection fingerprints) + opt-in Agentic Control Center event bus. Extracted from chitta-guard.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "author": "Capt. Anil Sharma <capt.anil.sharma@powerpbox.org>",
package/src/acc-bus.ts ADDED
@@ -0,0 +1,70 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 Capt. Anil Sharma (rocketlang). All rights reserved.
3
+ // See LICENSE for details.
4
+ //
5
+ // @rocketlang/chitta-detect — opt-in Agentic Control Center event bus (v0.2.0)
6
+ // @rule:ACC-003 — Opt-in. emit only when setEventBus() called.
7
+ // @rule:ACC-004 — Lightweight OSS receipt shape (strict subset of EE PRAMANA).
8
+ // @rule:ACC-YK-003 — Stateless-primitive contract preserved. No bus = no emit.
9
+ // @rule:INF-ACC-005 — emit() is a no-op when no bus has been set.
10
+
11
+ /**
12
+ * Lightweight receipt shape — structurally compatible with the canonical
13
+ * AccReceipt in /root/aegis/src/acc/types.ts. Defined locally so this
14
+ * primitive can ship without depending on the ACC package.
15
+ */
16
+ export interface AccReceipt {
17
+ receipt_id: string;
18
+ primitive: string;
19
+ event_type: string;
20
+ emitted_at: string;
21
+ agent_id?: string;
22
+ verdict?: string;
23
+ rules_fired?: string[];
24
+ summary?: string;
25
+ payload?: Record<string, unknown>;
26
+ }
27
+
28
+ export interface EventBus {
29
+ emit(receipt: AccReceipt): void;
30
+ }
31
+
32
+ // Module-private bus reference. null by default — emission is no-op.
33
+ let _bus: EventBus | null = null;
34
+
35
+ /**
36
+ * Opt-in: provide an event bus to receive lightweight ACC receipts
37
+ * for every chitta-detect orchestrator call. Pass null to detach.
38
+ *
39
+ * Without setEventBus, v0.2.0 behaves identically to v0.1.0 — no
40
+ * emission, no state, no side effect.
41
+ *
42
+ * @rule:ACC-003 @rule:ACC-YK-003
43
+ */
44
+ export function setEventBus(bus: EventBus | null): void {
45
+ _bus = bus;
46
+ }
47
+
48
+ /**
49
+ * Internal helper — emit a receipt. No-op when no bus is set.
50
+ * MUST NOT throw — bus implementation handles delivery failures.
51
+ *
52
+ * @rule:INF-ACC-005
53
+ */
54
+ export function emitAccReceipt(receipt: Omit<AccReceipt, 'primitive' | 'emitted_at'>): void {
55
+ if (!_bus) return;
56
+ try {
57
+ _bus.emit({
58
+ ...receipt,
59
+ primitive: 'chitta-detect',
60
+ emitted_at: new Date().toISOString(),
61
+ });
62
+ } catch {
63
+ // bus implementation failure must never break the primitive's caller
64
+ }
65
+ }
66
+
67
+ /** Test/introspection helper — does the primitive have a bus set right now? */
68
+ export function isBusWired(): boolean {
69
+ return _bus !== null;
70
+ }
package/src/index.ts CHANGED
@@ -31,6 +31,16 @@ export * as rateLimit from './rate-limit.js';
31
31
  export * as retrospective from './retrospective.js';
32
32
  export * as scan from './scan.js';
33
33
 
34
+ // @rule:ACC-003 — Opt-in event bus for Agentic Control Center observability.
35
+ // Stateless contract preserved (ACC-YK-003): emit is no-op
36
+ // when setEventBus has not been called. v0.2.0+.
37
+ export {
38
+ type AccReceipt,
39
+ type EventBus,
40
+ setEventBus,
41
+ isBusWired,
42
+ } from './acc-bus.js';
43
+
34
44
  // Re-export the types most consumers will name explicitly
35
45
  export type { SourceMetadata, TrustClassification, TrustClassifyResult } from './trust.js';
36
46
  export type { ImperativeScanResult } from './imperative.js';
package/src/scan.ts CHANGED
@@ -13,6 +13,7 @@ import { resolve as resolveTrust } from './trust.js';
13
13
  import { scan as fingerprintScan } from './fingerprint.js';
14
14
  import { classify as classifyToolOutput } from './tool-output.js';
15
15
  import type { SourceMetadata } from './trust.js';
16
+ import { emitAccReceipt } from './acc-bus.js';
16
17
 
17
18
  export type ScanVerdict = 'PASS' | 'ADVISORY' | 'INJECT_SUSPECT' | 'BLOCK';
18
19
 
@@ -140,7 +141,26 @@ export function evaluate(
140
141
  verdict = 'PASS';
141
142
  }
142
143
 
143
- return buildResult(scan_id, verdict, combinedConfidence, rules_fired, imp, fp, trust, toolOutputClassification, scanned_at);
144
+ const result = buildResult(scan_id, verdict, combinedConfidence, rules_fired, imp, fp, trust, toolOutputClassification, scanned_at);
145
+
146
+ // @rule:ACC-003 @rule:ACC-004 — emit cockpit receipt (no-op when bus unset)
147
+ emitAccReceipt({
148
+ receipt_id: scan_id,
149
+ event_type: 'scan.evaluated',
150
+ agent_id: agentContext.agent_id,
151
+ verdict: result.verdict,
152
+ rules_fired: result.rules_fired,
153
+ summary: `${agentContext.scan_type ?? 'memory_write'} → ${result.verdict} (confidence=${result.confidence}, action=${result.action})`,
154
+ payload: {
155
+ scan_type: agentContext.scan_type,
156
+ posture: agentContext.posture,
157
+ confidence: result.confidence,
158
+ fingerprint_matched: result.details.fingerprint_matched,
159
+ tool_output_classification: result.details.tool_output_classification,
160
+ },
161
+ });
162
+
163
+ return result;
144
164
  }
145
165
 
146
166
  function buildResult(