prizmkit 1.1.91 → 1.1.93
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/.env.example +0 -4
- package/bundled/dev-pipeline/README.md +9 -39
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +0 -4
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +0 -2
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -1
- package/bundled/dev-pipeline/launch-feature-daemon.sh +2 -3
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -1
- package/bundled/dev-pipeline/lib/branch.sh +8 -5
- package/bundled/dev-pipeline/lib/common.sh +122 -0
- package/bundled/dev-pipeline/lib/heartbeat.sh +13 -3
- package/bundled/dev-pipeline/run-bugfix.sh +149 -98
- package/bundled/dev-pipeline/run-feature.sh +90 -103
- package/bundled/dev-pipeline/run-recovery.sh +1 -32
- package/bundled/dev-pipeline/run-refactor.sh +148 -99
- package/bundled/dev-pipeline/scripts/update-bug-status.py +39 -4
- package/bundled/dev-pipeline/scripts/update-feature-status.py +43 -6
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +36 -4
- package/bundled/dev-pipeline/tests/test-deploy-safety.sh +3 -3
- package/bundled/dev-pipeline/tests/test_auto_skip.py +92 -3
- package/bundled/dev-pipeline-windows/.env.example +0 -4
- package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -4
- package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -2
- package/bundled/dev-pipeline-windows/lib/branch.ps1 +17 -4
- package/bundled/dev-pipeline-windows/lib/common.ps1 +9 -0
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +89 -108
- package/bundled/dev-pipeline-windows/run-recovery.ps1 +4 -19
- package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +39 -4
- package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +43 -6
- package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +36 -4
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +5 -15
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +4 -4
- package/bundled/skills/feature-pipeline-launcher/references/configuration.md +3 -13
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +3 -3
- package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +4 -14
- package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +1 -1
- package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +4 -14
- package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +4 -4
- package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +2 -12
- package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +3 -3
- package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +4 -14
- package/package.json +1 -1
- package/bundled/dev-pipeline/scripts/cleanup-logs.py +0 -192
- package/bundled/dev-pipeline-windows/scripts/cleanup-logs.py +0 -192
|
@@ -34,8 +34,17 @@ function Invoke-PrizmPipeline {
|
|
|
34
34
|
$envMaxRetryArgs = @('--max-retries', [string]$parsedEnvMaxRetries)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
$envMaxInfraRetryArgs = @()
|
|
38
|
+
if ($env:MAX_INFRA_RETRIES) {
|
|
39
|
+
$parsedEnvMaxInfraRetries = 0
|
|
40
|
+
if (-not [int]::TryParse($env:MAX_INFRA_RETRIES, [ref]$parsedEnvMaxInfraRetries) -or $parsedEnvMaxInfraRetries -lt 1) {
|
|
41
|
+
throw "MAX_INFRA_RETRIES must be a positive integer: $($env:MAX_INFRA_RETRIES)"
|
|
42
|
+
}
|
|
43
|
+
$envMaxInfraRetryArgs = @('--max-infra-retries', [string]$parsedEnvMaxInfraRetries)
|
|
44
|
+
}
|
|
45
|
+
|
|
37
46
|
if ($command -in @('help','--help','-h')) {
|
|
38
|
-
Write-Host "Usage: .\run-$Kind.ps1 run [item-id] [list-path] [--dry-run] [--mode lite|standard|full] [--critic] [--max-retries N] [--
|
|
47
|
+
Write-Host "Usage: .\run-$Kind.ps1 run [item-id] [list-path] [--dry-run] [--mode lite|standard|full] [--critic] [--max-retries N] [--max-infra-retries N]"
|
|
39
48
|
Write-Host " .\run-$Kind.ps1 status [list-path]"
|
|
40
49
|
Write-Host " .\run-$Kind.ps1 reset"
|
|
41
50
|
Write-Host ""
|
|
@@ -55,7 +64,7 @@ function Invoke-PrizmPipeline {
|
|
|
55
64
|
|
|
56
65
|
if ($command -eq 'status') {
|
|
57
66
|
$listPath = if ($remaining.Count -gt 0) { $remaining[0] } else { $defaultList }
|
|
58
|
-
Invoke-PrizmPythonText $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'status') + $envMaxRetryArgs)
|
|
67
|
+
Invoke-PrizmPythonText $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'status') + $envMaxRetryArgs + $envMaxInfraRetryArgs)
|
|
59
68
|
$global:PRIZM_EXIT_CODE = $LASTEXITCODE
|
|
60
69
|
return
|
|
61
70
|
}
|
|
@@ -78,15 +87,9 @@ function Invoke-PrizmPipeline {
|
|
|
78
87
|
}
|
|
79
88
|
$maxRetries = $null
|
|
80
89
|
if ($envMaxRetryArgs.Count -gt 0) { $maxRetries = [int]$envMaxRetryArgs[1] }
|
|
90
|
+
$maxInfraRetries = $null
|
|
91
|
+
if ($envMaxInfraRetryArgs.Count -gt 0) { $maxInfraRetries = [int]$envMaxInfraRetryArgs[1] }
|
|
81
92
|
$verboseEnabled = $env:VERBOSE -in @('1','true','yes','on')
|
|
82
|
-
$timeoutSeconds = 0
|
|
83
|
-
if ($env:SESSION_TIMEOUT) {
|
|
84
|
-
$parsedEnvTimeout = 0
|
|
85
|
-
if (-not [int]::TryParse($env:SESSION_TIMEOUT, [ref]$parsedEnvTimeout) -or $parsedEnvTimeout -lt 0) {
|
|
86
|
-
throw "SESSION_TIMEOUT must be a non-negative integer: $($env:SESSION_TIMEOUT)"
|
|
87
|
-
}
|
|
88
|
-
$timeoutSeconds = $parsedEnvTimeout
|
|
89
|
-
}
|
|
90
93
|
$heartbeatInterval = 30
|
|
91
94
|
if ($env:HEARTBEAT_INTERVAL) {
|
|
92
95
|
$parsedHeartbeatInterval = 0
|
|
@@ -115,26 +118,6 @@ function Invoke-PrizmPipeline {
|
|
|
115
118
|
$enableDeploy = $env:ENABLE_DEPLOY -in @('1','true','yes','on')
|
|
116
119
|
$stopOnFailure = $env:STOP_ON_FAILURE -in @('1','true','yes','on')
|
|
117
120
|
$devBranchOverride = if ($env:DEV_BRANCH) { $env:DEV_BRANCH.Trim() } else { '' }
|
|
118
|
-
$logCleanupEnabled = $true
|
|
119
|
-
if ($env:LOG_CLEANUP_ENABLED) {
|
|
120
|
-
$logCleanupEnabled = $env:LOG_CLEANUP_ENABLED -in @('1','true','yes','on')
|
|
121
|
-
}
|
|
122
|
-
$logRetentionDays = 14
|
|
123
|
-
if ($env:LOG_RETENTION_DAYS) {
|
|
124
|
-
$parsedLogRetentionDays = 0
|
|
125
|
-
if (-not [int]::TryParse($env:LOG_RETENTION_DAYS, [ref]$parsedLogRetentionDays) -or $parsedLogRetentionDays -lt 0) {
|
|
126
|
-
throw "LOG_RETENTION_DAYS must be a non-negative integer: $($env:LOG_RETENTION_DAYS)"
|
|
127
|
-
}
|
|
128
|
-
$logRetentionDays = $parsedLogRetentionDays
|
|
129
|
-
}
|
|
130
|
-
$logMaxTotalMb = 1024
|
|
131
|
-
if ($env:LOG_MAX_TOTAL_MB) {
|
|
132
|
-
$parsedLogMaxTotalMb = 0
|
|
133
|
-
if (-not [int]::TryParse($env:LOG_MAX_TOTAL_MB, [ref]$parsedLogMaxTotalMb) -or $parsedLogMaxTotalMb -lt 0) {
|
|
134
|
-
throw "LOG_MAX_TOTAL_MB must be a non-negative integer: $($env:LOG_MAX_TOTAL_MB)"
|
|
135
|
-
}
|
|
136
|
-
$logMaxTotalMb = $parsedLogMaxTotalMb
|
|
137
|
-
}
|
|
138
121
|
$featuresFilter = $null
|
|
139
122
|
|
|
140
123
|
for ($i = 0; $i -lt $remaining.Count; $i++) {
|
|
@@ -153,14 +136,13 @@ function Invoke-PrizmPipeline {
|
|
|
153
136
|
$maxRetries = $parsedMaxRetries
|
|
154
137
|
continue
|
|
155
138
|
}
|
|
156
|
-
'^--
|
|
139
|
+
'^--max-infra-retries$' {
|
|
157
140
|
$i++
|
|
158
|
-
|
|
159
|
-
$
|
|
160
|
-
|
|
161
|
-
throw "--timeout must be a non-negative integer: $($remaining[$i])"
|
|
141
|
+
$parsedMaxInfraRetries = 0
|
|
142
|
+
if (-not [int]::TryParse($remaining[$i], [ref]$parsedMaxInfraRetries) -or $parsedMaxInfraRetries -lt 1) {
|
|
143
|
+
throw "--max-infra-retries must be a positive integer: $($remaining[$i])"
|
|
162
144
|
}
|
|
163
|
-
$
|
|
145
|
+
$maxInfraRetries = $parsedMaxInfraRetries
|
|
164
146
|
continue
|
|
165
147
|
}
|
|
166
148
|
'^--features$' { $i++; $featuresFilter = $remaining[$i]; continue }
|
|
@@ -177,12 +159,15 @@ function Invoke-PrizmPipeline {
|
|
|
177
159
|
}
|
|
178
160
|
$maxRetryArgs = @()
|
|
179
161
|
if ($maxRetries -ne $null) { $maxRetryArgs = @('--max-retries', [string]$maxRetries) }
|
|
162
|
+
$maxInfraRetryArgs = @()
|
|
163
|
+
if ($maxInfraRetries -ne $null) { $maxInfraRetryArgs = @('--max-infra-retries', [string]$maxInfraRetries) }
|
|
180
164
|
if ($verboseEnabled) {
|
|
181
165
|
$modeLabel = if ($mode) { $mode } else { 'auto' }
|
|
182
166
|
$criticLabel = if ($critic) { $critic } else { 'plan-default' }
|
|
183
167
|
$retryLabel = if ($maxRetries -ne $null) { [string]$maxRetries } else { 'default' }
|
|
168
|
+
$infraRetryLabel = if ($maxInfraRetries -ne $null) { [string]$maxInfraRetries } else { 'default' }
|
|
184
169
|
Write-PrizmInfo "Verbose mode enabled."
|
|
185
|
-
Write-PrizmInfo "Effective options: mode=$modeLabel critic=$criticLabel maxRetries=$retryLabel
|
|
170
|
+
Write-PrizmInfo "Effective options: mode=$modeLabel critic=$criticLabel maxRetries=$retryLabel maxInfraRetries=$infraRetryLabel staleKillThreshold=$staleKillThreshold dryRun=$dryRun"
|
|
186
171
|
}
|
|
187
172
|
|
|
188
173
|
# Validate PRIZMKIT_EFFORT early (fail-fast before any sessions are spawned)
|
|
@@ -241,17 +226,27 @@ function Invoke-PrizmPipeline {
|
|
|
241
226
|
|
|
242
227
|
function Get-PrizmGitDirtyPaths {
|
|
243
228
|
param([string]$ProjectRoot)
|
|
244
|
-
$
|
|
229
|
+
$hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
|
|
230
|
+
$lines = & git -C $ProjectRoot status --porcelain -- . @hiddenToolWorktreeExcludes 2>$null
|
|
245
231
|
$paths = @()
|
|
246
232
|
foreach ($line in $lines) {
|
|
247
233
|
if ([string]::IsNullOrWhiteSpace($line) -or $line.Length -lt 4) { continue }
|
|
248
234
|
$path = $line.Substring(3).Trim()
|
|
249
235
|
if ($path -match ' -> ') { $path = ($path -split ' -> ')[-1].Trim() }
|
|
250
|
-
$paths += (($path -replace '\\', '/').Trim('"').TrimStart([char[]]@('
|
|
236
|
+
$paths += (($path -replace '\\', '/').Trim('"').TrimStart([char[]]@('/')))
|
|
251
237
|
}
|
|
252
238
|
return @($paths)
|
|
253
239
|
}
|
|
254
240
|
|
|
241
|
+
function Test-PrizmPipelineIgnoredPath {
|
|
242
|
+
param([string]$Path)
|
|
243
|
+
$normalizedPath = (($Path -replace '\\', '/').Trim('"').TrimStart([char[]]@('/')))
|
|
244
|
+
$segments = @($normalizedPath -split '/' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
|
|
245
|
+
if ($segments.Count -lt 2) { return $false }
|
|
246
|
+
if (-not $segments[0].StartsWith('.')) { return $false }
|
|
247
|
+
return $segments[1] -in @('worktree', 'worktrees')
|
|
248
|
+
}
|
|
249
|
+
|
|
255
250
|
function Test-PrizmPipelineBookkeepingPath {
|
|
256
251
|
param(
|
|
257
252
|
[string]$ProjectRoot,
|
|
@@ -270,6 +265,7 @@ function Invoke-PrizmPipeline {
|
|
|
270
265
|
function Test-PrizmGitWorkDirty {
|
|
271
266
|
param([string]$ProjectRoot, [string]$StateDir, [string]$ListPath)
|
|
272
267
|
foreach ($path in (Get-PrizmGitDirtyPaths $ProjectRoot)) {
|
|
268
|
+
if (Test-PrizmPipelineIgnoredPath $path) { continue }
|
|
273
269
|
if (-not (Test-PrizmPipelineBookkeepingPath $ProjectRoot $path $StateDir $ListPath)) {
|
|
274
270
|
return $true
|
|
275
271
|
}
|
|
@@ -279,7 +275,8 @@ function Invoke-PrizmPipeline {
|
|
|
279
275
|
|
|
280
276
|
function Test-PrizmGitDirty {
|
|
281
277
|
param([string]$ProjectRoot)
|
|
282
|
-
$
|
|
278
|
+
$hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
|
|
279
|
+
$dirty = & git -C $ProjectRoot status --porcelain -- . @hiddenToolWorktreeExcludes 2>$null | Select-Object -First 1
|
|
283
280
|
return -not [string]::IsNullOrWhiteSpace([string]$dirty)
|
|
284
281
|
}
|
|
285
282
|
|
|
@@ -294,12 +291,12 @@ function Invoke-PrizmPipeline {
|
|
|
294
291
|
}
|
|
295
292
|
|
|
296
293
|
function Write-PrizmStaleKillMarker {
|
|
297
|
-
param([string]$MarkerPath, [int]$StaleSeconds, [int]$Threshold)
|
|
294
|
+
param([string]$MarkerPath, [int]$StaleSeconds, [int]$Threshold, [string]$Reason = 'stale_session')
|
|
298
295
|
$markerDir = Split-Path $MarkerPath -Parent
|
|
299
296
|
if ($markerDir) { New-Item -ItemType Directory -Force -Path $markerDir | Out-Null }
|
|
300
297
|
[ordered]@{
|
|
301
298
|
killed_at = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
|
|
302
|
-
reason =
|
|
299
|
+
reason = $Reason
|
|
303
300
|
stale_seconds = $StaleSeconds
|
|
304
301
|
threshold = $Threshold
|
|
305
302
|
} | ConvertTo-Json -Compress | Set-Content -Path $MarkerPath -Encoding UTF8
|
|
@@ -307,14 +304,16 @@ function Invoke-PrizmPipeline {
|
|
|
307
304
|
|
|
308
305
|
function Invoke-PrizmGitAutoCommit {
|
|
309
306
|
param([string]$ProjectRoot, [string]$Message)
|
|
310
|
-
|
|
307
|
+
$hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
|
|
308
|
+
& git -C $ProjectRoot add -A -- . @hiddenToolWorktreeExcludes *> $null
|
|
311
309
|
& git -C $ProjectRoot commit --no-verify -m $Message *> $null
|
|
312
310
|
return $LASTEXITCODE -eq 0
|
|
313
311
|
}
|
|
314
312
|
|
|
315
313
|
function Invoke-PrizmGitIncludeRemainingArtifacts {
|
|
316
314
|
param([string]$ProjectRoot, [string]$ItemId)
|
|
317
|
-
|
|
315
|
+
$hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
|
|
316
|
+
& git -C $ProjectRoot add -A -- . @hiddenToolWorktreeExcludes *> $null
|
|
318
317
|
& git -C $ProjectRoot commit --no-verify --amend --no-edit *> $null
|
|
319
318
|
if ($LASTEXITCODE -eq 0) { return }
|
|
320
319
|
& git -C $ProjectRoot commit --no-verify -m "chore($ItemId): include remaining session artifacts" *> $null
|
|
@@ -534,26 +533,6 @@ function Invoke-PrizmPipeline {
|
|
|
534
533
|
}
|
|
535
534
|
}
|
|
536
535
|
|
|
537
|
-
function Invoke-PrizmLogCleanup {
|
|
538
|
-
if (-not $logCleanupEnabled) { return }
|
|
539
|
-
if (-not (Test-Path $stateDir)) { return }
|
|
540
|
-
|
|
541
|
-
try {
|
|
542
|
-
$cleanup = Invoke-PrizmPythonJson $python @(
|
|
543
|
-
(Join-Path $paths.ScriptsDir 'cleanup-logs.py'),
|
|
544
|
-
'--state-dir', $stateDir,
|
|
545
|
-
'--retention-days', [string]$logRetentionDays,
|
|
546
|
-
'--max-total-mb', [string]$logMaxTotalMb
|
|
547
|
-
)
|
|
548
|
-
if ($cleanup -and $cleanup.deleted_files -gt 0) {
|
|
549
|
-
$reclaimedKb = [int]([int64]$cleanup.reclaimed_bytes / 1024)
|
|
550
|
-
Write-PrizmInfo "Log cleanup: deleted $($cleanup.deleted_files) files, reclaimed ${reclaimedKb}KB"
|
|
551
|
-
}
|
|
552
|
-
} catch {
|
|
553
|
-
Write-PrizmWarn "Log cleanup failed (continuing)"
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
536
|
function Get-PrizmDeployIncompleteItems {
|
|
558
537
|
param([string]$Kind, [string]$ListPath)
|
|
559
538
|
|
|
@@ -657,7 +636,12 @@ function Invoke-PrizmPipeline {
|
|
|
657
636
|
$devBranchName = ''
|
|
658
637
|
$hadDirtyBaseline = if ($isGitRepository) { Test-PrizmGitWorkDirty $paths.ProjectRoot $stateDir $listPath } else { $false }
|
|
659
638
|
if ($hadDirtyBaseline) {
|
|
660
|
-
|
|
639
|
+
if ($dryRun) {
|
|
640
|
+
Write-PrizmWarn "Dirty working tree detected before $CurrentItemId; would auto-commit snapshot in real run."
|
|
641
|
+
} else {
|
|
642
|
+
Write-PrizmInfo "Dirty working tree detected before $CurrentItemId; auto-committing snapshot."
|
|
643
|
+
Invoke-PrizmGitAutoCommit $paths.ProjectRoot "chore: workspace snapshot ready for run $CurrentItemId" | Out-Null
|
|
644
|
+
}
|
|
661
645
|
}
|
|
662
646
|
|
|
663
647
|
if ($dryRun) {
|
|
@@ -672,7 +656,7 @@ function Invoke-PrizmPipeline {
|
|
|
672
656
|
}
|
|
673
657
|
}
|
|
674
658
|
} else {
|
|
675
|
-
$start = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'start', $idOption, $CurrentItemId, '--session-id', $sessionId) + $maxRetryArgs)
|
|
659
|
+
$start = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'start', $idOption, $CurrentItemId, '--session-id', $sessionId) + $maxRetryArgs + $maxInfraRetryArgs)
|
|
676
660
|
if ($start.retry_count -ne $null) { $retryCount = [string]$start.retry_count }
|
|
677
661
|
if ($start.resume_from_phase -ne $null) { $resumePhase = [string]$start.resume_from_phase }
|
|
678
662
|
|
|
@@ -683,7 +667,10 @@ function Invoke-PrizmPipeline {
|
|
|
683
667
|
$devBranchName = $candidateBranch
|
|
684
668
|
Write-PrizmInfo "Dev branch: $devBranchName"
|
|
685
669
|
} else {
|
|
686
|
-
Write-
|
|
670
|
+
Write-PrizmError "Failed to create dev branch: $candidateBranch from $originalBranch - aborting to avoid running on $originalBranch"
|
|
671
|
+
$script:PRIZM_ITEM_LIST_STATUS = ''
|
|
672
|
+
$script:PRIZM_ITEM_EXIT_CODE = 1
|
|
673
|
+
return
|
|
687
674
|
}
|
|
688
675
|
}
|
|
689
676
|
}
|
|
@@ -739,20 +726,18 @@ function Invoke-PrizmPipeline {
|
|
|
739
726
|
|
|
740
727
|
$elapsedSeconds = 0
|
|
741
728
|
$staleSeconds = 0
|
|
729
|
+
$staleReason = 'stale_session'
|
|
742
730
|
$previousLogSize = 0
|
|
743
731
|
$previousProgressSignature = ''
|
|
744
732
|
$previousChildActivitySignature = ''
|
|
745
733
|
$previousErrorLoopSignature = ''
|
|
746
|
-
$wasTimedOut = $false
|
|
747
734
|
$staleKillMarker = Join-Path $logsDir 'stale-kill.json'
|
|
748
735
|
$wasStaleKilled = $false
|
|
749
736
|
while ($true) {
|
|
750
|
-
$
|
|
751
|
-
$waitSeconds = if ($timeoutSeconds -gt 0) { [Math]::Min($heartbeatInterval, [Math]::Max(1, $remainingTimeout)) } else { $heartbeatInterval }
|
|
752
|
-
$completed = Wait-Job $job -Timeout $waitSeconds
|
|
737
|
+
$completed = Wait-Job $job -Timeout $heartbeatInterval
|
|
753
738
|
if ($completed) { break }
|
|
754
739
|
|
|
755
|
-
$elapsedSeconds += $
|
|
740
|
+
$elapsedSeconds += $heartbeatInterval
|
|
756
741
|
$currentLogSize = 0
|
|
757
742
|
if (Test-Path $sessionLog) {
|
|
758
743
|
$currentLogSize = [int64](Get-Item $sessionLog).Length
|
|
@@ -799,17 +784,14 @@ function Invoke-PrizmPipeline {
|
|
|
799
784
|
$previousErrorLoopSignature = $errorLoopSignature
|
|
800
785
|
|
|
801
786
|
if ($errorLoopDetected) {
|
|
787
|
+
$staleReason = 'error_loop'
|
|
802
788
|
$staleSeconds = $effectiveStaleKillThreshold
|
|
803
789
|
} elseif ($growth -gt 0 -or $childAdvanced -or $progressAdvanced) {
|
|
790
|
+
$staleReason = 'stale_session'
|
|
804
791
|
$staleSeconds = 0
|
|
805
792
|
} else {
|
|
806
|
-
$
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
if ($timeoutSeconds -gt 0 -and $elapsedSeconds -ge $timeoutSeconds) {
|
|
810
|
-
$wasTimedOut = $true
|
|
811
|
-
Stop-PrizmSessionProcess $pidPath
|
|
812
|
-
break
|
|
793
|
+
$staleReason = 'stale_session'
|
|
794
|
+
$staleSeconds += $heartbeatInterval
|
|
813
795
|
}
|
|
814
796
|
|
|
815
797
|
$fatalErrorCode = Get-PrizmProgressFatalErrorCode -ProgressFile $progressJson
|
|
@@ -825,8 +807,12 @@ function Invoke-PrizmPipeline {
|
|
|
825
807
|
}
|
|
826
808
|
if ($effectiveStaleKillThreshold -gt 0 -and $staleSeconds -ge $effectiveStaleKillThreshold) {
|
|
827
809
|
$wasStaleKilled = $true
|
|
828
|
-
|
|
829
|
-
|
|
810
|
+
if ($staleReason -eq 'error_loop') {
|
|
811
|
+
Write-PrizmWarn "Session stale-killed due to repeated read-offset/wasted-call error loop"
|
|
812
|
+
} else {
|
|
813
|
+
Write-PrizmWarn "Session stale-killed (no progress for ${effectiveStaleKillThreshold}s)"
|
|
814
|
+
}
|
|
815
|
+
Write-PrizmStaleKillMarker $staleKillMarker $staleSeconds $effectiveStaleKillThreshold $staleReason
|
|
830
816
|
Stop-PrizmSessionProcess $pidPath
|
|
831
817
|
if ($staleKillGraceSeconds -gt 0) { Start-Sleep -Seconds $staleKillGraceSeconds }
|
|
832
818
|
break
|
|
@@ -834,11 +820,7 @@ function Invoke-PrizmPipeline {
|
|
|
834
820
|
}
|
|
835
821
|
|
|
836
822
|
$exitCode = 0
|
|
837
|
-
if ($
|
|
838
|
-
Stop-Job $job
|
|
839
|
-
Remove-Job $job
|
|
840
|
-
$exitCode = 124
|
|
841
|
-
} elseif ($wasStaleKilled) {
|
|
823
|
+
if ($wasStaleKilled) {
|
|
842
824
|
Stop-Job $job
|
|
843
825
|
Remove-Job $job
|
|
844
826
|
$exitCode = 143
|
|
@@ -853,6 +835,15 @@ function Invoke-PrizmPipeline {
|
|
|
853
835
|
}
|
|
854
836
|
Stop-PrizmProgressParser $parserProcess
|
|
855
837
|
|
|
838
|
+
$staleKillReason = ''
|
|
839
|
+
if (Test-Path $staleKillMarker) {
|
|
840
|
+
try {
|
|
841
|
+
$staleKillData = Get-Content $staleKillMarker -Raw | ConvertFrom-Json
|
|
842
|
+
if ($staleKillData.PSObject.Properties['reason']) { $staleKillReason = [string]$staleKillData.reason }
|
|
843
|
+
} catch {
|
|
844
|
+
$staleKillReason = ''
|
|
845
|
+
}
|
|
846
|
+
}
|
|
856
847
|
$wasInfraError = ($exitCode -ne 0 -and (Test-PrizmInfraError -SessionLog $sessionLog -ProgressJson $progressJson))
|
|
857
848
|
$wasAiRuntimeError = Test-PrizmAiRuntimeError -SessionLog $sessionLog -ProgressJson $progressJson
|
|
858
849
|
$semanticCompletion = if ($Kind -eq 'feature' -and $isGitRepository) {
|
|
@@ -862,7 +853,7 @@ function Invoke-PrizmPipeline {
|
|
|
862
853
|
$status = 'crashed'
|
|
863
854
|
if ($semanticCompletion) {
|
|
864
855
|
$status = 'success'
|
|
865
|
-
if ($exitCode -ne 0 -or $wasStaleKilled -or $
|
|
856
|
+
if ($exitCode -ne 0 -or $wasStaleKilled -or $wasAiRuntimeError) {
|
|
866
857
|
Write-PrizmWarn "Session ended with a failure signal after semantic completion; treating as finalized success"
|
|
867
858
|
Write-PrizmWarn "Semantic completion commit: $($semanticCompletion.CommitSha)"
|
|
868
859
|
}
|
|
@@ -870,24 +861,23 @@ function Invoke-PrizmPipeline {
|
|
|
870
861
|
$status = 'infra_error'
|
|
871
862
|
Write-PrizmWarn "AI session failed due to structured AI runtime/context error"
|
|
872
863
|
Write-PrizmWarn "AI runtime errors are retried without consuming code retry budget"
|
|
873
|
-
} elseif ($wasTimedOut) {
|
|
874
|
-
$status = 'timed_out'
|
|
875
|
-
Write-PrizmWarn "AI session timed out after $timeoutSeconds seconds"
|
|
876
864
|
} elseif ($wasInfraError) {
|
|
877
865
|
$status = 'infra_error'
|
|
878
866
|
Write-PrizmWarn "AI session failed due to AI CLI/provider infrastructure error"
|
|
879
867
|
Write-PrizmWarn "Infrastructure errors are retried without consuming code retry budget"
|
|
880
868
|
} elseif ($wasStaleKilled -or (Test-Path $staleKillMarker)) {
|
|
881
|
-
|
|
882
|
-
|
|
869
|
+
if ($staleKillReason -eq 'error_loop') {
|
|
870
|
+
Write-PrizmWarn "Session was killed by heartbeat monitor due to repeated read-offset/wasted-call errors"
|
|
871
|
+
} else {
|
|
872
|
+
Write-PrizmWarn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
873
|
+
}
|
|
874
|
+
Write-PrizmWarn "Heartbeat-killed sessions are treated as failed; dev branch is preserved for inspection"
|
|
883
875
|
} elseif ($exitCode -ne 0) {
|
|
884
876
|
Write-PrizmWarn "AI session exited with code $exitCode"
|
|
885
877
|
} elseif (-not $isGitRepository) {
|
|
886
878
|
Write-PrizmWarn "AI session exited cleanly, but project is not a git repository; cannot verify work was committed."
|
|
887
879
|
} elseif (Test-PrizmGitCommitsSince $paths.ProjectRoot $baseCommit) {
|
|
888
880
|
$status = 'success'
|
|
889
|
-
} elseif ($hadDirtyBaseline) {
|
|
890
|
-
Write-PrizmWarn "AI session exited cleanly but produced no new commits; pre-existing dirty tree will not be auto-committed."
|
|
891
881
|
} elseif (Test-PrizmGitWorkDirty $paths.ProjectRoot $stateDir $listPath) {
|
|
892
882
|
Write-PrizmWarn "AI session exited cleanly but produced no commits; auto-committing dirty work tree."
|
|
893
883
|
if (Invoke-PrizmGitAutoCommit $paths.ProjectRoot "chore($CurrentItemId): auto-commit session work") {
|
|
@@ -903,17 +893,12 @@ function Invoke-PrizmPipeline {
|
|
|
903
893
|
$itemListStatus = ''
|
|
904
894
|
if ($status -eq 'success') {
|
|
905
895
|
if (Test-PrizmGitDirty $paths.ProjectRoot) {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
Invoke-PrizmGitIncludeBookkeepingArtifacts $paths.ProjectRoot $stateDir $listPath
|
|
909
|
-
} else {
|
|
910
|
-
Write-PrizmInfo "Auto-committing remaining session artifacts."
|
|
911
|
-
Invoke-PrizmGitIncludeRemainingArtifacts $paths.ProjectRoot $CurrentItemId
|
|
912
|
-
}
|
|
896
|
+
Write-PrizmInfo "Auto-committing remaining session artifacts."
|
|
897
|
+
Invoke-PrizmGitIncludeRemainingArtifacts $paths.ProjectRoot $CurrentItemId
|
|
913
898
|
}
|
|
914
899
|
|
|
915
900
|
if ($status -eq 'success') {
|
|
916
|
-
$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)
|
|
901
|
+
$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)
|
|
917
902
|
if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
|
|
918
903
|
$itemListStatus = [string]$updateResult.new_status
|
|
919
904
|
}
|
|
@@ -950,7 +935,7 @@ function Invoke-PrizmPipeline {
|
|
|
950
935
|
Write-PrizmRuntimeFailureLog $failureLog $CurrentItemId $sessionId $status $exitCode $staleKillMarker $progressJson $checkpointPath $paths.ProjectRoot $baseCommit
|
|
951
936
|
}
|
|
952
937
|
}
|
|
953
|
-
$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)
|
|
938
|
+
$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)
|
|
954
939
|
if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
|
|
955
940
|
$itemListStatus = [string]$updateResult.new_status
|
|
956
941
|
}
|
|
@@ -969,10 +954,6 @@ function Invoke-PrizmPipeline {
|
|
|
969
954
|
return
|
|
970
955
|
}
|
|
971
956
|
|
|
972
|
-
if (-not $dryRun) {
|
|
973
|
-
Invoke-PrizmLogCleanup
|
|
974
|
-
}
|
|
975
|
-
|
|
976
957
|
if ($itemId) {
|
|
977
958
|
Invoke-PrizmPipelineItem $itemId
|
|
978
959
|
$global:PRIZM_EXIT_CODE = $script:PRIZM_ITEM_EXIT_CODE
|
|
@@ -1030,7 +1011,7 @@ function Invoke-PrizmPipeline {
|
|
|
1030
1011
|
$global:PRIZM_EXIT_CODE = $lastExitCode
|
|
1031
1012
|
return
|
|
1032
1013
|
} elseif ($lastExitCode -ne 0 -and $stopOnFailure) {
|
|
1033
|
-
Write-PrizmInfo "STOP_ON_FAILURE: $nextItemId is $($script:PRIZM_ITEM_LIST_STATUS); retry budget not exhausted, continuing."
|
|
1014
|
+
Write-PrizmInfo "STOP_ON_FAILURE: $nextItemId is $($script:PRIZM_ITEM_LIST_STATUS); code/infra retry budget not exhausted, continuing."
|
|
1034
1015
|
}
|
|
1035
1016
|
}
|
|
1036
1017
|
}
|
|
@@ -62,7 +62,6 @@ function Get-PrizmRecoveryIntEnv {
|
|
|
62
62
|
return $parsed
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
$timeoutSeconds = Get-PrizmRecoveryIntEnv 'SESSION_TIMEOUT' 0 0
|
|
66
65
|
$heartbeatInterval = Get-PrizmRecoveryIntEnv 'HEARTBEAT_INTERVAL' 30 1
|
|
67
66
|
$staleKillThreshold = Get-PrizmRecoveryIntEnv 'STALE_KILL_THRESHOLD' 900 0
|
|
68
67
|
$staleKillGraceSeconds = Get-PrizmRecoveryIntEnv 'STALE_KILL_GRACE_SECONDS' 10 0
|
|
@@ -123,15 +122,12 @@ $staleSeconds = 0
|
|
|
123
122
|
$previousLogSize = 0
|
|
124
123
|
$previousProgressSignature = ''
|
|
125
124
|
$previousChildActivitySignature = ''
|
|
126
|
-
$wasTimedOut = $false
|
|
127
125
|
$wasStaleKilled = $false
|
|
128
126
|
while ($true) {
|
|
129
|
-
$
|
|
130
|
-
$waitSeconds = if ($timeoutSeconds -gt 0) { [Math]::Min($heartbeatInterval, [Math]::Max(1, $remainingTimeout)) } else { $heartbeatInterval }
|
|
131
|
-
$completed = Wait-Job $job -Timeout $waitSeconds
|
|
127
|
+
$completed = Wait-Job $job -Timeout $heartbeatInterval
|
|
132
128
|
if ($completed) { break }
|
|
133
129
|
|
|
134
|
-
$elapsedSeconds += $
|
|
130
|
+
$elapsedSeconds += $heartbeatInterval
|
|
135
131
|
$currentLogSize = 0
|
|
136
132
|
if (Test-Path $logPath) { $currentLogSize = [int64](Get-Item $logPath).Length }
|
|
137
133
|
$growth = $currentLogSize - $previousLogSize
|
|
@@ -145,13 +141,7 @@ while ($true) {
|
|
|
145
141
|
$childAdvanced = ($childSignature -and $childSignature -ne $previousChildActivitySignature)
|
|
146
142
|
$previousChildActivitySignature = $childSignature
|
|
147
143
|
|
|
148
|
-
if ($growth -gt 0 -or $childAdvanced -or $progressAdvanced) { $staleSeconds = 0 } else { $staleSeconds += $
|
|
149
|
-
|
|
150
|
-
if ($timeoutSeconds -gt 0 -and $elapsedSeconds -ge $timeoutSeconds) {
|
|
151
|
-
$wasTimedOut = $true
|
|
152
|
-
Stop-PrizmSessionProcess $pidPath
|
|
153
|
-
break
|
|
154
|
-
}
|
|
144
|
+
if ($growth -gt 0 -or $childAdvanced -or $progressAdvanced) { $staleSeconds = 0 } else { $staleSeconds += $heartbeatInterval }
|
|
155
145
|
|
|
156
146
|
if ($staleKillThreshold -gt 0 -and $staleSeconds -ge $staleKillThreshold) {
|
|
157
147
|
$wasStaleKilled = $true
|
|
@@ -164,11 +154,7 @@ while ($true) {
|
|
|
164
154
|
}
|
|
165
155
|
|
|
166
156
|
$exitCode = 0
|
|
167
|
-
if ($
|
|
168
|
-
Stop-Job $job
|
|
169
|
-
Remove-Job $job
|
|
170
|
-
$exitCode = 124
|
|
171
|
-
} elseif ($wasStaleKilled) {
|
|
157
|
+
if ($wasStaleKilled) {
|
|
172
158
|
Stop-Job $job
|
|
173
159
|
Remove-Job $job
|
|
174
160
|
$exitCode = 143
|
|
@@ -188,7 +174,6 @@ if (Test-Path $logPath) {
|
|
|
188
174
|
$sizeKb = [int](([int64](Get-Item $logPath).Length) / 1024)
|
|
189
175
|
Write-PrizmInfo "Session log: $lineCount lines, ${sizeKb}KB"
|
|
190
176
|
}
|
|
191
|
-
if ($wasTimedOut) { Write-PrizmWarn "Recovery session timed out after $timeoutSeconds seconds." }
|
|
192
177
|
if ($wasStaleKilled -or (Test-Path $staleKillMarker)) { Write-PrizmWarn "Recovery session was stale-killed." }
|
|
193
178
|
if ($exitCode -eq 0) { Write-PrizmSuccess "Recovery session completed." } else { Write-PrizmError "Recovery session failed. Log: $logPath" }
|
|
194
179
|
exit $exitCode
|
|
@@ -16,7 +16,7 @@ Usage:
|
|
|
16
16
|
--bug-list <path> --state-dir <path> \
|
|
17
17
|
--action <get_next|start|update|status|pause|reset|clean|unskip> \
|
|
18
18
|
[--bug-id <id>] [--session-status <status>] \
|
|
19
|
-
[--session-id <id>] [--max-retries <n>]
|
|
19
|
+
[--session-id <id>] [--max-retries <n>] [--max-infra-retries <n>]
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import argparse
|
|
@@ -75,7 +75,8 @@ def parse_args():
|
|
|
75
75
|
help="Session outcome status (required for 'update' action)",
|
|
76
76
|
)
|
|
77
77
|
parser.add_argument("--session-id", default=None, help="Session ID (optional, for 'update' action)")
|
|
78
|
-
parser.add_argument("--max-retries", type=int, default=3, help="Maximum retry count (default: 3)")
|
|
78
|
+
parser.add_argument("--max-retries", type=int, default=3, help="Maximum code retry count (default: 3)")
|
|
79
|
+
parser.add_argument("--max-infra-retries", type=int, default=3, help="Maximum infrastructure retry count (default: 3)")
|
|
79
80
|
parser.add_argument("--project-root", default=None, help="Project root directory. Required for 'clean' action.")
|
|
80
81
|
return parser.parse_args()
|
|
81
82
|
|
|
@@ -98,6 +99,9 @@ def load_bug_status(state_dir, bug_id):
|
|
|
98
99
|
"bug_id": bug_id,
|
|
99
100
|
"retry_count": 0,
|
|
100
101
|
"max_retries": 3,
|
|
102
|
+
"max_infra_retries": 3,
|
|
103
|
+
"infra_error_count": 0,
|
|
104
|
+
"last_infra_error_session_id": None,
|
|
101
105
|
"sessions": [],
|
|
102
106
|
"last_session_id": None,
|
|
103
107
|
"resume_from_phase": None,
|
|
@@ -111,6 +115,9 @@ def load_bug_status(state_dir, bug_id):
|
|
|
111
115
|
"bug_id": bug_id,
|
|
112
116
|
"retry_count": 0,
|
|
113
117
|
"max_retries": 3,
|
|
118
|
+
"max_infra_retries": 3,
|
|
119
|
+
"infra_error_count": 0,
|
|
120
|
+
"last_infra_error_session_id": None,
|
|
114
121
|
"sessions": [],
|
|
115
122
|
"last_session_id": None,
|
|
116
123
|
"resume_from_phase": None,
|
|
@@ -234,6 +241,7 @@ def action_get_next(bug_list_data, state_dir):
|
|
|
234
241
|
"title": chosen.get("title", ""),
|
|
235
242
|
"severity": chosen.get("severity", "medium"),
|
|
236
243
|
"retry_count": chosen_status_data.get("retry_count", 0),
|
|
244
|
+
"infra_error_count": chosen_status_data.get("infra_error_count", 0),
|
|
237
245
|
"resume_from_phase": chosen_status_data.get("resume_from_phase", None),
|
|
238
246
|
}
|
|
239
247
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
@@ -248,6 +256,7 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
248
256
|
session_status = args.session_status
|
|
249
257
|
session_id = args.session_id
|
|
250
258
|
max_retries = args.max_retries
|
|
259
|
+
max_infra_retries = args.max_infra_retries
|
|
251
260
|
|
|
252
261
|
if not bug_id:
|
|
253
262
|
error_out("--bug-id is required for 'update' action")
|
|
@@ -262,6 +271,8 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
262
271
|
new_status = get_bug_status_from_list(bug_list_path, bug_id)
|
|
263
272
|
|
|
264
273
|
if session_status == "success":
|
|
274
|
+
bs["infra_error_count"] = 0
|
|
275
|
+
bs["last_infra_error_session_id"] = None
|
|
265
276
|
new_status = "completed"
|
|
266
277
|
bs["resume_from_phase"] = None
|
|
267
278
|
err = update_bug_in_list(bug_list_path, bug_id, "completed")
|
|
@@ -286,11 +297,25 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
286
297
|
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
287
298
|
return
|
|
288
299
|
elif session_status == "infra_error":
|
|
289
|
-
|
|
290
|
-
|
|
300
|
+
# AI CLI/provider outage, auth failure, gateway error, etc.
|
|
301
|
+
# Infra failures do not consume the code retry budget, but they still
|
|
302
|
+
# need their own bounded budget so a flaky provider cannot loop forever.
|
|
303
|
+
infra_error_count = bs.get("infra_error_count", 0) + 1
|
|
304
|
+
bs["infra_error_count"] = infra_error_count
|
|
291
305
|
bs["last_infra_error_session_id"] = session_id
|
|
306
|
+
bs["max_infra_retries"] = max_infra_retries
|
|
307
|
+
bs["degraded_reason"] = "infra_error"
|
|
308
|
+
if session_id:
|
|
309
|
+
bs["last_session_id"] = session_id
|
|
292
310
|
bs["resume_from_phase"] = None
|
|
293
311
|
|
|
312
|
+
if infra_error_count >= max_infra_retries:
|
|
313
|
+
new_status = "failed"
|
|
314
|
+
if session_id:
|
|
315
|
+
bs["last_failed_session_id"] = session_id
|
|
316
|
+
else:
|
|
317
|
+
new_status = "pending"
|
|
318
|
+
|
|
294
319
|
err = update_bug_in_list(bug_list_path, bug_id, new_status)
|
|
295
320
|
if err:
|
|
296
321
|
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
@@ -338,6 +363,8 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
338
363
|
"session_status": session_status,
|
|
339
364
|
"new_status": new_status,
|
|
340
365
|
"retry_count": bs["retry_count"],
|
|
366
|
+
"infra_error_count": bs.get("infra_error_count", 0),
|
|
367
|
+
"max_infra_retries": max_infra_retries,
|
|
341
368
|
"resume_from_phase": bs.get("resume_from_phase"),
|
|
342
369
|
"updated_at": bs["updated_at"],
|
|
343
370
|
}
|
|
@@ -577,6 +604,8 @@ def action_reset(args, bug_list_path, state_dir):
|
|
|
577
604
|
old_retry = bs.get("retry_count", 0)
|
|
578
605
|
|
|
579
606
|
bs["retry_count"] = 0
|
|
607
|
+
bs["infra_error_count"] = 0
|
|
608
|
+
bs["last_infra_error_session_id"] = None
|
|
580
609
|
bs["sessions"] = []
|
|
581
610
|
bs["last_session_id"] = None
|
|
582
611
|
bs["resume_from_phase"] = None
|
|
@@ -652,6 +681,8 @@ def action_clean(args, bug_list_path, state_dir):
|
|
|
652
681
|
old_retry = bs.get("retry_count", 0)
|
|
653
682
|
|
|
654
683
|
bs["retry_count"] = 0
|
|
684
|
+
bs["infra_error_count"] = 0
|
|
685
|
+
bs["last_infra_error_session_id"] = None
|
|
655
686
|
bs["sessions"] = []
|
|
656
687
|
bs["last_session_id"] = None
|
|
657
688
|
bs["resume_from_phase"] = None
|
|
@@ -740,6 +771,8 @@ def action_start(args, bug_list_path, state_dir):
|
|
|
740
771
|
"bug_id": bug_id,
|
|
741
772
|
"old_status": old_status,
|
|
742
773
|
"new_status": "in_progress",
|
|
774
|
+
"retry_count": bs.get("retry_count", 0),
|
|
775
|
+
"infra_error_count": bs.get("infra_error_count", 0),
|
|
743
776
|
"updated_at": bs["updated_at"],
|
|
744
777
|
}
|
|
745
778
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
@@ -816,6 +849,8 @@ def action_unskip(args, bug_list_path, state_dir):
|
|
|
816
849
|
for bid in to_reset:
|
|
817
850
|
bs = load_bug_status(state_dir, bid)
|
|
818
851
|
bs["retry_count"] = 0
|
|
852
|
+
bs["infra_error_count"] = 0
|
|
853
|
+
bs["last_infra_error_session_id"] = None
|
|
819
854
|
bs["sessions"] = []
|
|
820
855
|
bs["last_session_id"] = None
|
|
821
856
|
bs["resume_from_phase"] = None
|