circle-ir-ai 2.17.0 → 2.18.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/CHANGELOG.md CHANGED
@@ -5,6 +5,91 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.18.0] - 2026-06-22
9
+
10
+ ### Added — findings-emission instrumentation env wiring (cognium-dev#145 PR C)
11
+
12
+ `circle-ir-ai` now honors the `CIRCLE_IR_INSTRUMENT_FINDINGS=1`
13
+ environment variable at analyzer-init time, flipping
14
+ `setFindingsInstrumentation(true)` on `circle-ir`'s opt-in
15
+ findings-emission hook. With the env var set, every call into
16
+ `circle-ir`'s `analyze()` — from both the scanner static path and the
17
+ mastra `runPatternMatch` LLM path — emits one `[finding]` JSON line on
18
+ stderr per `SastFinding` plus one `[findings-summary]` line per file.
19
+
20
+ Each `[finding]` payload carries the fields required to re-derive
21
+ coalesce candidates for cognium-dev#143 after the fact:
22
+
23
+ ```jsonc
24
+ {
25
+ "file": "VulnServlet.java",
26
+ "line": 9,
27
+ "rule_id": "sql-injection-jdbc",
28
+ "pass": "TaintMatcherPass",
29
+ "category": "security",
30
+ "severity": "high",
31
+ "cwe": "CWE-89",
32
+ "sink_type": "sql-query",
33
+ "source_type": "http-param",
34
+ "confidence": 0.95,
35
+ "dedup_group_id": "VulnServlet.java:9:sql-injection-jdbc"
36
+ }
37
+ ```
38
+
39
+ Per-file summary payload:
40
+
41
+ ```jsonc
42
+ {
43
+ "file": "VulnServlet.java",
44
+ "total": 3,
45
+ "unique_groups": 2,
46
+ "max_findings_per_group": 2,
47
+ "sources_count": 1,
48
+ "sinks_count": 1,
49
+ "by_rule": { "sql-injection-jdbc": 3 },
50
+ "by_severity": { "high": 3 }
51
+ }
52
+ ```
53
+
54
+ The wiring lives in `src/utils/analyzer-init.ts` so any call into
55
+ `ensureAnalyzerInitialized()` — which both `scanner.ts` and mastra's
56
+ `runPatternMatch()` already use — applies the env var idempotently. No
57
+ public API change; `setFindingsInstrumentation()` remains the
58
+ programmatic entry point for non-CLI consumers.
59
+
60
+ Output is `console.error` (per the upstream hook contract — see
61
+ `circle-ir/dist/analysis/findings-instrumentation.js:13-15`). Redirect
62
+ stderr to capture: `CIRCLE_IR_INSTRUMENT_FINDINGS=1 cognium-ai scan ./src
63
+ 2> findings.jsonl`. The flag is fully no-op when unset; no perf or
64
+ allocation overhead on the default path.
65
+
66
+ ### Why this matters
67
+
68
+ The empirical data collected here informs the **cognium-dev#143
69
+ "coalesce candidates"** decision. The `dedup_group_id` field plus per-
70
+ file `max_findings_per_group` count let us measure how often
71
+ `(file, line, rule_id)` clusters actually receive multiple
72
+ near-duplicate emissions in the wild. That measurement is the gating
73
+ input for whether circle-ir's findings pipeline should add a
74
+ post-emit coalesce pass or leave the existing dedup logic alone.
75
+
76
+ ### Verification
77
+
78
+ - `npm run build` — clean.
79
+ - `npm run typecheck` — clean.
80
+ - `npm test` — **900 / 900 pass + 3 skipped** (+2 new tests
81
+ `findings-instrumentation.test.ts` covering both env states).
82
+ - Manual: `CIRCLE_IR_INSTRUMENT_FINDINGS=1 ...` emits `[finding]` and
83
+ `[findings-summary]` lines on stderr; unsetting suppresses both.
84
+
85
+ ### Why minor (`2.17.0 → 2.18.0`)
86
+
87
+ Additive: new env-var honored at init time, no removed or renamed
88
+ exports, no change to the default observable output. Downstream
89
+ packages (`cognium-ai`, `@cognium-ai/mcp-server`, `circle-pack`) need a
90
+ dep range bump but no source-side change to benefit — setting the env
91
+ var is enough.
92
+
8
93
  ## [2.17.0] - 2026-06-22
9
94
 
10
95
  ### Dependencies
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer-init.d.ts","sourceRoot":"","sources":["../../src/utils/analyzer-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAuC,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAKtF;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBjG;AAGD,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"analyzer-init.d.ts","sourceRoot":"","sources":["../../src/utils/analyzer-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,WAAW,CAAC;AAgCnB;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BjG;AAGD,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC"}
@@ -5,14 +5,44 @@
5
5
  * This fixes issues when cognium-ai is installed globally or in various
6
6
  * node_modules configurations.
7
7
  */
8
- import { initAnalyzer, isAnalyzerInitialized } from 'circle-ir';
8
+ import { initAnalyzer, isAnalyzerInitialized, setFindingsInstrumentation, } from 'circle-ir';
9
9
  import { getWasmAnalyzerOptions } from './wasm-path.js';
10
10
  let initializationPromise = null;
11
+ let instrumentationApplied = false;
12
+ /**
13
+ * cognium-dev#145 PR C — honor `CIRCLE_IR_INSTRUMENT_FINDINGS=1` at
14
+ * analyzer-init time so every path that hits circle-ir's `analyze()`
15
+ * (scanner static path + mastra `runPatternMatch` LLM path) emits the
16
+ * per-file `[finding]` / `[findings-summary]` JSON lines on stderr.
17
+ *
18
+ * `circle-ir`'s library does not read the env var itself — only its
19
+ * own CLI does. We translate the env var to `setFindingsInstrumentation(true)`
20
+ * here so cognium-ai runs honor the same opt-in toggle without each CLI
21
+ * needing to re-implement the wiring.
22
+ *
23
+ * Idempotent: only flips the toggle on once per process even though
24
+ * `ensureAnalyzerInitialized` may be called many times. Never disables
25
+ * the flag — external `setFindingsInstrumentation(false)` calls still
26
+ * take effect.
27
+ */
28
+ function applyInstrumentationEnv() {
29
+ if (instrumentationApplied) {
30
+ return;
31
+ }
32
+ instrumentationApplied = true;
33
+ if (process.env.CIRCLE_IR_INSTRUMENT_FINDINGS === '1') {
34
+ setFindingsInstrumentation(true);
35
+ }
36
+ }
11
37
  /**
12
38
  * Initialize the analyzer with proper WASM path resolution.
13
39
  * Safe to call multiple times - will only initialize once.
14
40
  */
15
41
  export async function ensureAnalyzerInitialized(options) {
42
+ // Apply instrumentation toggle on every call (cheap, idempotent) so the
43
+ // env-var check happens even when the analyzer was warmed by an unrelated
44
+ // import path.
45
+ applyInstrumentationEnv();
16
46
  if (isAnalyzerInitialized()) {
17
47
  return;
18
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer-init.js","sourceRoot":"","sources":["../../src/utils/analyzer-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAwB,MAAM,WAAW,CAAC;AACtF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,IAAI,qBAAqB,GAAyB,IAAI,CAAC;AAEvD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,OAAkC;IAChF,IAAI,qBAAqB,EAAE,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,IAAI,qBAAqB,EAAE,CAAC;QAC1B,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,qBAAqB,GAAG,CAAC,KAAK,IAAI,EAAE;QAClC,gDAAgD;QAChD,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAC;QAE7C,uCAAuC;QACvC,MAAM,aAAa,GAAoB;YACrC,GAAG,WAAW;YACd,GAAG,OAAO;SACX,CAAC;QAEF,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAED,4BAA4B;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"analyzer-init.js","sourceRoot":"","sources":["../../src/utils/analyzer-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,0BAA0B,GAE3B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,IAAI,qBAAqB,GAAyB,IAAI,CAAC;AACvD,IAAI,sBAAsB,GAAG,KAAK,CAAC;AAEnC;;;;;;;;;;;;;;;GAeG;AACH,SAAS,uBAAuB;IAC9B,IAAI,sBAAsB,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IACD,sBAAsB,GAAG,IAAI,CAAC;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,GAAG,EAAE,CAAC;QACtD,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,OAAkC;IAChF,wEAAwE;IACxE,0EAA0E;IAC1E,eAAe;IACf,uBAAuB,EAAE,CAAC;IAE1B,IAAI,qBAAqB,EAAE,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,IAAI,qBAAqB,EAAE,CAAC;QAC1B,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,qBAAqB,GAAG,CAAC,KAAK,IAAI,EAAE;QAClC,gDAAgD;QAChD,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAC;QAE7C,uCAAuC;QACvC,MAAM,aAAa,GAAoB;YACrC,GAAG,WAAW;YACd,GAAG,OAAO;SACX,CAAC;QAEF,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAED,4BAA4B;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir-ai",
3
- "version": "2.17.0",
3
+ "version": "2.18.0",
4
4
  "description": "LLM-enhanced SAST analysis built on circle-ir",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",