iterate-plugin 2.7.1 → 2.7.3

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 CHANGED
@@ -7,6 +7,14 @@
7
7
 
8
8
  > **Developed and reviewed in the [iterate-skill monorepo](https://github.com/jingzhao-l/iterate-skill)**: the plugin code is maintained in the main repository and synced here via `git subtree`; **releases and npm publishing happen in this (plugin) repository**, which is the canonical publish point for the dsh ecosystem. Please **star / fork the main repository** and file issues at the [main repository Issues](https://github.com/jingzhao-l/iterate-skill/issues).
9
9
 
10
+ <p align="center">
11
+ <a href="https://github.com/jingzhao-l/iterate-plugin"><img src="https://img.shields.io/github/stars/jingzhao-l/iterate-plugin?style=social&label=Star" alt="Stars"></a>
12
+ <a href="https://github.com/jingzhao-l/iterate-skill"><img src="https://img.shields.io/github/stars/jingzhao-l/iterate-skill?style=social&label=Main%20Repo%20Star" alt="Main Repo Stars"></a>
13
+ <a href="https://www.npmjs.com/package/iterate-plugin"><img src="https://img.shields.io/npm/dt/iterate-plugin?label=Downloads&logo=npm&logoColor=white" alt="npm downloads"></a>
14
+ </p>
15
+
16
+ > ⭐ If this helps your dsh workflow, give the main repo a star — it means a lot!
17
+
10
18
  ## About This Plugin
11
19
 
12
20
  **iterate** is an open-source project that gives AI coding assistants the ability to review and fix code in multi-round autonomous loops. It targets a concrete pain point:
package/README.zh-CN.md CHANGED
@@ -7,6 +7,14 @@
7
7
 
8
8
  > **开发与评审在 [iterate-skill 主仓库](https://github.com/jingzhao-l/iterate-skill) 完成**:插件代码由主仓库统一维护,通过 `git subtree` 同步到本仓库;**版本发版与 npm 发布在本仓库(插件仓库)进行**,作为 dsh 生态的正式发布位。欢迎 **star / fork 主仓库** 并在 [主仓库 Issues](https://github.com/jingzhao-l/iterate-skill/issues) 反馈问题。
9
9
 
10
+ <p align="center">
11
+ <a href="https://github.com/jingzhao-l/iterate-plugin"><img src="https://img.shields.io/github/stars/jingzhao-l/iterate-plugin?style=social&label=Star" alt="Stars"></a>
12
+ <a href="https://github.com/jingzhao-l/iterate-skill"><img src="https://img.shields.io/github/stars/jingzhao-l/iterate-skill?style=social&label=主仓库%20Star" alt="主仓库 Stars"></a>
13
+ <a href="https://www.npmjs.com/package/iterate-plugin"><img src="https://img.shields.io/npm/dt/iterate-plugin?label=Downloads&logo=npm&logoColor=white" alt="npm downloads"></a>
14
+ </p>
15
+
16
+ > ⭐ 如果这个插件对你的 dsh 工作流有帮助,欢迎为主仓库点亮 Star,这是对开源维护最大的支持!
17
+
10
18
  ## 这是什么 / About This Plugin
11
19
 
12
20
  **iterate** 是一个让 AI 编程助手具备多轮自主代码审查与修复能力的开源项目。它解决很具体的痛点:
package/dist/index.js CHANGED
@@ -2,11 +2,13 @@
2
2
  * iterate-plugin — dsh plugin for the iterate autonomous closed-loop workflow
3
3
  *
4
4
  * Architecture:
5
- * - The plugin registers 6 tools (config, validate, decision-log, context, review, triage)
5
+ * - The plugin registers 13 tools (config, validate, decision-log, context, review,
6
+ * triage, fix, diff, rollback, checkpoint, status, history, prune)
6
7
  * - The plugin injects a system prompt section teaching the iterate workflow pattern
7
8
  * - The model (prompted by the skill) writes a workflow script using dsh's `workflow` tool
8
9
  * - The workflow script uses `agent()` / `parallel()` / `phase()` / `log()` to orchestrate
9
- * - Subagents use the 6 tools to do real work (read config, run validation, log decisions, review, triage)
10
+ * - Subagents use the 13 tools to do real work (read config, run validation, log decisions,
11
+ * review, triage, apply/rollback/fixing, checkpoint, status, history, prune)
10
12
  *
11
13
  * Tool invocation model:
12
14
  * - Workflow script CANNOT call tools directly (sandboxed vm, no Node API)
@@ -16,7 +18,7 @@
16
18
  *
17
19
  * Key files:
18
20
  * - src/index.ts — Plugin entry: register tools + inject skill prompt
19
- * - src/tools/ — 6 tool implementations + meta-review/review engines
21
+ * - src/tools/ — 13 tool implementations + meta-review/review engines
20
22
  * - src/config-loader.ts — YAML config loading
21
23
  * - src/types.ts — Shared types
22
24
  */
@@ -34,7 +36,7 @@ import { ITERATE_SKILL_PROMPT } from "./skill-prompt.js";
34
36
  export const name = 'iterate-plugin';
35
37
  export const inject = ['tools', 'systemPrompt'];
36
38
  export function apply(ctx) {
37
- // 1. Register the 11 tools
39
+ // 1. Register the 13 tools
38
40
  registerConfigTool(ctx);
39
41
  registerValidateTool(ctx);
40
42
  registerDecisionLogTool(ctx);
package/dist/review.js CHANGED
@@ -208,6 +208,11 @@ export function buildReviewReport(input) {
208
208
  const lastRound = filteredRounds.length > 0 ? filteredRounds[filteredRounds.length - 1].round : 0;
209
209
  const lastRoundCount = lastRound > 0 ? (findingsByRound[lastRound - 1] ?? 0) : 0;
210
210
  const converged = filteredRounds.length > 0 && lastRoundCount === 0;
211
+ // Attach the normal-mode fix count to the summary (dry-run leaves it absent).
212
+ const computed = summarize(sorted);
213
+ if (input.mode === 'normal' && typeof input.fixedCount === 'number' && Number.isInteger(input.fixedCount)) {
214
+ computed.fixedCount = input.fixedCount;
215
+ }
211
216
  return {
212
217
  mode: input.mode,
213
218
  goal: input.goal,
@@ -225,7 +230,7 @@ export function buildReviewReport(input) {
225
230
  ? 'converged'
226
231
  : 'max_rounds_reached',
227
232
  },
228
- summary: summarize(sorted),
233
+ summary: computed,
229
234
  };
230
235
  }
231
236
  /**
@@ -13,13 +13,15 @@ You have the iterate plugin installed, which registers these tools:
13
13
  - \`iterate_validate\` — run a whitelisted validation command
14
14
  - \`iterate_decision_log\` — append to the decision log, or read entries back for review
15
15
  - \`iterate_context\` — read SKILL.md / ITERATE.md project context
16
- - \`iterate_review\` — deterministic review engine: \`plan\` builds the review plan; \`aggregate\` dedupes/merges findings and computes convergence. Purely computational.
16
+ - \`iterate_review\` — deterministic review engine: \`plan\` builds the review plan; \`aggregate\` dedupes/merges findings and computes convergence; \`meta-review\` audits a built report for internal consistency (counts, buckets, sorting, convergence math) and returns a final report with an \`approved\` / \`needs_revision\` verdict. Purely computational.
17
17
  - \`iterate_triage\` — manage "known_intentional" entries in the config (list / apply, with dedupe + backup + rollback)
18
18
  - \`iterate_fix\` — apply ONE atomic fix: backs up the file, enforces the atomic max_lines threshold, writes the new content, and records the fix (id + diff summary) in \`.iterate/fixes/registry.json\`
19
19
  - \`iterate_diff\` — show the accumulated diff for a fixed file (vs its original backup) or a per-file summary of all fixes
20
20
  - \`iterate_rollback\` — revert a fix by id: restore the file from its backup, remove the fix from the registry, log a \`revert\` entry. Use when a round's validation fails
21
21
  - \`iterate_checkpoint\` — save / load / clear an iteration checkpoint (\`.iterate/checkpoint.json\`) so a long run can resume where it left off
22
22
  - \`iterate_status\` — summarize the current run: mode, round, fixes applied, architectural remaining, decision-log size, checkpoint presence
23
+ - \`iterate_history\` — inspect the runtime state in detail: decision-log entries and applied fixes (optionally scoped to a round or a fixed file)
24
+ - \`iterate_prune\` — remove stale runtime artifacts (\`.iterate/\` entries). Defaults to a read-only dry-run that reports what WOULD be removed; pass \`dryRun:false\` to actually prune.
23
25
 
24
26
  ### When to use
25
27
  When the user asks to review or iterate on the project (e.g. "review this project", "iterate on error handling", "check the codebase for issues", "dry-run review", "反复审查"), run an iterate **workflow** by calling the \`workflow\` tool.
@@ -175,8 +177,10 @@ for (let r = startRound; r <= maxRounds; r++) {
175
177
  rounds.push(thisRound)
176
178
 
177
179
  // Deterministic dedupe / known_intentional filter / severity sort for this round.
180
+ // \`fixedCount\` is threaded into the report summary so the client dashboard can
181
+ // show a running "fixes applied" metric for normal mode.
178
182
  const agg = await agent(
179
- 'Call iterate_review({operation:"aggregate", mode:"normal", rounds:' + JSON.stringify([thisRound]) + ', knownIntentional:' + JSON.stringify(knownIntentional) + '}) and return the report JSON.',
183
+ 'Call iterate_review({operation:"aggregate", mode:"normal", rounds:' + JSON.stringify([thisRound]) + ', knownIntentional:' + JSON.stringify(knownIntentional) + ', fixedCount:' + fixedCount + '}) and return the report JSON.',
180
184
  { label: 'review:aggregate:r' + r }
181
185
  )
182
186
  const findings = (agg && agg.report && agg.report.findings) ? agg.report.findings : thisRound.findings
@@ -4,6 +4,34 @@ import { defineTool } from '@deepseek-ai/dsh-tools';
4
4
  import { resolveProjectRoot } from "../config-loader.js";
5
5
  const LOG_DIR = '.iterate';
6
6
  const LOG_FILE = 'decision-log.jsonl';
7
+ /** All valid DecisionLogEntry `type` values (must stay in sync with Types). */
8
+ const VALID_ENTRY_TYPES = new Set([
9
+ 'round_start',
10
+ 'review_result',
11
+ 'atomic_fix',
12
+ 'architectural_fix',
13
+ 'revert',
14
+ 'round_failed',
15
+ 'validation',
16
+ 'decision',
17
+ 'report',
18
+ ]);
19
+ /**
20
+ * Validate a candidate (type, round, data) triple for an append operation.
21
+ * Returns an error string on failure, or null when the entry is well-formed.
22
+ */
23
+ function validateEntryInput(type, round, data) {
24
+ if (typeof type !== 'string' || !VALID_ENTRY_TYPES.has(type)) {
25
+ return `type must be one of: ${[...VALID_ENTRY_TYPES].join(', ')}.`;
26
+ }
27
+ if (typeof round !== 'number' || !Number.isInteger(round) || round < 1) {
28
+ return 'round must be a positive integer.';
29
+ }
30
+ if (data !== undefined && data !== null && typeof data !== 'object') {
31
+ return 'data must be an object (or omitted).';
32
+ }
33
+ return null;
34
+ }
7
35
  /**
8
36
  * Resolve the log file path, creating the directory if needed.
9
37
  */
@@ -73,13 +101,14 @@ export function registerDecisionLogTool(ctx) {
73
101
  type: {
74
102
  type: 'string',
75
103
  description: 'Entry type (required for append): round_start, review_result, atomic_fix, ' +
76
- 'architectural_fix, revert, validation, decision, report.',
104
+ 'architectural_fix, revert, round_failed, validation, decision, report.',
77
105
  enum: [
78
106
  'round_start',
79
107
  'review_result',
80
108
  'atomic_fix',
81
109
  'architectural_fix',
82
110
  'revert',
111
+ 'round_failed',
83
112
  'validation',
84
113
  'decision',
85
114
  'report',
@@ -132,17 +161,23 @@ export function registerDecisionLogTool(ctx) {
132
161
  };
133
162
  }
134
163
  if (args.operation === 'append') {
135
- if (!args.type || !args.round) {
164
+ const invalid = validateEntryInput(args.type, args.round, args.data);
165
+ if (invalid !== null) {
136
166
  return {
137
167
  operation: 'append',
138
- error: 'type and round are required for append operation.',
168
+ error: invalid,
139
169
  };
140
170
  }
171
+ const type = args.type;
172
+ const round = args.round;
173
+ const data = args.data === undefined || args.data === null
174
+ ? {}
175
+ : args.data;
141
176
  const entry = {
142
177
  timestamp: new Date().toISOString(),
143
- round: args.round,
144
- type: args.type,
145
- data: args.data ?? {},
178
+ round,
179
+ type,
180
+ data,
146
181
  };
147
182
  const result = appendDecisionEntry(projectRoot, entry);
148
183
  return {
@@ -62,6 +62,11 @@ export function registerReviewTool(ctx) {
62
62
  description: 'For `meta-review`: the ReviewReport JSON (as returned by `aggregate`) to audit for ' +
63
63
  'internal consistency and produce the final review report.',
64
64
  },
65
+ fixedCount: {
66
+ type: 'integer',
67
+ description: 'For `aggregate` (normal mode only): number of atomic fixes applied so far. ' +
68
+ 'Surfaces a running "fixes applied" metric on the report summary.',
69
+ },
65
70
  path: {
66
71
  type: 'string',
67
72
  description: 'Project root directory (default: current working directory).',
@@ -128,6 +133,7 @@ export function registerReviewTool(ctx) {
128
133
  maxReviewRounds,
129
134
  rounds,
130
135
  knownIntentional: args.knownIntentional,
136
+ fixedCount: typeof args.fixedCount === 'number' ? args.fixedCount : undefined,
131
137
  });
132
138
  return { operation: 'aggregate', mode, report: report };
133
139
  }