iterate-plugin 3.5.6 → 3.6.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 +64 -20
- package/README.zh-CN.md +53 -17
- package/dist/approval-gate.js +143 -23
- package/dist/atomic-fs.js +148 -17
- package/dist/config-loader.js +509 -34
- package/dist/config-write.js +83 -22
- package/dist/evidence.js +141 -87
- package/dist/file-lock.js +165 -0
- package/dist/index.js +54 -28
- package/dist/jobs.js +56 -11
- package/dist/live.js +52 -13
- package/dist/meta-review.js +132 -28
- package/dist/method-scope.js +31 -8
- package/dist/review-scope.js +32 -9
- package/dist/review.js +96 -17
- package/dist/session-hooks.js +55 -13
- package/dist/skill-prompt.js +417 -67
- package/dist/tools/checkpoint.js +85 -19
- package/dist/tools/config.js +44 -2
- package/dist/tools/context.js +22 -5
- package/dist/tools/decision-log.js +122 -27
- package/dist/tools/defense-events.js +90 -31
- package/dist/tools/defense-store.js +28 -3
- package/dist/tools/experience-bank.js +108 -43
- package/dist/tools/experience-store.js +54 -4
- package/dist/tools/fix.js +347 -119
- package/dist/tools/history.js +68 -14
- package/dist/tools/present.js +80 -0
- package/dist/tools/prune.js +156 -53
- package/dist/tools/quality-gate.js +52 -2
- package/dist/tools/quality-store.js +17 -1
- package/dist/tools/review.js +158 -7
- package/dist/tools/transcript.js +173 -36
- package/dist/tools/triage.js +67 -12
- package/dist/tools/validate.js +115 -24
- package/dist/transcript.js +267 -4
- package/lib/client.js +945 -181
- package/lib/parse.js +760 -57
- package/package.json +15 -12
- package/src/approval-gate.ts +160 -23
- package/src/atomic-fs.ts +152 -17
- package/src/client/index.ts +600 -129
- package/src/config-loader.ts +542 -35
- package/src/config-write.ts +108 -26
- package/src/evidence.ts +194 -92
- package/src/file-lock.ts +184 -0
- package/src/index.ts +53 -29
- package/src/jobs.ts +63 -12
- package/src/live.ts +48 -11
- package/src/meta-review.ts +151 -34
- package/src/method-scope.ts +31 -8
- package/src/review-scope.ts +33 -10
- package/src/review.ts +96 -17
- package/src/session-hooks.ts +54 -12
- package/src/skill-prompt.ts +417 -67
- package/src/tools/checkpoint.ts +81 -19
- package/src/tools/config.ts +44 -2
- package/src/tools/context.ts +25 -5
- package/src/tools/decision-log.ts +127 -22
- package/src/tools/defense-events.ts +87 -31
- package/src/tools/defense-store.ts +30 -3
- package/src/tools/experience-bank.ts +112 -44
- package/src/tools/experience-store.ts +54 -5
- package/src/tools/fix.ts +258 -20
- package/src/tools/history.ts +74 -15
- package/src/tools/present.ts +89 -0
- package/src/tools/prune.ts +160 -51
- package/src/tools/quality-gate.ts +57 -2
- package/src/tools/quality-store.ts +18 -1
- package/src/tools/review.ts +155 -6
- package/src/tools/transcript.ts +178 -36
- package/src/tools/triage.ts +70 -13
- package/src/tools/validate.ts +138 -32
- package/src/transcript.ts +279 -4
- package/src/types.ts +29 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# iterate-plugin for DeepSeek Harness (dsh)
|
|
2
2
|
|
|
3
|
-
> dsh 桌面端的 iterate 质量指挥中心 + 经验银行插件(v3.
|
|
4
|
-
> The iterate ecosystem's quality command center + experience bank plugin for dsh (v3.
|
|
3
|
+
> dsh 桌面端的 iterate 质量指挥中心 + 经验银行插件(v3.6)。把 iterate 生态的同一套 review/fix loop 直接搬进 dsh 界面,新增质量门禁、经验银行、防御事件流与原生指挥操作。
|
|
4
|
+
> The iterate ecosystem's quality command center + experience bank plugin for dsh (v3.6). Natively embedded inside the DeepSeek Harness (dsh) desktop client with quality gates, experience bank, defense events stream, and native command buttons.
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
7
7
|
<a href="README.md"><strong>English</strong></a> ·
|
|
@@ -61,7 +61,7 @@ dsh plugin --profile web add iterate-plugin
|
|
|
61
61
|
|
|
62
62
|
**v3.2 Quality Command Center**: the plugin has grown from a "passive observation panel" into an "active command center + knowledge base". It now ships quality gate view + writable compute, an experience bank with search / adopt / add, a defense events stream (record + bilingual labels), native command buttons, and a `task_mode` indicator.
|
|
63
63
|
|
|
64
|
-
Besides 17 pure-function tools, it carries a **build-free Web UI layer** (convergence dashboard, triage panel, stats card,
|
|
64
|
+
Besides 17 pure-function tools, it carries a **build-free Web UI layer** (convergence dashboard, triage panel, stats card, 11-tab runtime observatory — live activity stream + F1–F10 —, theme skin, etc.) that plugs straight into dsh's existing UI slots. Configuration (`iterate.config.yaml` and the review dimensions) is identical across the other two components of the iterate ecosystem ([skill](https://github.com/jingzhao-l/iterate-skill) / [headless engine](https://github.com/jingzhao-l/iterate-harness)) — zero migration cost.
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
@@ -69,6 +69,7 @@ Besides 17 pure-function tools, it carries a **build-free Web UI layer** (conver
|
|
|
69
69
|
|
|
70
70
|
- [✨ Features](#-features)
|
|
71
71
|
- [📦 Installation](#-installation)
|
|
72
|
+
- [🧭 Using the UI in dsh](#️-using-the-ui-in-dsh)
|
|
72
73
|
- [💬 Usage](#-usage)
|
|
73
74
|
- [⚙️ Project configuration](#️-project-configuration)
|
|
74
75
|
- [🔧 Registered tools](#-registered-tools)
|
|
@@ -103,15 +104,15 @@ Both modes share:
|
|
|
103
104
|
- Validates after each round's fixes
|
|
104
105
|
- Rolls back failed fixes, and can save / resume progress
|
|
105
106
|
|
|
106
|
-
### UI layer (build-free client slots, v3.
|
|
107
|
+
### UI layer (build-free client slots, v3.6: 11 tabs)
|
|
107
108
|
|
|
108
|
-
- **ConvergenceDashboard** (`conversation.input.dock`) — live round progress bar, severity stats, dimension badges, trend mini-chart above the input; normal mode also shows fix-count badges; plus a live workflow-phase chip (current phase + running/stopped) and a **
|
|
109
|
-
- **ObservatoryPanel** (`conversation.input.dock`) —
|
|
110
|
-
- **TriagePanel** (`conversation.chat.turnTail`) — per-finding y
|
|
109
|
+
- **ConvergenceDashboard** (`conversation.input.dock`) — live round progress bar, severity stats, dimension badges, trend mini-chart above the input; normal mode also shows fix-count badges; plus a live workflow-phase chip (current phase + running/stopped) and a **task_mode indicator (code / iterate)**, now backed by the persisted transcript (`iterate_status` / `iterate_transcript` emit `taskMode`). While a run is active the dashboard switches to a running state (round + phase) instead of the static empty state, and the start buttons are hidden.
|
|
110
|
+
- **ObservatoryPanel** (`conversation.input.dock`) — an **eleven-tab** runtime observatory below the input: **live activity stream** (default tab, type filter) + **F1** review threads (expand / collapse all), **F2** convergence trend (incl. the per-round comparison table: findings raised / fixed / severity mix / validation outcomes), **F3** finding locations (severity / dimension / search filter), **F4** fixes + rollback, **F5** checkpoint resume, **F6** run console, **F7** decision timeline (type / round filter + search), **F8** Quality Gate, **F9** Experience Bank, **F10** Defense Events. Number-key shortcuts: `1`–`9` jump to F1–F9, `0` to F10, `-` back to the live stream. **F8/F9/F10 are live** — they scan the session stream for the latest `iterate_quality_gate` / `iterate_experience` / `iterate_defense_events` results and render real data (PASS/FAIL chip + per-dimension score bars, experience entries with adopt buttons + client-side search, defense type-count chips + filtered event stream); when the session stream has none they distinguish "no data on disk" from "not pulled yet" and offer a **拉取磁盘快照 (pull disk snapshot)** instruction that has the model call the read-side tools and echo the `.iterate/` artifacts back into the stream. One-click JSON export of all observatory data — manifest + live + `qualityGate` / `experienceBank` / `defenseEvents` / `report` (download, copy fallback). **v3.5.3: reset actions surfaced** — F5 copies an `iterate_checkpoint clear` instruction, F8 an `iterate_quality_gate clear` instruction, F10 an `iterate_defense_events clear` instruction.
|
|
111
|
+
- **TriagePanel** (`conversation.chat.turnTail`) — per-finding triage with `y` (keep → fix), `n` (skip), `a` (known-intentional) keyboard shortcuts and `↑`/`↓` navigation (focus-guarded: only active while the panel has focus), filtering, batch ops (incl. select-all), localStorage persistence. **Write-back closed loop**: the primary button copies an `iterate_triage apply` instruction for the marked entries (the tool validates, dedupes, backs up, rolls back on failure); a secondary button copies the raw `known_intentional` YAML; **回读已写入条目** copies an `iterate_triage list` instruction to confirm what actually landed. Copy payloads are aligned to the target tool schemas. **v3.2: native command buttons** (approve architectural fix, trigger new round, rollback to checkpoint). **v3.3: §8 指派修复 (assign)** — one click copies an `iterate_fix` instruction carrying every in-scope finding (respecting the batch toggle).
|
|
111
112
|
- **StatsCard** (`conversation.chat.turnTail`) — convergence stats, round history, trend chart and completion summary when no findings remain.
|
|
112
113
|
- **iterate theme skin** (`theme.overrideTokens`) — a warm-amber 13-token `--dsw-*` override, light/dark modes, togglable in settings.
|
|
113
114
|
- **ProgressCapsule** (`shell.overlay`) — popup notification on each round completion / convergence (incl. convergence confirm).
|
|
114
|
-
- **SettingsPanel** (`settings.section`) — theme toggle, triage-persistence notes, config-management guide, runtime status overview (artifact layout + view/cleanup tool guide), one-click triage data reset.
|
|
115
|
+
- **SettingsPanel** (`settings.section`) — theme toggle, triage-persistence notes, config-management guide (covers `validation.commands` / `language` / `personalization.known_intentional` with an explicit "empty validation.commands = unprotected" warning; a field picker generates the matching `iterate_config write` instruction), runtime status overview (artifact layout + view/cleanup tool guide + disk-snapshot pull), one-click triage data reset.
|
|
115
116
|
|
|
116
117
|
The UI layer is **defensive by design**: it degrades gracefully if any of `slots` / `theme` / `React` is unavailable — it never crashes the client.
|
|
117
118
|
|
|
@@ -122,7 +123,7 @@ Beyond the 17 registered tools (full reference further down), the plugin closes
|
|
|
122
123
|
- **Findings triage loop** — review → UI triage (y/n/a) → `iterate_triage` writes back `known_intentional` → auto-filtered next round
|
|
123
124
|
- **Structured fix system** — each fix backs up first, writes a registry entry, records the diff; a failed validation can be reverted with `iterate_rollback`
|
|
124
125
|
- **Breakpoint resume** — checkpoints saved at the start of each round; interrupted long iterations can resume
|
|
125
|
-
- **History audit** — `iterate_history` reads the decision log (filtered by type /
|
|
126
|
+
- **History audit** — `iterate_history` reads the decision log (filtered by `type` / `since` / `round` / fixed `file` / `limit`, default latest 50, cap 200) plus a fix-registry summary (per-round fixed/failed counts, scoped by the same round/file filters) to audit run process and fix details
|
|
126
127
|
- **Runtime cleanup** — `iterate_prune` removes stale decision-log entries, stale checkpoints, orphaned fix backups, empty rounds and stray temp files left by crashed atomic writes; dry-run by default (report-only), real cleanup requires `dryRun:false`, and every cleanup is logged
|
|
127
128
|
- **Config read / write** — `iterate_config` supports validated, backed-up, rollback-capable partial writes
|
|
128
129
|
- **v3.2 Experience Bank** — `iterate_experience` queries historical fixes and patterns with search / filter / adopt, and can persist new verified fixes (`add`) — re-adding the same pattern+dimension bumps its hit count instead of duplicating it
|
|
@@ -167,7 +168,46 @@ Then add to your profile `cordis.patch.yml`:
|
|
|
167
168
|
name: 'iterate-plugin'
|
|
168
169
|
```
|
|
169
170
|
|
|
170
|
-
> The package carries its own `dsh.bundle.patch` (i.e. `cordis.patch.yml`); the npm package's `files` whitelist is `src` / `lib` / `dist` / `cordis.patch.yml` / `README.md` / `LICENSE`. `dist/` is the compiled output of the TypeScript server-side logic, shipped with the package so it works with dsh's `github:owner/repo#ref` git-clone install (Node does not strip TS types under `node_modules`).
|
|
171
|
+
> The package carries its own `dsh.bundle.patch` (i.e. `cordis.patch.yml`); the npm package's `files` whitelist is `src` / `lib` / `dist` / `cordis.patch.yml` / `README.md` / `README.zh-CN.md` / `LICENSE`. `dist/` is the compiled output of the TypeScript server-side logic, shipped with the package so it works with dsh's `github:owner/repo#ref` git-clone install (Node does not strip TS types under `node_modules`).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 🧭 Using the UI in dsh
|
|
176
|
+
|
|
177
|
+
The browser client has **no filesystem access** — every panel renders from the dsh session stream (tool results the model echoes back). That is why the plugin's UI is built around one interaction paradigm: **copy an instruction from a button → paste it back into the chat → the model calls the matching tool → the panel fills**. Client buttons never spawn processes.
|
|
178
|
+
|
|
179
|
+
### Starting an iteration (empty dashboard)
|
|
180
|
+
|
|
181
|
+
With no report yet, the convergence dashboard shows two buttons — **「完整迭代」 (full iteration)** and **「仅评审」 (review-only)** — each copying a **natural-language instruction** to the clipboard. These are **not slash commands**: the plugin registers no `/iterate` command; paste the text into the conversation and the model runs the iterate workflow through dsh's `workflow` tool. The full-iteration instruction also asks the model to preflight `validation.commands` first — if none is configured it stops and asks you to write one (the same fail-closed rule the workflow enforces), so an unprotected run never looks green.
|
|
182
|
+
|
|
183
|
+
While a run is active the dashboard switches to a **running state** (round + workflow-phase chips) instead of the static empty state, and the start buttons are hidden.
|
|
184
|
+
|
|
185
|
+
### Triage panel shortcuts
|
|
186
|
+
|
|
187
|
+
Focus must be inside the triage panel (the handler ignores keys typed elsewhere):
|
|
188
|
+
|
|
189
|
+
- `y` — keep the finding for fixing; `n` — skip it; `a` — mark it known-intentional (write-back candidate)
|
|
190
|
+
- `↑` / `↓` — move between findings (auto-advances after a verdict)
|
|
191
|
+
- batch buttons `y` / `n` / `a` apply the verdict to all findings at once
|
|
192
|
+
|
|
193
|
+
To write verdicts back, mark entries with `a` and click **生成应用指令** — it copies an `iterate_triage apply` instruction for exactly those entries (the tool validates, dedupes by file|dimension|line, backs up, and rolls back on failure). Paste it back, then click **回读已写入条目** to copy an `iterate_triage list` instruction and confirm what actually landed — the write-back → readback closed loop.
|
|
194
|
+
|
|
195
|
+
### Observatory tabs & shortcuts
|
|
196
|
+
|
|
197
|
+
The observatory below the input carries **11 tabs**: the live activity stream (default) plus **F1**–**F10**:
|
|
198
|
+
|
|
199
|
+
`F1` review threads · `F2` convergence trend (incl. per-round comparison) · `F3` finding locations · `F4` fixes + rollback · `F5` checkpoint resume · `F6` run console · `F7` decision timeline · `F8` quality gate · `F9` experience bank · `F10` defense events
|
|
200
|
+
|
|
201
|
+
Press `1`–`9` to jump to F1–F9, `0` for F10, and `-` to return to the live stream.
|
|
202
|
+
|
|
203
|
+
### Disk snapshot pull & export
|
|
204
|
+
|
|
205
|
+
- **拉取磁盘快照 (pull disk snapshot)** — a new session (or a refresh) starts with empty panels even when `.iterate/` already holds artifacts on disk. The pull button copies an instruction asking the model to call the read-side tools (`iterate_status`, `iterate_transcript` `read`, `iterate_quality_gate` `read`, `iterate_experience` `list`, `iterate_defense_events` `list`, `iterate_history`) and echo their **full** results into the stream; the session scanners then fill the dashboard, F2, F5, F8, F9, F10. Empty states distinguish "no data on disk" from "not pulled yet".
|
|
206
|
+
- **导出 JSON (export)** — one click serializes the whole observatory to JSON: manifest + live feed + `qualityGate` + `experienceBank` + `defenseEvents` + `report` (download first, copy-to-clipboard fallback).
|
|
207
|
+
|
|
208
|
+
### Config management from the settings page
|
|
209
|
+
|
|
210
|
+
The settings section copies a config-edit guide that lists the supported `iterate.config.yaml` fields — including `validation.commands` (with an explicit warning that an empty list means every round runs unprotected) — and offers a **field picker**: choose a field, and the button generates the matching `iterate_config write` instruction (schema-validated, auto-backup, auto-rollback) for you to paste back.
|
|
171
211
|
|
|
172
212
|
---
|
|
173
213
|
|
|
@@ -244,7 +284,7 @@ validation:
|
|
|
244
284
|
|
|
245
285
|
---
|
|
246
286
|
|
|
247
|
-
## 🔧 Registered tools (
|
|
287
|
+
## 🔧 Registered tools (17)
|
|
248
288
|
|
|
249
289
|
- `iterate_config` — read / write `iterate.config.yaml`. `operation=read` returns the full config or a named section; `operation=write` schema-validates, backs up, then merges and writes — auto rollback on failure
|
|
250
290
|
- `iterate_validate` — run a whitelisted validation command, return the result
|
|
@@ -257,7 +297,7 @@ validation:
|
|
|
257
297
|
- `iterate_rollback` — roll back an applied fix: restore the file from backup, remove that FixRecord from the registry, append a `revert` log. Used after a failed round validation
|
|
258
298
|
- `iterate_checkpoint` — iteration breakpoint: `save` persists progress to `.iterate/checkpoint.json`, `load` reads it back, `resume` loads + bumps the resume counter (interruption recovery), `clear` removes it (bounded findings payload, `round ≤ maxRounds` enforced). Resumable interrupted long iterations
|
|
259
299
|
- `iterate_status` — summarize current iteration state: mode, current/last round, fixes applied, remaining architectural, decision-log entry count, whether a checkpoint exists; **v3.4: also surfaces the persisted quality-gate snapshot, experience-bank summary, and defense-events summary** (`qualityGate` / `experienceBank` / `defenseEvents`)
|
|
260
|
-
- `iterate_history` — read iteration history (read-only): decision-log entries (filter by `type` / `since` / `limit`, default latest 50, cap 200) + fix-registry summary (per-round fixed/failed counts). For auditing the run, tracing logs, and inventorying fixes
|
|
300
|
+
- `iterate_history` — read iteration history (read-only): decision-log entries (filter by `type` / `since` / `round` / fixed `file` / `limit`, default latest 50, cap 200) + fix-registry summary (per-round fixed/failed counts, scoped by the same round/file filters; a `file`-scoped summary recomputes counts from the kept records). For auditing the run, tracing logs, and inventorying fixes
|
|
261
301
|
- `iterate_prune` — clean runtime artifacts: stale decision-log entries (by `retainDays`, default 30), stale checkpoints, orphaned fix backups, empty rounds, stray temp files (crashed atomic writes). Dry-run by default (report-only); real cleanup with `dryRun:false`, each cleanup logged
|
|
262
302
|
- `iterate_transcript` — runtime observatory: persist review transcripts, threads, fixes, and nudge directions to `.iterate/transcript.json` for the client observatory
|
|
263
303
|
- `iterate_experience` — **v3.2** query the experience bank (list / search / get), `add` a new verified fix (re-adding the same pattern+dimension bumps its hit count instead of duplicating it), or **v3.5 remove a stale/incorrect entry by `id`** so bad experiences never resurface. Persists to `.iterate/experience.json`
|
|
@@ -291,13 +331,17 @@ All runtime state lives under `.iterate/` at the project root (can be excluded v
|
|
|
291
331
|
### Node.js / DSH compatibility
|
|
292
332
|
|
|
293
333
|
- **Node.js**: `>=20` (`package.json` `engines.node`).
|
|
294
|
-
- **DSH**: declares `dsh.compatibility.dshReleases`
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
334
|
+
- **DSH**: declares `dsh.compatibility.dshReleases` in `package.json` — **that
|
|
335
|
+
field is the single source of truth** for release compatibility (this README
|
|
336
|
+
mirrors it verbatim; update both together). The following official releases
|
|
337
|
+
are declared `compatible`: `0.1.1-rc.1`, `0.1.2-alpha.4`, `0.1.2-alpha.5`,
|
|
338
|
+
`0.1.2-rc.1`, `0.1.3-alpha.1`, `0.1.5-alpha.1`, `0.1.5-alpha.2`,
|
|
339
|
+
`0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.6-alpha.1`, `0.1.6-alpha.2`,
|
|
340
|
+
`0.1.7-alpha.1`, `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`,
|
|
341
|
+
`0.2.0-rc.2`, `0.2.1-alpha.1` (18 releases, `0.1.1-rc.1` … `0.2.1-alpha.1`).
|
|
342
|
+
The plugin is built against `@deepseek-ai/dsh-tools` /
|
|
343
|
+
`@deepseek-ai/dsh-util-values` `0.2.1-alpha.1` and uses only public contracts
|
|
344
|
+
(tool registration, client slots + theme, bundle patch).
|
|
301
345
|
- **Disposable-Profile evidence (real, `dsh` CLI `0.1.1-rc.1`)**: on a temp
|
|
302
346
|
`$DSH_HOME`, `dsh plugin --profile <p> add <this-repo>` installed the bundle in
|
|
303
347
|
~449 ms; `dsh --profile <p> --dump-config` composed the `iterate-plugin` bundle
|
|
@@ -376,7 +420,7 @@ npm test
|
|
|
376
420
|
|
|
377
421
|
All tests pass:
|
|
378
422
|
|
|
379
|
-
- **
|
|
423
|
+
- **Full unit suite + type-check clean** (`npm test`, `npm run typecheck`) — the exact count is intentionally not pinned here to avoid doc drift; see `CHANGELOG.md` for per-release magnitudes
|
|
380
424
|
- Coverage: dedupe, filter, sort, multi-round convergence, meta-review audit, path safety, timeout clamping, config read/write + rollback, triage merge, diff computation, checkpoint validation, fix registry, history read + filter, prune cleanup report + dry-run semantics, UI pure functions (select-all key, runtime status guide), **v3.2: experience bank, quality gate, defense events, approval-gate fail-open path**.
|
|
381
425
|
|
|
382
426
|
---
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# iterate-plugin for DeepSeek Harness (dsh)
|
|
2
2
|
|
|
3
|
-
> dsh 桌面端的 iterate 质量指挥中心 + 经验银行插件(v3.
|
|
3
|
+
> dsh 桌面端的 iterate 质量指挥中心 + 经验银行插件(v3.6)。把 iterate 生态的同一套 review/fix loop 直接搬进 dsh 界面,新增质量门禁、经验银行、防御事件流与原生指挥操作。
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="README.md"><strong>English</strong></a> ·
|
|
@@ -60,7 +60,7 @@ dsh plugin --profile web add iterate-plugin
|
|
|
60
60
|
|
|
61
61
|
**v3.2 质量指挥中心**:插件已从"被动观察面板"升级为"主动指挥中心 + 知识库"。新增质量门禁读取与可写计算(compute)、经验银行(检索 / 采纳 / 新增 add)、防御事件流(记录 + 中英双语标签)、原生命令按钮与 `task_mode` 指示器。
|
|
62
62
|
|
|
63
|
-
除 17 个纯函数工具外,还内置一套**免构建的 Web UI 层**(收敛看板、分诊面板、统计卡片、
|
|
63
|
+
除 17 个纯函数工具外,还内置一套**免构建的 Web UI 层**(收敛看板、分诊面板、统计卡片、11 页签运行时观测台——实时活动流 + F1–F10——、主题皮肤等),直接挂在 dsh 客户端的既有 UI 槽位上。配置方式(`iterate.config.yaml` 与审查维度)与迭代生态的另外两个组件([技能](https://github.com/jingzhao-l/iterate-skill) / [无头引擎](https://github.com/jingzhao-l/iterate-harness))完全一致,迁移零成本。
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -68,6 +68,7 @@ dsh plugin --profile web add iterate-plugin
|
|
|
68
68
|
|
|
69
69
|
- [✨ 特性](#-特性)
|
|
70
70
|
- [📦 安装](#-安装)
|
|
71
|
+
- [🧭 在 dsh 中使用 UI](#️-在-dsh-中使用-ui)
|
|
71
72
|
- [💬 使用](#-使用)
|
|
72
73
|
- [⚙️ 项目配置](#️-项目配置)
|
|
73
74
|
- [🔧 注册工具](#-注册工具)
|
|
@@ -102,15 +103,15 @@ dsh plugin --profile web add iterate-plugin
|
|
|
102
103
|
- 每轮修复后验证
|
|
103
104
|
- 修复失败自动回滚
|
|
104
105
|
|
|
105
|
-
### UI 层(客户端免构建槽位,v3.
|
|
106
|
+
### UI 层(客户端免构建槽位,v3.6:11 个页签)
|
|
106
107
|
|
|
107
|
-
- **收敛看板 `ConvergenceDashboard`**(`conversation.input.dock`)— 输入框上方实时显示轮次进度条、严重度统计、维度徽章、趋势迷你图;normal 模式另显示修复计数徽章;还有运行阶段芯片(当前工作流阶段 + 运行中/已结束)与 **
|
|
108
|
-
- **运行时观测台 `ObservatoryPanel`**(`conversation.input.dock`)—
|
|
109
|
-
- **Findings 分诊面板 `TriagePanel`**(`conversation.chat.turnTail`)—
|
|
108
|
+
- **收敛看板 `ConvergenceDashboard`**(`conversation.input.dock`)— 输入框上方实时显示轮次进度条、严重度统计、维度徽章、趋势迷你图;normal 模式另显示修复计数徽章;还有运行阶段芯片(当前工作流阶段 + 运行中/已结束)与 **task_mode 指示器(code / iterate)**。运行期间看板切换为"运行中"状态(显示轮次与阶段),并隐藏启动按钮。
|
|
109
|
+
- **运行时观测台 `ObservatoryPanel`**(`conversation.input.dock`)— 输入框下方**十一个页签**运行时观测台:**实时活动流**(默认页,支持按活动类型筛选)+ **F1** 审查线程(全部展开/全部收起)、**F2** 收敛趋势(含跨轮对比表:每轮 findings / fixed / 严重度分布 / 验证结果)、**F3** 发现定位(按严重度/维度/关键词筛选)、**F4** 修复与回滚、**F5** 断点恢复、**F6** 运行控制台、**F7** 决策时间线(按类型/轮次筛选与关键词搜索)、**F8** 质量门禁、**F9** 经验银行、**F10** 防御事件。数字键快捷键:`1`–`9` 跳到 F1–F9,`0` 到 F10,`-` 回实时活动流。**F8/F9/F10 为实时数据**——扫描会话流中最近一次 `iterate_quality_gate` / `iterate_experience` / `iterate_defense_events` 结果并渲染真实数据(PASS/FAIL 徽章 + 分维度评分条、经验条目(含采纳按钮 + 客户端搜索)、防御类型计数芯片 + 筛选后的事件流);会话流中没有数据时区分"磁盘无数据"与"尚未拉取",并提供**拉取磁盘快照**指令(让模型调用只读工具、把 `.iterate/` 产物回显进会话流)。一键导出全部观测数据为 JSON——manifest + live + `qualityGate` / `experienceBank` / `defenseEvents` / `report`(优先下载,失败回退复制)。**v3.5.3 新增重置操作**:F5 复制 `iterate_checkpoint clear`、F8 复制 `iterate_quality_gate clear`、F10 复制 `iterate_defense_events clear` 指令。
|
|
110
|
+
- **Findings 分诊面板 `TriagePanel`**(`conversation.chat.turnTail`)— 逐条分诊,键盘快捷键 `y`(保留→修复)、`n`(跳过)、`a`(已知有意)与 `↑`/`↓` 移动(焦点守卫:仅面板内焦点时生效),支持筛选、批量(含一键全选所有 findings)、localStorage 持久化。**写回闭环**:主按钮复制已标记条目的 `iterate_triage apply` 指令(工具负责校验、去重、备份、失败回滚);次按钮复制裸 `known_intentional` YAML;**回读已写入条目**复制 `iterate_triage list` 指令核对实际落盘内容。复制载荷与目标工具 schema 对齐。**v3.2:原生命令按钮**(批准架构修复、触发新一轮、回滚到断点)。
|
|
110
111
|
- **收敛统计卡片 `StatsCard`**(`conversation.chat.turnTail`)— 无 findings 时显示收敛统计、历史轮次、趋势图、完成摘要。
|
|
111
112
|
- **iterate 主题皮肤**(`theme.overrideTokens`)— 暖琥珀配色的 13 个 `--dsw-*` token 覆盖,明暗双模式,可在设置页开关。
|
|
112
113
|
- **进度胶囊 `ProgressCapsule`**(`shell.overlay`)— 每轮完成 / 收敛时右下角弹出通知(含收敛确认)。
|
|
113
|
-
- **iterate 设置区 `SettingsPanel`**(`settings.section`)—
|
|
114
|
+
- **iterate 设置区 `SettingsPanel`**(`settings.section`)— 主题开关、分诊持久化说明、配置管理指引(覆盖 `validation.commands` / `language` / `personalization.known_intentional`,并显式警告"validation.commands 为空 = 本轮不受任何测试保护";字段选择器可生成对应的 `iterate_config write` 指令)、运行时状态概览(产物布局 + 查看/清理工具指引 + 磁盘快照拉取)、一键清空分诊数据。
|
|
114
115
|
|
|
115
116
|
UI 层为**防御式设计**:`slots` / `theme` / `React` 任一不可用时自动降级,不会崩溃客户端。
|
|
116
117
|
|
|
@@ -121,7 +122,7 @@ UI 层为**防御式设计**:`slots` / `theme` / `React` 任一不可用时自
|
|
|
121
122
|
- **findings 分诊闭环** — 审查 → UI 分诊(y/n/a)→ `iterate_triage` 写回 `known_intentional` → 下一轮自动过滤
|
|
122
123
|
- **结构化修复系统** — 每次修复先备份、写注册表、记录 diff,验证失败可 `iterate_rollback` 还原
|
|
123
124
|
- **断点续跑** — 长迭代在每轮开头保存 checkpoint,中断后可恢复进度
|
|
124
|
-
- **历史审计** — `iterate_history`
|
|
125
|
+
- **历史审计** — `iterate_history` 读取决策日志(可按 `type` / `since` / `round` / 修复文件 `file` / `limit` 过滤,默认取最新 50 条,上限 200 条)与修复注册表汇总(各轮 fixed/failed 计数,按同一 round/file 过滤收窄),审查运行过程与修复明细
|
|
125
126
|
- **运行时清理** — `iterate_prune` 清理过期的决策日志条目、陈旧断点、孤儿修复备份、空轮次与原子写入崩溃残留的临时文件;默认 dry-run 只报告不删除,显式 `dryRun:false` 才真正清理,每次清理写入决策日志
|
|
126
127
|
- **配置读写** — `iterate_config` 支持带校验、备份、回滚的局部写入
|
|
127
128
|
- **v3.2 经验银行** — `iterate_experience` 以检索 / 过滤 / 采纳查阅历史修复与模式,并可 `add` 持久化新的已验证修复——重复添加同一 pattern + dimension 时累加命中次数而非重复写入
|
|
@@ -166,7 +167,46 @@ pnpm add /path/to/iterate-skill/harness/iterate-plugin
|
|
|
166
167
|
name: 'iterate-plugin'
|
|
167
168
|
```
|
|
168
169
|
|
|
169
|
-
> 插件包自带 `dsh.bundle.patch`(即 `cordis.patch.yml`),npm 包内 `files` 已白名单化(`src` / `lib` / `dist` / `cordis.patch.yml` / `README.md` / `LICENSE`)。其中 `dist/` 为 TypeScript 服务端逻辑的编译产物,随包分发以兼容 dsh 的 `github:owner/repo#ref` git-clone 安装方式(Node 不擦除 `node_modules` 下的 TS 类型)。
|
|
170
|
+
> 插件包自带 `dsh.bundle.patch`(即 `cordis.patch.yml`),npm 包内 `files` 已白名单化(`src` / `lib` / `dist` / `cordis.patch.yml` / `README.md` / `README.zh-CN.md` / `LICENSE`)。其中 `dist/` 为 TypeScript 服务端逻辑的编译产物,随包分发以兼容 dsh 的 `github:owner/repo#ref` git-clone 安装方式(Node 不擦除 `node_modules` 下的 TS 类型)。
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 🧭 在 dsh 中使用 UI
|
|
175
|
+
|
|
176
|
+
浏览器客户端**没有文件系统访问权限**——所有面板渲染的都是 dsh 会话流里的数据(模型回显的工具结果)。因此本插件的 UI 围绕一个交互范式构建:**从按钮复制指令 → 粘贴回对话 → 模型调用对应工具 → 面板自动填充**。客户端按钮从不启动任何进程。
|
|
177
|
+
|
|
178
|
+
### 启动一次迭代(空态仪表盘)
|
|
179
|
+
|
|
180
|
+
还没有任何 report 时,收敛看板显示两个按钮——**「完整迭代」**与**「仅评审」**——各自把一段**自然语言指令**复制到剪贴板。这些**不是 slash 命令**:插件没有注册 `/iterate` 之类的命令;把文本粘贴进对话即可,模型会通过 dsh 的 `workflow` 工具运行 iterate 工作流。完整迭代指令还要求模型先预检 `validation.commands`——若未配置则停下来提示你写入(与工作流自身的 fail-closed 规则一致),不受测试保护的迭代绝不会看起来"全绿"。
|
|
181
|
+
|
|
182
|
+
运行期间,看板切换为**运行中状态**(显示轮次与工作流阶段芯片),并隐藏启动按钮。
|
|
183
|
+
|
|
184
|
+
### 分诊面板快捷键
|
|
185
|
+
|
|
186
|
+
快捷键只在分诊面板内焦点时生效(在别处输入时处理器会忽略):
|
|
187
|
+
|
|
188
|
+
- `y` — 保留该 finding(进入修复);`n` — 跳过;`a` — 标记为已知有意(写回候选)
|
|
189
|
+
- `↑` / `↓` — 在 findings 之间移动(判定后自动前进)
|
|
190
|
+
- 批量按钮 `y` / `n` / `a` 一次性对全部 findings 应用同一判定
|
|
191
|
+
|
|
192
|
+
要写回配置,用 `a` 标记条目后点击**生成应用指令**——它会为这些条目复制一条 `iterate_triage apply` 指令(工具负责校验、按 file|dimension|line 去重、备份、失败回滚)。粘贴回会话后,点击**回读已写入条目**复制 `iterate_triage list` 指令核对实际落盘内容——写回 → 回读闭环。
|
|
193
|
+
|
|
194
|
+
### 观测台页签与快捷键
|
|
195
|
+
|
|
196
|
+
输入框下方的观测台共 **11 个页签**:实时活动流(默认页)+ **F1–F10**:
|
|
197
|
+
|
|
198
|
+
`F1` 审查线程 · `F2` 收敛趋势(含跨轮对比)· `F3` 发现定位 · `F4` 修复与回滚 · `F5` 断点恢复 · `F6` 运行控制台 · `F7` 决策时间线 · `F8` 质量门禁 · `F9` 经验银行 · `F10` 防御事件
|
|
199
|
+
|
|
200
|
+
按 `1`–`9` 跳到 F1–F9,`0` 到 F10,`-` 回实时活动流。
|
|
201
|
+
|
|
202
|
+
### 磁盘快照拉取与导出
|
|
203
|
+
|
|
204
|
+
- **拉取磁盘快照**——新会话(或刷新后)面板是空的,哪怕磁盘上 `.iterate/` 早有产物。拉取按钮复制一条指令,让模型调用只读工具(`iterate_status`、`iterate_transcript` `read`、`iterate_quality_gate` `read`、`iterate_experience` `list`、`iterate_defense_events` `list`、`iterate_history`)并把**完整**结果回显进会话流;会话扫描器随之填充看板、F2、F5、F8、F9、F10。空态文案区分"磁盘无数据"与"尚未拉取"。
|
|
205
|
+
- **导出 JSON**——一键把整个观测台序列化为 JSON:manifest + 实时流 + `qualityGate` + `experienceBank` + `defenseEvents` + `report`(优先下载,失败回退复制到剪贴板)。
|
|
206
|
+
|
|
207
|
+
### 从设置页管理配置
|
|
208
|
+
|
|
209
|
+
设置区复制一份配置编辑指引,列出支持的 `iterate.config.yaml` 字段——包括 `validation.commands`(并显式警告:留空意味着每一轮迭代都不受任何测试保护)——并提供**字段选择器**:选中字段后,按钮会生成对应的 `iterate_config write` 指令(schema 校验、自动备份、失败自动回滚)供你粘贴回会话。
|
|
170
210
|
|
|
171
211
|
---
|
|
172
212
|
|
|
@@ -243,7 +283,7 @@ validation:
|
|
|
243
283
|
|
|
244
284
|
---
|
|
245
285
|
|
|
246
|
-
## 🔧 注册工具(
|
|
286
|
+
## 🔧 注册工具(17 个)
|
|
247
287
|
|
|
248
288
|
- `iterate_config` — 读取 / 写入 `iterate.config.yaml`。`operation=read` 返回完整配置或指定 section;`operation=write` 做 schema 校验、备份后局部合并写入,失败自动回滚
|
|
249
289
|
- `iterate_validate` — 运行白名单验证命令,返回结果
|
|
@@ -256,7 +296,7 @@ validation:
|
|
|
256
296
|
- `iterate_rollback` — 回滚一个已应用的修复:从备份还原文件、从注册表移除该 FixRecord、追加 `revert` 日志。用于某轮验证失败后
|
|
257
297
|
- `iterate_checkpoint` — 迭代断点:`save` 保存当前进度到 `.iterate/checkpoint.json`,`load` 读回,`resume` 加载并累加恢复计数(中断恢复),`clear` 清除(findings 载荷有上限,强制 `round ≤ maxRounds`)。长迭代可中断续跑
|
|
258
298
|
- `iterate_status` — 汇总当前迭代状态:模式、当前轮/总轮、已修复数、剩余 architectural、决策日志条数、是否存在 checkpoint;**v3.4:同时返回持久化的质量门禁快照、经验银行摘要与防御事件摘要**(`qualityGate` / `experienceBank` / `defenseEvents`)
|
|
259
|
-
- `iterate_history` — 读取迭代历史(只读):决策日志条目(可按 `type` / `since` / `limit` 过滤,默认取最新 50 条,上限 200 条)+ 修复注册表汇总(各轮 fixed/failed
|
|
299
|
+
- `iterate_history` — 读取迭代历史(只读):决策日志条目(可按 `type` / `since` / `round` / 修复文件 `file` / `limit` 过滤,默认取最新 50 条,上限 200 条)+ 修复注册表汇总(各轮 fixed/failed 计数,按同一 round/file 过滤收窄;`file` 过滤时按保留的记录重算计数)。用于审查运行过程、审计日志、盘点修复
|
|
260
300
|
- `iterate_prune` — 清理运行时产物:过期决策日志条目(按 `retainDays`,默认 30 天)、陈旧断点、孤儿修复备份、空轮次、崩溃原子写入残留的临时文件。默认 dry-run 只报告不删除;`dryRun:false` 才真正清理,每次清理写入决策日志
|
|
261
301
|
- `iterate_transcript` — 运行时观测台:把审查转录、线程、修复与 nudge 指令持久化到 `.iterate/transcript.json`,供客户端观测台读取
|
|
262
302
|
- `iterate_experience` — **v3.2** 查询经验银行(list / search / get),或 `add` 一条新的已验证修复:重复添加同一 pattern + dimension 累加命中次数而非重复写入。**v3.5 新增 `remove`:按 `id` 删除过时或错误的经验条目**。持久化到 `.iterate/experience.json`
|
|
@@ -290,11 +330,7 @@ validation:
|
|
|
290
330
|
### Node.js / DSH 兼容范围
|
|
291
331
|
|
|
292
332
|
- **Node.js**:`>=20`(`package.json` 的 `engines.node`)。
|
|
293
|
-
- **DSH
|
|
294
|
-
`0.1.2-alpha.4`、`0.1.2-alpha.5`、`0.1.2-rc.1`、`0.1.3-alpha.1` 五个版本为
|
|
295
|
-
`compatible`。插件基于 `@deepseek-ai/dsh-tools` / `@deepseek-ai/dsh-util-values`
|
|
296
|
-
`0.1.2-rc.1` 构建,只使用公开契约(工具注册、客户端 slots + theme、bundle patch);
|
|
297
|
-
`0.1.3-alpha.1` 为匹配当前 DSH 发布窗口的源码声明,插件不使用该发布变更的任何 API。
|
|
333
|
+
- **DSH**:`package.json` 的 `dsh.compatibility.dshReleases` 字段是发布兼容性的**唯一真源**(本 README 逐字镜像该字段;两者需同步更新)。以下官方版本声明为 `compatible`:`0.1.1-rc.1`、`0.1.2-alpha.4`、`0.1.2-alpha.5`、`0.1.2-rc.1`、`0.1.3-alpha.1`、`0.1.5-alpha.1`、`0.1.5-alpha.2`、`0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.6-alpha.1`、`0.1.6-alpha.2`、`0.1.7-alpha.1`、`0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.1`(共 18 个版本,`0.1.1-rc.1` … `0.2.1-alpha.1`)。插件基于 `@deepseek-ai/dsh-tools` / `@deepseek-ai/dsh-util-values` `0.2.1-alpha.1` 构建,只使用公开契约(工具注册、客户端 slots + theme、bundle patch)。
|
|
298
334
|
- **一次性 Profile 证据(真实,`dsh` CLI `0.1.1-rc.1`)**:在临时 `$DSH_HOME` 下
|
|
299
335
|
`dsh plugin --profile <p> add <本仓库>` 约 449ms 完成安装;`dsh --profile <p>
|
|
300
336
|
--dump-config` 正确合成 `iterate-plugin` bundle patch;`dsh plugin --profile <p>
|
|
@@ -363,7 +399,7 @@ npm test
|
|
|
363
399
|
|
|
364
400
|
所有测试通过:
|
|
365
401
|
|
|
366
|
-
-
|
|
402
|
+
- **全量单元测试 + 类型检查通过**(`npm test`、`npm run typecheck`——此处刻意不写具体数量以根除文档漂移,各版本量级见 `CHANGELOG.md`)
|
|
367
403
|
- 覆盖:去重、过滤、排序、多轮收敛、meta-review 审计、路径安全、超时钳制、配置读写与回滚、triage 合并、diff 计算、checkpoint 校验、修复注册表、历史读取与过滤、prune 清理报告与 dry-run 语义、UI 纯函数(select-all 键、运行时状态指引)、**v3.2:经验银行、质量门禁、防御事件、审批门禁 fail-open 路径**等
|
|
368
404
|
|
|
369
405
|
---
|
package/dist/approval-gate.js
CHANGED
|
@@ -6,9 +6,19 @@
|
|
|
6
6
|
* any I/O, so it is fully unit-testable:
|
|
7
7
|
*
|
|
8
8
|
* - `{ kind: 'allow' }` → run the call.
|
|
9
|
-
* - `{ kind: 'ask', reason }`
|
|
9
|
+
* - `{ kind: 'ask', reason, displayReason }` → prompt the human via the dsh
|
|
10
|
+
* approval service (`displayReason` carries the localized prompt text;
|
|
11
|
+
* dsh 0.2.x renders it when present).
|
|
10
12
|
* - `{ kind: 'deny', reason }` → refuse; the caller surfaces the reason.
|
|
11
13
|
*
|
|
14
|
+
* LANGUAGE RULE (project `config.language`, zh|en):
|
|
15
|
+
* - Human-facing text (the `ask` prompt / `displayReason`) FOLLOWS the
|
|
16
|
+
* configured language.
|
|
17
|
+
* - Structured/durable text (the `deny` reason, `deny.info.reason`,
|
|
18
|
+
* decision-log and console output) STAYS ENGLISH so logs, audits, and
|
|
19
|
+
* machine matchers never depend on a locale. `ask.reason` is the audited
|
|
20
|
+
* English summary; `displayReason` is the localized prompt.
|
|
21
|
+
*
|
|
12
22
|
* Policy (config `observatory.approval`, default 'ask'):
|
|
13
23
|
* - `allow` → destructive iterate calls always run (debug/trusted).
|
|
14
24
|
* - `deny` → destructive iterate calls are always refused (fail-closed).
|
|
@@ -16,36 +26,135 @@
|
|
|
16
26
|
*
|
|
17
27
|
* Destructive calls are exactly the ones that mutate the workspace:
|
|
18
28
|
* `iterate_fix` (writes files), `iterate_rollback` (restores from backups),
|
|
19
|
-
*
|
|
29
|
+
* `iterate_prune` with `dryRun === false` (deletes `.iterate/` artifacts —
|
|
30
|
+
* prune is read-only by default, so only an explicit `dryRun: false` gates),
|
|
31
|
+
* and `iterate_config` with `operation === 'write'` (rewrites
|
|
32
|
+
* `iterate.config.yaml`). `iterate_config` writes matter because the config
|
|
33
|
+
* is policy: a silent `reviewer: {evidence_validation: false}` or a
|
|
34
|
+
* `validation.commands` addition changes what later rounds are allowed to do,
|
|
35
|
+
* so a write is consented to exactly like a file write — the read operation
|
|
36
|
+
* stays free.
|
|
20
37
|
* Read-only calls are always allowed. Non-iterate calls are untouched — the
|
|
21
38
|
* gate only ever inspects iterate tools so it cannot alter unrelated behavior.
|
|
22
39
|
*/
|
|
23
|
-
/**
|
|
24
|
-
const DESTRUCTIVE_TOOLS = new Set([
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
/** Iterate tools subject to the gate (some only in specific operations). */
|
|
41
|
+
const DESTRUCTIVE_TOOLS = new Set([
|
|
42
|
+
'iterate_fix',
|
|
43
|
+
'iterate_rollback',
|
|
44
|
+
'iterate_prune',
|
|
45
|
+
'iterate_config',
|
|
46
|
+
]);
|
|
47
|
+
/**
|
|
48
|
+
* True when this specific call MUTATES the workspace and therefore needs
|
|
49
|
+
* consent. Two of the four gated tools are operation-conditional:
|
|
50
|
+
* - `iterate_prune` is read-only unless `dryRun === false`;
|
|
51
|
+
* - `iterate_config` reads freely, but `operation === 'write'` rewrites
|
|
52
|
+
* `iterate.config.yaml` — the file that carries the approval policy,
|
|
53
|
+
* the reviewer gates, and the command allow-list.
|
|
54
|
+
*/
|
|
55
|
+
function mutatesWorkspace(toolName, args) {
|
|
56
|
+
if (toolName === 'iterate_prune')
|
|
57
|
+
return args.dryRun === false;
|
|
58
|
+
if (toolName === 'iterate_config')
|
|
59
|
+
return args.operation === 'write';
|
|
60
|
+
return DESTRUCTIVE_TOOLS.has(toolName);
|
|
61
|
+
}
|
|
62
|
+
/** Config updates the model supplied (empty when absent/malformed). */
|
|
63
|
+
function readUpdates(args) {
|
|
64
|
+
const u = args.updates;
|
|
65
|
+
return u && typeof u === 'object' && !Array.isArray(u) ? u : {};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Config switches that DISABLE a safety gate, for the consent text. Writing
|
|
69
|
+
* `reviewer.evidence_validation: false` is legal config — but the human being
|
|
70
|
+
* asked must see that the call is about to turn a review gate off, not just
|
|
71
|
+
* "update a file".
|
|
72
|
+
*/
|
|
73
|
+
function disabledReviewGates(updates) {
|
|
74
|
+
const rv = updates.reviewer;
|
|
75
|
+
if (!rv || typeof rv !== 'object' || Array.isArray(rv))
|
|
76
|
+
return [];
|
|
77
|
+
const off = [];
|
|
78
|
+
for (const key of ['output_schema_validation', 'evidence_validation', 'coverage_validation']) {
|
|
79
|
+
if (rv[key] === false)
|
|
80
|
+
off.push(`reviewer.${key}`);
|
|
81
|
+
}
|
|
82
|
+
return off;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Human-readable reason rendered in the approval prompt.
|
|
86
|
+
*
|
|
87
|
+
* `language` selects the wording of the HUMAN-FACING text; call it with
|
|
88
|
+
* `'en'` for the structured, machine-readable string (deny reasons, audited
|
|
89
|
+
* ask summaries) and with the project's configured language for the prompt
|
|
90
|
+
* text (`displayReason`). The structured deny reason therefore never
|
|
91
|
+
* localizes, while the consent prompt follows `config.language`.
|
|
92
|
+
*/
|
|
93
|
+
export function describe(toolName, arguments0, language = 'en') {
|
|
94
|
+
const zh = language === 'zh';
|
|
27
95
|
const file = arguments0 && typeof arguments0.file === 'string'
|
|
28
96
|
? `\`${arguments0.file}\``
|
|
29
|
-
:
|
|
97
|
+
: zh
|
|
98
|
+
? '工作区'
|
|
99
|
+
: 'the workspace';
|
|
30
100
|
switch (toolName) {
|
|
31
101
|
case 'iterate_fix':
|
|
32
|
-
return
|
|
102
|
+
return zh
|
|
103
|
+
? `对 ${file} 应用一次原子修复`
|
|
104
|
+
: `Apply an atomic fix to ${file}`;
|
|
33
105
|
case 'iterate_rollback': {
|
|
34
|
-
|
|
35
|
-
|
|
106
|
+
// Rollback's parameters are `id` (required) + `path` (project root) —
|
|
107
|
+
// it has NO `file` param, so naming `arguments.file` could never
|
|
108
|
+
// identify the target ("restore the workspace from backup" every time).
|
|
109
|
+
// Name the fix id and, when present, the project scope instead.
|
|
110
|
+
const id = arguments0 && typeof arguments0.id === 'string' && arguments0.id
|
|
111
|
+
? `\`${arguments0.id}\``
|
|
112
|
+
: null;
|
|
113
|
+
const scope = arguments0 && typeof arguments0.path === 'string' && arguments0.path
|
|
114
|
+
? `\`${arguments0.path}\``
|
|
115
|
+
: null;
|
|
116
|
+
const target = id ?? scope ?? (zh ? '一次修复' : 'a fix');
|
|
117
|
+
const inScope = id && scope ? (zh ? `(位于 ${scope})` : ` in ${scope}`) : '';
|
|
118
|
+
return zh
|
|
119
|
+
? `回滚修复 ${target}${inScope}(从备份恢复其文件)`
|
|
120
|
+
: `Revert fix ${target}${inScope} (restore its file from backup)`;
|
|
36
121
|
}
|
|
37
122
|
case 'iterate_prune':
|
|
38
|
-
return
|
|
123
|
+
return zh
|
|
124
|
+
? '删除过期的 `.iterate/` 运行时产物'
|
|
125
|
+
: 'Delete stale `.iterate/` runtime artifacts';
|
|
126
|
+
case 'iterate_config': {
|
|
127
|
+
// Name WHAT is being written and shout when the write disables a review
|
|
128
|
+
// gate — the consent prompt is the last human look before the model
|
|
129
|
+
// rewrites the policy file. The WARNING marker stays literal in both
|
|
130
|
+
// languages so the UI's highlight rule matches on it.
|
|
131
|
+
const updates = readUpdates(arguments0 ?? {});
|
|
132
|
+
const keys = Object.keys(updates);
|
|
133
|
+
const scope = keys.length > 0 ? keys.map((k) => `\`${k}\``).join(', ') : (zh ? '配置' : 'the configuration');
|
|
134
|
+
const base = zh
|
|
135
|
+
? `更新 \`iterate.config.yaml\`(${scope})`
|
|
136
|
+
: `Update \`iterate.config.yaml\` (${scope})`;
|
|
137
|
+
const off = disabledReviewGates(updates);
|
|
138
|
+
if (off.length === 0)
|
|
139
|
+
return base;
|
|
140
|
+
return zh
|
|
141
|
+
? `${base} — WARNING:将关闭 ${off.join(', ')}`
|
|
142
|
+
: `${base} — WARNING: turns OFF ${off.join(', ')}`;
|
|
143
|
+
}
|
|
39
144
|
default:
|
|
40
|
-
return `Run ${toolName}`;
|
|
145
|
+
return zh ? `运行 ${toolName}` : `Run ${toolName}`;
|
|
41
146
|
}
|
|
42
147
|
}
|
|
43
148
|
/**
|
|
44
149
|
* Decide whether a tool execution may proceed under the given policy.
|
|
45
|
-
* Returns `allow` for read-only prune (`dryRun: true`), for
|
|
150
|
+
* Returns `allow` for read-only prune (`dryRun: true`), for config READS
|
|
151
|
+
* (`iterate_config` without `operation: 'write'`), for `allow`-policy
|
|
46
152
|
* deployments, and for any non-iterate tool.
|
|
153
|
+
*
|
|
154
|
+
* `language` only affects the HUMAN-FACING `ask.displayReason` text; the
|
|
155
|
+
* audited `ask.reason` and the `deny.reason` stay English (see header).
|
|
47
156
|
*/
|
|
48
|
-
export function decideApproval(execution, policy) {
|
|
157
|
+
export function decideApproval(execution, policy, language = 'en') {
|
|
49
158
|
// Defensive reads: a hostile/proxied execution object must degrade to "not
|
|
50
159
|
// our tool" (allow) rather than throw inside the gate.
|
|
51
160
|
let name = '';
|
|
@@ -69,21 +178,32 @@ export function decideApproval(execution, policy) {
|
|
|
69
178
|
const args = rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs)
|
|
70
179
|
? rawArgs
|
|
71
180
|
: {};
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
else if (name === 'iterate_prune') {
|
|
181
|
+
// Operation-conditional tools are read-only in their default operation —
|
|
182
|
+
// `iterate_prune` dry-runs and `iterate_config` reads need no consent.
|
|
183
|
+
if (!mutatesWorkspace(name, args))
|
|
77
184
|
return { kind: 'allow' };
|
|
78
|
-
}
|
|
79
185
|
if (policy === 'allow')
|
|
80
186
|
return { kind: 'allow' };
|
|
81
|
-
|
|
187
|
+
// Structured text (deny reason / audited ask summary) is always English;
|
|
188
|
+
// only the human prompt (`displayReason`) follows the project language.
|
|
189
|
+
const reason = describe(name, args, 'en');
|
|
82
190
|
if (policy === 'deny')
|
|
83
191
|
return { kind: 'deny', reason };
|
|
84
|
-
|
|
192
|
+
const localized = describe(name, args, language);
|
|
193
|
+
return {
|
|
194
|
+
kind: 'ask',
|
|
195
|
+
reason,
|
|
196
|
+
displayReason: language === 'zh' ? { en: reason, zh: localized } : { en: reason },
|
|
197
|
+
};
|
|
85
198
|
}
|
|
86
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* True when a tool name is ROUTED through the approval gate.
|
|
201
|
+
*
|
|
202
|
+
* Name-level only (the caller has not parsed arguments yet), so the two
|
|
203
|
+
* operation-conditional tools are included for their whole name and
|
|
204
|
+
* {@link decideApproval} narrows per call: prune with a dry run and
|
|
205
|
+
* `iterate_config` reads both come back `allow`.
|
|
206
|
+
*/
|
|
87
207
|
export function isDestructiveIterateTool(name) {
|
|
88
208
|
return typeof name === 'string' && DESTRUCTIVE_TOOLS.has(name);
|
|
89
209
|
}
|