prizmkit 1.1.99 → 1.1.100
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/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/lib/common.sh +244 -25
- package/bundled/dev-pipeline/reset-bug.sh +30 -0
- package/bundled/dev-pipeline/reset-feature.sh +30 -0
- package/bundled/dev-pipeline/reset-refactor.sh +30 -0
- package/bundled/dev-pipeline/run-bugfix.sh +128 -13
- package/bundled/dev-pipeline/run-feature.sh +130 -14
- package/bundled/dev-pipeline/run-refactor.sh +128 -13
- package/bundled/dev-pipeline/scripts/check-session-status.py +74 -1
- package/bundled/dev-pipeline/scripts/continuation.py +374 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +27 -30
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +15 -20
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +15 -20
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +146 -16
- package/bundled/dev-pipeline/scripts/update-bug-status.py +214 -6
- package/bundled/dev-pipeline/scripts/update-feature-status.py +237 -6
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +214 -6
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +3 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +3 -3
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +31 -66
- package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
- package/bundled/dev-pipeline/tests/conftest.py +1 -0
- package/bundled/dev-pipeline/tests/test_auto_skip.py +510 -0
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +103 -0
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +60 -0
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +43 -0
- package/bundled/dev-pipeline-windows/lib/common.ps1 +172 -10
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +93 -9
- package/bundled/dev-pipeline-windows/lib/reset.ps1 +34 -0
- package/bundled/dev-pipeline-windows/reset-bug.ps1 +1 -0
- package/bundled/dev-pipeline-windows/reset-feature.ps1 +1 -0
- package/bundled/dev-pipeline-windows/reset-refactor.ps1 +1 -0
- package/bundled/dev-pipeline-windows/scripts/check-session-status.py +74 -1
- package/bundled/dev-pipeline-windows/scripts/continuation.py +374 -0
- package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +27 -30
- package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +16 -20
- package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +16 -20
- package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +146 -16
- package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +214 -6
- package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +237 -6
- package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +214 -6
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +1 -1
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +2 -2
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +3 -3
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +3 -3
- package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +31 -68
- package/bundled/dev-pipeline-windows/templates/session-status-schema.json +1 -1
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
- package/bundled/dev-pipeline/scripts/monitor-log.sh +0 -104
- package/bundled/dev-pipeline-windows/scripts/monitor-log.ps1 +0 -102
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Tests for generate-bugfix-prompt.py core functions."""
|
|
2
2
|
|
|
3
|
+
from argparse import Namespace
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
3
6
|
from generate_bugfix_prompt import (
|
|
4
7
|
find_bug,
|
|
5
8
|
format_acceptance_criteria,
|
|
@@ -8,7 +11,9 @@ from generate_bugfix_prompt import (
|
|
|
8
11
|
format_environment,
|
|
9
12
|
process_conditional_blocks,
|
|
10
13
|
render_template,
|
|
14
|
+
load_log_size_section,
|
|
11
15
|
)
|
|
16
|
+
from continuation import append_continuation_handoff
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
# ---------------------------------------------------------------------------
|
|
@@ -166,3 +171,58 @@ class TestSharedHelpers:
|
|
|
166
171
|
def test_format_global_context_dict(self):
|
|
167
172
|
result = format_global_context({"lang": "Python"})
|
|
168
173
|
assert "**lang**: Python" in result
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ---------------------------------------------------------------------------
|
|
177
|
+
# Active compaction harness rollback
|
|
178
|
+
# ---------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
class TestHeadlessRecoveryReframing:
|
|
181
|
+
def test_bugfix_log_size_section_is_passive_checkpoint_guidance(self):
|
|
182
|
+
content = load_log_size_section(str(Path("dev-pipeline/scripts").resolve()))
|
|
183
|
+
|
|
184
|
+
assert "passive checkpoint guidance" in content
|
|
185
|
+
assert "Headless recovery must rely on durable checkpoints" in content
|
|
186
|
+
assert "fresh continuation session" in content
|
|
187
|
+
assert "optional interactive convenience only" in content
|
|
188
|
+
assert "COMPACT_NEEDED" not in content
|
|
189
|
+
assert "monitor-log" not in content
|
|
190
|
+
assert "background monitoring subagent" not in content
|
|
191
|
+
assert "Execute `/compact`" not in content
|
|
192
|
+
assert "run `/compact`" not in content.lower()
|
|
193
|
+
|
|
194
|
+
def test_bugfix_template_does_not_spawn_monitor_or_require_compact(self):
|
|
195
|
+
content = Path("dev-pipeline/templates/bugfix-bootstrap-prompt.md").read_text(encoding="utf-8")
|
|
196
|
+
|
|
197
|
+
assert "Do not spawn persistent background subagents for headless recovery" in content
|
|
198
|
+
assert "log-size monitor" not in content
|
|
199
|
+
assert "monitor-log" not in content
|
|
200
|
+
assert "COMPACT_NEEDED" not in content
|
|
201
|
+
assert "Run this command and keep it running" not in content
|
|
202
|
+
assert "Execute `/compact`" not in content
|
|
203
|
+
assert "run `/compact` after" not in content
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class TestBugfixContinuationHandoff:
|
|
207
|
+
def test_writes_specs_and_task_local_summaries(self, tmp_path):
|
|
208
|
+
args = Namespace(
|
|
209
|
+
output=str(tmp_path / ".prizmkit/state/bugfix/B-007/sessions/B-007-new/bootstrap-prompt.md"),
|
|
210
|
+
state_dir=str(tmp_path / ".prizmkit/state/bugfix"),
|
|
211
|
+
continuation_mode="context_overflow",
|
|
212
|
+
previous_session_id="B-007-old",
|
|
213
|
+
continuation_count="1",
|
|
214
|
+
context_overflow_count="1",
|
|
215
|
+
active_dev_branch="bugfix/B-007",
|
|
216
|
+
base_branch="main",
|
|
217
|
+
continuation_summary_path=".prizmkit/specs/B-007/continuation-summary.md",
|
|
218
|
+
)
|
|
219
|
+
prompt = append_continuation_handoff(
|
|
220
|
+
"BUGFIX PROMPT", args, str(tmp_path), "bugfix", "B-007", "B-007",
|
|
221
|
+
{"steps": [{"id": "S01", "skill": "diagnose", "status": "pending"}]},
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
assert prompt.startswith("BUGFIX PROMPT")
|
|
225
|
+
assert "This is an automatic continuation after context overflow." in prompt
|
|
226
|
+
assert "Do not attempt `/compact` as the recovery mechanism." in prompt
|
|
227
|
+
assert (tmp_path / ".prizmkit/specs/B-007/continuation-summary.md").exists()
|
|
228
|
+
assert (tmp_path / ".prizmkit/bugfix/B-007/continuation-summary.md").exists()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Tests for generate-refactor-prompt.py continuation behavior."""
|
|
2
|
+
|
|
3
|
+
from argparse import Namespace
|
|
4
|
+
|
|
5
|
+
from continuation import append_continuation_handoff
|
|
6
|
+
from generate_refactor_prompt import generate_refactor_checkpoint, merge_refactor_checkpoint_state
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestRefactorContinuationHandoff:
|
|
10
|
+
def test_writes_specs_and_task_local_summaries(self, tmp_path):
|
|
11
|
+
args = Namespace(
|
|
12
|
+
output=str(tmp_path / ".prizmkit/state/refactor/R-007/sessions/R-007-new/bootstrap-prompt.md"),
|
|
13
|
+
state_dir=str(tmp_path / ".prizmkit/state/refactor"),
|
|
14
|
+
continuation_mode="context_overflow",
|
|
15
|
+
previous_session_id="R-007-old",
|
|
16
|
+
continuation_count="1",
|
|
17
|
+
context_overflow_count="1",
|
|
18
|
+
active_dev_branch="refactor/R-007",
|
|
19
|
+
base_branch="main",
|
|
20
|
+
continuation_summary_path=".prizmkit/specs/R-007/continuation-summary.md",
|
|
21
|
+
)
|
|
22
|
+
prompt = append_continuation_handoff(
|
|
23
|
+
"REFACTOR PROMPT", args, str(tmp_path), "refactor", "R-007", "R-007",
|
|
24
|
+
{"steps": [{"id": "S01", "skill": "plan", "status": "pending"}]},
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
assert prompt.startswith("REFACTOR PROMPT")
|
|
28
|
+
assert "This is a fresh headless AI CLI session for the same task." in prompt
|
|
29
|
+
assert "Do not attempt `/compact` as the recovery mechanism." in prompt
|
|
30
|
+
assert (tmp_path / ".prizmkit/specs/R-007/continuation-summary.md").exists()
|
|
31
|
+
assert (tmp_path / ".prizmkit/refactor/R-007/continuation-summary.md").exists()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestRefactorCheckpointMerge:
|
|
35
|
+
def test_preserves_skipped_without_artifacts(self, tmp_path):
|
|
36
|
+
fresh = generate_refactor_checkpoint("R-008", "R-008-new")
|
|
37
|
+
existing = generate_refactor_checkpoint("R-008", "R-008-old")
|
|
38
|
+
existing["steps"][0]["status"] = "skipped"
|
|
39
|
+
|
|
40
|
+
merged = merge_refactor_checkpoint_state(existing, fresh, str(tmp_path))
|
|
41
|
+
|
|
42
|
+
assert merged["steps"][0]["status"] == "skipped"
|
|
43
|
+
assert merged["steps"][1]["status"] == "pending"
|
|
@@ -175,19 +175,30 @@ function Test-PrizmInfraError {
|
|
|
175
175
|
return ($haystack -match '(?i)auth_unavailable|no auth available|502 Bad Gateway|503 Service Unavailable|504 Gateway Timeout|gateway timeout|upstream (connect )?error|connection reset|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|rate limit|rate_limit|temporarily unavailable|overloaded')
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
function Test-
|
|
178
|
+
function Test-PrizmContextOverflowError {
|
|
179
179
|
param([string]$SessionLog, [string]$ProgressJson)
|
|
180
180
|
|
|
181
|
+
$parts = @()
|
|
182
|
+
$codeParts = @()
|
|
183
|
+
$progressErrorLike = $false
|
|
184
|
+
|
|
181
185
|
if ($ProgressJson -and (Test-Path $ProgressJson)) {
|
|
182
186
|
try {
|
|
183
187
|
$progress = Get-Content $ProgressJson -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
|
|
184
|
-
|
|
185
|
-
|
|
188
|
+
foreach ($name in @('fatal_error_code', 'api_error_code', 'error_code', 'stop_reason')) {
|
|
189
|
+
if ($progress.PSObject.Properties[$name] -and $progress.$name) { $codeParts += [string]$progress.$name }
|
|
190
|
+
}
|
|
191
|
+
if (($progress.PSObject.Properties['last_result_is_error'] -and $progress.last_result_is_error) -or ($progress.PSObject.Properties['api_error_status'] -and $progress.api_error_status)) {
|
|
192
|
+
$progressErrorLike = $true
|
|
186
193
|
}
|
|
194
|
+
$parts += ($progress | ConvertTo-Json -Depth 12 -Compress)
|
|
187
195
|
} catch {}
|
|
188
196
|
}
|
|
189
197
|
|
|
190
|
-
$
|
|
198
|
+
$codeText = $codeParts -join ' '
|
|
199
|
+
$codePattern = '(?i)\b(context_overflow|context_too_large|context_length_exceeded|model_context_window_exceeded)\b'
|
|
200
|
+
if ($codeText -match $codePattern) { return $true }
|
|
201
|
+
|
|
191
202
|
if ($SessionLog -and (Test-Path $SessionLog)) {
|
|
192
203
|
try {
|
|
193
204
|
$text = Get-Content $SessionLog -Raw -ErrorAction Stop
|
|
@@ -195,15 +206,166 @@ function Test-PrizmAiRuntimeError {
|
|
|
195
206
|
$parts += $text
|
|
196
207
|
} catch {}
|
|
197
208
|
}
|
|
198
|
-
if ($ProgressJson -and (Test-Path $ProgressJson)) {
|
|
199
|
-
try { $parts += (Get-Content $ProgressJson -Raw -ErrorAction Stop) } catch {}
|
|
200
|
-
}
|
|
201
209
|
if ($parts.Count -eq 0) { return $false }
|
|
202
210
|
|
|
203
211
|
$haystack = $parts -join "`n"
|
|
204
|
-
$
|
|
205
|
-
$
|
|
206
|
-
if (
|
|
212
|
+
$wrapperPattern = '(?i)\bPRIZMKIT_FATAL_ERROR\s*=\s*context_overflow\b'
|
|
213
|
+
if ($haystack -match $wrapperPattern) { return $true }
|
|
214
|
+
if ($haystack -match $codePattern) { return $true }
|
|
215
|
+
|
|
216
|
+
$errorPattern = '(?i)\bapi error\b|invalid_request_error|\bbad request\b|\bstatus\s*[:=]?\s*(400|413)\b|\bapi_error_status\b|\bapi_error_code\b|\blast_result_is_error\b\s*["'':=]*\s*true\b|\bis_error\b\s*["'':=]*\s*true\b|\berror\s*[:=]|\bfatal\s*[:=]'
|
|
217
|
+
$hasErrorContext = $progressErrorLike -or ($haystack -match $errorPattern)
|
|
218
|
+
if (-not $hasErrorContext) { return $false }
|
|
219
|
+
|
|
220
|
+
$weakPattern = '(?i)Your input exceeds the context window|input exceeds (?:the )?(?:model )?context window|context window of this model|context window (?:was )?exceeded|exceeded (?:the )?context window|maximum context length exceeded|prompt is too long|too many tokens|input token count exceeds|input tokens? exceeds?|token count exceeds'
|
|
221
|
+
if ($haystack -match $weakPattern) { return $true }
|
|
222
|
+
|
|
223
|
+
$requestTooLargePattern = '(?i)\brequest (?:is )?too large\b'
|
|
224
|
+
$requestSemanticsPattern = '(?i)\b(context|token|tokens|prompt|input|model)\b'
|
|
225
|
+
if (($haystack -match $requestTooLargePattern) -and ($haystack -match $requestSemanticsPattern)) { return $true }
|
|
226
|
+
|
|
227
|
+
return $false
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function Test-PrizmAiRuntimeError {
|
|
231
|
+
param([string]$SessionLog, [string]$ProgressJson)
|
|
232
|
+
|
|
233
|
+
if (Test-PrizmContextOverflowError -SessionLog $SessionLog -ProgressJson $ProgressJson) { return $false }
|
|
234
|
+
|
|
235
|
+
if ($ProgressJson -and (Test-Path $ProgressJson)) {
|
|
236
|
+
try {
|
|
237
|
+
$progress = Get-Content $ProgressJson -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
|
|
238
|
+
if ($progress.PSObject.Properties['fatal_error_code'] -and $progress.fatal_error_code) {
|
|
239
|
+
return $true
|
|
240
|
+
}
|
|
241
|
+
} catch {}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return $false
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function Get-PrizmContextProgressFingerprint {
|
|
248
|
+
param(
|
|
249
|
+
[string]$ProjectRoot,
|
|
250
|
+
[string]$TaskType,
|
|
251
|
+
[string]$TaskId,
|
|
252
|
+
[string]$ArtifactDir = '',
|
|
253
|
+
[string]$CheckpointFile = ''
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
$projectRootResolved = if ($ProjectRoot) { $ProjectRoot } else { (Get-Location).Path }
|
|
257
|
+
$artifactArg = if ($ArtifactDir) { $ArtifactDir } else { '' }
|
|
258
|
+
$checkpointArg = if ($CheckpointFile) { $CheckpointFile } else { '' }
|
|
259
|
+
$python = @'
|
|
260
|
+
import hashlib
|
|
261
|
+
import json
|
|
262
|
+
import os
|
|
263
|
+
import subprocess
|
|
264
|
+
import sys
|
|
265
|
+
|
|
266
|
+
project_root, task_type, task_id, artifact_dir, checkpoint_file = sys.argv[1:6]
|
|
267
|
+
project_root = os.path.abspath(project_root or ".")
|
|
268
|
+
artifact_dir = os.path.abspath(os.path.join(project_root, artifact_dir)) if artifact_dir and not os.path.isabs(artifact_dir) else artifact_dir
|
|
269
|
+
checkpoint_file = os.path.abspath(os.path.join(project_root, checkpoint_file)) if checkpoint_file and not os.path.isabs(checkpoint_file) else checkpoint_file
|
|
270
|
+
|
|
271
|
+
def run_git(args):
|
|
272
|
+
try:
|
|
273
|
+
return subprocess.check_output(["git", "-C", project_root, *args], stderr=subprocess.DEVNULL)
|
|
274
|
+
except Exception:
|
|
275
|
+
return b""
|
|
276
|
+
|
|
277
|
+
def sha_bytes(*parts):
|
|
278
|
+
h = hashlib.sha256()
|
|
279
|
+
for part in parts:
|
|
280
|
+
if isinstance(part, str):
|
|
281
|
+
part = part.encode("utf-8", errors="surrogateescape")
|
|
282
|
+
h.update(part or b"")
|
|
283
|
+
h.update(b"\0")
|
|
284
|
+
return h.hexdigest()
|
|
285
|
+
|
|
286
|
+
def checkpoint_cursor(path):
|
|
287
|
+
if not path or not os.path.exists(path):
|
|
288
|
+
return "missing"
|
|
289
|
+
try:
|
|
290
|
+
with open(path, encoding="utf-8") as fh:
|
|
291
|
+
data = json.load(fh)
|
|
292
|
+
except Exception as exc:
|
|
293
|
+
return "unreadable:{}".format(type(exc).__name__)
|
|
294
|
+
steps = data.get("steps") if isinstance(data, dict) else None
|
|
295
|
+
if not isinstance(steps, list):
|
|
296
|
+
return "no-steps"
|
|
297
|
+
counts = {"completed": 0, "skipped": 0, "pending": 0, "in_progress": 0, "failed": 0}
|
|
298
|
+
first_open = None
|
|
299
|
+
for step in steps:
|
|
300
|
+
if not isinstance(step, dict):
|
|
301
|
+
continue
|
|
302
|
+
status = str(step.get("status", "pending"))
|
|
303
|
+
counts[status] = counts.get(status, 0) + 1
|
|
304
|
+
if first_open is None and status in ("pending", "in_progress"):
|
|
305
|
+
first_open = "{}:{}:{}".format(step.get("id", ""), step.get("skill", ""), status)
|
|
306
|
+
return "first_open={};counts={}".format(first_open or "none", ",".join("{}:{}".format(k, counts[k]) for k in sorted(counts)))
|
|
307
|
+
|
|
308
|
+
def artifact_fingerprint(path):
|
|
309
|
+
if not path or not os.path.isdir(path):
|
|
310
|
+
return "missing"
|
|
311
|
+
h = hashlib.sha256()
|
|
312
|
+
for root, dirs, files in os.walk(path):
|
|
313
|
+
dirs[:] = sorted(d for d in dirs if d not in {".git", "node_modules", "__pycache__"})
|
|
314
|
+
for name in sorted(files):
|
|
315
|
+
file_path = os.path.join(root, name)
|
|
316
|
+
rel = os.path.relpath(file_path, path).replace(os.sep, "/")
|
|
317
|
+
h.update(rel.encode("utf-8", errors="surrogateescape"))
|
|
318
|
+
h.update(b"\0")
|
|
319
|
+
try:
|
|
320
|
+
with open(file_path, "rb") as fh:
|
|
321
|
+
for chunk in iter(lambda: fh.read(65536), b""):
|
|
322
|
+
h.update(chunk)
|
|
323
|
+
except Exception as exc:
|
|
324
|
+
h.update("unreadable:{}".format(type(exc).__name__).encode("utf-8"))
|
|
325
|
+
h.update(b"\0")
|
|
326
|
+
return h.hexdigest()
|
|
327
|
+
|
|
328
|
+
fingerprint = {
|
|
329
|
+
"task_type": task_type,
|
|
330
|
+
"task_id": task_id,
|
|
331
|
+
"git_diff_fingerprint": sha_bytes(run_git(["status", "--porcelain", "--untracked-files=all", "--", "."]), run_git(["diff", "--binary", "HEAD", "--", "."])),
|
|
332
|
+
"checkpoint_cursor": checkpoint_cursor(checkpoint_file),
|
|
333
|
+
"artifact_fingerprint": artifact_fingerprint(artifact_dir),
|
|
334
|
+
"head_commit": run_git(["rev-parse", "HEAD"]).decode("utf-8", errors="ignore").strip(),
|
|
335
|
+
}
|
|
336
|
+
print(json.dumps(fingerprint, sort_keys=True, ensure_ascii=False))
|
|
337
|
+
'@
|
|
338
|
+
$scriptPath = [System.IO.Path]::GetTempFileName()
|
|
339
|
+
try {
|
|
340
|
+
Set-Content -Path $scriptPath -Value $python -Encoding UTF8
|
|
341
|
+
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
|
|
342
|
+
if ($pythonCmd) {
|
|
343
|
+
$output = & $pythonCmd.Source $scriptPath $projectRootResolved $TaskType $TaskId $artifactArg $checkpointArg
|
|
344
|
+
} else {
|
|
345
|
+
$pyCmd = Get-Command py -ErrorAction SilentlyContinue
|
|
346
|
+
if (-not $pyCmd) { throw 'Python 3 is required for progress fingerprinting.' }
|
|
347
|
+
$output = & $pyCmd.Source -3 $scriptPath $projectRootResolved $TaskType $TaskId $artifactArg $checkpointArg
|
|
348
|
+
}
|
|
349
|
+
if ($LASTEXITCODE -ne 0) { throw 'progress fingerprint python helper failed' }
|
|
350
|
+
return ($output -join "`n")
|
|
351
|
+
} finally {
|
|
352
|
+
Remove-Item -Force $scriptPath -ErrorAction SilentlyContinue
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function Test-PrizmContextProgressChanged {
|
|
357
|
+
param([string]$BeforeJson, [string]$AfterJson)
|
|
358
|
+
try {
|
|
359
|
+
$before = if ($BeforeJson) { $BeforeJson | ConvertFrom-Json } else { $null }
|
|
360
|
+
$after = if ($AfterJson) { $AfterJson | ConvertFrom-Json } else { $null }
|
|
361
|
+
} catch {
|
|
362
|
+
return $true
|
|
363
|
+
}
|
|
364
|
+
foreach ($key in @('git_diff_fingerprint', 'checkpoint_cursor', 'artifact_fingerprint', 'head_commit')) {
|
|
365
|
+
$beforeValue = if ($before -and $before.PSObject.Properties[$key]) { [string]$before.$key } else { '' }
|
|
366
|
+
$afterValue = if ($after -and $after.PSObject.Properties[$key]) { [string]$after.$key } else { '' }
|
|
367
|
+
if ($beforeValue -ne $afterValue) { return $true }
|
|
368
|
+
}
|
|
207
369
|
return $false
|
|
208
370
|
}
|
|
209
371
|
|
|
@@ -50,8 +50,7 @@ function Invoke-PrizmPipeline {
|
|
|
50
50
|
Write-Host ""
|
|
51
51
|
Write-Host "Environment Variables:"
|
|
52
52
|
Write-Host " PRIZMKIT_EFFORT AI reasoning effort (low|medium|high|xhigh|max; max is Claude Code only)"
|
|
53
|
-
Write-Host " MAX_LOG_SIZE
|
|
54
|
-
Write-Host " LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)"
|
|
53
|
+
Write-Host " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
|
|
55
54
|
$global:PRIZM_EXIT_CODE = 0
|
|
56
55
|
return
|
|
57
56
|
}
|
|
@@ -626,7 +625,10 @@ function Invoke-PrizmPipeline {
|
|
|
626
625
|
}
|
|
627
626
|
|
|
628
627
|
function Invoke-PrizmPipelineItem {
|
|
629
|
-
param(
|
|
628
|
+
param(
|
|
629
|
+
[string]$CurrentItemId,
|
|
630
|
+
[object]$ContinuationState = $null
|
|
631
|
+
)
|
|
630
632
|
$script:PRIZM_ITEM_EXIT_CODE = 0
|
|
631
633
|
|
|
632
634
|
$sessionId = New-PrizmSessionId $Kind
|
|
@@ -636,6 +638,27 @@ function Invoke-PrizmPipeline {
|
|
|
636
638
|
$isGitRepository = if (-not $dryRun) { Test-PrizmGitRepository $paths.ProjectRoot } else { $false }
|
|
637
639
|
$originalBranch = if ($isGitRepository) { Get-PrizmCurrentBranch $paths.ProjectRoot } else { '' }
|
|
638
640
|
$devBranchName = ''
|
|
641
|
+
$activeDevBranch = ''
|
|
642
|
+
$continuationPending = $false
|
|
643
|
+
$continuationReason = ''
|
|
644
|
+
$contextOverflowCount = 0
|
|
645
|
+
$continuationCount = 0
|
|
646
|
+
$previousSessionId = ''
|
|
647
|
+
$noProgressCount = 0
|
|
648
|
+
if ($ContinuationState) {
|
|
649
|
+
if ($ContinuationState.PSObject.Properties['active_dev_branch'] -and $ContinuationState.active_dev_branch) { $activeDevBranch = [string]$ContinuationState.active_dev_branch }
|
|
650
|
+
if ($ContinuationState.PSObject.Properties['base_branch'] -and $ContinuationState.base_branch) { $originalBranch = [string]$ContinuationState.base_branch }
|
|
651
|
+
if ($ContinuationState.PSObject.Properties['continuation_pending']) { $continuationPending = [bool]$ContinuationState.continuation_pending }
|
|
652
|
+
if ($ContinuationState.PSObject.Properties['continuation_reason'] -and $ContinuationState.continuation_reason) { $continuationReason = [string]$ContinuationState.continuation_reason }
|
|
653
|
+
if ($ContinuationState.PSObject.Properties['context_overflow_count'] -and $ContinuationState.context_overflow_count -ne $null) { $contextOverflowCount = [int]$ContinuationState.context_overflow_count }
|
|
654
|
+
if ($ContinuationState.PSObject.Properties['continuation_count'] -and $ContinuationState.continuation_count -ne $null) { $continuationCount = [int]$ContinuationState.continuation_count }
|
|
655
|
+
if ($ContinuationState.PSObject.Properties['last_context_overflow_session_id'] -and $ContinuationState.last_context_overflow_session_id) { $previousSessionId = [string]$ContinuationState.last_context_overflow_session_id }
|
|
656
|
+
if ($ContinuationState.PSObject.Properties['no_progress_count'] -and $ContinuationState.no_progress_count -ne $null) { $noProgressCount = [int]$ContinuationState.no_progress_count }
|
|
657
|
+
}
|
|
658
|
+
if ($continuationPending -and $activeDevBranch) {
|
|
659
|
+
Write-PrizmInfo "Continuation pending ($continuationReason); reusing dev branch: $activeDevBranch"
|
|
660
|
+
Write-PrizmInfo "Continuation count: $continuationCount (context overflows: $contextOverflowCount)"
|
|
661
|
+
}
|
|
639
662
|
$hadDirtyBaseline = if ($isGitRepository) { Test-PrizmGitWorkDirty $paths.ProjectRoot $stateDir $listPath } else { $false }
|
|
640
663
|
if ($hadDirtyBaseline) {
|
|
641
664
|
if ($dryRun) {
|
|
@@ -664,7 +687,7 @@ function Invoke-PrizmPipeline {
|
|
|
664
687
|
|
|
665
688
|
if ($isGitRepository -and $originalBranch) {
|
|
666
689
|
Invoke-PrizmGitCommitPath $paths.ProjectRoot $listPath "chore($CurrentItemId): mark in_progress" | Out-Null
|
|
667
|
-
$candidateBranch = if ($devBranchOverride) { $devBranchOverride } else { New-PrizmDefaultDevBranchName $Kind $CurrentItemId }
|
|
690
|
+
$candidateBranch = if ($devBranchOverride) { $devBranchOverride } elseif ($continuationPending -and $activeDevBranch) { $activeDevBranch } else { New-PrizmDefaultDevBranchName $Kind $CurrentItemId }
|
|
668
691
|
if (New-PrizmDevBranch $paths.ProjectRoot $candidateBranch $originalBranch) {
|
|
669
692
|
$devBranchName = $candidateBranch
|
|
670
693
|
Write-PrizmInfo "Dev branch: $devBranchName"
|
|
@@ -679,6 +702,7 @@ function Invoke-PrizmPipeline {
|
|
|
679
702
|
|
|
680
703
|
$baseCommit = if ($isGitRepository) { Get-PrizmGitHead $paths.ProjectRoot } else { '' }
|
|
681
704
|
|
|
705
|
+
while ($true) {
|
|
682
706
|
$sessionDir = if ($dryRun) {
|
|
683
707
|
Join-Path ([System.IO.Path]::GetTempPath()) "prizmkit-dry-run\$sessionId"
|
|
684
708
|
} else {
|
|
@@ -697,6 +721,15 @@ function Invoke-PrizmPipeline {
|
|
|
697
721
|
}
|
|
698
722
|
|
|
699
723
|
$promptArgs = @((Join-Path $paths.ScriptsDir $promptScript), $listOption, $listPath, $idOption, $CurrentItemId, '--session-id', $sessionId, '--run-id', $runId, '--retry-count', $retryCount, '--resume-phase', $resumePhase, '--state-dir', $stateDir, '--output', $promptPath)
|
|
724
|
+
$continuationSummaryPath = ".prizmkit/$Kind/$CurrentItemId/continuation-summary.md"
|
|
725
|
+
if ($Kind -eq 'feature') {
|
|
726
|
+
$featureSlug = Get-PrizmFeatureSlugFromList $listPath $CurrentItemId
|
|
727
|
+
if ($featureSlug) { $continuationSummaryPath = ".prizmkit/specs/$featureSlug/continuation-summary.md" }
|
|
728
|
+
}
|
|
729
|
+
if ($continuationPending) {
|
|
730
|
+
$modeForContinuation = if ($continuationReason) { $continuationReason } else { 'context_overflow' }
|
|
731
|
+
$promptArgs += @('--continuation-mode', $modeForContinuation, '--previous-session-id', $previousSessionId, '--continuation-count', [string]$continuationCount, '--context-overflow-count', [string]$contextOverflowCount, '--task-type', $Kind, '--active-dev-branch', $activeDevBranch, '--base-branch', $originalBranch, '--continuation-summary-path', $continuationSummaryPath)
|
|
732
|
+
}
|
|
700
733
|
if ($mode) { $promptArgs += @('--mode', $mode) }
|
|
701
734
|
if ($critic) { $promptArgs += @('--critic', $critic) }
|
|
702
735
|
if ($dryRun) { $promptArgs += '--no-checkpoint' }
|
|
@@ -717,6 +750,10 @@ function Invoke-PrizmPipeline {
|
|
|
717
750
|
|
|
718
751
|
Write-PrizmInfo "Starting $cli session for $CurrentItemId ($sessionId)"
|
|
719
752
|
|
|
753
|
+
$artifactDirForFingerprint = if ($Kind -eq 'feature') { Split-Path $continuationSummaryPath -Parent } else { ".prizmkit/$Kind/$CurrentItemId" }
|
|
754
|
+
$checkpointForFingerprint = Join-Path $artifactDirForFingerprint 'workflow-checkpoint.json'
|
|
755
|
+
$progressBefore = Get-PrizmContextProgressFingerprint -ProjectRoot $paths.ProjectRoot -TaskType $Kind -TaskId $CurrentItemId -ArtifactDir $artifactDirForFingerprint -CheckpointFile $checkpointForFingerprint
|
|
756
|
+
|
|
720
757
|
$progressJson = Join-Path $logsDir 'progress.json'
|
|
721
758
|
$parserProcess = Start-PrizmProgressParser -PythonCommand $python -ScriptsDir $paths.ScriptsDir -SessionLog $sessionLog -ProgressFile $progressJson -CliCommand $cli
|
|
722
759
|
|
|
@@ -798,22 +835,34 @@ function Invoke-PrizmPipeline {
|
|
|
798
835
|
}
|
|
799
836
|
Stop-PrizmProgressParser $parserProcess
|
|
800
837
|
|
|
838
|
+
$wasContextOverflow = Test-PrizmContextOverflowError -SessionLog $sessionLog -ProgressJson $progressJson
|
|
801
839
|
$wasInfraError = ($exitCode -ne 0 -and (Test-PrizmInfraError -SessionLog $sessionLog -ProgressJson $progressJson))
|
|
802
840
|
$wasAiRuntimeError = Test-PrizmAiRuntimeError -SessionLog $sessionLog -ProgressJson $progressJson
|
|
803
841
|
$semanticCompletion = if ($Kind -eq 'feature' -and $isGitRepository) {
|
|
804
842
|
Get-PrizmFeatureSemanticCompletion $paths.ProjectRoot $listPath $CurrentItemId $baseCommit $paths.PrizmkitDir
|
|
805
843
|
} else { $null }
|
|
806
844
|
|
|
845
|
+
$hasSuccessfulCommit = $false
|
|
846
|
+
if ($Kind -ne 'feature' -and $isGitRepository) {
|
|
847
|
+
$hasSuccessfulCommit = Test-PrizmGitCommitsSince $paths.ProjectRoot $baseCommit
|
|
848
|
+
}
|
|
849
|
+
|
|
807
850
|
$status = 'crashed'
|
|
808
851
|
if ($semanticCompletion) {
|
|
809
852
|
$status = 'success'
|
|
810
|
-
if ($exitCode -ne 0 -or $wasStaleKilled -or $wasAiRuntimeError) {
|
|
853
|
+
if ($exitCode -ne 0 -or $wasStaleKilled -or $wasContextOverflow -or $wasAiRuntimeError) {
|
|
811
854
|
Write-PrizmWarn "Session ended with a failure signal after semantic completion; treating as finalized success"
|
|
812
855
|
Write-PrizmWarn "Semantic completion commit: $($semanticCompletion.CommitSha)"
|
|
813
856
|
}
|
|
857
|
+
} elseif ($hasSuccessfulCommit) {
|
|
858
|
+
$status = 'success'
|
|
859
|
+
} elseif ($wasContextOverflow) {
|
|
860
|
+
$status = 'context_overflow'
|
|
861
|
+
Write-PrizmWarn "AI session failed because the AI CLI exceeded the model context window"
|
|
862
|
+
Write-PrizmWarn "Context overflow is retried without consuming code retry budget"
|
|
814
863
|
} elseif ($wasAiRuntimeError) {
|
|
815
864
|
$status = 'infra_error'
|
|
816
|
-
Write-PrizmWarn "AI session failed due to structured AI runtime
|
|
865
|
+
Write-PrizmWarn "AI session failed due to structured AI runtime error"
|
|
817
866
|
Write-PrizmWarn "AI runtime errors are retried without consuming code retry budget"
|
|
818
867
|
} elseif ($wasInfraError) {
|
|
819
868
|
$status = 'infra_error'
|
|
@@ -841,6 +890,38 @@ function Invoke-PrizmPipeline {
|
|
|
841
890
|
|
|
842
891
|
$mergeSucceeded = $true
|
|
843
892
|
$itemListStatus = ''
|
|
893
|
+
$activeDevBranchForStatus = $devBranchName
|
|
894
|
+
$progressAfter = ''
|
|
895
|
+
$statusContinuationArgs = @('--active-dev-branch', $activeDevBranchForStatus, '--base-branch', $originalBranch, '--last-fatal-error-code', 'context_overflow', '--continuation-summary-path', $continuationSummaryPath)
|
|
896
|
+
if ($status -eq 'context_overflow') {
|
|
897
|
+
$progressAfter = Get-PrizmContextProgressFingerprint -ProjectRoot $paths.ProjectRoot -TaskType $Kind -TaskId $CurrentItemId -ArtifactDir $artifactDirForFingerprint -CheckpointFile $checkpointForFingerprint
|
|
898
|
+
if (Test-PrizmContextProgressChanged -BeforeJson $progressBefore -AfterJson $progressAfter) {
|
|
899
|
+
$noProgressCount = 0
|
|
900
|
+
Write-PrizmInfo "Context-overflow session made observable progress; continuing on $devBranchName"
|
|
901
|
+
} else {
|
|
902
|
+
$noProgressCount++
|
|
903
|
+
Write-PrizmWarn "Context-overflow session made no observable progress ($noProgressCount consecutive)"
|
|
904
|
+
}
|
|
905
|
+
$statusContinuationArgs = @('--active-dev-branch', $activeDevBranchForStatus, '--base-branch', $originalBranch, '--last-fatal-error-code', 'context_overflow', '--continuation-summary-path', $continuationSummaryPath, '--no-progress-count', [string]$noProgressCount, '--progress-fingerprint', $progressAfter)
|
|
906
|
+
if ($noProgressCount -ge 2) {
|
|
907
|
+
Write-PrizmWarn 'Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress'
|
|
908
|
+
$status = 'stalled_context_continuation'
|
|
909
|
+
} else {
|
|
910
|
+
$updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', 'context_overflow') + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
|
|
911
|
+
if ($updateResult -and $updateResult.PSObject.Properties['new_status']) { $itemListStatus = [string]$updateResult.new_status }
|
|
912
|
+
$continuationPending = $true
|
|
913
|
+
$continuationReason = 'context_overflow'
|
|
914
|
+
$previousSessionId = $sessionId
|
|
915
|
+
$activeDevBranch = $devBranchName
|
|
916
|
+
$contextOverflowCount++
|
|
917
|
+
$continuationCount++
|
|
918
|
+
$sessionId = New-PrizmSessionId $Kind
|
|
919
|
+
$runId = "run-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
920
|
+
Write-PrizmInfo "Launching automatic continuation for $CurrentItemId on same branch/worktree"
|
|
921
|
+
continue
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
844
925
|
if ($status -eq 'success') {
|
|
845
926
|
if (Test-PrizmGitDirty $paths.ProjectRoot) {
|
|
846
927
|
Write-PrizmInfo "Auto-committing remaining session artifacts."
|
|
@@ -848,7 +929,7 @@ function Invoke-PrizmPipeline {
|
|
|
848
929
|
}
|
|
849
930
|
|
|
850
931
|
if ($status -eq 'success') {
|
|
851
|
-
$updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs)
|
|
932
|
+
$updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
|
|
852
933
|
if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
|
|
853
934
|
$itemListStatus = [string]$updateResult.new_status
|
|
854
935
|
}
|
|
@@ -885,7 +966,7 @@ function Invoke-PrizmPipeline {
|
|
|
885
966
|
Write-PrizmRuntimeFailureLog $failureLog $CurrentItemId $sessionId $status $exitCode $staleKillMarker $progressJson $checkpointPath $paths.ProjectRoot $baseCommit
|
|
886
967
|
}
|
|
887
968
|
}
|
|
888
|
-
$updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs)
|
|
969
|
+
$updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
|
|
889
970
|
if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
|
|
890
971
|
$itemListStatus = [string]$updateResult.new_status
|
|
891
972
|
}
|
|
@@ -894,6 +975,9 @@ function Invoke-PrizmPipeline {
|
|
|
894
975
|
}
|
|
895
976
|
}
|
|
896
977
|
|
|
978
|
+
break
|
|
979
|
+
}
|
|
980
|
+
|
|
897
981
|
if ($status -eq 'success' -and $mergeSucceeded) {
|
|
898
982
|
Write-PrizmSuccess "$Kind item completed: $CurrentItemId"
|
|
899
983
|
} else {
|
|
@@ -951,7 +1035,7 @@ function Invoke-PrizmPipeline {
|
|
|
951
1035
|
}
|
|
952
1036
|
|
|
953
1037
|
$processedCount++
|
|
954
|
-
Invoke-PrizmPipelineItem $nextItemId
|
|
1038
|
+
Invoke-PrizmPipelineItem $nextItemId $next
|
|
955
1039
|
$lastExitCode = $script:PRIZM_ITEM_EXIT_CODE
|
|
956
1040
|
if ($dryRun) {
|
|
957
1041
|
$global:PRIZM_EXIT_CODE = $lastExitCode
|
|
@@ -14,6 +14,35 @@ function Get-PrizmFeatureSlug {
|
|
|
14
14
|
return "$numeric-$slug"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function Write-PrizmContinuationResetWarning {
|
|
18
|
+
param([string]$StatusPath, [string]$ItemId, [string]$Label)
|
|
19
|
+
if (-not (Test-Path $StatusPath)) { return }
|
|
20
|
+
try {
|
|
21
|
+
$status = Get-Content $StatusPath -Raw | ConvertFrom-Json
|
|
22
|
+
} catch {
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
if ($status.continuation_pending -eq $true) {
|
|
26
|
+
$reason = $status.continuation_reason
|
|
27
|
+
if (-not $reason) { $reason = 'context_overflow' }
|
|
28
|
+
Write-PrizmWarn "Continuation pending for $Label $ItemId ($reason). Manual reset will abandon automatic continuation progress."
|
|
29
|
+
if ($status.active_dev_branch) {
|
|
30
|
+
Write-PrizmWarn "Pending continuation branch: $($status.active_dev_branch)"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function Write-PrizmContinuationResetWarningsForState {
|
|
36
|
+
param([string]$StateDir, [string]$Label)
|
|
37
|
+
if (-not (Test-Path $StateDir)) { return }
|
|
38
|
+
Get-ChildItem -Path $StateDir -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
39
|
+
Write-PrizmContinuationResetWarning `
|
|
40
|
+
-StatusPath (Join-Path $_.FullName 'status.json') `
|
|
41
|
+
-ItemId $_.Name `
|
|
42
|
+
-Label $Label
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
17
46
|
function Invoke-PrizmReset {
|
|
18
47
|
param(
|
|
19
48
|
[ValidateSet('feature','bugfix','refactor')][string]$Kind,
|
|
@@ -60,6 +89,7 @@ function Invoke-PrizmReset {
|
|
|
60
89
|
}
|
|
61
90
|
|
|
62
91
|
if (-not $itemId) {
|
|
92
|
+
Write-PrizmContinuationResetWarningsForState -StateDir $stateDir -Label $label
|
|
63
93
|
& (Join-Path $paths.PipelineDir $runScript) reset
|
|
64
94
|
$global:PRIZM_RESET_EXIT_CODE = $LASTEXITCODE
|
|
65
95
|
return
|
|
@@ -67,6 +97,10 @@ function Invoke-PrizmReset {
|
|
|
67
97
|
|
|
68
98
|
if (-not (Test-Path $listPath)) { throw "List file not found: $listPath" }
|
|
69
99
|
New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
|
|
100
|
+
Write-PrizmContinuationResetWarning `
|
|
101
|
+
-StatusPath (Join-Path (Join-Path $stateDir $itemId) 'status.json') `
|
|
102
|
+
-ItemId $itemId `
|
|
103
|
+
-Label $label
|
|
70
104
|
|
|
71
105
|
$action = if ($clean) { 'clean' } else { 'reset' }
|
|
72
106
|
$resetArgs = @((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', $action, $idOption, $itemId)
|