circle-ir-ai 2.17.0 → 2.18.1
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,124 @@ 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.1] - 2026-06-23
|
|
9
|
+
|
|
10
|
+
### Dependencies
|
|
11
|
+
|
|
12
|
+
- Bump `circle-ir` `3.93.0` → `3.95.0`.
|
|
13
|
+
|
|
14
|
+
### What this pulls in
|
|
15
|
+
|
|
16
|
+
`circle-ir@3.94.0` shipped the `SastFinding.confidence` tri-state
|
|
17
|
+
field (`'high' | 'medium' | 'low'`) and the per-file
|
|
18
|
+
speculative-finding suppression infrastructure that the upcoming
|
|
19
|
+
`missing-sanitizer-gate` pass will use. Pre-3.94.0 passes leave the
|
|
20
|
+
field undefined and are treated as `'high'` (always emitted), so
|
|
21
|
+
scanner output is unchanged today.
|
|
22
|
+
|
|
23
|
+
`circle-ir@3.95.0` adds `AnalyzerOptions.enableEntryPointGate?:
|
|
24
|
+
boolean` (default `true`) — an opt-out toggle for the Java
|
|
25
|
+
entry-point classifier gate that suppresses
|
|
26
|
+
`interprocedural_param` taint sources on library-API methods not
|
|
27
|
+
reachable from a recognised HTTP / RPC / lifecycle entry point.
|
|
28
|
+
Java-only; no-op for other languages regardless of toggle state.
|
|
29
|
+
`circle-ir-ai` does not yet thread this flag through the mastra
|
|
30
|
+
workflow or scanner facade — callers that need the un-gated source
|
|
31
|
+
set can pass it directly via the `circle-ir` `analyze()` /
|
|
32
|
+
`InterproceduralPass` constructor.
|
|
33
|
+
|
|
34
|
+
### Verification
|
|
35
|
+
|
|
36
|
+
- `npm run build` — clean.
|
|
37
|
+
- Tests unchanged (900 pass + 3 skipped).
|
|
38
|
+
|
|
39
|
+
No API shape change in `circle-ir-ai`.
|
|
40
|
+
|
|
41
|
+
## [2.18.0] - 2026-06-22
|
|
42
|
+
|
|
43
|
+
### Added — findings-emission instrumentation env wiring (cognium-dev#145 PR C)
|
|
44
|
+
|
|
45
|
+
`circle-ir-ai` now honors the `CIRCLE_IR_INSTRUMENT_FINDINGS=1`
|
|
46
|
+
environment variable at analyzer-init time, flipping
|
|
47
|
+
`setFindingsInstrumentation(true)` on `circle-ir`'s opt-in
|
|
48
|
+
findings-emission hook. With the env var set, every call into
|
|
49
|
+
`circle-ir`'s `analyze()` — from both the scanner static path and the
|
|
50
|
+
mastra `runPatternMatch` LLM path — emits one `[finding]` JSON line on
|
|
51
|
+
stderr per `SastFinding` plus one `[findings-summary]` line per file.
|
|
52
|
+
|
|
53
|
+
Each `[finding]` payload carries the fields required to re-derive
|
|
54
|
+
coalesce candidates for cognium-dev#143 after the fact:
|
|
55
|
+
|
|
56
|
+
```jsonc
|
|
57
|
+
{
|
|
58
|
+
"file": "VulnServlet.java",
|
|
59
|
+
"line": 9,
|
|
60
|
+
"rule_id": "sql-injection-jdbc",
|
|
61
|
+
"pass": "TaintMatcherPass",
|
|
62
|
+
"category": "security",
|
|
63
|
+
"severity": "high",
|
|
64
|
+
"cwe": "CWE-89",
|
|
65
|
+
"sink_type": "sql-query",
|
|
66
|
+
"source_type": "http-param",
|
|
67
|
+
"confidence": 0.95,
|
|
68
|
+
"dedup_group_id": "VulnServlet.java:9:sql-injection-jdbc"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Per-file summary payload:
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
"file": "VulnServlet.java",
|
|
77
|
+
"total": 3,
|
|
78
|
+
"unique_groups": 2,
|
|
79
|
+
"max_findings_per_group": 2,
|
|
80
|
+
"sources_count": 1,
|
|
81
|
+
"sinks_count": 1,
|
|
82
|
+
"by_rule": { "sql-injection-jdbc": 3 },
|
|
83
|
+
"by_severity": { "high": 3 }
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The wiring lives in `src/utils/analyzer-init.ts` so any call into
|
|
88
|
+
`ensureAnalyzerInitialized()` — which both `scanner.ts` and mastra's
|
|
89
|
+
`runPatternMatch()` already use — applies the env var idempotently. No
|
|
90
|
+
public API change; `setFindingsInstrumentation()` remains the
|
|
91
|
+
programmatic entry point for non-CLI consumers.
|
|
92
|
+
|
|
93
|
+
Output is `console.error` (per the upstream hook contract — see
|
|
94
|
+
`circle-ir/dist/analysis/findings-instrumentation.js:13-15`). Redirect
|
|
95
|
+
stderr to capture: `CIRCLE_IR_INSTRUMENT_FINDINGS=1 cognium-ai scan ./src
|
|
96
|
+
2> findings.jsonl`. The flag is fully no-op when unset; no perf or
|
|
97
|
+
allocation overhead on the default path.
|
|
98
|
+
|
|
99
|
+
### Why this matters
|
|
100
|
+
|
|
101
|
+
The empirical data collected here informs the **cognium-dev#143
|
|
102
|
+
"coalesce candidates"** decision. The `dedup_group_id` field plus per-
|
|
103
|
+
file `max_findings_per_group` count let us measure how often
|
|
104
|
+
`(file, line, rule_id)` clusters actually receive multiple
|
|
105
|
+
near-duplicate emissions in the wild. That measurement is the gating
|
|
106
|
+
input for whether circle-ir's findings pipeline should add a
|
|
107
|
+
post-emit coalesce pass or leave the existing dedup logic alone.
|
|
108
|
+
|
|
109
|
+
### Verification
|
|
110
|
+
|
|
111
|
+
- `npm run build` — clean.
|
|
112
|
+
- `npm run typecheck` — clean.
|
|
113
|
+
- `npm test` — **900 / 900 pass + 3 skipped** (+2 new tests
|
|
114
|
+
`findings-instrumentation.test.ts` covering both env states).
|
|
115
|
+
- Manual: `CIRCLE_IR_INSTRUMENT_FINDINGS=1 ...` emits `[finding]` and
|
|
116
|
+
`[findings-summary]` lines on stderr; unsetting suppresses both.
|
|
117
|
+
|
|
118
|
+
### Why minor (`2.17.0 → 2.18.0`)
|
|
119
|
+
|
|
120
|
+
Additive: new env-var honored at init time, no removed or renamed
|
|
121
|
+
exports, no change to the default observable output. Downstream
|
|
122
|
+
packages (`cognium-ai`, `@cognium-ai/mcp-server`, `circle-pack`) need a
|
|
123
|
+
dep range bump but no source-side change to benefit — setting the env
|
|
124
|
+
var is enough.
|
|
125
|
+
|
|
8
126
|
## [2.17.0] - 2026-06-22
|
|
9
127
|
|
|
10
128
|
### Dependencies
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer-init.d.ts","sourceRoot":"","sources":["../../src/utils/analyzer-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,
|
|
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,
|
|
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.
|
|
3
|
+
"version": "2.18.1",
|
|
4
4
|
"description": "LLM-enhanced SAST analysis built on circle-ir",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"dependencies": {
|
|
96
96
|
"@ax-llm/ax": "^20.0.0",
|
|
97
97
|
"@mastra/core": "^1.18.0",
|
|
98
|
-
"circle-ir": "3.
|
|
98
|
+
"circle-ir": "3.95.0",
|
|
99
99
|
"minimatch": "^10.2.5",
|
|
100
100
|
"p-queue": "^9.1.0"
|
|
101
101
|
},
|