circle-ir-ai 2.16.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,139 @@ 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
|
+
|
|
93
|
+
## [2.17.0] - 2026-06-22
|
|
94
|
+
|
|
95
|
+
### Dependencies
|
|
96
|
+
|
|
97
|
+
- Bump `circle-ir` `3.89.1` → `3.90.0`.
|
|
98
|
+
|
|
99
|
+
### What 3.90.0 brings (inherited, no source-side changes here)
|
|
100
|
+
|
|
101
|
+
`circle-ir@3.90.0` adds the **findings-emission instrumentation hook**
|
|
102
|
+
that closes out cognium-dev#145 (PR B). Per-file `SastFinding[]`
|
|
103
|
+
finalization now emits to an opt-in JSONL sink controlled by the
|
|
104
|
+
engine's instrumentation surface (`emitFindingsInstrumentation`
|
|
105
|
+
callback / env-var hook — see circle-ir 3.90.0 release notes for the
|
|
106
|
+
exact wiring). This is the data source #143 will consume to evaluate
|
|
107
|
+
coalesce hypotheses against real CLI workloads.
|
|
108
|
+
|
|
109
|
+
Per-finding payload includes at minimum: `ruleId`, `file`, `line`,
|
|
110
|
+
`sinkType`, `sourceType`, `severity`, `confidence`, `dedup_group_id`.
|
|
111
|
+
**Payload schema is stable-additive** — the engine reserves the right
|
|
112
|
+
to add new fields driven by #143's analysis without a major bump.
|
|
113
|
+
Consumers should ignore unknown keys. Function signature is the
|
|
114
|
+
freeze point.
|
|
115
|
+
|
|
116
|
+
### What `circle-ir-ai` does with the hook (today: nothing)
|
|
117
|
+
|
|
118
|
+
Engine-side surface is opt-in; no `circle-ir-ai` source exercises
|
|
119
|
+
the hook yet. The intended consumer is PR C in `circle-ir-ai`
|
|
120
|
+
itself (separate cycle), which will wire the hook through the
|
|
121
|
+
mastra `runPatternMatch → analyze()` path so cognium-ai scans
|
|
122
|
+
surface the instrumentation without users having to import
|
|
123
|
+
`circle-ir` directly. Until PR C ships, the hook fires only for
|
|
124
|
+
direct `circle-ir` consumers that opt in.
|
|
125
|
+
|
|
126
|
+
### Verification
|
|
127
|
+
|
|
128
|
+
- `npm install --prefer-online` — clean; `npm ls circle-ir` shows
|
|
129
|
+
`3.90.0`.
|
|
130
|
+
- `npm run build` — clean.
|
|
131
|
+
- `npm run typecheck` — clean.
|
|
132
|
+
- `npm test` — **898 / 898 pass** (3 skipped).
|
|
133
|
+
|
|
134
|
+
### Why minor (`2.16.0 → 2.17.0`)
|
|
135
|
+
|
|
136
|
+
New engine surface is reachable via direct `circle-ir` import even
|
|
137
|
+
though no `circle-ir-ai` code-path exercises it yet. Minor bump
|
|
138
|
+
signals the underlying capability uplift to downstream consumers
|
|
139
|
+
(mcp-server, circle-pack) that may wire the hook independently.
|
|
140
|
+
|
|
8
141
|
## [2.16.0] - 2026-06-22
|
|
9
142
|
|
|
10
143
|
### Added
|
|
@@ -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.0",
|
|
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.90.0",
|
|
99
99
|
"minimatch": "^10.2.5",
|
|
100
100
|
"p-queue": "^9.1.0"
|
|
101
101
|
},
|