iterate-plugin 3.2.1 → 3.3.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 +123 -90
- package/README.zh-CN.md +129 -80
- package/dist/approval-gate.js +0 -17
- package/dist/tools/checkpoint.js +22 -3
- package/dist/tools/defense-events.js +4 -1
- package/dist/tools/defense-store.js +9 -3
- package/dist/tools/experience-bank.js +4 -1
- package/dist/tools/experience-store.js +9 -3
- package/dist/tools/quality-gate.js +4 -1
- package/dist/tools/quality-store.js +9 -3
- package/dist/tools/transcript.js +8 -1
- package/dist/transcript.js +10 -0
- package/lib/client.js +549 -88
- package/lib/parse.js +352 -0
- package/package.json +2 -2
- package/src/approval-gate.ts +0 -26
- package/src/client/index.ts +349 -73
- package/src/tools/checkpoint.ts +22 -3
- package/src/tools/defense-events.ts +4 -1
- package/src/tools/defense-store.ts +13 -4
- package/src/tools/experience-bank.ts +4 -1
- package/src/tools/experience-store.ts +13 -4
- package/src/tools/quality-gate.ts +4 -1
- package/src/tools/quality-store.ts +13 -4
- package/src/tools/transcript.ts +8 -1
- package/src/transcript.ts +11 -0
|
@@ -59,8 +59,16 @@ export function readDefenseEvents(projectRoot: string): DefenseEventStream {
|
|
|
59
59
|
return emptyStream()
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Write the defense events stream to disk.
|
|
64
|
+
* Returns `{ ok: true }` on success or `{ ok: false, error }` when the write
|
|
65
|
+
* fails — a caller must surface the failure instead of reporting success for
|
|
66
|
+
* an event that was never persisted.
|
|
67
|
+
*/
|
|
68
|
+
export function writeDefenseEvents(
|
|
69
|
+
projectRoot: string,
|
|
70
|
+
stream: DefenseEventStream,
|
|
71
|
+
): { ok: true } | { ok: false; error: string } {
|
|
64
72
|
const dirPath = path.join(projectRoot, '.iterate')
|
|
65
73
|
const filePath = path.join(dirPath, DEFENSE_EVENTS_FILE)
|
|
66
74
|
|
|
@@ -69,9 +77,10 @@ export function writeDefenseEvents(projectRoot: string, stream: DefenseEventStre
|
|
|
69
77
|
fs.mkdirSync(dirPath, { recursive: true })
|
|
70
78
|
}
|
|
71
79
|
fs.writeFileSync(filePath, JSON.stringify(stream, null, 2), 'utf-8')
|
|
72
|
-
} catch {
|
|
73
|
-
|
|
80
|
+
} catch (err) {
|
|
81
|
+
return { ok: false, error: `unable to write ${filePath}: ${String(err)}` }
|
|
74
82
|
}
|
|
83
|
+
return { ok: true }
|
|
75
84
|
}
|
|
76
85
|
|
|
77
86
|
/** Add a defense event to the stream. */
|
|
@@ -195,7 +195,10 @@ export function registerExperienceBankTool(ctx: { tools: { register: (def: Retur
|
|
|
195
195
|
}
|
|
196
196
|
const bank = readExperienceBank(projectRoot)
|
|
197
197
|
const { bank: next, added, entryId } = upsertExperience(bank, normalizeExperienceInput(raw as Record<string, unknown>))
|
|
198
|
-
writeExperienceBank(projectRoot, next)
|
|
198
|
+
const write = writeExperienceBank(projectRoot, next)
|
|
199
|
+
if (!write.ok) {
|
|
200
|
+
return { ok: false, kind: 'experience', operation: 'add', error: write.error }
|
|
201
|
+
}
|
|
199
202
|
const entry = next.entries.find((e) => e.id === entryId)
|
|
200
203
|
return {
|
|
201
204
|
ok: true,
|
|
@@ -35,8 +35,16 @@ export function readExperienceBank(projectRoot: string): ExperienceBank {
|
|
|
35
35
|
return emptyBank()
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Write the experience bank to disk.
|
|
40
|
+
* Returns `{ ok: true }` on success or `{ ok: false, error }` when the write
|
|
41
|
+
* fails — a caller must surface the failure instead of reporting success for
|
|
42
|
+
* an entry that was never persisted.
|
|
43
|
+
*/
|
|
44
|
+
export function writeExperienceBank(
|
|
45
|
+
projectRoot: string,
|
|
46
|
+
bank: ExperienceBank,
|
|
47
|
+
): { ok: true } | { ok: false; error: string } {
|
|
40
48
|
const dirPath = path.join(projectRoot, '.iterate')
|
|
41
49
|
const filePath = path.join(dirPath, EXPERIENCE_FILE)
|
|
42
50
|
|
|
@@ -45,9 +53,10 @@ export function writeExperienceBank(projectRoot: string, bank: ExperienceBank):
|
|
|
45
53
|
fs.mkdirSync(dirPath, { recursive: true })
|
|
46
54
|
}
|
|
47
55
|
fs.writeFileSync(filePath, JSON.stringify(bank, null, 2), 'utf-8')
|
|
48
|
-
} catch {
|
|
49
|
-
|
|
56
|
+
} catch (err) {
|
|
57
|
+
return { ok: false, error: `unable to write ${filePath}: ${String(err)}` }
|
|
50
58
|
}
|
|
59
|
+
return { ok: true }
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
/** Search experience entries by query string. */
|
|
@@ -171,7 +171,10 @@ export function registerQualityGateTool(ctx: { tools: { register: (def: ReturnTy
|
|
|
171
171
|
findingsByRound,
|
|
172
172
|
fixedByDimension,
|
|
173
173
|
})
|
|
174
|
-
writeQualityGate(projectRoot, snapshot)
|
|
174
|
+
const write = writeQualityGate(projectRoot, snapshot)
|
|
175
|
+
if (!write.ok) {
|
|
176
|
+
return { ok: false, kind: 'quality_gate', operation: 'compute', error: write.error }
|
|
177
|
+
}
|
|
175
178
|
return {
|
|
176
179
|
ok: true,
|
|
177
180
|
kind: 'quality_gate',
|
|
@@ -46,8 +46,16 @@ export function readQualityGate(projectRoot: string): QualityGateSnapshot {
|
|
|
46
46
|
return emptySnapshot()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Write the quality gate snapshot to disk.
|
|
51
|
+
* Returns `{ ok: true }` on success or `{ ok: false, error }` when the write
|
|
52
|
+
* fails — a caller must surface the failure instead of reporting success for
|
|
53
|
+
* a snapshot that was never persisted.
|
|
54
|
+
*/
|
|
55
|
+
export function writeQualityGate(
|
|
56
|
+
projectRoot: string,
|
|
57
|
+
snapshot: QualityGateSnapshot,
|
|
58
|
+
): { ok: true } | { ok: false; error: string } {
|
|
51
59
|
const dirPath = path.join(projectRoot, '.iterate')
|
|
52
60
|
const filePath = path.join(dirPath, QUALITY_GATE_FILE)
|
|
53
61
|
|
|
@@ -56,9 +64,10 @@ export function writeQualityGate(projectRoot: string, snapshot: QualityGateSnaps
|
|
|
56
64
|
fs.mkdirSync(dirPath, { recursive: true })
|
|
57
65
|
}
|
|
58
66
|
fs.writeFileSync(filePath, JSON.stringify(snapshot, null, 2), 'utf-8')
|
|
59
|
-
} catch {
|
|
60
|
-
|
|
67
|
+
} catch (err) {
|
|
68
|
+
return { ok: false, error: `unable to write ${filePath}: ${String(err)}` }
|
|
61
69
|
}
|
|
70
|
+
return { ok: true }
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
/**
|
package/src/tools/transcript.ts
CHANGED
|
@@ -136,6 +136,11 @@ export function registerTranscriptTool(ctx: {
|
|
|
136
136
|
description: 'For `capture`: run mode ("dry-run" | "normal"). Default dry-run.',
|
|
137
137
|
enum: ['dry-run', 'normal'],
|
|
138
138
|
},
|
|
139
|
+
taskMode: {
|
|
140
|
+
type: 'string',
|
|
141
|
+
description: 'For `capture`: harness execution mode ("code" | "iterate"). Default derives from the review loop (iterate).',
|
|
142
|
+
enum: ['code', 'iterate'],
|
|
143
|
+
},
|
|
139
144
|
goal: { type: 'string', description: 'For `capture`: run goal.' },
|
|
140
145
|
maxRounds: { type: 'integer', description: 'For `capture`: round cap.' },
|
|
141
146
|
roundsExecuted: { type: 'integer', description: 'For `capture`: number of rounds actually executed.' },
|
|
@@ -229,10 +234,11 @@ export function registerTranscriptTool(ctx: {
|
|
|
229
234
|
|
|
230
235
|
// capture
|
|
231
236
|
const mode = args.mode === 'normal' ? 'normal' : 'dry-run'
|
|
237
|
+
const taskMode = args.taskMode === 'code' || args.taskMode === 'iterate' ? args.taskMode : undefined
|
|
232
238
|
const goal = typeof args.goal === 'string' ? args.goal : ''
|
|
233
239
|
const maxRounds =
|
|
234
240
|
typeof args.maxRounds === 'number' ? Math.floor(args.maxRounds) : 0
|
|
235
|
-
const builder = new ReviewTranscriptBuilder({ project: projectRoot, mode, approval, goal, maxRounds })
|
|
241
|
+
const builder = new ReviewTranscriptBuilder({ project: projectRoot, mode, taskMode, approval, goal, maxRounds })
|
|
236
242
|
const report = args.report as Record<string, unknown> | null | undefined
|
|
237
243
|
const reportFindings: unknown =
|
|
238
244
|
report && typeof report === 'object' && Array.isArray(report.findings)
|
|
@@ -300,6 +306,7 @@ function rehydrateBuilder(manifest: TranscriptManifest, approval: 'ask' | 'deny'
|
|
|
300
306
|
const builder = new ReviewTranscriptBuilder({
|
|
301
307
|
project: manifest.project,
|
|
302
308
|
mode: manifest.mode ?? null,
|
|
309
|
+
taskMode: manifest.taskMode ?? null,
|
|
303
310
|
approval,
|
|
304
311
|
goal: manifest.goal,
|
|
305
312
|
maxRounds: manifest.maxRounds,
|
package/src/transcript.ts
CHANGED
|
@@ -126,6 +126,7 @@ function mergeReportIntoThread(
|
|
|
126
126
|
export class ReviewTranscriptBuilder {
|
|
127
127
|
private readonly project: string
|
|
128
128
|
private readonly mode: 'dry-run' | 'normal' | null
|
|
129
|
+
private readonly taskMode: 'code' | 'iterate' | null
|
|
129
130
|
private readonly approval: 'ask' | 'deny' | 'allow'
|
|
130
131
|
private goal = ''
|
|
131
132
|
private readonly phases: string[] = []
|
|
@@ -144,6 +145,7 @@ export class ReviewTranscriptBuilder {
|
|
|
144
145
|
constructor(input: {
|
|
145
146
|
project: string
|
|
146
147
|
mode?: 'dry-run' | 'normal' | null
|
|
148
|
+
taskMode?: 'code' | 'iterate' | null
|
|
147
149
|
approval?: 'ask' | 'deny' | 'allow'
|
|
148
150
|
goal?: string
|
|
149
151
|
maxRounds?: number
|
|
@@ -152,6 +154,14 @@ export class ReviewTranscriptBuilder {
|
|
|
152
154
|
this.project = input.project || ''
|
|
153
155
|
this.mode =
|
|
154
156
|
input.mode === 'dry-run' || input.mode === 'normal' ? input.mode : null
|
|
157
|
+
// v3.0: task_mode indicator. An explicit valid value wins; otherwise a
|
|
158
|
+
// run that exercises the review loop (any mode) defaults to "iterate".
|
|
159
|
+
this.taskMode =
|
|
160
|
+
input.taskMode === 'code' || input.taskMode === 'iterate'
|
|
161
|
+
? input.taskMode
|
|
162
|
+
: input.mode !== null && input.mode !== undefined
|
|
163
|
+
? 'iterate'
|
|
164
|
+
: null
|
|
155
165
|
this.approval =
|
|
156
166
|
input.approval === 'ask' || input.approval === 'deny' || input.approval === 'allow'
|
|
157
167
|
? input.approval
|
|
@@ -393,6 +403,7 @@ export class ReviewTranscriptBuilder {
|
|
|
393
403
|
updatedAt: this.updatedAt,
|
|
394
404
|
active: this.active,
|
|
395
405
|
mode: this.mode,
|
|
406
|
+
taskMode: this.taskMode,
|
|
396
407
|
goal: this.goal,
|
|
397
408
|
phases: this.phases,
|
|
398
409
|
round: this.round,
|