iterate-plugin 2.9.1 → 2.9.2
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/dist/config-loader.js +39 -1
- package/dist/tools/checkpoint.js +5 -5
- package/dist/tools/config.js +4 -4
- package/dist/tools/review.js +1 -1
- package/dist/tools/triage.js +2 -2
- package/package.json +1 -1
- package/src/config-loader.ts +36 -1
- package/src/tools/checkpoint.ts +5 -5
- package/src/tools/config.ts +4 -4
- package/src/tools/review.ts +1 -1
- package/src/tools/triage.ts +2 -2
package/dist/config-loader.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
2
3
|
import { join, resolve, sep } from 'node:path';
|
|
3
4
|
import yaml from 'js-yaml';
|
|
4
5
|
/**
|
|
@@ -168,9 +169,46 @@ export function validateConfig(config) {
|
|
|
168
169
|
*/
|
|
169
170
|
export function resolveProjectRoot(input) {
|
|
170
171
|
const raw = (input ?? '').trim();
|
|
171
|
-
const root = raw ? resolve(raw) : resolve(
|
|
172
|
+
const root = raw ? resolve(raw) : resolve(effectiveCwd());
|
|
172
173
|
if (!root || root === sep) {
|
|
173
174
|
return { ok: false, reason: 'Refusing filesystem root as project root.' };
|
|
174
175
|
}
|
|
175
176
|
return { ok: true, root };
|
|
176
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Resolve the default working directory for tools invoked without an explicit
|
|
180
|
+
* `path`. Prefers the process cwd, but a daemon-managed web server can start
|
|
181
|
+
* with cwd = `/` (e.g. launchd), which is not a usable project root. In that
|
|
182
|
+
* case fall back to the session workspace encoded in `DSH_SESSION_JSONL`
|
|
183
|
+
* (`…/sessions/<encoded-workspace>/<session-id>/session.jsonl.zstd`), where
|
|
184
|
+
* the workspace directory is `--`-wrapped with `/` → `-` and percent-encoded
|
|
185
|
+
* bytes spelled as `~<hex>` (e.g. `/Volumes/Eng-Dev/iterate-skill` →
|
|
186
|
+
* `--Volumes-Eng-Dev-iterate-skill--`).
|
|
187
|
+
*/
|
|
188
|
+
function effectiveCwd() {
|
|
189
|
+
let cwd = '';
|
|
190
|
+
try {
|
|
191
|
+
cwd = process.cwd();
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// cwd may be unreadable (deleted dir) — fall through to session workspace
|
|
195
|
+
}
|
|
196
|
+
if (cwd && cwd !== sep && cwd !== homedir())
|
|
197
|
+
return cwd;
|
|
198
|
+
const session = process.env.DSH_SESSION_JSONL;
|
|
199
|
+
if (session) {
|
|
200
|
+
const m = session.match(/\/sessions\/([^/]+)\//);
|
|
201
|
+
const encoded = m ? m[1] : undefined;
|
|
202
|
+
if (encoded && encoded.startsWith('--') && encoded.endsWith('--')) {
|
|
203
|
+
try {
|
|
204
|
+
const decoded = decodeURIComponent(encoded.slice(2, -2).replace(/~/g, '%'));
|
|
205
|
+
if (decoded && decoded.startsWith(sep))
|
|
206
|
+
return decoded;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// malformed encoding — fall through to cwd
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return cwd || sep;
|
|
214
|
+
}
|
package/dist/tools/checkpoint.js
CHANGED
|
@@ -149,7 +149,7 @@ export function registerCheckpointTool(ctx) {
|
|
|
149
149
|
const projectRoot = resolved.root;
|
|
150
150
|
if (args.operation === 'load') {
|
|
151
151
|
const checkpoint = readCheckpoint(projectRoot);
|
|
152
|
-
return { operation: 'load', ok: true, checkpoint: checkpoint
|
|
152
|
+
return { operation: 'load', ok: true, checkpoint: checkpoint };
|
|
153
153
|
}
|
|
154
154
|
if (args.operation === 'clear') {
|
|
155
155
|
const existed = existsSync(checkpointPath(projectRoot));
|
|
@@ -217,7 +217,7 @@ export function registerStatusTool(ctx) {
|
|
|
217
217
|
additionalProperties: false,
|
|
218
218
|
properties: {
|
|
219
219
|
ok: { type: 'boolean', required: true },
|
|
220
|
-
mode: { type: 'string' },
|
|
220
|
+
mode: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
221
221
|
currentRound: { type: 'integer' },
|
|
222
222
|
totalRounds: { type: 'integer' },
|
|
223
223
|
fixedCount: { type: 'integer' },
|
|
@@ -227,7 +227,7 @@ export function registerStatusTool(ctx) {
|
|
|
227
227
|
hasCheckpoint: { type: 'boolean' },
|
|
228
228
|
interrupted: { type: 'boolean', description: 'True when a checkpoint exists, meaning the previous run was interrupted before finishing.' },
|
|
229
229
|
resumeCount: { type: 'integer', description: 'How many times the current checkpoint has already been resumed.' },
|
|
230
|
-
lastUpdated: { type: 'string' },
|
|
230
|
+
lastUpdated: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
231
231
|
error: { type: 'string' },
|
|
232
232
|
},
|
|
233
233
|
},
|
|
@@ -258,7 +258,7 @@ export function registerStatusTool(ctx) {
|
|
|
258
258
|
});
|
|
259
259
|
return {
|
|
260
260
|
ok: true,
|
|
261
|
-
mode: status.mode ??
|
|
261
|
+
mode: status.mode ?? null,
|
|
262
262
|
currentRound: status.currentRound,
|
|
263
263
|
totalRounds: status.totalRounds,
|
|
264
264
|
fixedCount: status.fixedCount,
|
|
@@ -268,7 +268,7 @@ export function registerStatusTool(ctx) {
|
|
|
268
268
|
hasCheckpoint: status.hasCheckpoint,
|
|
269
269
|
interrupted: status.interrupted,
|
|
270
270
|
resumeCount: status.resumeCount,
|
|
271
|
-
lastUpdated: status.lastUpdated ??
|
|
271
|
+
lastUpdated: status.lastUpdated ?? null,
|
|
272
272
|
};
|
|
273
273
|
},
|
|
274
274
|
}));
|
package/dist/tools/config.js
CHANGED
|
@@ -47,14 +47,14 @@ export function registerConfigTool(ctx) {
|
|
|
47
47
|
properties: {
|
|
48
48
|
found: { type: 'boolean', required: true },
|
|
49
49
|
valid: { type: 'boolean' },
|
|
50
|
-
errors: { type: 'array', items: { type: 'string' } },
|
|
50
|
+
errors: { oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'null' }] },
|
|
51
51
|
section: { type: 'string' },
|
|
52
52
|
data: { type: 'json' },
|
|
53
53
|
config: { type: 'json' },
|
|
54
54
|
availableSections: { type: 'array', items: { type: 'string' } },
|
|
55
55
|
operation: { type: 'string' },
|
|
56
56
|
ok: { type: 'boolean' },
|
|
57
|
-
backupPath: { type: 'string' },
|
|
57
|
+
backupPath: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
58
58
|
error: { type: 'string' },
|
|
59
59
|
},
|
|
60
60
|
},
|
|
@@ -100,7 +100,7 @@ export function registerConfigTool(ctx) {
|
|
|
100
100
|
operation: 'write',
|
|
101
101
|
ok: true,
|
|
102
102
|
found: true,
|
|
103
|
-
backupPath: result.backupPath ??
|
|
103
|
+
backupPath: result.backupPath ?? null,
|
|
104
104
|
config: config,
|
|
105
105
|
};
|
|
106
106
|
}
|
|
@@ -112,7 +112,7 @@ export function registerConfigTool(ctx) {
|
|
|
112
112
|
return {
|
|
113
113
|
found: hasOverride,
|
|
114
114
|
valid: errors.length === 0,
|
|
115
|
-
errors: errors.length > 0 ? errors :
|
|
115
|
+
errors: errors.length > 0 ? errors : null,
|
|
116
116
|
section: 'validation_report',
|
|
117
117
|
};
|
|
118
118
|
}
|
package/dist/tools/review.js
CHANGED
package/dist/tools/triage.js
CHANGED
|
@@ -262,7 +262,7 @@ export function registerTriageTool(ctx) {
|
|
|
262
262
|
skipped: { type: 'integer' },
|
|
263
263
|
count: { type: 'integer' },
|
|
264
264
|
path: { type: 'string' },
|
|
265
|
-
backupPath: { type: 'string' },
|
|
265
|
+
backupPath: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
266
266
|
entries: { type: 'json' },
|
|
267
267
|
errors: { type: 'array', items: { type: 'string' } },
|
|
268
268
|
error: { type: 'string' },
|
|
@@ -321,7 +321,7 @@ export function registerTriageTool(ctx) {
|
|
|
321
321
|
skipped: result.skipped,
|
|
322
322
|
count: result.count,
|
|
323
323
|
path: result.configPath,
|
|
324
|
-
backupPath: result.backupPath ??
|
|
324
|
+
backupPath: result.backupPath ?? null,
|
|
325
325
|
};
|
|
326
326
|
}
|
|
327
327
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iterate-plugin",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.2",
|
|
4
4
|
"description": "dsh plugin that turns the iterate skill into an autonomous closed-loop harness: plan -> parallel review xN -> atomic fixes -> validate -> loop -> auto-stop, plus a dry-run pure-review mode with multi-round convergence and a meta-review that audits the report and emits a final review report.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/config-loader.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { homedir } from 'node:os'
|
|
2
3
|
import { join, resolve, sep } from 'node:path'
|
|
3
4
|
import yaml from 'js-yaml'
|
|
4
5
|
import type { IterateConfig } from './types.ts'
|
|
@@ -185,9 +186,43 @@ export type ProjectRootResult = { ok: true; root: string } | { ok: false; reason
|
|
|
185
186
|
*/
|
|
186
187
|
export function resolveProjectRoot(input?: string): ProjectRootResult {
|
|
187
188
|
const raw = (input ?? '').trim()
|
|
188
|
-
const root = raw ? resolve(raw) : resolve(
|
|
189
|
+
const root = raw ? resolve(raw) : resolve(effectiveCwd())
|
|
189
190
|
if (!root || root === sep) {
|
|
190
191
|
return { ok: false, reason: 'Refusing filesystem root as project root.' }
|
|
191
192
|
}
|
|
192
193
|
return { ok: true, root }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the default working directory for tools invoked without an explicit
|
|
198
|
+
* `path`. Prefers the process cwd, but a daemon-managed web server can start
|
|
199
|
+
* with cwd = `/` (e.g. launchd), which is not a usable project root. In that
|
|
200
|
+
* case fall back to the session workspace encoded in `DSH_SESSION_JSONL`
|
|
201
|
+
* (`…/sessions/<encoded-workspace>/<session-id>/session.jsonl.zstd`), where
|
|
202
|
+
* the workspace directory is `--`-wrapped with `/` → `-` and percent-encoded
|
|
203
|
+
* bytes spelled as `~<hex>` (e.g. `/Volumes/Eng-Dev/iterate-skill` →
|
|
204
|
+
* `--Volumes-Eng-Dev-iterate-skill--`).
|
|
205
|
+
*/
|
|
206
|
+
function effectiveCwd(): string {
|
|
207
|
+
let cwd = ''
|
|
208
|
+
try {
|
|
209
|
+
cwd = process.cwd()
|
|
210
|
+
} catch {
|
|
211
|
+
// cwd may be unreadable (deleted dir) — fall through to session workspace
|
|
212
|
+
}
|
|
213
|
+
if (cwd && cwd !== sep && cwd !== homedir()) return cwd
|
|
214
|
+
const session = process.env.DSH_SESSION_JSONL
|
|
215
|
+
if (session) {
|
|
216
|
+
const m = session.match(/\/sessions\/([^/]+)\//)
|
|
217
|
+
const encoded = m ? m[1] : undefined
|
|
218
|
+
if (encoded && encoded.startsWith('--') && encoded.endsWith('--')) {
|
|
219
|
+
try {
|
|
220
|
+
const decoded = decodeURIComponent(encoded.slice(2, -2).replace(/~/g, '%'))
|
|
221
|
+
if (decoded && decoded.startsWith(sep)) return decoded
|
|
222
|
+
} catch {
|
|
223
|
+
// malformed encoding — fall through to cwd
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return cwd || sep
|
|
193
228
|
}
|
package/src/tools/checkpoint.ts
CHANGED
|
@@ -173,7 +173,7 @@ export function registerCheckpointTool(ctx: { tools: { register: (def: ReturnTyp
|
|
|
173
173
|
|
|
174
174
|
if (args.operation === 'load') {
|
|
175
175
|
const checkpoint = readCheckpoint(projectRoot)
|
|
176
|
-
return { operation: 'load', ok: true, checkpoint:
|
|
176
|
+
return { operation: 'load', ok: true, checkpoint: checkpoint as unknown as JsonValue | null }
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
if (args.operation === 'clear') {
|
|
@@ -245,7 +245,7 @@ export function registerStatusTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
245
245
|
additionalProperties: false,
|
|
246
246
|
properties: {
|
|
247
247
|
ok: { type: 'boolean', required: true },
|
|
248
|
-
mode: { type: 'string' },
|
|
248
|
+
mode: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
249
249
|
currentRound: { type: 'integer' },
|
|
250
250
|
totalRounds: { type: 'integer' },
|
|
251
251
|
fixedCount: { type: 'integer' },
|
|
@@ -255,7 +255,7 @@ export function registerStatusTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
255
255
|
hasCheckpoint: { type: 'boolean' },
|
|
256
256
|
interrupted: { type: 'boolean', description: 'True when a checkpoint exists, meaning the previous run was interrupted before finishing.' },
|
|
257
257
|
resumeCount: { type: 'integer', description: 'How many times the current checkpoint has already been resumed.' },
|
|
258
|
-
lastUpdated: { type: 'string' },
|
|
258
|
+
lastUpdated: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
259
259
|
error: { type: 'string' },
|
|
260
260
|
},
|
|
261
261
|
},
|
|
@@ -285,7 +285,7 @@ export function registerStatusTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
285
285
|
})
|
|
286
286
|
return {
|
|
287
287
|
ok: true,
|
|
288
|
-
mode: status.mode ??
|
|
288
|
+
mode: status.mode ?? null,
|
|
289
289
|
currentRound: status.currentRound,
|
|
290
290
|
totalRounds: status.totalRounds,
|
|
291
291
|
fixedCount: status.fixedCount,
|
|
@@ -295,7 +295,7 @@ export function registerStatusTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
295
295
|
hasCheckpoint: status.hasCheckpoint,
|
|
296
296
|
interrupted: status.interrupted,
|
|
297
297
|
resumeCount: status.resumeCount,
|
|
298
|
-
lastUpdated: status.lastUpdated ??
|
|
298
|
+
lastUpdated: status.lastUpdated ?? null,
|
|
299
299
|
}
|
|
300
300
|
},
|
|
301
301
|
}),
|
package/src/tools/config.ts
CHANGED
|
@@ -60,14 +60,14 @@ export function registerConfigTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
60
60
|
properties: {
|
|
61
61
|
found: { type: 'boolean', required: true },
|
|
62
62
|
valid: { type: 'boolean' },
|
|
63
|
-
errors: { type: 'array', items: { type: 'string' } },
|
|
63
|
+
errors: { oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'null' }] },
|
|
64
64
|
section: { type: 'string' },
|
|
65
65
|
data: { type: 'json' },
|
|
66
66
|
config: { type: 'json' },
|
|
67
67
|
availableSections: { type: 'array', items: { type: 'string' } },
|
|
68
68
|
operation: { type: 'string' },
|
|
69
69
|
ok: { type: 'boolean' },
|
|
70
|
-
backupPath: { type: 'string' },
|
|
70
|
+
backupPath: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
71
71
|
error: { type: 'string' },
|
|
72
72
|
},
|
|
73
73
|
},
|
|
@@ -113,7 +113,7 @@ export function registerConfigTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
113
113
|
operation: 'write',
|
|
114
114
|
ok: true,
|
|
115
115
|
found: true,
|
|
116
|
-
backupPath: result.backupPath ??
|
|
116
|
+
backupPath: result.backupPath ?? null,
|
|
117
117
|
config: config as unknown as JsonValue,
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -127,7 +127,7 @@ export function registerConfigTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
127
127
|
return {
|
|
128
128
|
found: hasOverride,
|
|
129
129
|
valid: errors.length === 0,
|
|
130
|
-
errors: errors.length > 0 ? errors :
|
|
130
|
+
errors: errors.length > 0 ? errors : null,
|
|
131
131
|
section: 'validation_report',
|
|
132
132
|
}
|
|
133
133
|
}
|
package/src/tools/review.ts
CHANGED
|
@@ -213,7 +213,7 @@ export function registerReviewTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
213
213
|
operation: 'aggregate',
|
|
214
214
|
mode,
|
|
215
215
|
report: report as unknown as JsonValue,
|
|
216
|
-
schemaValidation: schemaValidation as unknown as JsonValue |
|
|
216
|
+
schemaValidation: (schemaValidation ?? null) as unknown as JsonValue | null,
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
package/src/tools/triage.ts
CHANGED
|
@@ -302,7 +302,7 @@ export function registerTriageTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
302
302
|
skipped: { type: 'integer' },
|
|
303
303
|
count: { type: 'integer' },
|
|
304
304
|
path: { type: 'string' },
|
|
305
|
-
backupPath: { type: 'string' },
|
|
305
|
+
backupPath: { oneOf: [{ type: 'string' }, { type: 'null' }] },
|
|
306
306
|
entries: { type: 'json' },
|
|
307
307
|
errors: { type: 'array', items: { type: 'string' } },
|
|
308
308
|
error: { type: 'string' },
|
|
@@ -363,7 +363,7 @@ export function registerTriageTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
363
363
|
skipped: result.skipped,
|
|
364
364
|
count: result.count,
|
|
365
365
|
path: result.configPath,
|
|
366
|
-
backupPath: result.backupPath ??
|
|
366
|
+
backupPath: result.backupPath ?? null,
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
|