sequant 2.9.0 → 2.10.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +14 -3
- package/dist/bin/cli.js +97 -17
- package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
- package/dist/marketplace/external_plugins/sequant/.mcp.json +1 -1
- package/dist/marketplace/external_plugins/sequant/README.md +56 -2
- package/dist/marketplace/external_plugins/sequant/hooks/parallel-marker.sh +50 -0
- package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +20 -7
- package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +75 -10
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/trust-model.md +18 -0
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +215 -390
- package/dist/marketplace/external_plugins/sequant/skills/assess/references/predicted-collision-detection.md +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/docs/SKILL.md +4 -4
- package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +26 -6
- package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +3 -1
- package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +38 -2
- package/dist/marketplace/external_plugins/sequant/skills/merger/SKILL.md +2 -2
- package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +337 -57
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/anti-pattern-detection.md +6 -6
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/call-site-review.md +2 -2
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/code-review-checklist.md +2 -2
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/fixtures/injection-issue-body.md +36 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +21 -7
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +11 -11
- package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/setup/SKILL.md +5 -5
- package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +2 -0
- package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +1 -1
- package/dist/src/commands/assess-render.d.ts +23 -0
- package/dist/src/commands/assess-render.js +60 -0
- package/dist/src/commands/doctor.js +8 -13
- package/dist/src/commands/init.js +13 -1
- package/dist/src/commands/locks.js +2 -0
- package/dist/src/commands/logs.js +14 -5
- package/dist/src/commands/merge.js +154 -2
- package/dist/src/commands/ready-tui-adapter.js +6 -1
- package/dist/src/commands/ready.d.ts +25 -3
- package/dist/src/commands/ready.js +39 -13
- package/dist/src/commands/resume.d.ts +113 -0
- package/dist/src/commands/resume.js +193 -0
- package/dist/src/commands/run-display.js +37 -4
- package/dist/src/commands/run-flags.d.ts +42 -1
- package/dist/src/commands/run-flags.js +53 -1
- package/dist/src/commands/run-progress.js +26 -1
- package/dist/src/commands/run.js +11 -10
- package/dist/src/commands/state.js +7 -0
- package/dist/src/commands/status.d.ts +9 -0
- package/dist/src/commands/status.js +24 -1
- package/dist/src/commands/sync.js +90 -19
- package/dist/src/commands/update.js +28 -5
- package/dist/src/lib/ac-parser.d.ts +14 -0
- package/dist/src/lib/ac-parser.js +99 -5
- package/dist/src/lib/assess/index.d.ts +10 -0
- package/dist/src/lib/assess/index.js +9 -0
- package/dist/src/lib/assess/renderer.d.ts +64 -0
- package/dist/src/lib/assess/renderer.js +481 -0
- package/dist/src/lib/assess/types.d.ts +224 -0
- package/dist/src/lib/assess/types.js +241 -0
- package/dist/src/lib/ci/outputs.d.ts +15 -2
- package/dist/src/lib/ci/outputs.js +17 -5
- package/dist/src/lib/cli-flags.d.ts +33 -0
- package/dist/src/lib/cli-flags.js +46 -0
- package/dist/src/lib/cli-ui/run-renderer-types.d.ts +21 -7
- package/dist/src/lib/cli-ui/run-renderer.d.ts +10 -0
- package/dist/src/lib/cli-ui/run-renderer.js +62 -0
- package/dist/src/lib/errors.d.ts +78 -6
- package/dist/src/lib/errors.js +133 -15
- package/dist/src/lib/locks/index.d.ts +3 -3
- package/dist/src/lib/locks/index.js +2 -2
- package/dist/src/lib/locks/lock-manager.d.ts +20 -2
- package/dist/src/lib/locks/lock-manager.js +47 -3
- package/dist/src/lib/locks/types.d.ts +34 -3
- package/dist/src/lib/locks/types.js +16 -0
- package/dist/src/lib/mcp-config.d.ts +45 -0
- package/dist/src/lib/mcp-config.js +77 -1
- package/dist/src/lib/merge-check/combined-branch-test.d.ts +21 -2
- package/dist/src/lib/merge-check/combined-branch-test.js +233 -110
- package/dist/src/lib/merge-check/command-result.d.ts +36 -0
- package/dist/src/lib/merge-check/command-result.js +56 -0
- package/dist/src/lib/merge-check/index.d.ts +4 -0
- package/dist/src/lib/merge-check/index.js +1 -1
- package/dist/src/lib/merge-check/report.js +5 -1
- package/dist/src/lib/merge-check/types.d.ts +9 -0
- package/dist/src/lib/merge-check/watch.d.ts +121 -0
- package/dist/src/lib/merge-check/watch.js +215 -0
- package/dist/src/lib/qa/infra-blocked-ci.d.ts +90 -0
- package/dist/src/lib/qa/infra-blocked-ci.js +80 -0
- package/dist/src/lib/settings.d.ts +14 -0
- package/dist/src/lib/settings.js +61 -8
- package/dist/src/lib/shutdown.d.ts +42 -2
- package/dist/src/lib/shutdown.js +75 -5
- package/dist/src/lib/skills-check.d.ts +26 -0
- package/dist/src/lib/skills-check.js +31 -0
- package/dist/src/lib/stacks.d.ts +110 -1
- package/dist/src/lib/stacks.js +244 -5
- package/dist/src/lib/templates.d.ts +74 -0
- package/dist/src/lib/templates.js +171 -16
- package/dist/src/lib/test-tautology-detector.d.ts +9 -2
- package/dist/src/lib/test-tautology-detector.js +153 -12
- package/dist/src/lib/version-check.d.ts +31 -0
- package/dist/src/lib/version-check.js +45 -2
- package/dist/src/lib/workflow/batch-executor.d.ts +125 -6
- package/dist/src/lib/workflow/batch-executor.js +477 -44
- package/dist/src/lib/workflow/chain-resume.d.ts +13 -11
- package/dist/src/lib/workflow/chain-resume.js +24 -20
- package/dist/src/lib/workflow/completed-status.d.ts +52 -0
- package/dist/src/lib/workflow/completed-status.js +57 -0
- package/dist/src/lib/workflow/config-resolver.d.ts +26 -0
- package/dist/src/lib/workflow/config-resolver.js +54 -2
- package/dist/src/lib/workflow/drivers/agent-driver.d.ts +7 -0
- package/dist/src/lib/workflow/drivers/aider.d.ts +2 -0
- package/dist/src/lib/workflow/drivers/aider.js +2 -0
- package/dist/src/lib/workflow/drivers/claude-code.d.ts +14 -0
- package/dist/src/lib/workflow/drivers/claude-code.js +20 -2
- package/dist/src/lib/workflow/git-diff-utils.d.ts +35 -3
- package/dist/src/lib/workflow/git-diff-utils.js +77 -4
- package/dist/src/lib/workflow/heartbeat.d.ts +38 -0
- package/dist/src/lib/workflow/heartbeat.js +90 -0
- package/dist/src/lib/workflow/log-writer.d.ts +44 -1
- package/dist/src/lib/workflow/log-writer.js +75 -6
- package/dist/src/lib/workflow/metrics-schema.d.ts +3 -3
- package/dist/src/lib/workflow/phase-executor.d.ts +203 -14
- package/dist/src/lib/workflow/phase-executor.js +457 -52
- package/dist/src/lib/workflow/phase-registry.js +2 -1
- package/dist/src/lib/workflow/platforms/github.d.ts +64 -0
- package/dist/src/lib/workflow/platforms/github.js +152 -0
- package/dist/src/lib/workflow/qa-cache.d.ts +6 -1
- package/dist/src/lib/workflow/qa-cache.js +22 -9
- package/dist/src/lib/workflow/ready-gate.d.ts +17 -4
- package/dist/src/lib/workflow/ready-gate.js +25 -9
- package/dist/src/lib/workflow/run-log-schema.d.ts +14 -0
- package/dist/src/lib/workflow/run-log-schema.js +47 -1
- package/dist/src/lib/workflow/run-orchestrator.d.ts +19 -0
- package/dist/src/lib/workflow/run-orchestrator.js +141 -20
- package/dist/src/lib/workflow/skills-preflight.d.ts +89 -0
- package/dist/src/lib/workflow/skills-preflight.js +112 -0
- package/dist/src/lib/workflow/state-cleanup.js +9 -2
- package/dist/src/lib/workflow/state-manager.d.ts +33 -0
- package/dist/src/lib/workflow/state-manager.js +83 -0
- package/dist/src/lib/workflow/state-schema.d.ts +26 -0
- package/dist/src/lib/workflow/state-schema.js +47 -0
- package/dist/src/lib/workflow/types.d.ts +126 -4
- package/dist/src/lib/workflow/types.js +1 -0
- package/dist/src/lib/workflow/worktree-manager.d.ts +28 -2
- package/dist/src/lib/workflow/worktree-manager.js +102 -23
- package/dist/src/mcp/tools/run.d.ts +9 -1
- package/dist/src/mcp/tools/run.js +20 -1
- package/dist/src/mcp/tools/status.js +6 -0
- package/dist/src/ui/tui/ElapsedTimer.d.ts +12 -3
- package/dist/src/ui/tui/ElapsedTimer.js +12 -10
- package/dist/src/ui/tui/IssueBox.js +10 -2
- package/dist/src/ui/tui/row-cap.js +2 -1
- package/dist/src/ui/tui/theme.d.ts +7 -0
- package/dist/src/ui/tui/theme.js +9 -0
- package/package.json +8 -7
- package/templates/hooks/parallel-marker.sh +50 -0
- package/templates/hooks/post-tool.sh +20 -7
- package/templates/hooks/pre-tool.sh +75 -10
- package/templates/scripts/cleanup-worktree.sh +182 -19
- package/templates/scripts/new-feature.sh +264 -16
- package/templates/skills/_shared/references/trust-model.md +18 -0
- package/templates/skills/assess/SKILL.md +215 -390
- package/templates/skills/assess/references/predicted-collision-detection.md +1 -1
- package/templates/skills/docs/SKILL.md +4 -4
- package/templates/skills/exec/SKILL.md +26 -6
- package/templates/skills/fullsolve/SKILL.md +3 -1
- package/templates/skills/loop/SKILL.md +38 -2
- package/templates/skills/merger/SKILL.md +2 -2
- package/templates/skills/qa/SKILL.md +337 -57
- package/templates/skills/qa/references/anti-pattern-detection.md +6 -6
- package/templates/skills/qa/references/call-site-review.md +2 -2
- package/templates/skills/qa/references/code-review-checklist.md +2 -2
- package/templates/skills/qa/references/fixtures/injection-issue-body.md +36 -0
- package/templates/skills/qa/references/quality-gates.md +21 -7
- package/templates/skills/qa/references/testing-requirements.md +1 -1
- package/templates/skills/qa/scripts/quality-checks.sh +11 -11
- package/templates/skills/release/SKILL.md +1 -1
- package/templates/skills/setup/SKILL.md +5 -5
- package/templates/skills/spec/SKILL.md +2 -0
- package/templates/skills/test/SKILL.md +1 -1
- package/dist/src/lib/phase-spinner.d.ts +0 -146
- package/dist/src/lib/phase-spinner.js +0 -255
- package/dist/src/lib/workflow/pr-operations.d.ts +0 -86
- package/dist/src/lib/workflow/pr-operations.js +0 -326
- package/dist/src/lib/workflow/run-summary.d.ts +0 -36
- package/dist/src/lib/workflow/run-summary.js +0 -142
|
@@ -364,6 +364,89 @@ export class StateManager {
|
|
|
364
364
|
console.log(`State: PR #${pr.number} linked to issue #${issueNumber}`);
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Record or clear an in-progress auto-wait (#860). `wakeAtMs` sets the
|
|
369
|
+
* pause marker (and which phase is paused); `null` clears it on wake.
|
|
370
|
+
*
|
|
371
|
+
* Unlike the sibling updaters this NEVER throws on an untracked issue —
|
|
372
|
+
* it is called from a liveness hook during a live wait, and a bookkeeping
|
|
373
|
+
* miss must not interrupt the pause it is describing.
|
|
374
|
+
*/
|
|
375
|
+
async updateAutoWait(issueNumber, phase, wakeAtMs) {
|
|
376
|
+
await this.withLock(async () => {
|
|
377
|
+
const state = await this.getState();
|
|
378
|
+
const issueState = state.issues[String(issueNumber)];
|
|
379
|
+
if (!issueState)
|
|
380
|
+
return;
|
|
381
|
+
issueState.autoWait =
|
|
382
|
+
wakeAtMs === null
|
|
383
|
+
? undefined
|
|
384
|
+
: { wakeAt: new Date(wakeAtMs).toISOString(), phase };
|
|
385
|
+
issueState.lastActivity = new Date().toISOString();
|
|
386
|
+
await this.saveState(state);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Record a durable waitable-window halt (#892 AC-1). Preserves an existing
|
|
391
|
+
* re-entry counter so repeated halts on a still-closed window keep counting
|
|
392
|
+
* toward the re-entry bound instead of resetting it.
|
|
393
|
+
*
|
|
394
|
+
* Like `updateAutoWait`, NEVER throws on an untracked issue — it runs on a
|
|
395
|
+
* halt path where bookkeeping must not mask the real failure.
|
|
396
|
+
*/
|
|
397
|
+
async updateWindowHalt(issueNumber, phase, resumeAtMs) {
|
|
398
|
+
await this.withLock(async () => {
|
|
399
|
+
const state = await this.getState();
|
|
400
|
+
const issueState = state.issues[String(issueNumber)];
|
|
401
|
+
if (!issueState)
|
|
402
|
+
return;
|
|
403
|
+
issueState.windowHalt = {
|
|
404
|
+
resumeAt: new Date(resumeAtMs).toISOString(),
|
|
405
|
+
phase,
|
|
406
|
+
reentries: issueState.windowHalt?.reentries ?? 0,
|
|
407
|
+
};
|
|
408
|
+
issueState.lastActivity = new Date().toISOString();
|
|
409
|
+
await this.saveState(state);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Clear a stale window-halt record (#892) — on any phase success (the
|
|
414
|
+
* window demonstrably reopened; progress also resets the re-entry counter)
|
|
415
|
+
* or a non-window failure (the halt cause is no longer waitable, so an
|
|
416
|
+
* unattended re-entry must not fire on it). No-ops (no state write) when
|
|
417
|
+
* nothing is recorded; never throws on an untracked issue.
|
|
418
|
+
*/
|
|
419
|
+
async clearWindowHalt(issueNumber) {
|
|
420
|
+
await this.withLock(async () => {
|
|
421
|
+
const state = await this.getState();
|
|
422
|
+
const issueState = state.issues[String(issueNumber)];
|
|
423
|
+
if (!issueState?.windowHalt)
|
|
424
|
+
return;
|
|
425
|
+
issueState.windowHalt = undefined;
|
|
426
|
+
issueState.lastActivity = new Date().toISOString();
|
|
427
|
+
await this.saveState(state);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Consume one re-entry attempt for a halted issue (#892 AC-3). Returns the
|
|
432
|
+
* new count, or `null` when the issue has no window-halt record (nothing to
|
|
433
|
+
* resume). Called by `sequant resume` immediately before re-entry so a
|
|
434
|
+
* re-entry that halts again (window still closed) is already counted.
|
|
435
|
+
*/
|
|
436
|
+
async incrementWindowHaltReentries(issueNumber) {
|
|
437
|
+
let newCount = null;
|
|
438
|
+
await this.withLock(async () => {
|
|
439
|
+
const state = await this.getState();
|
|
440
|
+
const issueState = state.issues[String(issueNumber)];
|
|
441
|
+
if (!issueState?.windowHalt)
|
|
442
|
+
return;
|
|
443
|
+
issueState.windowHalt.reentries += 1;
|
|
444
|
+
newCount = issueState.windowHalt.reentries;
|
|
445
|
+
issueState.lastActivity = new Date().toISOString();
|
|
446
|
+
await this.saveState(state);
|
|
447
|
+
});
|
|
448
|
+
return newCount;
|
|
449
|
+
}
|
|
367
450
|
/**
|
|
368
451
|
* Update worktree information for an issue
|
|
369
452
|
*/
|
|
@@ -213,6 +213,14 @@ export declare const RelayStateSchema: z.ZodObject<{
|
|
|
213
213
|
messageCount: z.ZodNumber;
|
|
214
214
|
}, z.core.$strip>;
|
|
215
215
|
export type RelayState = z.infer<typeof RelayStateSchema>;
|
|
216
|
+
/**
|
|
217
|
+
* Maximum scheduler re-entries per window-halted issue (#892 AC-3). Mirrors
|
|
218
|
+
* `AUTO_WAIT_MAX_WAITS` (#804): both bound how often sequant returns to the
|
|
219
|
+
* same closed rate-limit window before declaring the halt terminal. Lives
|
|
220
|
+
* here — beside the `windowHalt.reentries` field it bounds — so display
|
|
221
|
+
* surfaces (`sequant status`) can import it without pulling in the run path.
|
|
222
|
+
*/
|
|
223
|
+
export declare const MAX_RESUME_REENTRIES = 2;
|
|
216
224
|
/**
|
|
217
225
|
* Complete state for a single issue
|
|
218
226
|
*/
|
|
@@ -342,6 +350,15 @@ export declare const IssueStateSchema: z.ZodObject<{
|
|
|
342
350
|
token: z.ZodString;
|
|
343
351
|
originCwd: z.ZodString;
|
|
344
352
|
}, z.core.$strip>>;
|
|
353
|
+
autoWait: z.ZodOptional<z.ZodObject<{
|
|
354
|
+
wakeAt: z.ZodString;
|
|
355
|
+
phase: z.ZodString;
|
|
356
|
+
}, z.core.$strip>>;
|
|
357
|
+
windowHalt: z.ZodOptional<z.ZodObject<{
|
|
358
|
+
resumeAt: z.ZodString;
|
|
359
|
+
phase: z.ZodString;
|
|
360
|
+
reentries: z.ZodNumber;
|
|
361
|
+
}, z.core.$strip>>;
|
|
345
362
|
resolvedAt: z.ZodOptional<z.ZodString>;
|
|
346
363
|
lastActivity: z.ZodString;
|
|
347
364
|
createdAt: z.ZodString;
|
|
@@ -482,6 +499,15 @@ export declare const WorkflowStateSchema: z.ZodObject<{
|
|
|
482
499
|
token: z.ZodString;
|
|
483
500
|
originCwd: z.ZodString;
|
|
484
501
|
}, z.core.$strip>>;
|
|
502
|
+
autoWait: z.ZodOptional<z.ZodObject<{
|
|
503
|
+
wakeAt: z.ZodString;
|
|
504
|
+
phase: z.ZodString;
|
|
505
|
+
}, z.core.$strip>>;
|
|
506
|
+
windowHalt: z.ZodOptional<z.ZodObject<{
|
|
507
|
+
resumeAt: z.ZodString;
|
|
508
|
+
phase: z.ZodString;
|
|
509
|
+
reentries: z.ZodNumber;
|
|
510
|
+
}, z.core.$strip>>;
|
|
485
511
|
resolvedAt: z.ZodOptional<z.ZodString>;
|
|
486
512
|
lastActivity: z.ZodString;
|
|
487
513
|
createdAt: z.ZodString;
|
|
@@ -197,6 +197,14 @@ export const RelayStateSchema = z.object({
|
|
|
197
197
|
startedAt: z.string().datetime(),
|
|
198
198
|
messageCount: z.number().int().nonnegative(),
|
|
199
199
|
});
|
|
200
|
+
/**
|
|
201
|
+
* Maximum scheduler re-entries per window-halted issue (#892 AC-3). Mirrors
|
|
202
|
+
* `AUTO_WAIT_MAX_WAITS` (#804): both bound how often sequant returns to the
|
|
203
|
+
* same closed rate-limit window before declaring the halt terminal. Lives
|
|
204
|
+
* here — beside the `windowHalt.reentries` field it bounds — so display
|
|
205
|
+
* surfaces (`sequant status`) can import it without pulling in the run path.
|
|
206
|
+
*/
|
|
207
|
+
export const MAX_RESUME_REENTRIES = 2;
|
|
200
208
|
/**
|
|
201
209
|
* Complete state for a single issue
|
|
202
210
|
*/
|
|
@@ -248,6 +256,45 @@ export const IssueStateSchema = z.object({
|
|
|
248
256
|
originCwd: z.string(),
|
|
249
257
|
})
|
|
250
258
|
.optional(),
|
|
259
|
+
/**
|
|
260
|
+
* An in-progress auto-wait (#860): the phase is deliberately paused until a
|
|
261
|
+
* rate-limit window reopens at `wakeAt`. Written at wait start and cleared
|
|
262
|
+
* on wake, so `sequant status` can say "waiting until 07:01" instead of
|
|
263
|
+
* showing an hours-stale in-progress phase indistinguishable from a hang
|
|
264
|
+
* (#856). The write itself also refreshes `state.json`'s mtime — the
|
|
265
|
+
* activity proxy several liveness surfaces poll.
|
|
266
|
+
*/
|
|
267
|
+
autoWait: z
|
|
268
|
+
.object({
|
|
269
|
+
/** ISO timestamp of the scheduled wake (resetsAt + buffer). */
|
|
270
|
+
wakeAt: z.string().datetime(),
|
|
271
|
+
/** Phase that is paused. */
|
|
272
|
+
phase: z.string(),
|
|
273
|
+
})
|
|
274
|
+
.optional(),
|
|
275
|
+
/**
|
|
276
|
+
* A durable halt on an exhausted rate-limit window (#892): the run exited
|
|
277
|
+
* cleanly (lock released) and can be re-entered by `sequant resume` once
|
|
278
|
+
* the window reopens at `resumeAt`. Unlike `autoWait` (a live in-process
|
|
279
|
+
* pause), this record survives reboots — it is the machine-readable
|
|
280
|
+
* contract between the halt and an unattended scheduler re-entry.
|
|
281
|
+
* Written at a waitable-window halt, cleared on any phase success or a
|
|
282
|
+
* non-window failure (the halt cause is then no longer waitable).
|
|
283
|
+
*/
|
|
284
|
+
windowHalt: z
|
|
285
|
+
.object({
|
|
286
|
+
/** ISO timestamp after which re-entry can proceed (resetsAt + buffer). */
|
|
287
|
+
resumeAt: z.string().datetime(),
|
|
288
|
+
/** Phase that halted. */
|
|
289
|
+
phase: z.string(),
|
|
290
|
+
/**
|
|
291
|
+
* Re-entry attempts consumed (#892 AC-3). Incremented by `sequant
|
|
292
|
+
* resume` before each re-entry; a window that never reopens is bounded
|
|
293
|
+
* by MAX_RESUME_REENTRIES instead of ping-ponging a scheduler.
|
|
294
|
+
*/
|
|
295
|
+
reentries: z.number().int().min(0),
|
|
296
|
+
})
|
|
297
|
+
.optional(),
|
|
251
298
|
/** When the issue transitioned to a terminal status (merged/abandoned/closed) */
|
|
252
299
|
resolvedAt: z.string().datetime().optional(),
|
|
253
300
|
/** Most recent activity timestamp */
|
|
@@ -9,6 +9,7 @@ import type { ShutdownManager } from "../shutdown.js";
|
|
|
9
9
|
import type { WorktreeInfo } from "./worktree-manager.js";
|
|
10
10
|
import type { SequantError } from "../errors.js";
|
|
11
11
|
import type { ErrorCategory } from "./error-classifier.js";
|
|
12
|
+
import type { ReadyResult } from "./ready-gate.js";
|
|
12
13
|
export type { WorkflowEventEmitter, WorkflowEvents, WorkflowEventListener, IssueEventStatus, BaseEventPayload, RunEventPayload, PhaseStartedPayload, PhaseCompletedPayload, PhaseFailedPayload, IssueStatusChangedPayload, QaVerdictPayload, ProgressPayload, } from "./event-emitter.js";
|
|
13
14
|
/**
|
|
14
15
|
* Canonical Zod schema for all workflow phases.
|
|
@@ -131,6 +132,14 @@ export interface ExecutionConfig {
|
|
|
131
132
|
* poll budget is preserved.
|
|
132
133
|
*/
|
|
133
134
|
onActivity?: (text: string) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Runtime callback invoked while an auto-wait (#804) is in progress, once
|
|
137
|
+
* per tick plus once when it ends. Used to keep the renderer and the `-q`
|
|
138
|
+
* heartbeat showing the wait and its wake time, so a multi-hour pause reads
|
|
139
|
+
* as deliberate rather than as the silent stall of #574. Not serialized —
|
|
140
|
+
* set per-call by the orchestrator, like {@link onActivity}.
|
|
141
|
+
*/
|
|
142
|
+
onAutoWait?: (notice: AutoWaitNotice) => void;
|
|
134
143
|
/**
|
|
135
144
|
* Enable interactive relay (#383). When true, phase-executor sets
|
|
136
145
|
* `SEQUANT_RELAY=true` in the agent environment so the PostToolUse hook
|
|
@@ -147,6 +156,53 @@ export interface ExecutionConfig {
|
|
|
147
156
|
* QA pass does NOT skip the checks that catch the #318/#529/#570 class.
|
|
148
157
|
*/
|
|
149
158
|
fullQa?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Run the post-QA ready gate after the standard phases succeed (#817).
|
|
161
|
+
*
|
|
162
|
+
* When true, `runIssueWithLogging` invokes the existing `sequant ready`
|
|
163
|
+
* engine (`runReadyGate`) at the PR seam — before rebase/PR so the gate's
|
|
164
|
+
* auto-fix commits land in the PR — driving the issue to the configured
|
|
165
|
+
* `settings.ready.policy` threshold. It NEVER merges: the run terminates with
|
|
166
|
+
* the issue in `waiting_for_human_merge` (ready) or `blocked` (guard halt).
|
|
167
|
+
* Default off; when unset the run path is byte-identical to pre-#817.
|
|
168
|
+
*/
|
|
169
|
+
readyGate?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Total wait budget, in minutes, for auto-waiting out an exhausted
|
|
172
|
+
* rate-limit window (#804). `0` (the default) disables auto-wait entirely,
|
|
173
|
+
* preserving the #761/#799 halt behavior byte-for-byte.
|
|
174
|
+
*
|
|
175
|
+
* When a phase fails with a window-exhausted `RateLimitError` whose reset
|
|
176
|
+
* lies within the remaining budget, the executor sleeps until the reset and
|
|
177
|
+
* retries the phase instead of returning the failure. Named for the
|
|
178
|
+
* *behavior* (waiting), not the mechanism, so it survives a future move from
|
|
179
|
+
* in-process sleep to out-of-process rescheduling.
|
|
180
|
+
*
|
|
181
|
+
* This is a TOTAL budget across the issue, not a per-occurrence allowance —
|
|
182
|
+
* see {@link AutoWaitLedger}.
|
|
183
|
+
*/
|
|
184
|
+
autoWaitMinutes?: number;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* A single liveness notice emitted during an auto-wait (#804 AC-7).
|
|
188
|
+
*/
|
|
189
|
+
export interface AutoWaitNotice {
|
|
190
|
+
/** Issue the wait belongs to. */
|
|
191
|
+
issueNumber: number;
|
|
192
|
+
/** Phase whose retry is being waited for. */
|
|
193
|
+
phase: string;
|
|
194
|
+
/** Epoch ms at which the wait ends (reset + buffer). */
|
|
195
|
+
wakeAtMs: number;
|
|
196
|
+
/** Ms remaining at the time of this notice. `0` on the final notice. */
|
|
197
|
+
remainingMs: number;
|
|
198
|
+
/**
|
|
199
|
+
* Display string, already formatted. Built from `formatRateLimitMessage`
|
|
200
|
+
* plus the wake time — never by re-appending `resetsAt` to an
|
|
201
|
+
* already-formatted driver message (the #799 doubled-string trap).
|
|
202
|
+
*/
|
|
203
|
+
message: string;
|
|
204
|
+
/** True on the terminal notice, once the wait has ended or been aborted. */
|
|
205
|
+
done: boolean;
|
|
150
206
|
}
|
|
151
207
|
/**
|
|
152
208
|
* Default execution configuration
|
|
@@ -205,6 +261,14 @@ export interface IssueResult {
|
|
|
205
261
|
prNumber?: number;
|
|
206
262
|
/** PR URL if created after successful QA */
|
|
207
263
|
prUrl?: string;
|
|
264
|
+
/**
|
|
265
|
+
* Set when PR creation was attempted after passing QA but failed (#879).
|
|
266
|
+
* A failed `createPR` used to be a non-fatal yellow warning while the issue
|
|
267
|
+
* still reported success — so a run could "pass" while producing no PR. When
|
|
268
|
+
* present, `success` is false and the run summary counts the issue as failed
|
|
269
|
+
* with this string as the reason.
|
|
270
|
+
*/
|
|
271
|
+
prCreationError?: string;
|
|
208
272
|
/**
|
|
209
273
|
* Set when the issue was skipped because another sequant session holds
|
|
210
274
|
* the per-issue lock (#625). Surfaced in the summary as
|
|
@@ -232,6 +296,25 @@ export interface IssueResult {
|
|
|
232
296
|
* privacy contract). Absent on success.
|
|
233
297
|
*/
|
|
234
298
|
failureCategory?: ErrorCategory;
|
|
299
|
+
/**
|
|
300
|
+
* Outcome of the post-QA ready gate (#817), present only when the run was
|
|
301
|
+
* invoked with `--ready-gate` and the gate actually ran (i.e. the standard
|
|
302
|
+
* phases succeeded). Carries the terminal reason, the persisted issue status
|
|
303
|
+
* (`waiting_for_human_merge` / `blocked` — never merged), and the rendered
|
|
304
|
+
* report the summary and PR body surface. Absent on runs without the flag.
|
|
305
|
+
*/
|
|
306
|
+
readyGate?: ReadyResult;
|
|
307
|
+
/**
|
|
308
|
+
* Why the ready gate did NOT run, when `--ready-gate` was requested but the
|
|
309
|
+
* gate threw (#817). Mutually exclusive with {@link IssueResult.readyGate}.
|
|
310
|
+
*
|
|
311
|
+
* A gate crash is deliberately non-fatal — the phase work is already
|
|
312
|
+
* committed and the PR still opens — but it must not be silent. Without this
|
|
313
|
+
* field a run whose gate died is byte-identical in the summary to one that
|
|
314
|
+
* never asked for a gate, so the user believes a second look happened when it
|
|
315
|
+
* did not. The summary renders this as an explicit "gate did not run" line.
|
|
316
|
+
*/
|
|
317
|
+
readyGateError?: string;
|
|
235
318
|
}
|
|
236
319
|
/**
|
|
237
320
|
* CLI options for the run command, merged with settings and env config.
|
|
@@ -263,8 +346,6 @@ export interface RunOptions {
|
|
|
263
346
|
autoDetectPhases?: boolean;
|
|
264
347
|
/** Enable automatic worktree creation for issue isolation */
|
|
265
348
|
worktreeIsolation?: boolean;
|
|
266
|
-
/** Reuse existing worktrees instead of creating new ones */
|
|
267
|
-
reuseWorktrees?: boolean;
|
|
268
349
|
/** Suppress version warnings and non-essential output */
|
|
269
350
|
quiet?: boolean;
|
|
270
351
|
/** Chain issues: each branches from previous (requires --sequential) */
|
|
@@ -299,6 +380,13 @@ export interface RunOptions {
|
|
|
299
380
|
* Resolution priority: this CLI flag → settings.run.mcp → default (true)
|
|
300
381
|
*/
|
|
301
382
|
noMcp?: boolean;
|
|
383
|
+
/**
|
|
384
|
+
* Total minutes willing to wait for an exhausted rate-limit window to reopen
|
|
385
|
+
* before halting (#804). `0` (default) keeps today's immediate halt.
|
|
386
|
+
* Resolution priority: this CLI flag → SEQUANT_AUTO_WAIT_MINUTES →
|
|
387
|
+
* settings.run.autoWaitMinutes → default (0).
|
|
388
|
+
*/
|
|
389
|
+
autoWaitMinutes?: number;
|
|
302
390
|
/**
|
|
303
391
|
* Resume from last completed phase.
|
|
304
392
|
* Reads phase markers from GitHub issue comments and skips completed phases.
|
|
@@ -324,7 +412,9 @@ export interface RunOptions {
|
|
|
324
412
|
noPr?: boolean;
|
|
325
413
|
/**
|
|
326
414
|
* Force re-execution of issues even if they have completed status.
|
|
327
|
-
* Bypasses the pre-flight state guard that skips
|
|
415
|
+
* Bypasses the pre-flight state guard that skips completed issues — see
|
|
416
|
+
* `isCompletedIssueStatus` (completed-status.ts) for exactly which statuses
|
|
417
|
+
* that covers, and why `blocked` is not one of them.
|
|
328
418
|
*/
|
|
329
419
|
force?: boolean;
|
|
330
420
|
/**
|
|
@@ -361,6 +451,17 @@ export interface RunOptions {
|
|
|
361
451
|
* #705: now a hidden no-op alias — the boxed Ink TUI is the default, so
|
|
362
452
|
* `--experimental-tui` only parses for backward compatibility and no longer
|
|
363
453
|
* gates rendering. Kept so existing scripts/muscle-memory don't break.
|
|
454
|
+
*
|
|
455
|
+
* INTENTIONALLY INERT — do not delete (#810). A dead-surface sweep of
|
|
456
|
+
* `RunOptions` will correctly observe that nothing branches on this field.
|
|
457
|
+
* That is the design, not a defect: the flag's whole job is to parse and do
|
|
458
|
+
* nothing, so scripts written against #705 keep working. Its inertness is
|
|
459
|
+
* asserted, not incidental — `run-flags.test.ts` ("--experimental-tui is a
|
|
460
|
+
* no-op"), `cli.integration.test.ts` (hidden from `--help`, still parses),
|
|
461
|
+
* and `run-tui.integration.test.ts` all pin it. Contrast `reuseWorktrees`,
|
|
462
|
+
* removed in #810: that field had no flag, no consumer, and no test, so it
|
|
463
|
+
* promised behavior nothing delivered. The distinction is a flag deliberately
|
|
464
|
+
* kept parseable versus a type field nobody could ever reach.
|
|
364
465
|
*/
|
|
365
466
|
experimentalTui?: boolean;
|
|
366
467
|
/**
|
|
@@ -375,6 +476,16 @@ export interface RunOptions {
|
|
|
375
476
|
* Resolution priority: this CLI flag → settings.run.relay → default (true).
|
|
376
477
|
*/
|
|
377
478
|
relay?: boolean;
|
|
479
|
+
/**
|
|
480
|
+
* Run the post-QA ready gate after the standard phases succeed (#817). Set via
|
|
481
|
+
* `--ready-gate`. When true, the run drives the issue to the configured
|
|
482
|
+
* `settings.ready.policy` threshold through the existing `sequant ready`
|
|
483
|
+
* engine before creating the PR, then STOPS at the human merge gate — it never
|
|
484
|
+
* merges. Off by default; opt-in only, so an unset flag leaves the run path
|
|
485
|
+
* (including the #749 break-to-PR behavior) unchanged. Reuses `ready`'s policy
|
|
486
|
+
* and bounds wholesale — no new settings accompany this flag.
|
|
487
|
+
*/
|
|
488
|
+
readyGate?: boolean;
|
|
378
489
|
}
|
|
379
490
|
/**
|
|
380
491
|
* CLI arguments for run command
|
|
@@ -415,12 +526,23 @@ export interface BatchResult {
|
|
|
415
526
|
* `"activity"` (#543): sub-phase activity ping. `extra.text` carries a short
|
|
416
527
|
* one-line snippet (e.g. last line of agent output) for the dashboard's
|
|
417
528
|
* `nowLine`. Fires at most ~10 Hz from the phase executor.
|
|
529
|
+
*
|
|
530
|
+
* `"waiting"` (#804): an auto-wait for a rate-limit window is in progress.
|
|
531
|
+
* `extra.text` is the display message and `extra.wakeAtMs` the wake time;
|
|
532
|
+
* a `"waiting"` event WITHOUT `wakeAtMs` is the terminal notice that clears
|
|
533
|
+
* the waiting state. Unlike `"activity"`, this must reach both display paths
|
|
534
|
+
* — a multi-hour pause with no signal is the #574 complaint at 60x scale.
|
|
418
535
|
*/
|
|
419
|
-
export type ProgressCallback = (issue: number, phase: string, event: "start" | "complete" | "failed" | "activity", extra?: {
|
|
536
|
+
export type ProgressCallback = (issue: number, phase: string, event: "start" | "complete" | "failed" | "activity" | "waiting", extra?: {
|
|
420
537
|
durationSeconds?: number;
|
|
421
538
|
error?: string;
|
|
422
539
|
iteration?: number;
|
|
423
540
|
text?: string;
|
|
541
|
+
/**
|
|
542
|
+
* `"waiting"` (#804): epoch ms at which an auto-wait ends. Absent on the
|
|
543
|
+
* terminal notice, which clears the waiting state.
|
|
544
|
+
*/
|
|
545
|
+
wakeAtMs?: number;
|
|
424
546
|
}) => void;
|
|
425
547
|
/**
|
|
426
548
|
* #672 AC-2: fired once per issue after the executor has resolved the final
|
|
@@ -145,6 +145,21 @@ export declare function filterResumedPhases(issueNumber: number, phases: Phase[]
|
|
|
145
145
|
phases: Phase[];
|
|
146
146
|
skipped: Phase[];
|
|
147
147
|
};
|
|
148
|
+
/**
|
|
149
|
+
* Run the frozen dependency install for a freshly provisioned worktree and
|
|
150
|
+
* surface (rather than swallow) a failed install.
|
|
151
|
+
*
|
|
152
|
+
* Mirrors the status check in `reinstallIfLockfileChanged` (#846): a plain
|
|
153
|
+
* `npm install` self-heals a stale/absent lockfile, but the frozen `npm ci`
|
|
154
|
+
* hard-fails (exit 1, no node_modules). Without this check a failing install
|
|
155
|
+
* left a silently dependency-less worktree whose breakage only surfaced later
|
|
156
|
+
* as a confusing phase error. The warning names the resolved command so the
|
|
157
|
+
* user can rerun it by hand.
|
|
158
|
+
*
|
|
159
|
+
* @returns true if the install succeeded, false if it failed (warn-and-continue)
|
|
160
|
+
* @internal Exported for testing
|
|
161
|
+
*/
|
|
162
|
+
export declare function installWorktreeDeps(worktreePath: string, packageManager: string | undefined, verbose: boolean): boolean;
|
|
148
163
|
/**
|
|
149
164
|
* Create or reuse a worktree for an issue
|
|
150
165
|
* @param baseBranch - Optional branch to use as base instead of origin/main (for chain mode)
|
|
@@ -225,17 +240,25 @@ export declare function rebaseBeforePR(worktreePath: string, issueNumber: number
|
|
|
225
240
|
* @param opts.qaVerdict QA verdict for the run; a non-A+ stopping state
|
|
226
241
|
* (anything other than `READY_FOR_MERGE`) surfaces a note so a human reviewer
|
|
227
242
|
* sees why the run broke to PR without reaching A+ (#749).
|
|
243
|
+
* @param opts.readyGateReport Rendered `sequant ready` gap report (#817). Set
|
|
244
|
+
* only when the run used `--ready-gate`; surfaces the gate outcome (threshold
|
|
245
|
+
* reached vs guard halt) in the PR body the same way `sequant ready` does.
|
|
228
246
|
* @internal Exported for testing
|
|
229
247
|
*/
|
|
230
248
|
export declare function buildAutomatedPRBody(issueNumber: number, opts?: {
|
|
231
249
|
stackManifest?: string;
|
|
232
250
|
qaVerdict?: string;
|
|
251
|
+
readyGateReport?: string;
|
|
233
252
|
}): string;
|
|
234
253
|
/**
|
|
235
254
|
* Push branch and create a PR after successful QA.
|
|
236
255
|
*
|
|
237
256
|
* Handles both fresh PR creation and detection of existing PRs.
|
|
238
|
-
*
|
|
257
|
+
*
|
|
258
|
+
* Returns `{ success: false, error }` on failure. As of #879 the caller
|
|
259
|
+
* (`runIssueWithLogging`) treats an attempted-but-failed PR as a run failure:
|
|
260
|
+
* a passing run that produced no PR is not a success. This function itself
|
|
261
|
+
* still only reports — it never throws — so relay teardown runs regardless.
|
|
239
262
|
*
|
|
240
263
|
* @param worktreePath Path to the worktree
|
|
241
264
|
* @param issueNumber Issue number
|
|
@@ -246,10 +269,13 @@ export declare function buildAutomatedPRBody(issueNumber: number, opts?: {
|
|
|
246
269
|
* @param stackOptions When set under --stacked, `prBase` overrides the default
|
|
247
270
|
* PR target (otherwise gh defaults to the repo's default branch) and
|
|
248
271
|
* `stackManifest` is appended to the PR body. (#605)
|
|
272
|
+
* @param qaVerdict QA verdict surfaced in the PR body when non-A+ (#749).
|
|
273
|
+
* @param readyGateReport Rendered `sequant ready` gap report, set only when the
|
|
274
|
+
* run used `--ready-gate` (#817).
|
|
249
275
|
* @returns PRCreationResult with PR info or error
|
|
250
276
|
* @internal Exported for testing
|
|
251
277
|
*/
|
|
252
278
|
export declare function createPR(worktreePath: string, issueNumber: number, issueTitle: string, branch: string, verbose: boolean, labels?: string[], stackOptions?: {
|
|
253
279
|
prBase?: string;
|
|
254
280
|
stackManifest?: string;
|
|
255
|
-
}, qaVerdict?: string): PRCreationResult;
|
|
281
|
+
}, qaVerdict?: string, readyGateReport?: string): PRCreationResult;
|