@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 +63 -0
- package/package.json +2 -2
- package/src/acc-bus.ts +70 -0
- package/src/index.ts +10 -0
- package/src/scan.ts +21 -1
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.
|
|
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
|
-
|
|
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(
|