sequant 2.8.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 +23 -4
- package/dist/bin/cli.js +99 -18
- 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 +58 -2
- package/dist/marketplace/external_plugins/sequant/hooks/parallel-marker.sh +50 -0
- package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +38 -10
- package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +405 -67
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/trust-model.md +18 -0
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +250 -344
- package/dist/marketplace/external_plugins/sequant/skills/assess/references/predicted-collision-detection.md +10 -7
- 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 +4 -2
- 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/reflect/SKILL.md +27 -13
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/documentation-tiers.md +80 -68
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/phase-reflection.md +31 -15
- package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +11 -3
- 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/spec/references/verification-criteria.md +1 -1
- 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 +20 -6
- 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.d.ts +20 -0
- package/dist/src/commands/run-display.js +117 -5
- 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/stats.js +47 -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/assess-collision-detect.d.ts +19 -2
- package/dist/src/lib/assess-collision-detect.js +68 -4
- 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 +79 -9
- package/dist/src/lib/errors.d.ts +84 -6
- package/dist/src/lib/errors.js +142 -17
- 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/manifest.js +1 -17
- 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 +46 -7
- package/dist/src/lib/workflow/batch-executor.d.ts +138 -6
- package/dist/src/lib/workflow/batch-executor.js +550 -54
- package/dist/src/lib/workflow/chain-preflight.d.ts +89 -0
- package/dist/src/lib/workflow/chain-preflight.js +199 -0
- package/dist/src/lib/workflow/chain-resume.d.ts +118 -0
- package/dist/src/lib/workflow/chain-resume.js +170 -0
- 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/dependency-markers.d.ts +29 -0
- package/dist/src/lib/workflow/dependency-markers.js +79 -0
- 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 +21 -0
- package/dist/src/lib/workflow/drivers/claude-code.js +50 -8
- package/dist/src/lib/workflow/error-classifier.d.ts +9 -2
- package/dist/src/lib/workflow/error-classifier.js +14 -1
- 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 +81 -14
- package/dist/src/lib/workflow/metrics-schema.d.ts +42 -3
- package/dist/src/lib/workflow/metrics-schema.js +16 -0
- package/dist/src/lib/workflow/metrics-writer.d.ts +2 -1
- package/dist/src/lib/workflow/phase-executor.d.ts +234 -13
- package/dist/src/lib/workflow/phase-executor.js +533 -56
- 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 +37 -0
- package/dist/src/lib/workflow/run-log-schema.js +92 -2
- package/dist/src/lib/workflow/run-orchestrator.d.ts +33 -0
- package/dist/src/lib/workflow/run-orchestrator.js +429 -47
- 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/status-derivation.d.ts +30 -0
- package/dist/src/lib/workflow/status-derivation.js +27 -0
- package/dist/src/lib/workflow/types.d.ts +149 -4
- package/dist/src/lib/workflow/types.js +1 -0
- package/dist/src/lib/workflow/worktree-manager.d.ts +70 -2
- package/dist/src/lib/workflow/worktree-manager.js +201 -52
- package/dist/src/mcp/tools/run.d.ts +11 -1
- package/dist/src/mcp/tools/run.js +22 -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 +9 -10
- package/templates/hooks/parallel-marker.sh +50 -0
- package/templates/hooks/post-tool.sh +38 -10
- package/templates/hooks/pre-tool.sh +405 -67
- package/templates/scripts/cleanup-worktree.sh +282 -30
- package/templates/scripts/new-feature.sh +264 -16
- package/templates/skills/_shared/references/trust-model.md +18 -0
- package/templates/skills/assess/SKILL.md +250 -344
- package/templates/skills/assess/references/predicted-collision-detection.md +10 -7
- package/templates/skills/docs/SKILL.md +4 -4
- package/templates/skills/exec/SKILL.md +26 -6
- package/templates/skills/fullsolve/SKILL.md +4 -2
- 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/reflect/SKILL.md +27 -13
- package/templates/skills/reflect/references/documentation-tiers.md +80 -68
- package/templates/skills/reflect/references/phase-reflection.md +31 -15
- package/templates/skills/release/SKILL.md +11 -3
- package/templates/skills/setup/SKILL.md +5 -5
- package/templates/skills/spec/SKILL.md +2 -0
- package/templates/skills/spec/references/verification-criteria.md +1 -1
- 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
|
@@ -17,10 +17,19 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { randomUUID } from "node:crypto";
|
|
19
19
|
import { z } from "zod";
|
|
20
|
+
import { ERROR_CATEGORIES } from "./error-classifier.js";
|
|
20
21
|
/**
|
|
21
22
|
* Outcome of a workflow run
|
|
22
23
|
*/
|
|
23
24
|
export const RunOutcomeSchema = z.enum(["success", "partial", "failed"]);
|
|
25
|
+
/**
|
|
26
|
+
* Bounded-enum classification of the failure that ended a run (#761 AC-7).
|
|
27
|
+
*
|
|
28
|
+
* Sourced from `ERROR_CATEGORIES` so the metric can never carry free text —
|
|
29
|
+
* error *messages* stay excluded per the privacy contract above MetricRunSchema
|
|
30
|
+
* (they could contain sensitive info); a closed enum cannot.
|
|
31
|
+
*/
|
|
32
|
+
export const FailureCategorySchema = z.enum(ERROR_CATEGORIES);
|
|
24
33
|
/**
|
|
25
34
|
* Available phases (aligned with run-log-schema.ts)
|
|
26
35
|
*/
|
|
@@ -81,6 +90,12 @@ export const MetricRunSchema = z.object({
|
|
|
81
90
|
model: z.string(),
|
|
82
91
|
/** CLI flags used (e.g., ["--chain", "--sequential"]) */
|
|
83
92
|
flags: z.array(z.string()),
|
|
93
|
+
/**
|
|
94
|
+
* Category of the failure that ended the run (#761 AC-7). Optional and
|
|
95
|
+
* enum-only; absent on success and on records written before this field
|
|
96
|
+
* existed (additive — no `version` bump required).
|
|
97
|
+
*/
|
|
98
|
+
failureCategory: FailureCategorySchema.optional(),
|
|
84
99
|
/** Aggregate metrics */
|
|
85
100
|
metrics: RunMetricsSchema,
|
|
86
101
|
});
|
|
@@ -121,6 +136,7 @@ export function createMetricRun(options) {
|
|
|
121
136
|
duration: options.duration,
|
|
122
137
|
model: options.model ?? "unknown",
|
|
123
138
|
flags: options.flags ?? [],
|
|
139
|
+
failureCategory: options.failureCategory,
|
|
124
140
|
metrics: {
|
|
125
141
|
tokensUsed: options.metrics?.tokensUsed ?? 0,
|
|
126
142
|
filesChanged: options.metrics?.filesChanged ?? 0,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* });
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
import { type Metrics, type MetricRun, type MetricPhase, type RunOutcome, type RunMetrics } from "./metrics-schema.js";
|
|
23
|
+
import { type Metrics, type MetricRun, type MetricPhase, type RunOutcome, type RunMetrics, type FailureCategory } from "./metrics-schema.js";
|
|
24
24
|
export interface MetricsWriterOptions {
|
|
25
25
|
/** Path to metrics file (default: .sequant/metrics.json) */
|
|
26
26
|
metricsPath?: string;
|
|
@@ -69,6 +69,7 @@ export declare class MetricsWriter {
|
|
|
69
69
|
duration: number;
|
|
70
70
|
model?: string;
|
|
71
71
|
flags?: string[];
|
|
72
|
+
failureCategory?: FailureCategory;
|
|
72
73
|
metrics?: Partial<RunMetrics>;
|
|
73
74
|
}): Promise<MetricRun>;
|
|
74
75
|
/**
|
|
@@ -11,6 +11,7 @@ import { ShutdownManager } from "../shutdown.js";
|
|
|
11
11
|
import { Phase, ExecutionConfig, PhaseResult, QaVerdict, PhasePauseHandle } from "./types.js";
|
|
12
12
|
import type { QaSummary } from "./run-log-schema.js";
|
|
13
13
|
import type { AgentPhaseResult, ResumeHandle } from "./drivers/index.js";
|
|
14
|
+
import { RateLimitError, SequantError } from "../errors.js";
|
|
14
15
|
/**
|
|
15
16
|
* Leading + trailing throttle. Fires the wrapped callback immediately on the
|
|
16
17
|
* first call, drops subsequent calls that arrive inside `intervalMs` but
|
|
@@ -35,7 +36,181 @@ export declare function createThrottledReporter(fn: (text: string) => void, inte
|
|
|
35
36
|
export declare const SPEC_RETRY_BACKOFF_MS: number;
|
|
36
37
|
/** @internal Exported for testing only */
|
|
37
38
|
export declare const SPEC_EXTRA_RETRIES: number;
|
|
39
|
+
/**
|
|
40
|
+
* A rate limit whose window resets further out than this is treated as
|
|
41
|
+
* exhausted rather than transient (#761 AC-2): no retry can succeed inside a
|
|
42
|
+
* closed window, so consuming cold-start retries (each burning up to a full
|
|
43
|
+
* `phaseTimeout`) only delays the labeled halt. Five minutes comfortably
|
|
44
|
+
* exceeds any backoff this executor performs while staying far below the
|
|
45
|
+
* five-hour/seven-day windows the check exists to catch.
|
|
46
|
+
*
|
|
47
|
+
* @internal Exported for testing only
|
|
48
|
+
*/
|
|
49
|
+
export declare const RATE_LIMIT_WINDOW_SKIP_THRESHOLD_MS: number;
|
|
50
|
+
/**
|
|
51
|
+
* Base backoff for transient rate-limit retries (#761 AC-4), doubled per
|
|
52
|
+
* attempt (5s, 10s). Same scale as `SPEC_RETRY_BACKOFF_MS` — long enough to
|
|
53
|
+
* outlive a momentary throttle, short enough to be negligible next to a
|
|
54
|
+
* phase's runtime.
|
|
55
|
+
*
|
|
56
|
+
* @internal Exported for testing only
|
|
57
|
+
*/
|
|
58
|
+
export declare const RATE_LIMIT_RETRY_BACKOFF_MS = 5000;
|
|
59
|
+
/**
|
|
60
|
+
* True when a failure is a rate limit whose reset lies beyond
|
|
61
|
+
* {@link RATE_LIMIT_WINDOW_SKIP_THRESHOLD_MS} — i.e. window exhaustion, not a
|
|
62
|
+
* transient throttle. Metadata-absent rate limits (the assistant-error channel
|
|
63
|
+
* carries no `resetsAt`, see #761 AC-9) return false and fall through to the
|
|
64
|
+
* transient path: with no timing signal, retry-with-backoff is the safe
|
|
65
|
+
* default, skipping all retries is not.
|
|
66
|
+
*
|
|
67
|
+
* @internal Exported for testing only
|
|
68
|
+
*/
|
|
69
|
+
export declare function isWindowExhaustedRateLimit(error: SequantError | undefined, now?: number): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Buffer added to a rate-limit reset before waking (#804 AC-5). `resetsAt` is a
|
|
72
|
+
* floor, not an exact moment: clock skew between this host and the API, plus
|
|
73
|
+
* server-side rounding, otherwise produce an immediate second rejection on
|
|
74
|
+
* wake. One minute is negligible against the five-hour/seven-day windows this
|
|
75
|
+
* exists for.
|
|
76
|
+
*
|
|
77
|
+
* @internal Exported for testing only
|
|
78
|
+
*/
|
|
79
|
+
export declare const AUTO_WAIT_BUFFER_MS: number;
|
|
80
|
+
/**
|
|
81
|
+
* Hard cap on auto-waits per issue (#804 AC-6), independent of the minutes
|
|
82
|
+
* budget. A window that is still closed on wake must not produce an unbounded
|
|
83
|
+
* pause loop, so the count bounds the *number* of pauses while
|
|
84
|
+
* `autoWaitMinutes` bounds their *total duration*. Either bound being spent
|
|
85
|
+
* halts with today's labeled message.
|
|
86
|
+
*
|
|
87
|
+
* @internal Exported for testing only
|
|
88
|
+
*/
|
|
89
|
+
export declare const AUTO_WAIT_MAX_WAITS = 2;
|
|
90
|
+
/**
|
|
91
|
+
* Granularity of the auto-wait sleep (#804 AC-7). The wait is performed as a
|
|
92
|
+
* series of ticks rather than one multi-hour `delayFn` call so that (a) the
|
|
93
|
+
* renderer/heartbeat can be refreshed with the remaining time, and (b) a
|
|
94
|
+
* Ctrl-C is observed promptly instead of at the wake time.
|
|
95
|
+
*
|
|
96
|
+
* @internal Exported for testing only
|
|
97
|
+
*/
|
|
98
|
+
export declare const AUTO_WAIT_TICK_MS: number;
|
|
99
|
+
/**
|
|
100
|
+
* Mutable per-issue accounting for auto-wait (#804 AC-6).
|
|
101
|
+
*
|
|
102
|
+
* Deliberately per-ISSUE, not per-phase: `executePhaseWithRetry` runs once per
|
|
103
|
+
* phase, so a ledger created inside it would grant every phase its own full
|
|
104
|
+
* budget and bound. `runIssueWithLogging` creates one and threads it through
|
|
105
|
+
* all of an issue's phases.
|
|
106
|
+
*/
|
|
107
|
+
export interface AutoWaitLedger {
|
|
108
|
+
/** Total wait budget in ms. `0` disables auto-wait entirely. */
|
|
109
|
+
budgetMs: number;
|
|
110
|
+
/** Number of waits already granted for this issue. */
|
|
111
|
+
waits: number;
|
|
112
|
+
/** Cumulative ms already spent waiting for this issue. */
|
|
113
|
+
spentMs: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Build a fresh ledger from a minutes budget. A missing, negative or
|
|
117
|
+
* non-finite budget yields a disabled ledger (`budgetMs: 0`) — the default,
|
|
118
|
+
* which preserves pre-#804 behavior exactly.
|
|
119
|
+
*/
|
|
120
|
+
export declare function createAutoWaitLedger(budgetMinutes?: number): AutoWaitLedger;
|
|
121
|
+
/**
|
|
122
|
+
* A granted auto-wait: how long to sleep, when to wake, and the narrowed
|
|
123
|
+
* rate-limit error that justified it (carried so callers need no cast).
|
|
124
|
+
*/
|
|
125
|
+
export interface AutoWaitDecision {
|
|
126
|
+
/** Ms to sleep. Always > 0. */
|
|
127
|
+
waitMs: number;
|
|
128
|
+
/** Epoch ms to wake at — `resetsAt` normalized to ms, plus the buffer. */
|
|
129
|
+
wakeAtMs: number;
|
|
130
|
+
/** The rate limit that triggered the wait. Never a `BillingError`. */
|
|
131
|
+
error: RateLimitError;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Decide whether to wait out an exhausted rate-limit window (#804 AC-3).
|
|
135
|
+
*
|
|
136
|
+
* Deliberately separate from {@link isWindowExhaustedRateLimit} and
|
|
137
|
+
* {@link RATE_LIMIT_WINDOW_SKIP_THRESHOLD_MS}, which answer *"is this transient
|
|
138
|
+
* or exhausted?"*. This answers a different question — *"am I willing to wait
|
|
139
|
+
* that long?"* — and fires ONLY once the former is already true. Keeping them
|
|
140
|
+
* apart is what leaves `autoWaitMinutes` the single user-facing dial for the
|
|
141
|
+
* wait-vs-halt outcome.
|
|
142
|
+
*
|
|
143
|
+
* Returns `null` (no wait — halt as before) when:
|
|
144
|
+
* - auto-wait is off, or the per-issue wait count is spent;
|
|
145
|
+
* - the failure is not a window-exhausted `RateLimitError`. A `BillingError`
|
|
146
|
+
* lands here: it is a sibling class, not a subclass, so the `instanceof`
|
|
147
|
+
* check inside `isWindowExhaustedRateLimit` excludes it. That is load-bearing
|
|
148
|
+
* — a `BillingError` may still carry `resetsAt` (an explicit
|
|
149
|
+
* `credits_required`, or a window that has already passed — see the #860
|
|
150
|
+
* narrowing in `isBillingFailure`), so gating on the timestamp's presence
|
|
151
|
+
* instead of the error type would wait out a credits failure that no amount
|
|
152
|
+
* of waiting can heal (AC-4). Since #860, a *live* recognized window
|
|
153
|
+
* (`five_hour`/`seven_day*` + future reset) classifies as `RateLimitError`
|
|
154
|
+
* upstream even when `out_of_credits` is present, which is what lets the
|
|
155
|
+
* real captured subscription payloads reach this decision at all;
|
|
156
|
+
* - the reset has already passed (nothing to wait for);
|
|
157
|
+
* - the required wait exceeds the budget REMAINING, not the total (AC-6).
|
|
158
|
+
*
|
|
159
|
+
* @internal Exported for testing only
|
|
160
|
+
*/
|
|
161
|
+
export declare function shouldAutoWaitForReset(error: SequantError | undefined, ledger: AutoWaitLedger, now?: number): AutoWaitDecision | null;
|
|
162
|
+
/**
|
|
163
|
+
* Sleep until an auto-wait's wake time, in ticks (#804 AC-7).
|
|
164
|
+
*
|
|
165
|
+
* Chunking the sleep is what makes a multi-hour pause survivable:
|
|
166
|
+
* - `onTick` refreshes the live display so the wait is visible rather than a
|
|
167
|
+
* silent stall (the #574 complaint at 60x scale);
|
|
168
|
+
* - each tick races the injected `delayFn` against the abort signal, so Ctrl-C
|
|
169
|
+
* returns immediately instead of blocking until the wake.
|
|
170
|
+
*
|
|
171
|
+
* Reuses the caller's `delayFn` so the wait stays fully test-injectable.
|
|
172
|
+
*
|
|
173
|
+
* Returns the ms actually slept and whether the wait was aborted.
|
|
174
|
+
*
|
|
175
|
+
* @internal Exported for testing only
|
|
176
|
+
*/
|
|
177
|
+
export declare function waitForWindowReset(waitMs: number, options: {
|
|
178
|
+
delayFn: (ms: number) => Promise<void>;
|
|
179
|
+
signal?: AbortSignal;
|
|
180
|
+
onTick?: (remainingMs: number) => void;
|
|
181
|
+
now?: () => number;
|
|
182
|
+
tickMs?: number;
|
|
183
|
+
}): Promise<{
|
|
184
|
+
sleptMs: number;
|
|
185
|
+
aborted: boolean;
|
|
186
|
+
}>;
|
|
187
|
+
/**
|
|
188
|
+
* Run one granted auto-wait end to end (#804): emit the live notices, sleep,
|
|
189
|
+
* update the ledger, and report whether Ctrl-C interrupted it.
|
|
190
|
+
*
|
|
191
|
+
* Shared by both arms of the retry ladder (the cold-start loop and the
|
|
192
|
+
* `skipColdStartRetry` single-attempt path) so the two cannot drift on
|
|
193
|
+
* bookkeeping or messaging.
|
|
194
|
+
*
|
|
195
|
+
* @internal Exported for testing only
|
|
196
|
+
*/
|
|
197
|
+
export declare function performAutoWait(issueNumber: number, phase: Phase, config: ExecutionConfig, decision: AutoWaitDecision, ledger: AutoWaitLedger, delayFn: (ms: number) => Promise<void>, shutdownManager?: ShutdownManager, spinner?: PhasePauseHandle): Promise<{
|
|
198
|
+
aborted: boolean;
|
|
199
|
+
}>;
|
|
38
200
|
export declare function parseQaVerdict(output: string): QaVerdict | null;
|
|
201
|
+
/**
|
|
202
|
+
* Distinguish a QA turn that produced *no verdict at all* from one whose output
|
|
203
|
+
* was present but unparseable (#853). Returns true when the output is empty /
|
|
204
|
+
* whitespace, or when its tail contains deferral language — the agent treating
|
|
205
|
+
* its one-shot phase as if a later turn were available.
|
|
206
|
+
*
|
|
207
|
+
* Both cases are hard failures either way; this only refines which message is
|
|
208
|
+
* emitted, so a false positive is harmless (it swaps one failing message for
|
|
209
|
+
* another). Kept deliberately conservative and literal to stay ReDoS-safe.
|
|
210
|
+
*
|
|
211
|
+
* @internal Exported for testing only.
|
|
212
|
+
*/
|
|
213
|
+
export declare function endedWithoutVerdict(output: string | undefined): boolean;
|
|
39
214
|
/**
|
|
40
215
|
* Parse condensed QA summary from QA phase output (#434).
|
|
41
216
|
*
|
|
@@ -77,22 +252,59 @@ export declare function formatDuration(seconds: number): string;
|
|
|
77
252
|
*/
|
|
78
253
|
export declare function resolveBaseRef(cwd: string): string;
|
|
79
254
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
255
|
+
* Three-way classification of what the exec phase left in the worktree (#879).
|
|
256
|
+
*
|
|
257
|
+
* - `commits`: HEAD has commits unique to it relative to the base ref — real,
|
|
258
|
+
* deliverable work that can rebase, push, and become a PR.
|
|
259
|
+
* - `uncommitted`: no such commits, but the tree is dirty. This is NOT a
|
|
260
|
+
* deliverable: uncommitted work cannot rebase, push, or become a PR (#879's
|
|
261
|
+
* defect — a dirty tree used to be counted as exec success, producing a run
|
|
262
|
+
* that "passed" with no commits and no PR). `paths` names the dirty files.
|
|
263
|
+
* - `none`: no commits and a clean tree — exec produced literally nothing
|
|
264
|
+
* (#534's original empty-branch class).
|
|
265
|
+
* - `unknown`: a git command failed. Callers fail OPEN on this (treat as work)
|
|
266
|
+
* — a transient git error is better diagnosed as a real run than as a
|
|
267
|
+
* spurious phase failure on every exec.
|
|
268
|
+
*/
|
|
269
|
+
export type ExecChangeState = {
|
|
270
|
+
kind: "commits";
|
|
271
|
+
} | {
|
|
272
|
+
kind: "uncommitted";
|
|
273
|
+
paths: string[];
|
|
274
|
+
} | {
|
|
275
|
+
kind: "none";
|
|
276
|
+
} | {
|
|
277
|
+
kind: "unknown";
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* Classify what the exec phase produced in the worktree (#879).
|
|
83
281
|
*
|
|
84
|
-
* Uses `git rev-list --count <base>..HEAD` (commits reachable from HEAD
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
282
|
+
* Uses `git rev-list --count <base>..HEAD` (commits reachable from HEAD but not
|
|
283
|
+
* the base) instead of `git diff <base>..HEAD`, because the two-dot diff also
|
|
284
|
+
* fires in reverse when the base has advanced past HEAD — on stale branches
|
|
285
|
+
* that would falsely report "has commits" even when exec produced nothing,
|
|
286
|
+
* reintroducing the bug #534 is fixing.
|
|
89
287
|
*
|
|
90
288
|
* The base ref defaults to `origin/main` but is overridden to the worktree's
|
|
91
|
-
* recorded base (see #537) so zero-diff execs are still detected on
|
|
92
|
-
*
|
|
289
|
+
* recorded base (see #537) so zero-diff execs are still detected on custom-base
|
|
290
|
+
* worktrees (e.g. those created with `--base feature/epic`).
|
|
291
|
+
*
|
|
292
|
+
* Read-only: runs only `git rev-list` and `git status --porcelain`, so it never
|
|
293
|
+
* mutates the worktree — an exec phase that fails on an `uncommitted` result
|
|
294
|
+
* leaves the dirty files exactly where the agent left them (#879 AC-3).
|
|
295
|
+
*
|
|
296
|
+
* @internal Exported for testing only.
|
|
297
|
+
*/
|
|
298
|
+
export declare function classifyExecChanges(cwd: string): ExecChangeState;
|
|
299
|
+
/**
|
|
300
|
+
* Check whether the exec phase produced deliverable work in the worktree.
|
|
93
301
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
302
|
+
* Thin boolean wrapper over {@link classifyExecChanges}: only `commits` (real
|
|
303
|
+
* work) and `unknown` (git error — fail open) count as "has changes". Note the
|
|
304
|
+
* #879 behaviour change: an `uncommitted`-only tree now returns **false**, since
|
|
305
|
+
* uncommitted work is not a deliverable. Both callers (the exec guard in
|
|
306
|
+
* {@link mapAgentSuccessToPhaseResult} and the ready gate) want this stricter
|
|
307
|
+
* semantics.
|
|
96
308
|
*
|
|
97
309
|
* @internal Exported for testing only.
|
|
98
310
|
*/
|
|
@@ -163,7 +375,16 @@ export declare function executePhaseWithRetry(issueNumber: number, phase: Phase,
|
|
|
163
375
|
/** @internal Injected for testing — defaults to module-level executePhase */
|
|
164
376
|
executePhaseFn?: typeof executePhase,
|
|
165
377
|
/** @internal Injected for testing — defaults to setTimeout-based delay */
|
|
166
|
-
delayFn?: (ms: number) => Promise<void
|
|
378
|
+
delayFn?: (ms: number) => Promise<void>,
|
|
379
|
+
/**
|
|
380
|
+
* Per-issue auto-wait accounting (#804). Deliberately the LAST parameter:
|
|
381
|
+
* the #761/#799 regression tests call this function positionally with
|
|
382
|
+
* `executePhaseFn` at 8 and `delayFn` at 9, and AC-2 requires those tests to
|
|
383
|
+
* pass unmodified. Defaults to a fresh disabled-or-config-derived ledger, so
|
|
384
|
+
* a caller that does not thread one still gets correct (bounded) behavior —
|
|
385
|
+
* just scoped to this phase rather than the issue.
|
|
386
|
+
*/
|
|
387
|
+
autoWaitLedger?: AutoWaitLedger): Promise<PhaseResult & {
|
|
167
388
|
sessionId?: string;
|
|
168
389
|
resumeHandle?: ResumeHandle;
|
|
169
390
|
}>;
|