sequant 1.16.1 → 1.18.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.
Files changed (83) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +14 -2
  3. package/README.md +2 -0
  4. package/dist/bin/cli.js +2 -1
  5. package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +21 -0
  6. package/dist/marketplace/external_plugins/sequant/README.md +38 -0
  7. package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +292 -0
  8. package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +463 -0
  9. package/dist/marketplace/external_plugins/sequant/skills/_shared/references/prompt-templates.md +350 -0
  10. package/dist/marketplace/external_plugins/sequant/skills/_shared/references/subagent-types.md +131 -0
  11. package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +474 -0
  12. package/dist/marketplace/external_plugins/sequant/skills/clean/SKILL.md +211 -0
  13. package/dist/marketplace/external_plugins/sequant/skills/docs/SKILL.md +337 -0
  14. package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +807 -0
  15. package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +678 -0
  16. package/dist/marketplace/external_plugins/sequant/skills/improve/SKILL.md +668 -0
  17. package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +374 -0
  18. package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +570 -0
  19. package/dist/marketplace/external_plugins/sequant/skills/qa/references/code-quality-exemplars.md +107 -0
  20. package/dist/marketplace/external_plugins/sequant/skills/qa/references/code-review-checklist.md +65 -0
  21. package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +179 -0
  22. package/dist/marketplace/external_plugins/sequant/skills/qa/references/semgrep-rules.md +207 -0
  23. package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +109 -0
  24. package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +622 -0
  25. package/dist/marketplace/external_plugins/sequant/skills/reflect/SKILL.md +175 -0
  26. package/dist/marketplace/external_plugins/sequant/skills/reflect/references/documentation-tiers.md +70 -0
  27. package/dist/marketplace/external_plugins/sequant/skills/reflect/references/phase-reflection.md +95 -0
  28. package/dist/marketplace/external_plugins/sequant/skills/security-review/SKILL.md +358 -0
  29. package/dist/marketplace/external_plugins/sequant/skills/security-review/references/security-checklists.md +432 -0
  30. package/dist/marketplace/external_plugins/sequant/skills/solve/SKILL.md +697 -0
  31. package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +754 -0
  32. package/dist/marketplace/external_plugins/sequant/skills/spec/references/parallel-groups.md +72 -0
  33. package/dist/marketplace/external_plugins/sequant/skills/spec/references/recommended-workflow.md +92 -0
  34. package/dist/marketplace/external_plugins/sequant/skills/spec/references/verification-criteria.md +104 -0
  35. package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +600 -0
  36. package/dist/marketplace/external_plugins/sequant/skills/testgen/SKILL.md +576 -0
  37. package/dist/marketplace/external_plugins/sequant/skills/verify/SKILL.md +281 -0
  38. package/dist/src/commands/run.d.ts +13 -274
  39. package/dist/src/commands/run.js +43 -1958
  40. package/dist/src/commands/sync.js +3 -0
  41. package/dist/src/commands/update.js +3 -0
  42. package/dist/src/lib/plugin-version-sync.d.ts +2 -1
  43. package/dist/src/lib/plugin-version-sync.js +28 -7
  44. package/dist/src/lib/solve-comment-parser.d.ts +26 -0
  45. package/dist/src/lib/solve-comment-parser.js +63 -7
  46. package/dist/src/lib/upstream/assessment.js +6 -3
  47. package/dist/src/lib/upstream/relevance.d.ts +5 -0
  48. package/dist/src/lib/upstream/relevance.js +24 -0
  49. package/dist/src/lib/upstream/report.js +18 -46
  50. package/dist/src/lib/upstream/types.d.ts +2 -0
  51. package/dist/src/lib/workflow/batch-executor.d.ts +117 -0
  52. package/dist/src/lib/workflow/batch-executor.js +574 -0
  53. package/dist/src/lib/workflow/phase-executor.d.ts +40 -0
  54. package/dist/src/lib/workflow/phase-executor.js +381 -0
  55. package/dist/src/lib/workflow/phase-mapper.d.ts +65 -0
  56. package/dist/src/lib/workflow/phase-mapper.js +147 -0
  57. package/dist/src/lib/workflow/pr-operations.d.ts +86 -0
  58. package/dist/src/lib/workflow/pr-operations.js +326 -0
  59. package/dist/src/lib/workflow/pr-status.d.ts +49 -0
  60. package/dist/src/lib/workflow/pr-status.js +131 -0
  61. package/dist/src/lib/workflow/run-reflect.d.ts +32 -0
  62. package/dist/src/lib/workflow/run-reflect.js +191 -0
  63. package/dist/src/lib/workflow/run-summary.d.ts +36 -0
  64. package/dist/src/lib/workflow/run-summary.js +142 -0
  65. package/dist/src/lib/workflow/state-cleanup.d.ts +79 -0
  66. package/dist/src/lib/workflow/state-cleanup.js +250 -0
  67. package/dist/src/lib/workflow/state-rebuild.d.ts +38 -0
  68. package/dist/src/lib/workflow/state-rebuild.js +140 -0
  69. package/dist/src/lib/workflow/state-utils.d.ts +14 -162
  70. package/dist/src/lib/workflow/state-utils.js +10 -677
  71. package/dist/src/lib/workflow/worktree-discovery.d.ts +61 -0
  72. package/dist/src/lib/workflow/worktree-discovery.js +229 -0
  73. package/dist/src/lib/workflow/worktree-manager.d.ts +205 -0
  74. package/dist/src/lib/workflow/worktree-manager.js +918 -0
  75. package/package.json +4 -2
  76. package/templates/skills/exec/SKILL.md +2 -2
  77. package/templates/skills/fullsolve/SKILL.md +15 -5
  78. package/templates/skills/loop/SKILL.md +1 -1
  79. package/templates/skills/qa/SKILL.md +47 -7
  80. package/templates/skills/solve/SKILL.md +92 -6
  81. package/templates/skills/spec/SKILL.md +57 -4
  82. package/templates/skills/test/SKILL.md +10 -0
  83. package/templates/skills/testgen/SKILL.md +1 -1
@@ -0,0 +1,250 @@
1
+ /**
2
+ * State cleanup and reconciliation utilities
3
+ *
4
+ * @module state-cleanup
5
+ * @example
6
+ * ```typescript
7
+ * import { cleanupStaleEntries, reconcileStateAtStartup } from './state-cleanup';
8
+ *
9
+ * // Clean up orphaned entries
10
+ * const result = await cleanupStaleEntries({ dryRun: true });
11
+ * console.log(`Would remove ${result.removed.length} entries`);
12
+ *
13
+ * // Reconcile state at startup
14
+ * const reconcileResult = await reconcileStateAtStartup();
15
+ * console.log(`Advanced ${reconcileResult.advanced.length} issues to merged`);
16
+ * ```
17
+ */
18
+ import { spawnSync } from "child_process";
19
+ import { StateManager } from "./state-manager.js";
20
+ import { checkPRMergeStatus, isIssueMergedIntoMain } from "./pr-status.js";
21
+ /**
22
+ * Get list of active worktree paths
23
+ */
24
+ function getActiveWorktrees() {
25
+ const result = spawnSync("git", ["worktree", "list", "--porcelain"], {
26
+ stdio: "pipe",
27
+ });
28
+ if (result.status !== 0) {
29
+ return [];
30
+ }
31
+ const output = result.stdout.toString();
32
+ const paths = [];
33
+ for (const line of output.split("\n")) {
34
+ if (line.startsWith("worktree ")) {
35
+ paths.push(line.substring(9));
36
+ }
37
+ }
38
+ return paths;
39
+ }
40
+ /**
41
+ * Clean up stale and orphaned entries from workflow state
42
+ *
43
+ * - Checks GitHub to detect if associated PR was merged
44
+ * - Orphaned entries with merged PRs get status "merged" and are removed automatically
45
+ * - Orphaned entries without merged PRs get status "abandoned" (kept for review)
46
+ * - Use removeAll to remove both merged and abandoned orphaned entries in one step
47
+ * - Use maxAgeDays to remove old merged/abandoned issues
48
+ */
49
+ export async function cleanupStaleEntries(options = {}) {
50
+ const manager = new StateManager({
51
+ statePath: options.statePath,
52
+ verbose: options.verbose,
53
+ });
54
+ if (!manager.stateExists()) {
55
+ return {
56
+ success: true,
57
+ removed: [],
58
+ orphaned: [],
59
+ merged: [],
60
+ };
61
+ }
62
+ try {
63
+ const state = await manager.getState();
64
+ const removed = [];
65
+ const orphaned = [];
66
+ const merged = [];
67
+ // Get list of active worktrees
68
+ const activeWorktrees = getActiveWorktrees();
69
+ for (const [issueNumStr, issueState] of Object.entries(state.issues)) {
70
+ const issueNum = parseInt(issueNumStr, 10);
71
+ // Check if worktree exists (if issue has one)
72
+ if (issueState.worktree &&
73
+ !activeWorktrees.includes(issueState.worktree)) {
74
+ if (options.verbose) {
75
+ console.log(`🔍 Orphaned: #${issueNum} (worktree not found: ${issueState.worktree})`);
76
+ }
77
+ // Check if this issue has a PR and if it's merged
78
+ let prMerged = false;
79
+ if (issueState.pr?.number) {
80
+ if (options.verbose) {
81
+ console.log(` Checking PR #${issueState.pr.number} status...`);
82
+ }
83
+ const prStatus = checkPRMergeStatus(issueState.pr.number);
84
+ prMerged = prStatus === "MERGED";
85
+ if (options.verbose) {
86
+ console.log(` PR status: ${prStatus ?? "unknown"}`);
87
+ }
88
+ }
89
+ if (!options.dryRun) {
90
+ if (prMerged || issueState.status === "merged") {
91
+ // Merged PRs are auto-removed
92
+ merged.push(issueNum);
93
+ removed.push(issueNum);
94
+ if (options.verbose) {
95
+ console.log(` ✓ Merged PR detected, removing entry`);
96
+ }
97
+ delete state.issues[issueNumStr];
98
+ }
99
+ else if (issueState.status === "abandoned" || options.removeAll) {
100
+ // Already abandoned or removeAll flag - remove it
101
+ orphaned.push(issueNum);
102
+ removed.push(issueNum);
103
+ if (options.verbose) {
104
+ console.log(` ✓ Removing abandoned entry`);
105
+ }
106
+ delete state.issues[issueNumStr];
107
+ }
108
+ else {
109
+ // Mark as abandoned (kept for review)
110
+ orphaned.push(issueNum);
111
+ issueState.status = "abandoned";
112
+ if (options.verbose) {
113
+ console.log(` → Marked as abandoned (kept for review)`);
114
+ }
115
+ }
116
+ }
117
+ else {
118
+ // Dry run - report what would happen
119
+ if (prMerged || issueState.status === "merged") {
120
+ merged.push(issueNum);
121
+ removed.push(issueNum);
122
+ }
123
+ else if (issueState.status === "abandoned" || options.removeAll) {
124
+ orphaned.push(issueNum);
125
+ removed.push(issueNum);
126
+ }
127
+ else {
128
+ orphaned.push(issueNum);
129
+ }
130
+ }
131
+ continue;
132
+ }
133
+ // Check age for merged/abandoned issues
134
+ if (options.maxAgeDays &&
135
+ (issueState.status === "merged" || issueState.status === "abandoned")) {
136
+ const lastActivity = new Date(issueState.lastActivity);
137
+ const ageDays = (Date.now() - lastActivity.getTime()) / (1000 * 60 * 60 * 24);
138
+ if (ageDays > options.maxAgeDays) {
139
+ removed.push(issueNum);
140
+ if (options.verbose) {
141
+ console.log(`🗑️ Stale: #${issueNum} (${Math.floor(ageDays)} days old)`);
142
+ }
143
+ if (!options.dryRun) {
144
+ delete state.issues[issueNumStr];
145
+ }
146
+ }
147
+ }
148
+ }
149
+ // Save updated state
150
+ if (!options.dryRun && (removed.length > 0 || orphaned.length > 0)) {
151
+ await manager.saveState(state);
152
+ }
153
+ return {
154
+ success: true,
155
+ removed,
156
+ orphaned,
157
+ merged,
158
+ };
159
+ }
160
+ catch (error) {
161
+ return {
162
+ success: false,
163
+ removed: [],
164
+ orphaned: [],
165
+ merged: [],
166
+ error: String(error),
167
+ };
168
+ }
169
+ }
170
+ /**
171
+ * Lightweight state reconciliation at run start
172
+ *
173
+ * Checks issues in `ready_for_merge` state and advances them to `merged`
174
+ * if their PRs are merged or their branches are in main.
175
+ *
176
+ * This prevents re-running already completed issues.
177
+ *
178
+ * @param options - Reconciliation options
179
+ * @returns Result with lists of advanced and still-pending issues
180
+ */
181
+ export async function reconcileStateAtStartup(options = {}) {
182
+ const manager = new StateManager({
183
+ statePath: options.statePath,
184
+ verbose: options.verbose,
185
+ });
186
+ // Graceful degradation: if state file doesn't exist, skip
187
+ if (!manager.stateExists()) {
188
+ return {
189
+ success: true,
190
+ advanced: [],
191
+ stillPending: [],
192
+ };
193
+ }
194
+ try {
195
+ const state = await manager.getState();
196
+ const advanced = [];
197
+ const stillPending = [];
198
+ // Find issues in ready_for_merge state
199
+ for (const [issueNumStr, issueState] of Object.entries(state.issues)) {
200
+ if (issueState.status !== "ready_for_merge") {
201
+ continue;
202
+ }
203
+ const issueNum = parseInt(issueNumStr, 10);
204
+ let isMerged = false;
205
+ // Check 1: If we have PR info, check PR status via gh
206
+ if (issueState.pr?.number) {
207
+ const prStatus = checkPRMergeStatus(issueState.pr.number);
208
+ if (prStatus === "MERGED") {
209
+ isMerged = true;
210
+ if (options.verbose) {
211
+ console.log(` #${issueNum}: PR #${issueState.pr.number} is merged`);
212
+ }
213
+ }
214
+ }
215
+ // Check 2: If no PR or PR check failed, check git for merged branch
216
+ if (!isMerged) {
217
+ isMerged = isIssueMergedIntoMain(issueNum);
218
+ if (isMerged && options.verbose) {
219
+ console.log(` #${issueNum}: Branch merged into main (git check)`);
220
+ }
221
+ }
222
+ if (isMerged) {
223
+ // Advance state to merged
224
+ issueState.status = "merged";
225
+ issueState.lastActivity = new Date().toISOString();
226
+ advanced.push(issueNum);
227
+ }
228
+ else {
229
+ stillPending.push(issueNum);
230
+ }
231
+ }
232
+ // Save state if any issues were advanced
233
+ if (advanced.length > 0) {
234
+ await manager.saveState(state);
235
+ }
236
+ return {
237
+ success: true,
238
+ advanced,
239
+ stillPending,
240
+ };
241
+ }
242
+ catch (error) {
243
+ return {
244
+ success: false,
245
+ advanced: [],
246
+ stillPending: [],
247
+ error: String(error),
248
+ };
249
+ }
250
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * State reconstruction from run logs
3
+ *
4
+ * @module state-rebuild
5
+ * @example
6
+ * ```typescript
7
+ * import { rebuildStateFromLogs } from './state-rebuild';
8
+ *
9
+ * // Rebuild state from run logs
10
+ * const result = await rebuildStateFromLogs();
11
+ * console.log(`Processed ${result.logsProcessed} logs, found ${result.issuesFound} issues`);
12
+ * ```
13
+ */
14
+ export interface RebuildOptions {
15
+ /** Log directory path (default: .sequant/logs) */
16
+ logPath?: string;
17
+ /** State file path (default: .sequant/state.json) */
18
+ statePath?: string;
19
+ /** Enable verbose logging */
20
+ verbose?: boolean;
21
+ }
22
+ export interface RebuildResult {
23
+ /** Whether rebuild was successful */
24
+ success: boolean;
25
+ /** Number of log files processed */
26
+ logsProcessed: number;
27
+ /** Number of issues found */
28
+ issuesFound: number;
29
+ /** Error message if failed */
30
+ error?: string;
31
+ }
32
+ /**
33
+ * Rebuild workflow state from run logs
34
+ *
35
+ * Scans all run logs in .sequant/logs/ and reconstructs state
36
+ * based on the most recent activity for each issue.
37
+ */
38
+ export declare function rebuildStateFromLogs(options?: RebuildOptions): Promise<RebuildResult>;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * State reconstruction from run logs
3
+ *
4
+ * @module state-rebuild
5
+ * @example
6
+ * ```typescript
7
+ * import { rebuildStateFromLogs } from './state-rebuild';
8
+ *
9
+ * // Rebuild state from run logs
10
+ * const result = await rebuildStateFromLogs();
11
+ * console.log(`Processed ${result.logsProcessed} logs, found ${result.issuesFound} issues`);
12
+ * ```
13
+ */
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import { StateManager } from "./state-manager.js";
17
+ import { createEmptyState, createIssueState, createPhaseState, } from "./state-schema.js";
18
+ import { RunLogSchema, LOG_PATHS } from "./run-log-schema.js";
19
+ /**
20
+ * Rebuild workflow state from run logs
21
+ *
22
+ * Scans all run logs in .sequant/logs/ and reconstructs state
23
+ * based on the most recent activity for each issue.
24
+ */
25
+ export async function rebuildStateFromLogs(options = {}) {
26
+ const logPath = options.logPath ?? LOG_PATHS.project;
27
+ if (!fs.existsSync(logPath)) {
28
+ return {
29
+ success: false,
30
+ logsProcessed: 0,
31
+ issuesFound: 0,
32
+ error: `Log directory not found: ${logPath}`,
33
+ };
34
+ }
35
+ try {
36
+ // Find all log files
37
+ const files = fs.readdirSync(logPath).filter((f) => f.endsWith(".json"));
38
+ if (files.length === 0) {
39
+ return {
40
+ success: true,
41
+ logsProcessed: 0,
42
+ issuesFound: 0,
43
+ };
44
+ }
45
+ // Sort by timestamp (newest first)
46
+ files.sort().reverse();
47
+ // Build state from logs
48
+ const state = createEmptyState();
49
+ const issueMap = new Map();
50
+ for (const file of files) {
51
+ const filePath = path.join(logPath, file);
52
+ try {
53
+ const content = fs.readFileSync(filePath, "utf-8");
54
+ const logData = JSON.parse(content);
55
+ const log = RunLogSchema.safeParse(logData);
56
+ if (!log.success) {
57
+ if (options.verbose) {
58
+ console.log(`⚠️ Invalid log format: ${file}`);
59
+ }
60
+ continue;
61
+ }
62
+ const runLog = log.data;
63
+ // Process each issue in the log
64
+ for (const issueLog of runLog.issues) {
65
+ // Skip if we already have newer data for this issue
66
+ if (issueMap.has(issueLog.issueNumber)) {
67
+ continue;
68
+ }
69
+ // Create issue state from log
70
+ const issueState = createIssueState(issueLog.issueNumber, issueLog.title);
71
+ // Determine status from log
72
+ if (issueLog.status === "success") {
73
+ issueState.status = "ready_for_merge";
74
+ }
75
+ else if (issueLog.status === "failure") {
76
+ issueState.status = "in_progress";
77
+ }
78
+ else {
79
+ issueState.status = "in_progress";
80
+ }
81
+ // Add phase states from log
82
+ for (const phaseLog of issueLog.phases) {
83
+ const phaseState = createPhaseState(phaseLog.status === "success"
84
+ ? "completed"
85
+ : phaseLog.status === "failure"
86
+ ? "failed"
87
+ : phaseLog.status === "skipped"
88
+ ? "skipped"
89
+ : "completed");
90
+ phaseState.startedAt = phaseLog.startTime;
91
+ phaseState.completedAt = phaseLog.endTime;
92
+ if (phaseLog.error) {
93
+ phaseState.error = phaseLog.error;
94
+ }
95
+ issueState.phases[phaseLog.phase] = phaseState;
96
+ // Update current phase to last executed
97
+ issueState.currentPhase = phaseLog.phase;
98
+ }
99
+ // Set last activity from most recent phase
100
+ const lastPhase = issueLog.phases[issueLog.phases.length - 1];
101
+ if (lastPhase) {
102
+ issueState.lastActivity = lastPhase.endTime;
103
+ }
104
+ issueMap.set(issueLog.issueNumber, issueState);
105
+ }
106
+ if (options.verbose) {
107
+ console.log(`✓ Processed: ${file}`);
108
+ }
109
+ }
110
+ catch (err) {
111
+ if (options.verbose) {
112
+ console.log(`⚠️ Error reading ${file}: ${err}`);
113
+ }
114
+ }
115
+ }
116
+ // Copy issues to state
117
+ for (const [num, issueState] of issueMap) {
118
+ state.issues[String(num)] = issueState;
119
+ }
120
+ // Save rebuilt state
121
+ const manager = new StateManager({
122
+ statePath: options.statePath,
123
+ verbose: options.verbose,
124
+ });
125
+ await manager.saveState(state);
126
+ return {
127
+ success: true,
128
+ logsProcessed: files.length,
129
+ issuesFound: issueMap.size,
130
+ };
131
+ }
132
+ catch (error) {
133
+ return {
134
+ success: false,
135
+ logsProcessed: 0,
136
+ issuesFound: 0,
137
+ error: String(error),
138
+ };
139
+ }
140
+ }
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * State utilities for rebuilding and cleaning up workflow state
3
3
  *
4
+ * This module re-exports focused utilities from dedicated modules:
5
+ * - pr-status: PR merge detection and branch status
6
+ * - state-rebuild: State reconstruction from run logs
7
+ * - worktree-discovery: Worktree discovery for state bootstrapping
8
+ * - state-cleanup: Cleanup of stale entries and startup reconciliation
9
+ *
4
10
  * @example
5
11
  * ```typescript
6
12
  * import { rebuildStateFromLogs, cleanupStaleEntries } from './state-utils';
@@ -12,165 +18,11 @@
12
18
  * const result = await cleanupStaleEntries({ dryRun: true });
13
19
  * ```
14
20
  */
15
- import { type Phase } from "./state-schema.js";
16
- /**
17
- * PR merge status from GitHub
18
- */
19
- export type PRMergeStatus = "MERGED" | "CLOSED" | "OPEN" | null;
20
- /**
21
- * Check the merge status of a PR using the gh CLI
22
- *
23
- * @param prNumber - The PR number to check
24
- * @returns "MERGED" | "CLOSED" | "OPEN" | null (null if PR not found or gh unavailable)
25
- */
26
- export declare function checkPRMergeStatus(prNumber: number): PRMergeStatus;
27
- export interface RebuildOptions {
28
- /** Log directory path (default: .sequant/logs) */
29
- logPath?: string;
30
- /** State file path (default: .sequant/state.json) */
31
- statePath?: string;
32
- /** Enable verbose logging */
33
- verbose?: boolean;
34
- }
35
- export interface RebuildResult {
36
- /** Whether rebuild was successful */
37
- success: boolean;
38
- /** Number of log files processed */
39
- logsProcessed: number;
40
- /** Number of issues found */
41
- issuesFound: number;
42
- /** Error message if failed */
43
- error?: string;
44
- }
45
- /**
46
- * Rebuild workflow state from run logs
47
- *
48
- * Scans all run logs in .sequant/logs/ and reconstructs state
49
- * based on the most recent activity for each issue.
50
- */
51
- export declare function rebuildStateFromLogs(options?: RebuildOptions): Promise<RebuildResult>;
52
- export interface CleanupOptions {
53
- /** State file path (default: .sequant/state.json) */
54
- statePath?: string;
55
- /** Only report what would be cleaned (don't modify) */
56
- dryRun?: boolean;
57
- /** Enable verbose logging */
58
- verbose?: boolean;
59
- /** Remove issues older than this many days */
60
- maxAgeDays?: number;
61
- /** Remove all orphaned entries (both merged and abandoned) in one step */
62
- removeAll?: boolean;
63
- }
64
- export interface CleanupResult {
65
- /** Whether cleanup was successful */
66
- success: boolean;
67
- /** Issues that were removed or would be removed */
68
- removed: number[];
69
- /** Issues that were marked as orphaned (abandoned) */
70
- orphaned: number[];
71
- /** Issues detected as merged PRs */
72
- merged: number[];
73
- /** Error message if failed */
74
- error?: string;
75
- }
76
- /**
77
- * Clean up stale and orphaned entries from workflow state
78
- *
79
- * - Checks GitHub to detect if associated PR was merged
80
- * - Orphaned entries with merged PRs get status "merged" and are removed automatically
81
- * - Orphaned entries without merged PRs get status "abandoned" (kept for review)
82
- * - Use removeAll to remove both merged and abandoned orphaned entries in one step
83
- * - Use maxAgeDays to remove old merged/abandoned issues
84
- */
85
- export declare function cleanupStaleEntries(options?: CleanupOptions): Promise<CleanupResult>;
86
- export interface DiscoverOptions {
87
- /** State file path (default: .sequant/state.json) */
88
- statePath?: string;
89
- /** Enable verbose logging */
90
- verbose?: boolean;
91
- }
92
- export interface DiscoveredWorktree {
93
- /** Issue number extracted from branch name */
94
- issueNumber: number;
95
- /** Issue title (fetched from GitHub or placeholder) */
96
- title: string;
97
- /** Full path to the worktree */
98
- worktreePath: string;
99
- /** Branch name */
100
- branch: string;
101
- /** Inferred current phase from logs (if available) */
102
- inferredPhase?: Phase;
103
- }
104
- export interface SkippedWorktree {
105
- /** Path to the worktree */
106
- path: string;
107
- /** Reason it was skipped */
108
- reason: string;
109
- }
110
- export interface DiscoverResult {
111
- /** Whether discovery was successful */
112
- success: boolean;
113
- /** Number of worktrees scanned */
114
- worktreesScanned: number;
115
- /** Number of worktrees already tracked */
116
- alreadyTracked: number;
117
- /** Discovered worktrees not yet in state */
118
- discovered: DiscoveredWorktree[];
119
- /** Worktrees that were skipped (not matching pattern, etc.) */
120
- skipped: SkippedWorktree[];
121
- /** Error message if failed */
122
- error?: string;
123
- }
124
- /**
125
- * Discover worktrees that are not yet tracked in state
126
- *
127
- * Scans all git worktrees, identifies those with issue-related branch names,
128
- * and returns information about worktrees not yet in the state file.
129
- */
130
- export declare function discoverUntrackedWorktrees(options?: DiscoverOptions): Promise<DiscoverResult>;
131
- export interface ReconcileOptions {
132
- /** State file path (default: .sequant/state.json) */
133
- statePath?: string;
134
- /** Enable verbose logging */
135
- verbose?: boolean;
136
- }
137
- export interface ReconcileResult {
138
- /** Whether reconciliation was successful */
139
- success: boolean;
140
- /** Issues that were advanced from ready_for_merge to merged */
141
- advanced: number[];
142
- /** Issues checked but still ready_for_merge */
143
- stillPending: number[];
144
- /** Error message if failed */
145
- error?: string;
146
- }
147
- /**
148
- * Check if a branch has been merged into main using git
149
- *
150
- * @param branchName - The branch name to check (e.g., "feature/33-some-title")
151
- * @returns true if the branch is merged into main, false otherwise
152
- */
153
- export declare function isBranchMergedIntoMain(branchName: string): boolean;
154
- /**
155
- * Check if a feature branch for an issue is merged into main
156
- *
157
- * Tries multiple detection methods:
158
- * 1. Check if branch exists and is merged via `git branch --merged main`
159
- * 2. Check for merge commits mentioning the issue
160
- *
161
- * @param issueNumber - The issue number to check
162
- * @returns true if the issue's work is merged into main
163
- */
164
- export declare function isIssueMergedIntoMain(issueNumber: number): boolean;
165
- /**
166
- * Lightweight state reconciliation at run start
167
- *
168
- * Checks issues in `ready_for_merge` state and advances them to `merged`
169
- * if their PRs are merged or their branches are in main.
170
- *
171
- * This prevents re-running already completed issues.
172
- *
173
- * @param options - Reconciliation options
174
- * @returns Result with lists of advanced and still-pending issues
175
- */
176
- export declare function reconcileStateAtStartup(options?: ReconcileOptions): Promise<ReconcileResult>;
21
+ export type { PRMergeStatus } from "./pr-status.js";
22
+ export { checkPRMergeStatus, isBranchMergedIntoMain, isIssueMergedIntoMain, } from "./pr-status.js";
23
+ export type { RebuildOptions, RebuildResult } from "./state-rebuild.js";
24
+ export { rebuildStateFromLogs } from "./state-rebuild.js";
25
+ export type { DiscoverOptions, DiscoveredWorktree, SkippedWorktree, DiscoverResult, } from "./worktree-discovery.js";
26
+ export { discoverUntrackedWorktrees } from "./worktree-discovery.js";
27
+ export type { CleanupOptions, CleanupResult, ReconcileOptions, ReconcileResult, } from "./state-cleanup.js";
28
+ export { cleanupStaleEntries, reconcileStateAtStartup, } from "./state-cleanup.js";