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
|
@@ -2,28 +2,29 @@
|
|
|
2
2
|
* Chain resume planning (#760).
|
|
3
3
|
*
|
|
4
4
|
* When a `--chain` run fails mid-way, earlier links may already be complete
|
|
5
|
-
* (`
|
|
5
|
+
* (see `completed-status.ts`) with a checkpoint commit on their feature branch
|
|
6
6
|
* (`createCheckpointCommit`, worktree-manager.ts). Re-running the same chain
|
|
7
7
|
* should skip that completed prefix and resume at the first incomplete link,
|
|
8
8
|
* rebased onto the last completed link's committed tip — NOT `main` (which is
|
|
9
9
|
* the #748 wrong-base failure this reuses the #748 rebase path to avoid).
|
|
10
10
|
*
|
|
11
|
-
* The
|
|
12
|
-
*
|
|
13
|
-
* dropping the completed prefix leaves the first incomplete
|
|
14
|
-
* where `executeSequential`'s successor-rebase never fires, so
|
|
15
|
-
* builds on `main`. This module computes a *chain-correct* resume
|
|
16
|
-
* preserves the completed prefix as the resume base.
|
|
11
|
+
* The non-chain pre-flight guard (`run-orchestrator.ts`) drops completed issues
|
|
12
|
+
* from the run using the same {@link isCompletedIssueStatus} predicate, but it
|
|
13
|
+
* is chain-unaware: dropping the completed prefix leaves the first incomplete
|
|
14
|
+
* link at index 0, where `executeSequential`'s successor-rebase never fires, so
|
|
15
|
+
* it silently builds on `main`. This module computes a *chain-correct* resume
|
|
16
|
+
* plan that preserves the completed prefix as the resume base.
|
|
17
17
|
*
|
|
18
18
|
* The planner is pure over an injected {@link CompletedLinkResolver} so the
|
|
19
19
|
* skip/fail-fast state machine (AC-3) is unit-testable without real git; the
|
|
20
20
|
* real-git rebase is covered by the integration test.
|
|
21
21
|
*/
|
|
22
|
+
import { type CompletedIssueStatus } from "./completed-status.js";
|
|
22
23
|
/** A completed link that will be skipped (not re-executed) on resume. */
|
|
23
24
|
export interface ChainResumeSkip {
|
|
24
25
|
issueNumber: number;
|
|
25
26
|
/** Why it was skipped — the terminal-ish status that made it complete. */
|
|
26
|
-
status:
|
|
27
|
+
status: CompletedIssueStatus;
|
|
27
28
|
/** The link's local feature branch (from state), if known. */
|
|
28
29
|
branch?: string;
|
|
29
30
|
/** The link's worktree path (from state), if known — used for the dirty check. */
|
|
@@ -45,9 +46,10 @@ export interface ChainResumePlan {
|
|
|
45
46
|
/** First incomplete issue number (the resume point), if any. */
|
|
46
47
|
resumeIssue?: number;
|
|
47
48
|
/**
|
|
48
|
-
* Set when resume cannot proceed safely (AC-3):
|
|
49
|
-
* branch/checkpoint is gone
|
|
50
|
-
*
|
|
49
|
+
* Set when resume cannot proceed safely (AC-3): an unmerged completed link's
|
|
50
|
+
* (`ready_for_merge` or `waiting_for_human_merge`) branch/checkpoint is gone
|
|
51
|
+
* and its tip is unreconstructable. The caller must abort rather than
|
|
52
|
+
* silently execute the successor on the wrong base.
|
|
51
53
|
*/
|
|
52
54
|
failFast?: string;
|
|
53
55
|
/** True when every link in the chain is already complete. */
|
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
* Chain resume planning (#760).
|
|
3
3
|
*
|
|
4
4
|
* When a `--chain` run fails mid-way, earlier links may already be complete
|
|
5
|
-
* (`
|
|
5
|
+
* (see `completed-status.ts`) with a checkpoint commit on their feature branch
|
|
6
6
|
* (`createCheckpointCommit`, worktree-manager.ts). Re-running the same chain
|
|
7
7
|
* should skip that completed prefix and resume at the first incomplete link,
|
|
8
8
|
* rebased onto the last completed link's committed tip — NOT `main` (which is
|
|
9
9
|
* the #748 wrong-base failure this reuses the #748 rebase path to avoid).
|
|
10
10
|
*
|
|
11
|
-
* The
|
|
12
|
-
*
|
|
13
|
-
* dropping the completed prefix leaves the first incomplete
|
|
14
|
-
* where `executeSequential`'s successor-rebase never fires, so
|
|
15
|
-
* builds on `main`. This module computes a *chain-correct* resume
|
|
16
|
-
* preserves the completed prefix as the resume base.
|
|
11
|
+
* The non-chain pre-flight guard (`run-orchestrator.ts`) drops completed issues
|
|
12
|
+
* from the run using the same {@link isCompletedIssueStatus} predicate, but it
|
|
13
|
+
* is chain-unaware: dropping the completed prefix leaves the first incomplete
|
|
14
|
+
* link at index 0, where `executeSequential`'s successor-rebase never fires, so
|
|
15
|
+
* it silently builds on `main`. This module computes a *chain-correct* resume
|
|
16
|
+
* plan that preserves the completed prefix as the resume base.
|
|
17
17
|
*
|
|
18
18
|
* The planner is pure over an injected {@link CompletedLinkResolver} so the
|
|
19
19
|
* skip/fail-fast state machine (AC-3) is unit-testable without real git; the
|
|
20
20
|
* real-git rebase is covered by the integration test.
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
import { isCompletedIssueStatus, } from "./completed-status.js";
|
|
23
23
|
/**
|
|
24
24
|
* Compute a chain-correct resume plan.
|
|
25
25
|
*
|
|
@@ -37,7 +37,7 @@ export function computeChainResumePlan(orderedLinks, baseBranch, resolver) {
|
|
|
37
37
|
const skipped = [];
|
|
38
38
|
let firstIncomplete = 0;
|
|
39
39
|
for (const link of orderedLinks) {
|
|
40
|
-
if (
|
|
40
|
+
if (isCompletedIssueStatus(link.status)) {
|
|
41
41
|
skipped.push({
|
|
42
42
|
issueNumber: link.issueNumber,
|
|
43
43
|
status: link.status,
|
|
@@ -72,17 +72,18 @@ export function computeChainResumePlan(orderedLinks, baseBranch, resolver) {
|
|
|
72
72
|
resumeBaseCommit = resolver.resolveBaseTip();
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
|
-
// ready_for_merge: the checkpoint tip lives only
|
|
76
|
-
// branch. If that branch is gone (worktree/branch
|
|
77
|
-
// tip is unreconstructable — fail fast instead of
|
|
78
|
-
// successor onto main (which would miss the completed
|
|
75
|
+
// ready_for_merge / waiting_for_human_merge: the checkpoint tip lives only
|
|
76
|
+
// on the local feature branch. If that branch is gone (worktree/branch
|
|
77
|
+
// destroyed mid-way), the tip is unreconstructable — fail fast instead of
|
|
78
|
+
// wrong-basing the successor onto main (which would miss the completed
|
|
79
|
+
// link's work).
|
|
79
80
|
if (!last.branch) {
|
|
80
81
|
return {
|
|
81
82
|
skipped,
|
|
82
83
|
active,
|
|
83
84
|
resumeIssue: active[0],
|
|
84
85
|
allComplete: false,
|
|
85
|
-
failFast: `#${last.issueNumber} is
|
|
86
|
+
failFast: `#${last.issueNumber} is ${last.status} but no branch is recorded in state — ` +
|
|
86
87
|
`cannot reconstruct the resume base. Re-run with --force to redo the chain from scratch.`,
|
|
87
88
|
};
|
|
88
89
|
}
|
|
@@ -93,24 +94,27 @@ export function computeChainResumePlan(orderedLinks, baseBranch, resolver) {
|
|
|
93
94
|
active,
|
|
94
95
|
resumeIssue: active[0],
|
|
95
96
|
allComplete: false,
|
|
96
|
-
failFast: `#${last.issueNumber} is
|
|
97
|
+
failFast: `#${last.issueNumber} is ${last.status} but its branch "${last.branch}" no longer exists — ` +
|
|
97
98
|
`the resume base is unreconstructable. Re-run with --force to redo the chain from scratch.`,
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
101
|
// The branch exists, but a tip is only a valid resume base if it actually
|
|
101
102
|
// contains the link's work. `createCheckpointCommit` sweeps trailing
|
|
102
103
|
// uncommitted changes into a checkpoint commit; when it fails (commit hook,
|
|
103
|
-
// staging error, or unrelated dirty files)
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
104
|
+
// staging error, or unrelated dirty files) a completed status was *already*
|
|
105
|
+
// written — `ready_for_merge` on a plain run, or `waiting_for_human_merge`
|
|
106
|
+
// when #817's `--ready-gate` owned the terminal status (#837) — so this link
|
|
107
|
+
// still reads as a completed prefix while its tip is missing work. Both
|
|
108
|
+
// statuses reach this branch, so the check covers gated links too. Rebasing
|
|
109
|
+
// the successor onto such a tip would be exactly the silent wrong-base
|
|
110
|
+
// execution AC-3 forbids — fail fast instead.
|
|
107
111
|
if (last.worktree && resolver.isWorktreeDirty(last.worktree)) {
|
|
108
112
|
return {
|
|
109
113
|
skipped,
|
|
110
114
|
active,
|
|
111
115
|
resumeIssue: active[0],
|
|
112
116
|
allComplete: false,
|
|
113
|
-
failFast: `#${last.issueNumber} is
|
|
117
|
+
failFast: `#${last.issueNumber} is ${last.status} but its worktree has uncommitted changes — ` +
|
|
114
118
|
`its checkpoint commit never landed, so branch "${last.branch}" is missing that work and ` +
|
|
115
119
|
`resuming #${active[0]} here would build on an incomplete base. Commit them in ${last.worktree}, ` +
|
|
116
120
|
`or re-run with --force to redo the chain from scratch.`,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which persisted issue statuses mean "this issue is already done" (#837).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for every pre-flight guard that skips finished work.
|
|
5
|
+
* It exists because the same predicate was previously spelled out inline at two
|
|
6
|
+
* sites with two different lists, and #817's `--ready-gate` extended the status
|
|
7
|
+
* vocabulary without either site following:
|
|
8
|
+
*
|
|
9
|
+
* - `chain-resume.ts` peels the completed prefix off a `--chain` run.
|
|
10
|
+
* - `run-orchestrator.ts` drops finished issues from a non-chain run.
|
|
11
|
+
*
|
|
12
|
+
* A gated issue deliberately terminates in `waiting_for_human_merge` (policy
|
|
13
|
+
* threshold reached) rather than `ready_for_merge`, since `ready_for_merge`
|
|
14
|
+
* would read as auto-merge-ready and defeat the human merge gate the feature
|
|
15
|
+
* exists to preserve. Both guards missed it, so re-running re-executed
|
|
16
|
+
* already-gated issues from phase 0 — a full spec/exec/qa pipeline plus another
|
|
17
|
+
* full-weight ready gate.
|
|
18
|
+
*
|
|
19
|
+
* `blocked` is deliberately NOT a completed status, for two reasons:
|
|
20
|
+
*
|
|
21
|
+
* 1. It is a *generic* member of `IssueStatusSchema` ("waiting on external input
|
|
22
|
+
* or dependency"), not a ready-gate-exclusive terminal. Admitting it here
|
|
23
|
+
* would silently apply to every other writer of that status, present and
|
|
24
|
+
* future.
|
|
25
|
+
* 2. A guard halt IS the human-attention signal. Skipping it as complete would
|
|
26
|
+
* report the issue as passed when it demonstrably did not.
|
|
27
|
+
*
|
|
28
|
+
* So a `blocked` issue is re-executed rather than skipped — the same
|
|
29
|
+
* conservative rule already applied to issues whose state lookup fails.
|
|
30
|
+
* Re-running wastes tokens; silently dropping an issue the user must look at is
|
|
31
|
+
* the worse failure. Once the user clears the blocker, the re-run is what lets
|
|
32
|
+
* work resume.
|
|
33
|
+
*
|
|
34
|
+
* NOTE: this is "done, do not re-run", which is NOT the same set as "might have
|
|
35
|
+
* a merged PR" — `state-cleanup.ts`'s merge-detection sweep deliberately keeps
|
|
36
|
+
* its own wider list (it also scans `in_progress`, #592, and
|
|
37
|
+
* `waiting_for_qa_gate`, #606). Do not unify the two.
|
|
38
|
+
*
|
|
39
|
+
* When adding a status to `IssueStatusSchema`, decide here whether it belongs.
|
|
40
|
+
*/
|
|
41
|
+
export declare const COMPLETED_ISSUE_STATUSES: readonly ["ready_for_merge", "merged", "waiting_for_human_merge"];
|
|
42
|
+
/** A persisted status that counts as completed work. */
|
|
43
|
+
export type CompletedIssueStatus = (typeof COMPLETED_ISSUE_STATUSES)[number];
|
|
44
|
+
/**
|
|
45
|
+
* True iff `status` marks the issue as already finished, so a re-run should
|
|
46
|
+
* skip it unless `--force` is passed.
|
|
47
|
+
*
|
|
48
|
+
* Accepts `string | undefined` because persisted state may predate the current
|
|
49
|
+
* schema or be absent entirely; an unknown or missing status is treated as
|
|
50
|
+
* incomplete (re-execute), never as complete.
|
|
51
|
+
*/
|
|
52
|
+
export declare function isCompletedIssueStatus(status: string | undefined): status is CompletedIssueStatus;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which persisted issue statuses mean "this issue is already done" (#837).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for every pre-flight guard that skips finished work.
|
|
5
|
+
* It exists because the same predicate was previously spelled out inline at two
|
|
6
|
+
* sites with two different lists, and #817's `--ready-gate` extended the status
|
|
7
|
+
* vocabulary without either site following:
|
|
8
|
+
*
|
|
9
|
+
* - `chain-resume.ts` peels the completed prefix off a `--chain` run.
|
|
10
|
+
* - `run-orchestrator.ts` drops finished issues from a non-chain run.
|
|
11
|
+
*
|
|
12
|
+
* A gated issue deliberately terminates in `waiting_for_human_merge` (policy
|
|
13
|
+
* threshold reached) rather than `ready_for_merge`, since `ready_for_merge`
|
|
14
|
+
* would read as auto-merge-ready and defeat the human merge gate the feature
|
|
15
|
+
* exists to preserve. Both guards missed it, so re-running re-executed
|
|
16
|
+
* already-gated issues from phase 0 — a full spec/exec/qa pipeline plus another
|
|
17
|
+
* full-weight ready gate.
|
|
18
|
+
*
|
|
19
|
+
* `blocked` is deliberately NOT a completed status, for two reasons:
|
|
20
|
+
*
|
|
21
|
+
* 1. It is a *generic* member of `IssueStatusSchema` ("waiting on external input
|
|
22
|
+
* or dependency"), not a ready-gate-exclusive terminal. Admitting it here
|
|
23
|
+
* would silently apply to every other writer of that status, present and
|
|
24
|
+
* future.
|
|
25
|
+
* 2. A guard halt IS the human-attention signal. Skipping it as complete would
|
|
26
|
+
* report the issue as passed when it demonstrably did not.
|
|
27
|
+
*
|
|
28
|
+
* So a `blocked` issue is re-executed rather than skipped — the same
|
|
29
|
+
* conservative rule already applied to issues whose state lookup fails.
|
|
30
|
+
* Re-running wastes tokens; silently dropping an issue the user must look at is
|
|
31
|
+
* the worse failure. Once the user clears the blocker, the re-run is what lets
|
|
32
|
+
* work resume.
|
|
33
|
+
*
|
|
34
|
+
* NOTE: this is "done, do not re-run", which is NOT the same set as "might have
|
|
35
|
+
* a merged PR" — `state-cleanup.ts`'s merge-detection sweep deliberately keeps
|
|
36
|
+
* its own wider list (it also scans `in_progress`, #592, and
|
|
37
|
+
* `waiting_for_qa_gate`, #606). Do not unify the two.
|
|
38
|
+
*
|
|
39
|
+
* When adding a status to `IssueStatusSchema`, decide here whether it belongs.
|
|
40
|
+
*/
|
|
41
|
+
export const COMPLETED_ISSUE_STATUSES = [
|
|
42
|
+
"ready_for_merge",
|
|
43
|
+
"merged",
|
|
44
|
+
"waiting_for_human_merge",
|
|
45
|
+
];
|
|
46
|
+
const COMPLETED_ISSUE_STATUS_SET = new Set(COMPLETED_ISSUE_STATUSES);
|
|
47
|
+
/**
|
|
48
|
+
* True iff `status` marks the issue as already finished, so a re-run should
|
|
49
|
+
* skip it unless `--force` is passed.
|
|
50
|
+
*
|
|
51
|
+
* Accepts `string | undefined` because persisted state may predate the current
|
|
52
|
+
* schema or be absent entirely; an unknown or missing status is treated as
|
|
53
|
+
* incomplete (re-execute), never as complete.
|
|
54
|
+
*/
|
|
55
|
+
export function isCompletedIssueStatus(status) {
|
|
56
|
+
return status !== undefined && COMPLETED_ISSUE_STATUS_SET.has(status);
|
|
57
|
+
}
|
|
@@ -42,6 +42,32 @@ export declare function normalizeCommanderOptions(options: RunOptions): RunOptio
|
|
|
42
42
|
* This replaces the inline merging logic previously in run.ts.
|
|
43
43
|
*/
|
|
44
44
|
export declare function resolveRunOptions(cliOptions: RunOptions, settings: SequantSettings): RunOptions;
|
|
45
|
+
/**
|
|
46
|
+
* Fall back to `fallback` unless `value` is a usable positive number.
|
|
47
|
+
*
|
|
48
|
+
* `??` alone is not enough for these (#833). `NaN` is not nullish, so a
|
|
49
|
+
* malformed value survives `?? default` and flows on into `setTimeout`, which
|
|
50
|
+
* clamps a `NaN` delay to 0 and aborts the phase on its first tick, or into
|
|
51
|
+
* `while (iteration < maxIterations)`, which is false on entry and runs zero
|
|
52
|
+
* phases. Both read as a phase/agent fault rather than a bad input, which is
|
|
53
|
+
* what makes the silent version expensive. Non-finite and non-positive values
|
|
54
|
+
* therefore fall back *to* the default instead of through it.
|
|
55
|
+
*
|
|
56
|
+
* `bin/cli.ts` rejects these at the flag boundary with a message naming the
|
|
57
|
+
* flag — that is the user-facing fix. This is the structural backstop for
|
|
58
|
+
* programmatic callers, `settings.json`, and whatever calls this next.
|
|
59
|
+
*
|
|
60
|
+
* Exported because `phaseTimeout` has two producers, not one: this module and
|
|
61
|
+
* `commands/ready.ts`, whose value reaches the driver through
|
|
62
|
+
* `ready-gate.ts`'s own `buildPhaseConfig` and never passes through
|
|
63
|
+
* `buildExecutionConfig`. Guarding only here would have left that path open.
|
|
64
|
+
* Chain it to express the layering — CLI, then settings, then the default:
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* positiveOr(options.timeout, positiveOr(settings.run.timeout, DEFAULT))
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function positiveOr(value: number | undefined, fallback: number): number;
|
|
45
71
|
/**
|
|
46
72
|
* Build an ExecutionConfig from merged RunOptions and settings.
|
|
47
73
|
* Extracts the phase-timeout, MCP, retry, and mode resolution logic
|
|
@@ -97,6 +97,10 @@ export function normalizeCommanderOptions(options) {
|
|
|
97
97
|
...(raw.retry === false && { noRetry: true }),
|
|
98
98
|
...(raw.rebase === false && { noRebase: true }),
|
|
99
99
|
...(raw.pr === false && { noPr: true }),
|
|
100
|
+
// #804: map the flag-derived key onto the interface field. Guarded on
|
|
101
|
+
// `undefined` (not truthiness) so an explicit `--auto-wait 0` still
|
|
102
|
+
// overrides a non-zero setting.
|
|
103
|
+
...(raw.autoWait !== undefined && { autoWaitMinutes: raw.autoWait }),
|
|
100
104
|
};
|
|
101
105
|
}
|
|
102
106
|
/**
|
|
@@ -117,6 +121,7 @@ export function resolveRunOptions(cliOptions, settings) {
|
|
|
117
121
|
qualityLoop: defined.qualityLoop ?? settings.run.qualityLoop,
|
|
118
122
|
maxIterations: defined.maxIterations ?? settings.run.maxIterations,
|
|
119
123
|
noSmartTests: defined.noSmartTests ?? !settings.run.smartTests,
|
|
124
|
+
autoWaitMinutes: defined.autoWaitMinutes ?? settings.run.autoWaitMinutes,
|
|
120
125
|
// Agent settings
|
|
121
126
|
isolateParallel: defined.isolateParallel ?? settings.agents.isolateParallel,
|
|
122
127
|
// Env overrides
|
|
@@ -129,6 +134,36 @@ export function resolveRunOptions(cliOptions, settings) {
|
|
|
129
134
|
merged.autoDetectPhases = autoDetectPhases;
|
|
130
135
|
return merged;
|
|
131
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Fall back to `fallback` unless `value` is a usable positive number.
|
|
139
|
+
*
|
|
140
|
+
* `??` alone is not enough for these (#833). `NaN` is not nullish, so a
|
|
141
|
+
* malformed value survives `?? default` and flows on into `setTimeout`, which
|
|
142
|
+
* clamps a `NaN` delay to 0 and aborts the phase on its first tick, or into
|
|
143
|
+
* `while (iteration < maxIterations)`, which is false on entry and runs zero
|
|
144
|
+
* phases. Both read as a phase/agent fault rather than a bad input, which is
|
|
145
|
+
* what makes the silent version expensive. Non-finite and non-positive values
|
|
146
|
+
* therefore fall back *to* the default instead of through it.
|
|
147
|
+
*
|
|
148
|
+
* `bin/cli.ts` rejects these at the flag boundary with a message naming the
|
|
149
|
+
* flag — that is the user-facing fix. This is the structural backstop for
|
|
150
|
+
* programmatic callers, `settings.json`, and whatever calls this next.
|
|
151
|
+
*
|
|
152
|
+
* Exported because `phaseTimeout` has two producers, not one: this module and
|
|
153
|
+
* `commands/ready.ts`, whose value reaches the driver through
|
|
154
|
+
* `ready-gate.ts`'s own `buildPhaseConfig` and never passes through
|
|
155
|
+
* `buildExecutionConfig`. Guarding only here would have left that path open.
|
|
156
|
+
* Chain it to express the layering — CLI, then settings, then the default:
|
|
157
|
+
*
|
|
158
|
+
* ```ts
|
|
159
|
+
* positiveOr(options.timeout, positiveOr(settings.run.timeout, DEFAULT))
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export function positiveOr(value, fallback) {
|
|
163
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0
|
|
164
|
+
? value
|
|
165
|
+
: fallback;
|
|
166
|
+
}
|
|
132
167
|
/**
|
|
133
168
|
* Build an ExecutionConfig from merged RunOptions and settings.
|
|
134
169
|
* Extracts the phase-timeout, MCP, retry, and mode resolution logic
|
|
@@ -157,15 +192,32 @@ export function buildExecutionConfig(mergedOptions, settings, issueCount) {
|
|
|
157
192
|
parallel: isParallel,
|
|
158
193
|
dryRun: mergedOptions.dryRun ?? false,
|
|
159
194
|
verbose: mergedOptions.verbose ?? false,
|
|
160
|
-
|
|
195
|
+
// #833: chained so the layering is CLI → settings → default, matching
|
|
196
|
+
// `commands/ready.ts`. A malformed CLI value falls back to the user's
|
|
197
|
+
// configured setting rather than skipping past it to the hardcoded
|
|
198
|
+
// default; a malformed setting falls back to the default. In the normal
|
|
199
|
+
// path `mergedOptions` already carries the settings value, so this only
|
|
200
|
+
// differs when one of the two layers is unusable — which is the case that
|
|
201
|
+
// matters.
|
|
202
|
+
phaseTimeout: positiveOr(mergedOptions.timeout, positiveOr(settings.run.timeout, DEFAULT_CONFIG.phaseTimeout)),
|
|
161
203
|
qualityLoop: mergedOptions.qualityLoop ?? false,
|
|
162
|
-
maxIterations: mergedOptions.maxIterations
|
|
204
|
+
maxIterations: positiveOr(mergedOptions.maxIterations, positiveOr(settings.run.maxIterations, DEFAULT_CONFIG.maxIterations)),
|
|
163
205
|
noSmartTests: mergedOptions.noSmartTests ?? false,
|
|
164
206
|
mcp: mcpEnabled,
|
|
165
207
|
retry: retryEnabled,
|
|
208
|
+
// #804: default 0 (off) — the whole regression contract for auto-wait is
|
|
209
|
+
// that an unset flag leaves the #761/#799 halt path untouched.
|
|
210
|
+
autoWaitMinutes: mergedOptions.autoWaitMinutes ??
|
|
211
|
+
settings.run.autoWaitMinutes ??
|
|
212
|
+
DEFAULT_CONFIG.autoWaitMinutes,
|
|
166
213
|
agent: mergedOptions.agent ?? settings.run.agent,
|
|
167
214
|
aiderSettings: settings.run.aider,
|
|
168
215
|
isolateParallel: mergedOptions.isolateParallel,
|
|
169
216
|
relayEnabled,
|
|
217
|
+
// #817: opt-in only, no settings backing (AC-4). A missing `--ready-gate`
|
|
218
|
+
// resolves to false, keeping the run path byte-identical (AC-5). This is the
|
|
219
|
+
// load-bearing wire the #795 inert-flag class guards against — the flag is
|
|
220
|
+
// useless if it stops reaching the executor here.
|
|
221
|
+
readyGate: mergedOptions.readyGate ?? false,
|
|
170
222
|
};
|
|
171
223
|
}
|
|
@@ -98,6 +98,13 @@ export interface AgentPhaseResult {
|
|
|
98
98
|
export interface AgentDriver {
|
|
99
99
|
/** Human-readable name for logging */
|
|
100
100
|
name: string;
|
|
101
|
+
/**
|
|
102
|
+
* True when this driver executes phases by resolving slash-command skills
|
|
103
|
+
* from the project's `.claude/skills/` directory (claude-code). Drivers
|
|
104
|
+
* whose prompts do the work inline (aider's `driverOverrides` templates)
|
|
105
|
+
* return false, and the `run` skills pre-flight (#813) is skipped for them.
|
|
106
|
+
*/
|
|
107
|
+
resolvesSkills: boolean;
|
|
101
108
|
/** Execute a phase prompt and return structured result */
|
|
102
109
|
executePhase(prompt: string, config: AgentExecutionConfig): Promise<AgentPhaseResult>;
|
|
103
110
|
/** Check if this driver is available/configured */
|
|
@@ -9,6 +9,8 @@ import type { AgentDriver, AgentExecutionConfig, AgentPhaseResult, ResumeHandle
|
|
|
9
9
|
import type { AiderSettings } from "../../settings.js";
|
|
10
10
|
export declare class AiderDriver implements AgentDriver {
|
|
11
11
|
name: string;
|
|
12
|
+
/** Aider phases use inline `driverOverrides` prompts — no skills (#813). */
|
|
13
|
+
resolvesSkills: boolean;
|
|
12
14
|
private settings?;
|
|
13
15
|
constructor(settings?: AiderSettings);
|
|
14
16
|
/**
|
|
@@ -10,6 +10,8 @@ import { execSync } from "child_process";
|
|
|
10
10
|
import { RingBuffer } from "../ring-buffer.js";
|
|
11
11
|
export class AiderDriver {
|
|
12
12
|
name = "aider";
|
|
13
|
+
/** Aider phases use inline `driverOverrides` prompts — no skills (#813). */
|
|
14
|
+
resolvesSkills = false;
|
|
13
15
|
settings;
|
|
14
16
|
constructor(settings) {
|
|
15
17
|
this.settings = settings;
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import type { AgentDriver, AgentExecutionConfig, AgentPhaseResult, ResumeHandle } from "./agent-driver.js";
|
|
8
8
|
export declare class ClaudeCodeDriver implements AgentDriver {
|
|
9
9
|
name: string;
|
|
10
|
+
/** Phases run slash-command skills from `.claude/skills/` (#813). */
|
|
11
|
+
resolvesSkills: boolean;
|
|
10
12
|
/**
|
|
11
13
|
* Track session ID across calls so callers can implement resume.
|
|
12
14
|
* Set after each executePhase() call.
|
|
@@ -42,6 +44,18 @@ export declare class ClaudeCodeDriver implements AgentDriver {
|
|
|
42
44
|
* RateLimitError would wrongly re-enable the retry / MCP-fallback path. When
|
|
43
45
|
* the `rate_limit_event` is itself a billing failure its richer metadata
|
|
44
46
|
* (`canUserPurchaseCredits`, etc.) is preserved.
|
|
47
|
+
*
|
|
48
|
+
* Counter-exception (#860): when the `rate_limit_event` carries the FULL
|
|
49
|
+
* captured subscription-window shape — waitable window evidence (recognized
|
|
50
|
+
* window type + future `resetsAt`) *plus* the `out_of_credits` marker — the
|
|
51
|
+
* richer structured signal wins over the bare `billing_error` enum. A
|
|
52
|
+
* subscription plan's five-hour exhaustion surfaces assistant-side as a
|
|
53
|
+
* billing error, and overriding on that enum here would strip the metadata
|
|
54
|
+
* `--auto-wait` needs and re-inert the feature this classification exists
|
|
55
|
+
* to enable. Deliberately no wider than the evidenced shape: a pure
|
|
56
|
+
* throttle event (window, no billing markers) beside a `billing_error`
|
|
57
|
+
* enum keeps the #732 rule — billing wins — because there the two signals
|
|
58
|
+
* genuinely conflict and no capture justifies trusting the throttle.
|
|
45
59
|
*/
|
|
46
60
|
private buildStructuredError;
|
|
47
61
|
/**
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
8
8
|
import { getMcpServersConfig } from "../../system.js";
|
|
9
|
-
import { RateLimitError, BillingError, createRateLimitError, isRateLimitFailureInfo, } from "../../errors.js";
|
|
9
|
+
import { RateLimitError, BillingError, createRateLimitError, isWaitableWindow, isRateLimitFailureInfo, } from "../../errors.js";
|
|
10
10
|
import { RingBuffer } from "../ring-buffer.js";
|
|
11
11
|
export class ClaudeCodeDriver {
|
|
12
12
|
name = "claude-code";
|
|
13
|
+
/** Phases run slash-command skills from `.claude/skills/` (#813). */
|
|
14
|
+
resolvesSkills = true;
|
|
13
15
|
/**
|
|
14
16
|
* Track session ID across calls so callers can implement resume.
|
|
15
17
|
* Set after each executePhase() call.
|
|
@@ -282,11 +284,27 @@ export class ClaudeCodeDriver {
|
|
|
282
284
|
* RateLimitError would wrongly re-enable the retry / MCP-fallback path. When
|
|
283
285
|
* the `rate_limit_event` is itself a billing failure its richer metadata
|
|
284
286
|
* (`canUserPurchaseCredits`, etc.) is preserved.
|
|
287
|
+
*
|
|
288
|
+
* Counter-exception (#860): when the `rate_limit_event` carries the FULL
|
|
289
|
+
* captured subscription-window shape — waitable window evidence (recognized
|
|
290
|
+
* window type + future `resetsAt`) *plus* the `out_of_credits` marker — the
|
|
291
|
+
* richer structured signal wins over the bare `billing_error` enum. A
|
|
292
|
+
* subscription plan's five-hour exhaustion surfaces assistant-side as a
|
|
293
|
+
* billing error, and overriding on that enum here would strip the metadata
|
|
294
|
+
* `--auto-wait` needs and re-inert the feature this classification exists
|
|
295
|
+
* to enable. Deliberately no wider than the evidenced shape: a pure
|
|
296
|
+
* throttle event (window, no billing markers) beside a `billing_error`
|
|
297
|
+
* enum keeps the #732 rule — billing wins — because there the two signals
|
|
298
|
+
* genuinely conflict and no capture justifies trusting the throttle.
|
|
285
299
|
*/
|
|
286
300
|
buildStructuredError(rateLimitInfo, assistantError, apiRetryError) {
|
|
287
301
|
if (rateLimitInfo) {
|
|
288
302
|
const err = createRateLimitError(rateLimitInfo);
|
|
289
|
-
|
|
303
|
+
const isCapturedSubscriptionShape = isWaitableWindow(rateLimitInfo) &&
|
|
304
|
+
rateLimitInfo.overageDisabledReason === "out_of_credits";
|
|
305
|
+
if (err instanceof RateLimitError &&
|
|
306
|
+
assistantError === "billing_error" &&
|
|
307
|
+
!isCapturedSubscriptionShape) {
|
|
290
308
|
return new BillingError("Billing error");
|
|
291
309
|
}
|
|
292
310
|
return err;
|
|
@@ -18,18 +18,50 @@ export interface GitDiffStatsResult {
|
|
|
18
18
|
/** Total lines deleted across all files */
|
|
19
19
|
totalDeletions: number;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the ref diff stats should compare against (#878).
|
|
23
|
+
*
|
|
24
|
+
* Worktrees are created from `origin/<base>` (worktree-manager), but callers
|
|
25
|
+
* historically passed the bare branch name and the diff ran against the
|
|
26
|
+
* *local* ref. When local `<base>` lags the remote — routine, since nothing
|
|
27
|
+
* in the run path updates it — `<base>...HEAD` attributes commits the run
|
|
28
|
+
* never made (phantom filesModified).
|
|
29
|
+
*
|
|
30
|
+
* Candidates are the origin-qualified and bare forms of `baseBranch`
|
|
31
|
+
* (already-remote-qualified input keeps a single candidate). Among the
|
|
32
|
+
* candidates that resolve to a commit, pick the one nearest to HEAD
|
|
33
|
+
* (smallest `rev-list --count <cand>..HEAD`), preferring the
|
|
34
|
+
* origin-qualified form on a tie. Nearest-wins matches the worktree's
|
|
35
|
+
* actual creation point in both staleness directions: a stale local
|
|
36
|
+
* default branch (this issue) and a chain-mode worktree branched from a
|
|
37
|
+
* local base that is ahead of its pushed counterpart. Falls back to
|
|
38
|
+
* `baseBranch` verbatim when no candidate resolves (e.g. remote-less repo
|
|
39
|
+
* with a missing branch) — the diff then fails gracefully to empty, the
|
|
40
|
+
* pre-#878 behavior.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveDiffBase(worktreePath: string, baseBranch: string): string;
|
|
21
43
|
/**
|
|
22
44
|
* Get git commit SHA for a worktree (AC-2)
|
|
23
45
|
*
|
|
46
|
+
* When `baseRef` is provided, returns undefined if HEAD has no commits
|
|
47
|
+
* unique to it (#878) — a branch that never moved off its base would
|
|
48
|
+
* otherwise log the base tip as if it were the phase's commit. Callers
|
|
49
|
+
* recording plain "where is HEAD" markers (run start/end) omit `baseRef`.
|
|
50
|
+
*
|
|
24
51
|
* @param worktreePath - Path to the git worktree
|
|
25
|
-
* @
|
|
52
|
+
* @param baseRef - Optional resolved base ref (see resolveDiffBase); when
|
|
53
|
+
* given, a HEAD with zero commits past it yields undefined
|
|
54
|
+
* @returns The current HEAD commit SHA, or undefined on error / no unique
|
|
55
|
+
* commits
|
|
26
56
|
*/
|
|
27
|
-
export declare function getCommitHash(worktreePath: string): string | undefined;
|
|
57
|
+
export declare function getCommitHash(worktreePath: string, baseRef?: string): string | undefined;
|
|
28
58
|
/**
|
|
29
59
|
* Get git diff statistics for a worktree (AC-1, AC-3, AC-4)
|
|
30
60
|
*
|
|
31
61
|
* Efficiently captures both filesModified and fileDiffStats using
|
|
32
|
-
* minimal git commands.
|
|
62
|
+
* minimal git commands. The base is resolved via resolveDiffBase (#878) so
|
|
63
|
+
* the comparison targets the ref the worktree was actually created from
|
|
64
|
+
* (origin/<base> in the common case) rather than a possibly-stale local ref.
|
|
33
65
|
*
|
|
34
66
|
* @param worktreePath - Path to the git worktree
|
|
35
67
|
* @param baseBranch - Branch to compare against (default: "main")
|