@kyo-so/cli 0.7.1 → 0.8.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/.agents/skills/kyoso-review/SKILL.md +13 -4
- package/CHANGELOG.md +16 -0
- package/README.ja.md +12 -2
- package/README.md +12 -2
- package/README.zh-CN.md +12 -2
- package/dist/bin/kyoso.js +134 -24
- package/dist/config/configOverrides.d.ts +2 -0
- package/dist/config/projectScope.d.ts +2 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/runReview.d.ts +1 -0
- package/dist/index.js +128 -25
- package/package.json +1 -1
|
@@ -29,10 +29,19 @@ Do not use this skill for every coding task. It is intended for deliberate revie
|
|
|
29
29
|
- selected files
|
|
30
30
|
- unified diff if available
|
|
31
31
|
- constraints
|
|
32
|
-
4.
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
4. Run the review through the first available path:
|
|
33
|
+
- Prefer the corresponding Kyoso MCP tool when it is available:
|
|
34
|
+
- `plan_review`
|
|
35
|
+
- `security_review`
|
|
36
|
+
- `diff_review`
|
|
37
|
+
- If the MCP tools are unavailable, use the CLI fallback with JSON output:
|
|
38
|
+
- `plan_review` -> `npx -y @kyo-so/cli plan --goal <text> [--plan <path-or-text>] [--file <path>] --json`
|
|
39
|
+
- `security_review` -> `npx -y @kyo-so/cli security --goal <text> [--diff <path>] [--file <path>] --json`
|
|
40
|
+
- `diff_review` -> `npx -y @kyo-so/cli diff --base <ref> --head <ref> --json`
|
|
41
|
+
- `bunx @kyo-so/cli` may be used instead of `npx -y @kyo-so/cli`.
|
|
42
|
+
- The CLI also accepts `--repo-summary`, repeatable `--constraint`, and repeatable `--file` flags. For a large review, adjust an agent timeout with `--set agents.<agent>.timeoutMs=<ms>`.
|
|
43
|
+
- Run the CLI without a config trust flag first. Inspect `audit.warnings` in the JSON result; if it contains `untrusted config was not executed`, or the command fails with an untrusted-config message, ask the user whether to rerun with `--trust-config` to use it or `--ignore-config` to skip it. Never add `--trust-config` without confirmation.
|
|
44
|
+
- Keep `--json` enabled and interpret the returned `decision` exactly like the MCP result.
|
|
36
45
|
5. Treat `decision: block` as a stop signal. Present the result to the user before implementing.
|
|
37
46
|
6. Treat `decision: approve_with_changes` as requiring changes to the plan or implementation.
|
|
38
47
|
7. Do not claim Kyoso modified files. Kyoso only reviews.
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] - 2026-07-10
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Repeatable `--set <config-key>=<value>` option on the `plan`, `security`,
|
|
15
|
+
and `diff` commands for overriding config values such as
|
|
16
|
+
`agents.<agent>.model`, `agents.<agent>.effort`, and `timeoutMs` from the
|
|
17
|
+
command line. Overrides are restricted to the shared project-scope
|
|
18
|
+
allowlist, applied after config files (including with `--ignore-config`),
|
|
19
|
+
and schema-validated.
|
|
20
|
+
- CLI fallback in the bundled `kyoso-review` skill: when the Kyoso MCP
|
|
21
|
+
server is not registered, the skill falls back to
|
|
22
|
+
`npx`/`bunx @kyo-so/cli plan|security|diff --json`. The fallback runs
|
|
23
|
+
without config trust flags first and requires user confirmation before
|
|
24
|
+
`--trust-config` or `--ignore-config`. Documented in all README languages.
|
|
25
|
+
|
|
10
26
|
## [0.7.1] - 2026-07-09
|
|
11
27
|
|
|
12
28
|
### Changed
|
package/README.ja.md
CHANGED
|
@@ -136,7 +136,7 @@ Nix dev shell は Node.js 24 と nixpkgs が提供する Bun version を固定
|
|
|
136
136
|
```bash
|
|
137
137
|
kyoso plan --goal "Review this OAuth callback plan" --plan plan.md
|
|
138
138
|
kyoso security --goal "Review this auth diff" --diff changes.patch
|
|
139
|
-
kyoso diff --base main --head HEAD
|
|
139
|
+
kyoso diff --base main --head HEAD --set agents.claude.effort=high
|
|
140
140
|
kyoso doctor
|
|
141
141
|
kyoso init
|
|
142
142
|
kyoso setup codex
|
|
@@ -203,6 +203,8 @@ MCP stdout は protocol messages 専用です。logs は stderr または local
|
|
|
203
203
|
|
|
204
204
|
同梱の `kyoso-review` skill は意図的に狭い用途にしています。Kyoso、multi-agent review、plan review、security review、CISA Secure by Design review、diff review を明示的に依頼したときだけ trigger されるべきです。
|
|
205
205
|
|
|
206
|
+
skill は、利用可能な場合は Kyoso MCP tools を優先します。MCP server が未登録の場合は、記載された CLI fallback に従い、`npx -y @kyo-so/cli` または `bunx @kyo-so/cli` から JSON output を取得します。
|
|
207
|
+
|
|
206
208
|
`npx @kyo-so/cli setup codex --write` と `bunx @kyo-so/cli setup codex --write` は、既定で `.agents/skills/kyoso-review/` にコピーします。`--global` を追加すると `~/.agents/skills/kyoso-review/` にコピーします。
|
|
207
209
|
|
|
208
210
|
`npx @kyo-so/cli setup claude-code --write` と `bunx @kyo-so/cli setup claude-code --write` は、既定で `.claude/skills/kyoso-review/` にコピーします。`--global` を追加すると `~/.claude/skills/kyoso-review/` にコピーします。
|
|
@@ -281,7 +283,15 @@ Kyoso は次の順に config を load します。
|
|
|
281
283
|
- built-in defaults
|
|
282
284
|
- user global TOML: `$XDG_CONFIG_HOME/kyoso/config.toml`、または `~/.config/kyoso/config.toml`
|
|
283
285
|
- project TOML: `<cwd>/kyoso.toml`
|
|
284
|
-
- `--network` などの CLI flags
|
|
286
|
+
- `--network` などの CLI flags と `--set agents.claude.effort=high` などの反復可能な overrides
|
|
287
|
+
|
|
288
|
+
`plan`、`security`、`diff` は、反復可能な `--set <key>=<value>` overrides を受け付けます。CLI で指定した値は config files より優先され、`--ignore-config` との併用も可能です。
|
|
289
|
+
|
|
290
|
+
- Agent keys: `agents.<codex|claude>.<enabled|model|effort|role|timeoutMs>`
|
|
291
|
+
- Verification keys: `verification.<enabled|maxFindings|timeoutMs>`
|
|
292
|
+
- Judge keys: `judge.<mode|provider|timeoutMs>`
|
|
293
|
+
|
|
294
|
+
未知の key は拒否されます。boolean / numeric config keys は schema の型へ変換し、string keys は文字列のまま保持した後、config 全体を再検証します。
|
|
285
295
|
|
|
286
296
|
Project `kyoso.toml` は declarative で、trust approval は不要です。tools toggles、agent `enabled` / `model` / `effort` / `role` / `timeoutMs`、workspace byte limits と additive `workspace.deny`、verification settings、advisory judge settings、tightening-only security/network settings を設定できます。
|
|
287
297
|
|
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ Known distribution risk: `@modelcontextprotocol/server` has no stable release ye
|
|
|
137
137
|
```bash
|
|
138
138
|
kyoso plan --goal "Review this OAuth callback plan" --plan plan.md
|
|
139
139
|
kyoso security --goal "Review this auth diff" --diff changes.patch
|
|
140
|
-
kyoso diff --base main --head HEAD
|
|
140
|
+
kyoso diff --base main --head HEAD --set agents.claude.effort=high
|
|
141
141
|
kyoso doctor
|
|
142
142
|
kyoso init
|
|
143
143
|
kyoso setup codex
|
|
@@ -204,6 +204,8 @@ MCP stdout is reserved for protocol messages. Logs go to stderr or local audit t
|
|
|
204
204
|
|
|
205
205
|
The bundled `kyoso-review` skill is intentionally narrow. It should trigger only when you explicitly ask for Kyoso, multi-agent review, plan review, security review, CISA Secure by Design review, or diff review.
|
|
206
206
|
|
|
207
|
+
The skill prefers the Kyoso MCP tools when available. If the MCP server is not registered, it follows its documented CLI fallback and requests JSON output from `npx -y @kyo-so/cli` or `bunx @kyo-so/cli`.
|
|
208
|
+
|
|
207
209
|
`npx @kyo-so/cli setup codex --write` and `bunx @kyo-so/cli setup codex --write` copy it to `.agents/skills/kyoso-review/` by default. Add `--global` to copy it to `~/.agents/skills/kyoso-review/`.
|
|
208
210
|
|
|
209
211
|
`npx @kyo-so/cli setup claude-code --write` and `bunx @kyo-so/cli setup claude-code --write` copy it to `.claude/skills/kyoso-review/` by default. Add `--global` to copy it to `~/.claude/skills/kyoso-review/`.
|
|
@@ -282,7 +284,15 @@ Kyoso loads config in this order:
|
|
|
282
284
|
- built-in defaults
|
|
283
285
|
- user global TOML: `$XDG_CONFIG_HOME/kyoso/config.toml`, or `~/.config/kyoso/config.toml`
|
|
284
286
|
- project TOML: `<cwd>/kyoso.toml`
|
|
285
|
-
- CLI flags such as `--network`
|
|
287
|
+
- CLI flags such as `--network` and repeatable overrides such as `--set agents.claude.effort=high`
|
|
288
|
+
|
|
289
|
+
`plan`, `security`, and `diff` accept repeatable `--set <key>=<value>` overrides. Values set on the CLI take precedence over config files, including when `--ignore-config` is used.
|
|
290
|
+
|
|
291
|
+
- Agent keys: `agents.<codex|claude>.<enabled|model|effort|role|timeoutMs>`
|
|
292
|
+
- Verification keys: `verification.<enabled|maxFindings|timeoutMs>`
|
|
293
|
+
- Judge keys: `judge.<mode|provider|timeoutMs>`
|
|
294
|
+
|
|
295
|
+
Unknown keys are rejected. Boolean and numeric config keys are converted to their schema types; string keys remain strings. The complete config is then validated.
|
|
286
296
|
|
|
287
297
|
Project `kyoso.toml` is declarative and does not require trust approval. It can set safe project-scoped keys such as tool toggles, agent `enabled` / `model` / `effort` / `role` / `timeoutMs`, workspace byte limits and additive `workspace.deny`, verification settings, advisory judge settings, and tightening-only security/network settings.
|
|
288
298
|
|
package/README.zh-CN.md
CHANGED
|
@@ -136,7 +136,7 @@ Nix dev shell 会 pin Node.js 24 和 nixpkgs 提供的 Bun version。确认 `.en
|
|
|
136
136
|
```bash
|
|
137
137
|
kyoso plan --goal "Review this OAuth callback plan" --plan plan.md
|
|
138
138
|
kyoso security --goal "Review this auth diff" --diff changes.patch
|
|
139
|
-
kyoso diff --base main --head HEAD
|
|
139
|
+
kyoso diff --base main --head HEAD --set agents.claude.effort=high
|
|
140
140
|
kyoso doctor
|
|
141
141
|
kyoso init
|
|
142
142
|
kyoso setup codex
|
|
@@ -203,6 +203,8 @@ MCP stdout 专用于 protocol messages。Logs 会写到 stderr 或 local audit t
|
|
|
203
203
|
|
|
204
204
|
内置的 `kyoso-review` skill 有意保持范围很窄。只有当你明确请求 Kyoso、multi-agent review、plan review、security review、CISA Secure by Design review 或 diff review 时,才应触发它。
|
|
205
205
|
|
|
206
|
+
当 Kyoso MCP tools 可用时,skill 会优先使用它们。如果尚未注册 MCP server,skill 会按照文档中的 CLI fallback,通过 `npx -y @kyo-so/cli` 或 `bunx @kyo-so/cli` 获取 JSON output。
|
|
207
|
+
|
|
206
208
|
`npx @kyo-so/cli setup codex --write` 和 `bunx @kyo-so/cli setup codex --write` 默认将其复制到 `.agents/skills/kyoso-review/`。添加 `--global` 会复制到 `~/.agents/skills/kyoso-review/`。
|
|
207
209
|
|
|
208
210
|
`npx @kyo-so/cli setup claude-code --write` 和 `bunx @kyo-so/cli setup claude-code --write` 默认将其复制到 `.claude/skills/kyoso-review/`。添加 `--global` 会复制到 `~/.claude/skills/kyoso-review/`。
|
|
@@ -281,7 +283,15 @@ Kyoso 按以下顺序 load config:
|
|
|
281
283
|
- built-in defaults
|
|
282
284
|
- user global TOML: `$XDG_CONFIG_HOME/kyoso/config.toml`,或 `~/.config/kyoso/config.toml`
|
|
283
285
|
- project TOML: `<cwd>/kyoso.toml`
|
|
284
|
-
- `--network` 等 CLI flags
|
|
286
|
+
- `--network` 等 CLI flags,以及 `--set agents.claude.effort=high` 等可重复的 overrides
|
|
287
|
+
|
|
288
|
+
`plan`、`security` 和 `diff` 接受可重复的 `--set <key>=<value>` overrides。CLI 指定的值优先于 config files,也可以与 `--ignore-config` 一起使用。
|
|
289
|
+
|
|
290
|
+
- Agent keys: `agents.<codex|claude>.<enabled|model|effort|role|timeoutMs>`
|
|
291
|
+
- Verification keys: `verification.<enabled|maxFindings|timeoutMs>`
|
|
292
|
+
- Judge keys: `judge.<mode|provider|timeoutMs>`
|
|
293
|
+
|
|
294
|
+
未知 key 会被拒绝。Boolean / numeric config keys 会转换为 schema 类型,string keys 保持字符串,然后重新验证完整 config。
|
|
285
295
|
|
|
286
296
|
Project `kyoso.toml` 是 declarative config,不需要 trust approval。它可以设置 tools toggles、agent `enabled` / `model` / `effort` / `role` / `timeoutMs`、workspace byte limits 和 additive `workspace.deny`、verification settings、advisory judge settings,以及 tightening-only security/network settings。
|
|
287
297
|
|
package/dist/bin/kyoso.js
CHANGED
|
@@ -169739,6 +169739,28 @@ var defaultConfig = {
|
|
|
169739
169739
|
|
|
169740
169740
|
// src/config/projectScope.ts
|
|
169741
169741
|
var PROJECT_GLOBAL_ONLY_MESSAGE = "Move global-only settings to the user global config:";
|
|
169742
|
+
var kyosoConfigOverridePaths = [
|
|
169743
|
+
"agents.codex.enabled",
|
|
169744
|
+
"agents.codex.model",
|
|
169745
|
+
"agents.codex.effort",
|
|
169746
|
+
"agents.codex.role",
|
|
169747
|
+
"agents.codex.timeoutMs",
|
|
169748
|
+
"agents.claude.enabled",
|
|
169749
|
+
"agents.claude.model",
|
|
169750
|
+
"agents.claude.effort",
|
|
169751
|
+
"agents.claude.role",
|
|
169752
|
+
"agents.claude.timeoutMs",
|
|
169753
|
+
"verification.enabled",
|
|
169754
|
+
"verification.maxFindings",
|
|
169755
|
+
"verification.timeoutMs",
|
|
169756
|
+
"judge.mode",
|
|
169757
|
+
"judge.provider",
|
|
169758
|
+
"judge.timeoutMs"
|
|
169759
|
+
];
|
|
169760
|
+
var CONFIG_OVERRIDE_PATHS = new Set(kyosoConfigOverridePaths);
|
|
169761
|
+
function isAllowedConfigOverridePath(path) {
|
|
169762
|
+
return CONFIG_OVERRIDE_PATHS.has(path.join("."));
|
|
169763
|
+
}
|
|
169742
169764
|
function mergeProjectTomlConfig(baseConfig, projectConfig, options) {
|
|
169743
169765
|
const violations = collectProjectScopeViolations(projectConfig);
|
|
169744
169766
|
if (violations.length > 0) {
|
|
@@ -169771,13 +169793,9 @@ function collectProjectScopeViolations(config) {
|
|
|
169771
169793
|
}
|
|
169772
169794
|
function isAllowedProjectPath(path) {
|
|
169773
169795
|
const [top, second, third, fourth] = path;
|
|
169774
|
-
if (
|
|
169796
|
+
if (isAllowedConfigOverridePath(path))
|
|
169775
169797
|
return true;
|
|
169776
|
-
|
|
169777
|
-
if (top === "agents" && path.length === 3 && ["codex", "claude"].includes(second ?? "") && ["enabled", "model", "effort", "role", "timeoutMs"].includes(third ?? "")) {
|
|
169778
|
-
return true;
|
|
169779
|
-
}
|
|
169780
|
-
if (top === "verification" && path.length === 2 && ["enabled", "maxFindings", "timeoutMs"].includes(second ?? "")) {
|
|
169798
|
+
if (top === "tools" && path.length === 2 && ["planReview", "securityReview", "diffReview"].includes(second ?? "")) {
|
|
169781
169799
|
return true;
|
|
169782
169800
|
}
|
|
169783
169801
|
if (top === "workspace" && path.length === 2 && ["maxContextBytes", "maxDiffBytes", "deny"].includes(second ?? "")) {
|
|
@@ -169789,9 +169807,6 @@ function isAllowedProjectPath(path) {
|
|
|
169789
169807
|
if (top === "secrets" && path.length === 2 && ["blockOnDetectedSecret", "allowOverride"].includes(second ?? "")) {
|
|
169790
169808
|
return true;
|
|
169791
169809
|
}
|
|
169792
|
-
if (top === "judge" && path.length === 2 && ["mode", "provider", "timeoutMs"].includes(second ?? "")) {
|
|
169793
|
-
return true;
|
|
169794
|
-
}
|
|
169795
169810
|
if (top === "securityReview" && second === "cisaSecureByDesign" && path.length >= 3) {
|
|
169796
169811
|
if (third === "dimensions") {
|
|
169797
169812
|
return path.length === 4 && [
|
|
@@ -184349,7 +184364,7 @@ var REDACTION = "[KYOSO_REDACTED]";
|
|
|
184349
184364
|
var DEFAULT_AGENT_TIMEOUT_MS = 120000;
|
|
184350
184365
|
var RAW_OUTPUT_MAX_CHARS = 16384;
|
|
184351
184366
|
var KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
|
|
184352
|
-
var KYOSO_VERSION = "0.
|
|
184367
|
+
var KYOSO_VERSION = "0.8.0";
|
|
184353
184368
|
|
|
184354
184369
|
// src/security/sanitizeText.ts
|
|
184355
184370
|
var SENSITIVE_TEXT_PATTERNS = [
|
|
@@ -199812,6 +199827,90 @@ var StdioServerTransport = class {
|
|
|
199812
199827
|
// src/core/runReview.ts
|
|
199813
199828
|
import { resolve as resolve6 } from "node:path";
|
|
199814
199829
|
|
|
199830
|
+
// src/config/configOverrides.ts
|
|
199831
|
+
var NUMBER_VALUE = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
|
|
199832
|
+
function applyConfigOverrides(config2, assignments) {
|
|
199833
|
+
if (assignments.length === 0)
|
|
199834
|
+
return config2;
|
|
199835
|
+
const overrides = assignments.map(parseConfigOverride);
|
|
199836
|
+
const baseConfig = config2;
|
|
199837
|
+
const overridden = structuredClone(config2);
|
|
199838
|
+
for (const override of overrides) {
|
|
199839
|
+
writePath2(overridden, override.path, parseConfigOverrideValue(override.value, readPath2(baseConfig, override.path)));
|
|
199840
|
+
}
|
|
199841
|
+
const parsed = kyosoConfigSchema.safeParse(overridden);
|
|
199842
|
+
if (parsed.success)
|
|
199843
|
+
return parsed.data;
|
|
199844
|
+
const issue2 = parsed.error.issues[0];
|
|
199845
|
+
const issuePath = issue2?.path.map(String).join(".") ?? "config";
|
|
199846
|
+
const assignment = findAssignmentForPath(overrides, issuePath) ?? assignments.at(-1) ?? "";
|
|
199847
|
+
throw new Error(`Invalid --set value ${JSON.stringify(assignment)}: ${issuePath}: ${issue2?.message ?? "config validation failed"}.`);
|
|
199848
|
+
}
|
|
199849
|
+
function findAssignmentForPath(overrides, path) {
|
|
199850
|
+
for (let index = overrides.length - 1;index >= 0; index -= 1) {
|
|
199851
|
+
const override = overrides[index];
|
|
199852
|
+
if (override?.path.join(".") === path)
|
|
199853
|
+
return override.assignment;
|
|
199854
|
+
}
|
|
199855
|
+
return;
|
|
199856
|
+
}
|
|
199857
|
+
function parseConfigOverride(assignment) {
|
|
199858
|
+
const separator = assignment.indexOf("=");
|
|
199859
|
+
if (separator <= 0) {
|
|
199860
|
+
throw new Error(`Invalid --set value ${JSON.stringify(assignment)}. Expected key=value.`);
|
|
199861
|
+
}
|
|
199862
|
+
const key = assignment.slice(0, separator);
|
|
199863
|
+
const path = key.split(".");
|
|
199864
|
+
if (!isAllowedConfigOverridePath(path)) {
|
|
199865
|
+
throw new Error(`Unknown --set key ${JSON.stringify(key)}.`);
|
|
199866
|
+
}
|
|
199867
|
+
return {
|
|
199868
|
+
assignment,
|
|
199869
|
+
path,
|
|
199870
|
+
value: assignment.slice(separator + 1)
|
|
199871
|
+
};
|
|
199872
|
+
}
|
|
199873
|
+
function parseConfigOverrideValue(value, currentValue) {
|
|
199874
|
+
if (typeof currentValue === "boolean") {
|
|
199875
|
+
if (value === "true")
|
|
199876
|
+
return true;
|
|
199877
|
+
if (value === "false")
|
|
199878
|
+
return false;
|
|
199879
|
+
return value;
|
|
199880
|
+
}
|
|
199881
|
+
if (typeof currentValue === "number" && NUMBER_VALUE.test(value)) {
|
|
199882
|
+
const parsed = Number(value);
|
|
199883
|
+
if (Number.isFinite(parsed))
|
|
199884
|
+
return parsed;
|
|
199885
|
+
}
|
|
199886
|
+
return value;
|
|
199887
|
+
}
|
|
199888
|
+
function readPath2(target, path) {
|
|
199889
|
+
let current = target;
|
|
199890
|
+
for (const key of path) {
|
|
199891
|
+
if (!isRecord6(current))
|
|
199892
|
+
return;
|
|
199893
|
+
current = current[key];
|
|
199894
|
+
}
|
|
199895
|
+
return current;
|
|
199896
|
+
}
|
|
199897
|
+
function writePath2(target, path, value) {
|
|
199898
|
+
let current = target;
|
|
199899
|
+
for (const key of path.slice(0, -1)) {
|
|
199900
|
+
const child = current[key];
|
|
199901
|
+
if (!isRecord6(child)) {
|
|
199902
|
+
throw new Error(`Cannot apply --set key ${JSON.stringify(path.join("."))}.`);
|
|
199903
|
+
}
|
|
199904
|
+
current = child;
|
|
199905
|
+
}
|
|
199906
|
+
const leaf = path.at(-1);
|
|
199907
|
+
if (leaf)
|
|
199908
|
+
current[leaf] = value;
|
|
199909
|
+
}
|
|
199910
|
+
function isRecord6(value) {
|
|
199911
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
199912
|
+
}
|
|
199913
|
+
|
|
199815
199914
|
// src/acp/AcpAgentProcess.ts
|
|
199816
199915
|
import { spawn } from "node:child_process";
|
|
199817
199916
|
import { readFile as readFile7, realpath } from "node:fs/promises";
|
|
@@ -202148,14 +202247,14 @@ var zCancelRequestNotification = object({
|
|
|
202148
202247
|
});
|
|
202149
202248
|
// node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js
|
|
202150
202249
|
var CANCEL_REQUEST_METHOD = "$/cancel_request";
|
|
202151
|
-
function
|
|
202250
|
+
function isRecord7(value) {
|
|
202152
202251
|
return typeof value === "object" && value !== null;
|
|
202153
202252
|
}
|
|
202154
202253
|
function isJsonRpcId(value) {
|
|
202155
202254
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
202156
202255
|
}
|
|
202157
202256
|
function cancelRequestId(params) {
|
|
202158
|
-
if (!
|
|
202257
|
+
if (!isRecord7(params) || !isJsonRpcId(params["requestId"])) {
|
|
202159
202258
|
return;
|
|
202160
202259
|
}
|
|
202161
202260
|
return params["requestId"];
|
|
@@ -202502,7 +202601,7 @@ class Connection {
|
|
|
202502
202601
|
if (this.abortController.signal.aborted) {
|
|
202503
202602
|
return;
|
|
202504
202603
|
}
|
|
202505
|
-
if (!
|
|
202604
|
+
if (!isRecord7(message)) {
|
|
202506
202605
|
console.error("Invalid message", { message });
|
|
202507
202606
|
return;
|
|
202508
202607
|
}
|
|
@@ -202595,7 +202694,7 @@ class Connection {
|
|
|
202595
202694
|
pendingResponse.cleanup?.();
|
|
202596
202695
|
if ("result" in response) {
|
|
202597
202696
|
pendingResponse.resolve(response.result);
|
|
202598
|
-
} else if ("error" in response &&
|
|
202697
|
+
} else if ("error" in response && isRecord7(response.error)) {
|
|
202599
202698
|
const { code, message, data } = response.error;
|
|
202600
202699
|
pendingResponse.reject(new RequestError(code, message, data));
|
|
202601
202700
|
} else {
|
|
@@ -202805,7 +202904,7 @@ function ndJsonStream(output2, input2) {
|
|
|
202805
202904
|
if (trimmedLine) {
|
|
202806
202905
|
try {
|
|
202807
202906
|
const message = JSON.parse(trimmedLine);
|
|
202808
|
-
if (
|
|
202907
|
+
if (isRecord7(message)) {
|
|
202809
202908
|
controller.enqueue(message);
|
|
202810
202909
|
} else {
|
|
202811
202910
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -203866,7 +203965,7 @@ function isSeverity(value) {
|
|
|
203866
203965
|
return typeof value === "string" && severities.includes(value);
|
|
203867
203966
|
}
|
|
203868
203967
|
function normalizeCisaSecureByDesign(value) {
|
|
203869
|
-
if (!
|
|
203968
|
+
if (!isRecord8(value))
|
|
203870
203969
|
return;
|
|
203871
203970
|
const normalized = {};
|
|
203872
203971
|
const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
|
|
@@ -203907,7 +204006,7 @@ function normalizeFindingFiles(value) {
|
|
|
203907
204006
|
if (!Array.isArray(value))
|
|
203908
204007
|
return;
|
|
203909
204008
|
const files = value.flatMap((item) => {
|
|
203910
|
-
if (!
|
|
204009
|
+
if (!isRecord8(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
|
|
203911
204010
|
return [];
|
|
203912
204011
|
}
|
|
203913
204012
|
const file2 = {
|
|
@@ -203926,7 +204025,7 @@ function normalizeFindingFiles(value) {
|
|
|
203926
204025
|
function normalizeLineNumber(value) {
|
|
203927
204026
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
203928
204027
|
}
|
|
203929
|
-
function
|
|
204028
|
+
function isRecord8(value) {
|
|
203930
204029
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
203931
204030
|
}
|
|
203932
204031
|
|
|
@@ -205550,7 +205649,7 @@ function parseVerificationVerdicts(rawText) {
|
|
|
205550
205649
|
if (!Array.isArray(parsed.verdicts))
|
|
205551
205650
|
return;
|
|
205552
205651
|
return parsed.verdicts.flatMap((item) => {
|
|
205553
|
-
if (!
|
|
205652
|
+
if (!isRecord9(item))
|
|
205554
205653
|
return [];
|
|
205555
205654
|
if (typeof item.findingId !== "string")
|
|
205556
205655
|
return [];
|
|
@@ -205628,7 +205727,7 @@ function verificationNote(reasoning) {
|
|
|
205628
205727
|
function isVerdict(value) {
|
|
205629
205728
|
return value === "confirmed" || value === "refuted" || value === "uncertain";
|
|
205630
205729
|
}
|
|
205631
|
-
function
|
|
205730
|
+
function isRecord9(value) {
|
|
205632
205731
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
205633
205732
|
}
|
|
205634
205733
|
|
|
@@ -205677,7 +205776,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
205677
205776
|
}
|
|
205678
205777
|
throw error51;
|
|
205679
205778
|
}
|
|
205680
|
-
const
|
|
205779
|
+
const baseLoaded = options.config !== undefined ? {
|
|
205681
205780
|
config: options.config,
|
|
205682
205781
|
configHash: options.configHash,
|
|
205683
205782
|
configTrustStatus: "trusted",
|
|
@@ -205694,6 +205793,10 @@ async function runReview(tool, request, options = {}) {
|
|
|
205694
205793
|
env: options.env,
|
|
205695
205794
|
trustPrompt: options.trustPrompt
|
|
205696
205795
|
});
|
|
205796
|
+
const loaded = options.configOverrides && options.configOverrides.length > 0 ? {
|
|
205797
|
+
...baseLoaded,
|
|
205798
|
+
config: applyConfigOverrides(baseLoaded.config, options.configOverrides)
|
|
205799
|
+
} : baseLoaded;
|
|
205697
205800
|
const trace = createTraceWriter({
|
|
205698
205801
|
enabled: loaded.config.audit.enabled,
|
|
205699
205802
|
directory: loaded.config.audit.directory,
|
|
@@ -206395,6 +206498,7 @@ async function main() {
|
|
|
206395
206498
|
ignoreConfig,
|
|
206396
206499
|
trustConfig: trustConfig2,
|
|
206397
206500
|
allowUnknownConfig,
|
|
206501
|
+
configOverrides: configOverrideFlags(parsed.flags),
|
|
206398
206502
|
promptForTrust: canPromptForConfigTrust()
|
|
206399
206503
|
});
|
|
206400
206504
|
console.log(booleanFlag(parsed.flags, "json") ? JSON.stringify(result, null, 2) : result.summaryMarkdown);
|
|
@@ -206471,6 +206575,12 @@ function parseNetworkFlag(value) {
|
|
|
206471
206575
|
return value;
|
|
206472
206576
|
throw new Error(`Invalid --network value "${value}". Expected model_only or unrestricted.`);
|
|
206473
206577
|
}
|
|
206578
|
+
function configOverrideFlags(flags) {
|
|
206579
|
+
if (flags.set === true) {
|
|
206580
|
+
throw new Error("Missing value for --set. Expected key=value.");
|
|
206581
|
+
}
|
|
206582
|
+
return stringArrayFlag(flags, "set");
|
|
206583
|
+
}
|
|
206474
206584
|
function canPromptForConfigTrust() {
|
|
206475
206585
|
return process.stdin.isTTY === true && process.stderr.isTTY === true;
|
|
206476
206586
|
}
|
|
@@ -206479,9 +206589,9 @@ var HELP = `Kyoso
|
|
|
206479
206589
|
Usage:
|
|
206480
206590
|
kyoso mcp [--config kyoso.toml|kyoso.config.ts] [--ignore-config] [--trust-config] [--allow-unknown-config] [--network model_only|unrestricted]
|
|
206481
206591
|
kyoso setup [codex|claude-code] [--write] [--runner npx|bunx] [--command <command>] [--global]
|
|
206482
|
-
kyoso plan --goal <text> [--plan <path-or-text>] [--file <path>] [--json] [--trust-config] [--allow-unknown-config]
|
|
206483
|
-
kyoso security --goal <text> [--diff <path>] [--file <path>] [--allow-secret-redaction] [--trust-config] [--allow-unknown-config]
|
|
206484
|
-
kyoso diff --base main --head HEAD [--json] [--trust-config] [--allow-unknown-config]
|
|
206592
|
+
kyoso plan --goal <text> [--plan <path-or-text>] [--file <path>] [--set <key>=<value>]... [--json] [--trust-config] [--allow-unknown-config]
|
|
206593
|
+
kyoso security --goal <text> [--diff <path>] [--file <path>] [--set <key>=<value>]... [--json] [--allow-secret-redaction] [--trust-config] [--allow-unknown-config]
|
|
206594
|
+
kyoso diff --base main --head HEAD [--set <key>=<value>]... [--json] [--trust-config] [--allow-unknown-config]
|
|
206485
206595
|
kyoso doctor [--trust-config] [--allow-unknown-config]
|
|
206486
206596
|
kyoso init [--force]
|
|
206487
206597
|
`;
|
|
@@ -6,6 +6,8 @@ type Violation = {
|
|
|
6
6
|
path: string;
|
|
7
7
|
reason?: string;
|
|
8
8
|
};
|
|
9
|
+
export declare const kyosoConfigOverridePaths: readonly ["agents.codex.enabled", "agents.codex.model", "agents.codex.effort", "agents.codex.role", "agents.codex.timeoutMs", "agents.claude.enabled", "agents.claude.model", "agents.claude.effort", "agents.claude.role", "agents.claude.timeoutMs", "verification.enabled", "verification.maxFindings", "verification.timeoutMs", "judge.mode", "judge.provider", "judge.timeoutMs"];
|
|
10
|
+
export declare function isAllowedConfigOverridePath(path: string[]): boolean;
|
|
9
11
|
export declare function mergeProjectTomlConfig(baseConfig: unknown, projectConfig: unknown, options: ProjectScopeOptions): unknown;
|
|
10
12
|
export declare function collectProjectScopeViolations(config: unknown): Violation[];
|
|
11
13
|
export declare function flattenLeaves(value: unknown, path?: string[]): Array<{
|
package/dist/core/constants.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export declare const DEFAULT_MAX_DIFF_BYTES = 300000;
|
|
|
4
4
|
export declare const RAW_OUTPUT_MAX_CHARS = 16384;
|
|
5
5
|
export declare const TRACE_DIR = ".kyoso/traces";
|
|
6
6
|
export declare const KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
|
|
7
|
-
export declare const KYOSO_VERSION = "0.
|
|
7
|
+
export declare const KYOSO_VERSION = "0.8.0";
|
package/dist/core/runReview.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { AcpAgentManager } from "../acp/AcpAgentManager.js";
|
|
|
4
4
|
import type { KyosoResult, KyosoReviewRequest, NetworkMode, ReviewTool } from "./types.js";
|
|
5
5
|
export type RunReviewOptions = LoadConfigOptions & {
|
|
6
6
|
config?: KyosoConfig;
|
|
7
|
+
configOverrides?: string[];
|
|
7
8
|
configHash?: string;
|
|
8
9
|
agentManager?: AcpAgentManager;
|
|
9
10
|
env?: NodeJS.ProcessEnv;
|
package/dist/index.js
CHANGED
|
@@ -184076,6 +184076,28 @@ import { createInterface } from "node:readline/promises";
|
|
|
184076
184076
|
|
|
184077
184077
|
// src/config/projectScope.ts
|
|
184078
184078
|
var PROJECT_GLOBAL_ONLY_MESSAGE = "Move global-only settings to the user global config:";
|
|
184079
|
+
var kyosoConfigOverridePaths = [
|
|
184080
|
+
"agents.codex.enabled",
|
|
184081
|
+
"agents.codex.model",
|
|
184082
|
+
"agents.codex.effort",
|
|
184083
|
+
"agents.codex.role",
|
|
184084
|
+
"agents.codex.timeoutMs",
|
|
184085
|
+
"agents.claude.enabled",
|
|
184086
|
+
"agents.claude.model",
|
|
184087
|
+
"agents.claude.effort",
|
|
184088
|
+
"agents.claude.role",
|
|
184089
|
+
"agents.claude.timeoutMs",
|
|
184090
|
+
"verification.enabled",
|
|
184091
|
+
"verification.maxFindings",
|
|
184092
|
+
"verification.timeoutMs",
|
|
184093
|
+
"judge.mode",
|
|
184094
|
+
"judge.provider",
|
|
184095
|
+
"judge.timeoutMs"
|
|
184096
|
+
];
|
|
184097
|
+
var CONFIG_OVERRIDE_PATHS = new Set(kyosoConfigOverridePaths);
|
|
184098
|
+
function isAllowedConfigOverridePath(path) {
|
|
184099
|
+
return CONFIG_OVERRIDE_PATHS.has(path.join("."));
|
|
184100
|
+
}
|
|
184079
184101
|
function mergeProjectTomlConfig(baseConfig, projectConfig, options) {
|
|
184080
184102
|
const violations = collectProjectScopeViolations(projectConfig);
|
|
184081
184103
|
if (violations.length > 0) {
|
|
@@ -184108,13 +184130,9 @@ function collectProjectScopeViolations(config2) {
|
|
|
184108
184130
|
}
|
|
184109
184131
|
function isAllowedProjectPath(path) {
|
|
184110
184132
|
const [top, second, third, fourth] = path;
|
|
184111
|
-
if (
|
|
184133
|
+
if (isAllowedConfigOverridePath(path))
|
|
184112
184134
|
return true;
|
|
184113
|
-
|
|
184114
|
-
if (top === "agents" && path.length === 3 && ["codex", "claude"].includes(second ?? "") && ["enabled", "model", "effort", "role", "timeoutMs"].includes(third ?? "")) {
|
|
184115
|
-
return true;
|
|
184116
|
-
}
|
|
184117
|
-
if (top === "verification" && path.length === 2 && ["enabled", "maxFindings", "timeoutMs"].includes(second ?? "")) {
|
|
184135
|
+
if (top === "tools" && path.length === 2 && ["planReview", "securityReview", "diffReview"].includes(second ?? "")) {
|
|
184118
184136
|
return true;
|
|
184119
184137
|
}
|
|
184120
184138
|
if (top === "workspace" && path.length === 2 && ["maxContextBytes", "maxDiffBytes", "deny"].includes(second ?? "")) {
|
|
@@ -184126,9 +184144,6 @@ function isAllowedProjectPath(path) {
|
|
|
184126
184144
|
if (top === "secrets" && path.length === 2 && ["blockOnDetectedSecret", "allowOverride"].includes(second ?? "")) {
|
|
184127
184145
|
return true;
|
|
184128
184146
|
}
|
|
184129
|
-
if (top === "judge" && path.length === 2 && ["mode", "provider", "timeoutMs"].includes(second ?? "")) {
|
|
184130
|
-
return true;
|
|
184131
|
-
}
|
|
184132
184147
|
if (top === "securityReview" && second === "cisaSecureByDesign" && path.length >= 3) {
|
|
184133
184148
|
if (third === "dimensions") {
|
|
184134
184149
|
return path.length === 4 && [
|
|
@@ -185548,6 +185563,90 @@ async function exists(path) {
|
|
|
185548
185563
|
}
|
|
185549
185564
|
}
|
|
185550
185565
|
|
|
185566
|
+
// src/config/configOverrides.ts
|
|
185567
|
+
var NUMBER_VALUE = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
|
|
185568
|
+
function applyConfigOverrides(config2, assignments) {
|
|
185569
|
+
if (assignments.length === 0)
|
|
185570
|
+
return config2;
|
|
185571
|
+
const overrides = assignments.map(parseConfigOverride);
|
|
185572
|
+
const baseConfig = config2;
|
|
185573
|
+
const overridden = structuredClone(config2);
|
|
185574
|
+
for (const override of overrides) {
|
|
185575
|
+
writePath2(overridden, override.path, parseConfigOverrideValue(override.value, readPath2(baseConfig, override.path)));
|
|
185576
|
+
}
|
|
185577
|
+
const parsed = kyosoConfigSchema.safeParse(overridden);
|
|
185578
|
+
if (parsed.success)
|
|
185579
|
+
return parsed.data;
|
|
185580
|
+
const issue2 = parsed.error.issues[0];
|
|
185581
|
+
const issuePath = issue2?.path.map(String).join(".") ?? "config";
|
|
185582
|
+
const assignment = findAssignmentForPath(overrides, issuePath) ?? assignments.at(-1) ?? "";
|
|
185583
|
+
throw new Error(`Invalid --set value ${JSON.stringify(assignment)}: ${issuePath}: ${issue2?.message ?? "config validation failed"}.`);
|
|
185584
|
+
}
|
|
185585
|
+
function findAssignmentForPath(overrides, path) {
|
|
185586
|
+
for (let index = overrides.length - 1;index >= 0; index -= 1) {
|
|
185587
|
+
const override = overrides[index];
|
|
185588
|
+
if (override?.path.join(".") === path)
|
|
185589
|
+
return override.assignment;
|
|
185590
|
+
}
|
|
185591
|
+
return;
|
|
185592
|
+
}
|
|
185593
|
+
function parseConfigOverride(assignment) {
|
|
185594
|
+
const separator = assignment.indexOf("=");
|
|
185595
|
+
if (separator <= 0) {
|
|
185596
|
+
throw new Error(`Invalid --set value ${JSON.stringify(assignment)}. Expected key=value.`);
|
|
185597
|
+
}
|
|
185598
|
+
const key = assignment.slice(0, separator);
|
|
185599
|
+
const path = key.split(".");
|
|
185600
|
+
if (!isAllowedConfigOverridePath(path)) {
|
|
185601
|
+
throw new Error(`Unknown --set key ${JSON.stringify(key)}.`);
|
|
185602
|
+
}
|
|
185603
|
+
return {
|
|
185604
|
+
assignment,
|
|
185605
|
+
path,
|
|
185606
|
+
value: assignment.slice(separator + 1)
|
|
185607
|
+
};
|
|
185608
|
+
}
|
|
185609
|
+
function parseConfigOverrideValue(value, currentValue) {
|
|
185610
|
+
if (typeof currentValue === "boolean") {
|
|
185611
|
+
if (value === "true")
|
|
185612
|
+
return true;
|
|
185613
|
+
if (value === "false")
|
|
185614
|
+
return false;
|
|
185615
|
+
return value;
|
|
185616
|
+
}
|
|
185617
|
+
if (typeof currentValue === "number" && NUMBER_VALUE.test(value)) {
|
|
185618
|
+
const parsed = Number(value);
|
|
185619
|
+
if (Number.isFinite(parsed))
|
|
185620
|
+
return parsed;
|
|
185621
|
+
}
|
|
185622
|
+
return value;
|
|
185623
|
+
}
|
|
185624
|
+
function readPath2(target, path) {
|
|
185625
|
+
let current = target;
|
|
185626
|
+
for (const key of path) {
|
|
185627
|
+
if (!isRecord4(current))
|
|
185628
|
+
return;
|
|
185629
|
+
current = current[key];
|
|
185630
|
+
}
|
|
185631
|
+
return current;
|
|
185632
|
+
}
|
|
185633
|
+
function writePath2(target, path, value) {
|
|
185634
|
+
let current = target;
|
|
185635
|
+
for (const key of path.slice(0, -1)) {
|
|
185636
|
+
const child = current[key];
|
|
185637
|
+
if (!isRecord4(child)) {
|
|
185638
|
+
throw new Error(`Cannot apply --set key ${JSON.stringify(path.join("."))}.`);
|
|
185639
|
+
}
|
|
185640
|
+
current = child;
|
|
185641
|
+
}
|
|
185642
|
+
const leaf = path.at(-1);
|
|
185643
|
+
if (leaf)
|
|
185644
|
+
current[leaf] = value;
|
|
185645
|
+
}
|
|
185646
|
+
function isRecord4(value) {
|
|
185647
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
185648
|
+
}
|
|
185649
|
+
|
|
185551
185650
|
// src/acp/AcpAgentProcess.ts
|
|
185552
185651
|
import { spawn } from "node:child_process";
|
|
185553
185652
|
import { readFile as readFile4, realpath } from "node:fs/promises";
|
|
@@ -187883,14 +187982,14 @@ var zCancelRequestNotification = object({
|
|
|
187883
187982
|
});
|
|
187884
187983
|
// node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js
|
|
187885
187984
|
var CANCEL_REQUEST_METHOD = "$/cancel_request";
|
|
187886
|
-
function
|
|
187985
|
+
function isRecord5(value) {
|
|
187887
187986
|
return typeof value === "object" && value !== null;
|
|
187888
187987
|
}
|
|
187889
187988
|
function isJsonRpcId(value) {
|
|
187890
187989
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
187891
187990
|
}
|
|
187892
187991
|
function cancelRequestId(params) {
|
|
187893
|
-
if (!
|
|
187992
|
+
if (!isRecord5(params) || !isJsonRpcId(params["requestId"])) {
|
|
187894
187993
|
return;
|
|
187895
187994
|
}
|
|
187896
187995
|
return params["requestId"];
|
|
@@ -188237,7 +188336,7 @@ class Connection {
|
|
|
188237
188336
|
if (this.abortController.signal.aborted) {
|
|
188238
188337
|
return;
|
|
188239
188338
|
}
|
|
188240
|
-
if (!
|
|
188339
|
+
if (!isRecord5(message)) {
|
|
188241
188340
|
console.error("Invalid message", { message });
|
|
188242
188341
|
return;
|
|
188243
188342
|
}
|
|
@@ -188330,7 +188429,7 @@ class Connection {
|
|
|
188330
188429
|
pendingResponse.cleanup?.();
|
|
188331
188430
|
if ("result" in response) {
|
|
188332
188431
|
pendingResponse.resolve(response.result);
|
|
188333
|
-
} else if ("error" in response &&
|
|
188432
|
+
} else if ("error" in response && isRecord5(response.error)) {
|
|
188334
188433
|
const { code, message, data } = response.error;
|
|
188335
188434
|
pendingResponse.reject(new RequestError(code, message, data));
|
|
188336
188435
|
} else {
|
|
@@ -188540,7 +188639,7 @@ function ndJsonStream(output, input) {
|
|
|
188540
188639
|
if (trimmedLine) {
|
|
188541
188640
|
try {
|
|
188542
188641
|
const message = JSON.parse(trimmedLine);
|
|
188543
|
-
if (
|
|
188642
|
+
if (isRecord5(message)) {
|
|
188544
188643
|
controller.enqueue(message);
|
|
188545
188644
|
} else {
|
|
188546
188645
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -189601,7 +189700,7 @@ function isSeverity(value) {
|
|
|
189601
189700
|
return typeof value === "string" && severities.includes(value);
|
|
189602
189701
|
}
|
|
189603
189702
|
function normalizeCisaSecureByDesign(value) {
|
|
189604
|
-
if (!
|
|
189703
|
+
if (!isRecord6(value))
|
|
189605
189704
|
return;
|
|
189606
189705
|
const normalized = {};
|
|
189607
189706
|
const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
|
|
@@ -189642,7 +189741,7 @@ function normalizeFindingFiles(value) {
|
|
|
189642
189741
|
if (!Array.isArray(value))
|
|
189643
189742
|
return;
|
|
189644
189743
|
const files = value.flatMap((item) => {
|
|
189645
|
-
if (!
|
|
189744
|
+
if (!isRecord6(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
|
|
189646
189745
|
return [];
|
|
189647
189746
|
}
|
|
189648
189747
|
const file2 = {
|
|
@@ -189661,7 +189760,7 @@ function normalizeFindingFiles(value) {
|
|
|
189661
189760
|
function normalizeLineNumber(value) {
|
|
189662
189761
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
189663
189762
|
}
|
|
189664
|
-
function
|
|
189763
|
+
function isRecord6(value) {
|
|
189665
189764
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
189666
189765
|
}
|
|
189667
189766
|
|
|
@@ -191019,7 +191118,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
191019
191118
|
const parsed = JSON.parse(json2);
|
|
191020
191119
|
const summaryText = typeof parsed.summaryText === "string" && parsed.summaryText.trim().length > 0 ? sanitizeText(parsed.summaryText) : fallbackSummaryText;
|
|
191021
191120
|
const disagreementComments = Array.isArray(parsed.disagreementComments) ? parsed.disagreementComments.flatMap((item) => {
|
|
191022
|
-
if (!
|
|
191121
|
+
if (!isRecord7(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
|
|
191023
191122
|
return [];
|
|
191024
191123
|
}
|
|
191025
191124
|
return [
|
|
@@ -191035,7 +191134,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
191035
191134
|
return { summaryText, disagreementComments, analysis };
|
|
191036
191135
|
}
|
|
191037
191136
|
function parseAnalysis(value) {
|
|
191038
|
-
if (!
|
|
191137
|
+
if (!isRecord7(value))
|
|
191039
191138
|
return;
|
|
191040
191139
|
if (!Array.isArray(value.blindSpots) || !Array.isArray(value.contradictions) || !Array.isArray(value.partialCoverage)) {
|
|
191041
191140
|
return;
|
|
@@ -191043,7 +191142,7 @@ function parseAnalysis(value) {
|
|
|
191043
191142
|
return {
|
|
191044
191143
|
blindSpots: value.blindSpots.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => typeof item === "string" ? [sanitizeAnalysisText(item)] : []),
|
|
191045
191144
|
contradictions: value.contradictions.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
191046
|
-
if (!
|
|
191145
|
+
if (!isRecord7(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
|
|
191047
191146
|
return [];
|
|
191048
191147
|
}
|
|
191049
191148
|
return [
|
|
@@ -191054,7 +191153,7 @@ function parseAnalysis(value) {
|
|
|
191054
191153
|
];
|
|
191055
191154
|
}),
|
|
191056
191155
|
partialCoverage: value.partialCoverage.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
191057
|
-
if (!
|
|
191156
|
+
if (!isRecord7(item) || typeof item.note !== "string")
|
|
191058
191157
|
return [];
|
|
191059
191158
|
const findingId = typeof item.findingId === "string" ? sanitizeAnalysisText(item.findingId) : undefined;
|
|
191060
191159
|
return [
|
|
@@ -191101,7 +191200,7 @@ function extractFirstJsonObject2(text) {
|
|
|
191101
191200
|
}
|
|
191102
191201
|
return;
|
|
191103
191202
|
}
|
|
191104
|
-
function
|
|
191203
|
+
function isRecord7(value) {
|
|
191105
191204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
191106
191205
|
}
|
|
191107
191206
|
|
|
@@ -191559,7 +191658,7 @@ function parseVerificationVerdicts(rawText) {
|
|
|
191559
191658
|
if (!Array.isArray(parsed.verdicts))
|
|
191560
191659
|
return;
|
|
191561
191660
|
return parsed.verdicts.flatMap((item) => {
|
|
191562
|
-
if (!
|
|
191661
|
+
if (!isRecord8(item))
|
|
191563
191662
|
return [];
|
|
191564
191663
|
if (typeof item.findingId !== "string")
|
|
191565
191664
|
return [];
|
|
@@ -191637,7 +191736,7 @@ function verificationNote(reasoning) {
|
|
|
191637
191736
|
function isVerdict(value) {
|
|
191638
191737
|
return value === "confirmed" || value === "refuted" || value === "uncertain";
|
|
191639
191738
|
}
|
|
191640
|
-
function
|
|
191739
|
+
function isRecord8(value) {
|
|
191641
191740
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
191642
191741
|
}
|
|
191643
191742
|
|
|
@@ -191686,7 +191785,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
191686
191785
|
}
|
|
191687
191786
|
throw error51;
|
|
191688
191787
|
}
|
|
191689
|
-
const
|
|
191788
|
+
const baseLoaded = options.config !== undefined ? {
|
|
191690
191789
|
config: options.config,
|
|
191691
191790
|
configHash: options.configHash,
|
|
191692
191791
|
configTrustStatus: "trusted",
|
|
@@ -191703,6 +191802,10 @@ async function runReview(tool, request, options = {}) {
|
|
|
191703
191802
|
env: options.env,
|
|
191704
191803
|
trustPrompt: options.trustPrompt
|
|
191705
191804
|
});
|
|
191805
|
+
const loaded = options.configOverrides && options.configOverrides.length > 0 ? {
|
|
191806
|
+
...baseLoaded,
|
|
191807
|
+
config: applyConfigOverrides(baseLoaded.config, options.configOverrides)
|
|
191808
|
+
} : baseLoaded;
|
|
191706
191809
|
const trace = createTraceWriter({
|
|
191707
191810
|
enabled: loaded.config.audit.enabled,
|
|
191708
191811
|
directory: loaded.config.audit.directory,
|