sequant 1.20.3 → 2.0.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 (137) hide show
  1. package/.claude-plugin/marketplace.json +2 -4
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +29 -9
  4. package/dist/bin/cli.js +25 -2
  5. package/dist/src/commands/doctor.js +42 -9
  6. package/dist/src/commands/init.d.ts +1 -0
  7. package/dist/src/commands/init.js +52 -0
  8. package/dist/src/commands/logs.d.ts +1 -0
  9. package/dist/src/commands/logs.js +18 -2
  10. package/dist/src/commands/run.d.ts +7 -0
  11. package/dist/src/commands/run.js +235 -68
  12. package/dist/src/commands/serve.d.ts +13 -0
  13. package/dist/src/commands/serve.js +131 -0
  14. package/dist/src/commands/stats.d.ts +1 -0
  15. package/dist/src/commands/stats.js +185 -26
  16. package/dist/src/commands/status.d.ts +2 -0
  17. package/dist/src/commands/status.js +99 -50
  18. package/dist/src/index.d.ts +2 -2
  19. package/dist/src/index.js +4 -1
  20. package/dist/src/lib/ac-parser.d.ts +2 -0
  21. package/dist/src/lib/ac-parser.js +12 -2
  22. package/dist/src/lib/assess-comment-parser.d.ts +137 -0
  23. package/dist/src/lib/assess-comment-parser.js +344 -0
  24. package/dist/src/lib/ci/config.d.ts +22 -0
  25. package/dist/src/lib/ci/config.js +134 -0
  26. package/dist/src/lib/ci/index.d.ts +12 -0
  27. package/dist/src/lib/ci/index.js +10 -0
  28. package/dist/src/lib/ci/inputs.d.ts +29 -0
  29. package/dist/src/lib/ci/inputs.js +103 -0
  30. package/dist/src/lib/ci/labels.d.ts +34 -0
  31. package/dist/src/lib/ci/labels.js +101 -0
  32. package/dist/src/lib/ci/outputs.d.ts +25 -0
  33. package/dist/src/lib/ci/outputs.js +84 -0
  34. package/dist/src/lib/ci/triggers.d.ts +9 -0
  35. package/dist/src/lib/ci/triggers.js +86 -0
  36. package/dist/src/lib/ci/types.d.ts +131 -0
  37. package/dist/src/lib/ci/types.js +47 -0
  38. package/dist/src/lib/mcp-config.d.ts +54 -0
  39. package/dist/src/lib/mcp-config.js +172 -0
  40. package/dist/src/lib/merge-check/index.js +6 -12
  41. package/dist/src/lib/merge-check/types.d.ts +20 -7
  42. package/dist/src/lib/merge-check/types.js +11 -0
  43. package/dist/src/lib/phase-signal.d.ts +3 -3
  44. package/dist/src/lib/phase-signal.js +5 -3
  45. package/dist/src/lib/settings.d.ts +52 -0
  46. package/dist/src/lib/settings.js +41 -0
  47. package/dist/src/lib/shutdown.d.ts +16 -5
  48. package/dist/src/lib/shutdown.js +32 -12
  49. package/dist/src/lib/solve-comment-parser.d.ts +9 -102
  50. package/dist/src/lib/solve-comment-parser.js +13 -248
  51. package/dist/src/lib/stacks.d.ts +8 -0
  52. package/dist/src/lib/stacks.js +34 -0
  53. package/dist/src/lib/system.js +3 -7
  54. package/dist/src/lib/test-tautology-detector.d.ts +10 -0
  55. package/dist/src/lib/test-tautology-detector.js +43 -4
  56. package/dist/src/lib/upstream/assessment.js +9 -59
  57. package/dist/src/lib/upstream/issues.js +12 -75
  58. package/dist/src/lib/version-check.d.ts +2 -2
  59. package/dist/src/lib/version-check.js +6 -3
  60. package/dist/src/lib/version.d.ts +4 -0
  61. package/dist/src/lib/version.js +25 -0
  62. package/dist/src/lib/workflow/batch-executor.d.ts +18 -86
  63. package/dist/src/lib/workflow/batch-executor.js +232 -55
  64. package/dist/src/lib/workflow/drivers/agent-driver.d.ts +56 -0
  65. package/dist/src/lib/workflow/drivers/agent-driver.js +8 -0
  66. package/dist/src/lib/workflow/drivers/aider.d.ts +18 -0
  67. package/dist/src/lib/workflow/drivers/aider.js +160 -0
  68. package/dist/src/lib/workflow/drivers/claude-code.d.ts +17 -0
  69. package/dist/src/lib/workflow/drivers/claude-code.js +165 -0
  70. package/dist/src/lib/workflow/drivers/index.d.ts +20 -0
  71. package/dist/src/lib/workflow/drivers/index.js +27 -0
  72. package/dist/src/lib/workflow/error-classifier.d.ts +16 -0
  73. package/dist/src/lib/workflow/error-classifier.js +90 -0
  74. package/dist/src/lib/workflow/log-writer.d.ts +6 -3
  75. package/dist/src/lib/workflow/log-writer.js +57 -27
  76. package/dist/src/lib/workflow/metrics-schema.d.ts +9 -9
  77. package/dist/src/lib/workflow/phase-detection.d.ts +23 -0
  78. package/dist/src/lib/workflow/phase-detection.js +45 -29
  79. package/dist/src/lib/workflow/phase-executor.d.ts +42 -3
  80. package/dist/src/lib/workflow/phase-executor.js +340 -220
  81. package/dist/src/lib/workflow/phase-mapper.d.ts +1 -1
  82. package/dist/src/lib/workflow/phase-mapper.js +7 -7
  83. package/dist/src/lib/workflow/platforms/github.d.ts +157 -0
  84. package/dist/src/lib/workflow/platforms/github.js +466 -0
  85. package/dist/src/lib/workflow/platforms/index.d.ts +17 -0
  86. package/dist/src/lib/workflow/platforms/index.js +25 -0
  87. package/dist/src/lib/workflow/platforms/platform-provider.d.ts +67 -0
  88. package/dist/src/lib/workflow/platforms/platform-provider.js +8 -0
  89. package/dist/src/lib/workflow/pr-status.d.ts +2 -4
  90. package/dist/src/lib/workflow/pr-status.js +3 -16
  91. package/dist/src/lib/workflow/qa-cache.d.ts +58 -0
  92. package/dist/src/lib/workflow/qa-cache.js +88 -0
  93. package/dist/src/lib/workflow/reconcile.d.ts +69 -0
  94. package/dist/src/lib/workflow/reconcile.js +290 -0
  95. package/dist/src/lib/workflow/ring-buffer.d.ts +17 -0
  96. package/dist/src/lib/workflow/ring-buffer.js +37 -0
  97. package/dist/src/lib/workflow/run-log-schema.d.ts +115 -24
  98. package/dist/src/lib/workflow/run-log-schema.js +47 -12
  99. package/dist/src/lib/workflow/run-reflect.js +1 -1
  100. package/dist/src/lib/workflow/state-cleanup.js +21 -0
  101. package/dist/src/lib/workflow/state-manager.d.ts +34 -3
  102. package/dist/src/lib/workflow/state-manager.js +278 -126
  103. package/dist/src/lib/workflow/state-schema.d.ts +34 -30
  104. package/dist/src/lib/workflow/state-schema.js +35 -25
  105. package/dist/src/lib/workflow/state-utils.d.ts +3 -1
  106. package/dist/src/lib/workflow/state-utils.js +1 -0
  107. package/dist/src/lib/workflow/types.d.ts +208 -6
  108. package/dist/src/lib/workflow/types.js +20 -1
  109. package/dist/src/lib/workflow/worktree-discovery.d.ts +1 -1
  110. package/dist/src/lib/workflow/worktree-discovery.js +6 -14
  111. package/dist/src/lib/workflow/worktree-manager.js +33 -51
  112. package/dist/src/mcp/index.d.ts +4 -0
  113. package/dist/src/mcp/index.js +4 -0
  114. package/dist/src/mcp/resources.d.ts +7 -0
  115. package/dist/src/mcp/resources.js +111 -0
  116. package/dist/src/mcp/run-registry.d.ts +34 -0
  117. package/dist/src/mcp/run-registry.js +42 -0
  118. package/dist/src/mcp/server.d.ts +12 -0
  119. package/dist/src/mcp/server.js +50 -0
  120. package/dist/src/mcp/tools/logs.d.ts +7 -0
  121. package/dist/src/mcp/tools/logs.js +149 -0
  122. package/dist/src/mcp/tools/run.d.ts +121 -0
  123. package/dist/src/mcp/tools/run.js +591 -0
  124. package/dist/src/mcp/tools/status.d.ts +7 -0
  125. package/dist/src/mcp/tools/status.js +127 -0
  126. package/package.json +10 -1
  127. package/templates/hooks/post-tool.sh +19 -8
  128. package/templates/hooks/pre-tool.sh +36 -49
  129. package/templates/mcp.json +6 -0
  130. package/templates/skills/assess/SKILL.md +354 -352
  131. package/templates/skills/exec/SKILL.md +64 -1
  132. package/templates/skills/fullsolve/SKILL.md +35 -4
  133. package/templates/skills/qa/SKILL.md +486 -9
  134. package/templates/skills/qa/scripts/quality-checks.sh +1 -1
  135. package/templates/skills/setup/SKILL.md +386 -0
  136. package/templates/skills/solve/SKILL.md +38 -664
  137. package/templates/skills/spec/SKILL.md +90 -31
@@ -21,19 +21,19 @@ import { z } from "zod";
21
21
  */
22
22
  export declare const RunOutcomeSchema: z.ZodEnum<{
23
23
  success: "success";
24
- failed: "failed";
25
24
  partial: "partial";
25
+ failed: "failed";
26
26
  }>;
27
27
  export type RunOutcome = z.infer<typeof RunOutcomeSchema>;
28
28
  /**
29
29
  * Available phases (aligned with run-log-schema.ts)
30
30
  */
31
31
  export declare const MetricPhaseSchema: z.ZodEnum<{
32
+ qa: "qa";
32
33
  loop: "loop";
33
34
  spec: "spec";
34
- exec: "exec";
35
- qa: "qa";
36
35
  "security-review": "security-review";
36
+ exec: "exec";
37
37
  testgen: "testgen";
38
38
  test: "test";
39
39
  }>;
@@ -67,18 +67,18 @@ export declare const MetricRunSchema: z.ZodObject<{
67
67
  date: z.ZodString;
68
68
  issues: z.ZodArray<z.ZodNumber>;
69
69
  phases: z.ZodArray<z.ZodEnum<{
70
+ qa: "qa";
70
71
  loop: "loop";
71
72
  spec: "spec";
72
- exec: "exec";
73
- qa: "qa";
74
73
  "security-review": "security-review";
74
+ exec: "exec";
75
75
  testgen: "testgen";
76
76
  test: "test";
77
77
  }>>;
78
78
  outcome: z.ZodEnum<{
79
79
  success: "success";
80
- failed: "failed";
81
80
  partial: "partial";
81
+ failed: "failed";
82
82
  }>;
83
83
  duration: z.ZodNumber;
84
84
  model: z.ZodString;
@@ -107,18 +107,18 @@ export declare const MetricsSchema: z.ZodObject<{
107
107
  date: z.ZodString;
108
108
  issues: z.ZodArray<z.ZodNumber>;
109
109
  phases: z.ZodArray<z.ZodEnum<{
110
+ qa: "qa";
110
111
  loop: "loop";
111
112
  spec: "spec";
112
- exec: "exec";
113
- qa: "qa";
114
113
  "security-review": "security-review";
114
+ exec: "exec";
115
115
  testgen: "testgen";
116
116
  test: "test";
117
117
  }>>;
118
118
  outcome: z.ZodEnum<{
119
119
  success: "success";
120
- failed: "failed";
121
120
  partial: "partial";
121
+ failed: "failed";
122
122
  }>;
123
123
  duration: z.ZodNumber;
124
124
  model: z.ZodString;
@@ -86,6 +86,29 @@ export declare function getResumablePhases(requestedPhases: readonly string[], c
86
86
  export declare function isPhaseCompletedOrPast(targetPhase: Phase, comments: {
87
87
  body: string;
88
88
  }[]): boolean;
89
+ /**
90
+ * Result of detecting prior QA findings from issue comments.
91
+ */
92
+ export interface PriorQAFindings {
93
+ /** The commit SHA from the last QA phase marker (if present) */
94
+ commitSHA: string | null;
95
+ /** ISO 8601 timestamp of the last QA completion */
96
+ timestamp: string;
97
+ /** Status of the last QA run */
98
+ status: string;
99
+ }
100
+ /**
101
+ * Detect the most recent QA phase marker from issue comments.
102
+ *
103
+ * Extracts the commit SHA and metadata from the latest QA phase marker,
104
+ * enabling incremental re-runs by identifying what changed since last QA.
105
+ *
106
+ * @param comments - Array of objects with a `body` string field
107
+ * @returns Prior QA findings, or null if no QA phase markers found
108
+ */
109
+ export declare function detectPriorQAFindings(comments: {
110
+ body: string;
111
+ }[]): PriorQAFindings | null;
89
112
  /**
90
113
  * Get the current phase status for an issue from GitHub comments.
91
114
  *
@@ -10,7 +10,7 @@
10
10
  * <!-- SEQUANT_PHASE: {"phase":"exec","status":"completed","timestamp":"..."} -->
11
11
  * ```
12
12
  */
13
- import { execSync } from "child_process";
13
+ import { GitHubProvider } from "./platforms/github.js";
14
14
  import { PhaseMarkerSchema, WORKFLOW_PHASES, } from "./state-schema.js";
15
15
  /** Regex to extract phase marker JSON from HTML comments */
16
16
  const PHASE_MARKER_REGEX = /<!-- SEQUANT_PHASE: (\{[^}]+\}) -->/g;
@@ -178,6 +178,37 @@ export function isPhaseCompletedOrPast(targetPhase, comments) {
178
178
  }
179
179
  return false;
180
180
  }
181
+ /**
182
+ * Detect the most recent QA phase marker from issue comments.
183
+ *
184
+ * Extracts the commit SHA and metadata from the latest QA phase marker,
185
+ * enabling incremental re-runs by identifying what changed since last QA.
186
+ *
187
+ * @param comments - Array of objects with a `body` string field
188
+ * @returns Prior QA findings, or null if no QA phase markers found
189
+ */
190
+ export function detectPriorQAFindings(comments) {
191
+ const allMarkers = [];
192
+ for (const comment of comments) {
193
+ const markers = parsePhaseMarkers(comment.body);
194
+ for (const marker of markers) {
195
+ if (marker.phase === "qa") {
196
+ allMarkers.push(marker);
197
+ }
198
+ }
199
+ }
200
+ if (allMarkers.length === 0) {
201
+ return null;
202
+ }
203
+ // Sort by timestamp descending, return latest
204
+ allMarkers.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
205
+ const latest = allMarkers[0];
206
+ return {
207
+ commitSHA: latest.commitSHA ?? null,
208
+ timestamp: latest.timestamp,
209
+ status: latest.status,
210
+ };
211
+ }
181
212
  /**
182
213
  * Get the current phase status for an issue from GitHub comments.
183
214
  *
@@ -187,16 +218,12 @@ export function isPhaseCompletedOrPast(targetPhase, comments) {
187
218
  * @returns Latest phase marker, or null if no markers found or on error
188
219
  */
189
220
  export function getIssuePhase(issueNumber) {
190
- try {
191
- const output = execSync(`gh issue view ${issueNumber} --json comments --jq '[.comments[].body]'`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
192
- const bodies = JSON.parse(output);
193
- const comments = bodies.map((body) => ({ body }));
194
- return detectPhaseFromComments(comments);
195
- }
196
- catch {
197
- // GitHub CLI failure — fall through to normal execution
221
+ const github = new GitHubProvider();
222
+ const bodies = github.fetchIssueCommentBodiesSync(String(issueNumber));
223
+ if (bodies.length === 0)
198
224
  return null;
199
- }
225
+ const comments = bodies.map((body) => ({ body }));
226
+ return detectPhaseFromComments(comments);
200
227
  }
201
228
  /**
202
229
  * Get completed phases for an issue from GitHub comments.
@@ -207,15 +234,10 @@ export function getIssuePhase(issueNumber) {
207
234
  * @returns Array of completed phase names, or empty array on error
208
235
  */
209
236
  export function getCompletedPhases(issueNumber) {
210
- try {
211
- const output = execSync(`gh issue view ${issueNumber} --json comments --jq '[.comments[].body]'`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
212
- const bodies = JSON.parse(output);
213
- const comments = bodies.map((body) => ({ body }));
214
- return getCompletedPhasesFromComments(comments);
215
- }
216
- catch {
217
- return [];
218
- }
237
+ const github = new GitHubProvider();
238
+ const bodies = github.fetchIssueCommentBodiesSync(String(issueNumber));
239
+ const comments = bodies.map((body) => ({ body }));
240
+ return getCompletedPhasesFromComments(comments);
219
241
  }
220
242
  /**
221
243
  * Get resumable phases for an issue from GitHub comments.
@@ -228,14 +250,8 @@ export function getCompletedPhases(issueNumber) {
228
250
  * @returns Filtered phases that still need to run
229
251
  */
230
252
  export function getResumablePhasesForIssue(issueNumber, requestedPhases) {
231
- try {
232
- const output = execSync(`gh issue view ${issueNumber} --json comments --jq '[.comments[].body]'`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
233
- const bodies = JSON.parse(output);
234
- const comments = bodies.map((body) => ({ body }));
235
- return getResumablePhases(requestedPhases, comments);
236
- }
237
- catch {
238
- // On error, return all phases (no filtering)
239
- return [...requestedPhases];
240
- }
253
+ const github = new GitHubProvider();
254
+ const bodies = github.fetchIssueCommentBodiesSync(String(issueNumber));
255
+ const comments = bodies.map((body) => ({ body }));
256
+ return getResumablePhases(requestedPhases, comments);
241
257
  }
@@ -1,19 +1,56 @@
1
1
  /**
2
2
  * Phase execution engine for workflow orchestration.
3
3
  *
4
- * Handles executing individual phases via the Claude Agent SDK,
4
+ * Handles executing individual phases via an AgentDriver interface,
5
5
  * including cold-start retry logic and MCP fallback strategies.
6
+ *
7
+ * The SDK import has been moved to ClaudeCodeDriver — this module
8
+ * is agent-agnostic.
6
9
  */
7
10
  import { ShutdownManager } from "../shutdown.js";
8
11
  import { PhaseSpinner } from "../phase-spinner.js";
9
12
  import { Phase, ExecutionConfig, PhaseResult, QaVerdict } from "./types.js";
13
+ import type { QaSummary } from "./run-log-schema.js";
14
+ /**
15
+ * Spec-specific retry configuration.
16
+ * Spec failures have a higher failure rate (~8.6%) than other phases due to
17
+ * transient GitHub API issues and rate limits. One extra retry with backoff
18
+ * recovers most of these without user intervention.
19
+ */
20
+ /** @internal Exported for testing only */
21
+ export declare const SPEC_RETRY_BACKOFF_MS = 5000;
22
+ /** @internal Exported for testing only */
23
+ export declare const SPEC_EXTRA_RETRIES = 1;
10
24
  export declare function parseQaVerdict(output: string): QaVerdict | null;
25
+ /**
26
+ * Parse condensed QA summary from QA phase output (#434).
27
+ *
28
+ * Handles multiple AC table formats produced by the QA skill:
29
+ * - 5-column: | AC-N | source | desc | STATUS | notes |
30
+ * - 4-column: | AC-N | desc | STATUS | notes |
31
+ * - 3-column: | AC-N | desc | STATUS |
32
+ *
33
+ * Status cells may contain emoji prefixes (✅ MET), shorthand
34
+ * (PARTIAL), or trailing text (MET — explanation).
35
+ *
36
+ * @internal Exported for testing only
37
+ */
38
+ export declare function parseQaSummary(output: string): QaSummary | null;
11
39
  /**
12
40
  * Format duration in human-readable format
13
41
  */
14
42
  export declare function formatDuration(seconds: number): string;
15
43
  /**
16
- * Execute a single phase for an issue using Claude Agent SDK
44
+ * Get the prompt for a phase with the issue number substituted.
45
+ * Selects self-contained prompts for non-Claude agents.
46
+ * Includes AGENTS.md content as context so non-Claude agents
47
+ * receive project conventions and workflow instructions.
48
+ *
49
+ * @internal Exported for testing only
50
+ */
51
+ export declare function getPhasePrompt(phase: Phase, issueNumber: number, agent?: string): Promise<string>;
52
+ /**
53
+ * Execute a single phase for an issue using the configured AgentDriver.
17
54
  */
18
55
  declare function executePhase(issueNumber: number, phase: Phase, config: ExecutionConfig, sessionId?: string, worktreePath?: string, shutdownManager?: ShutdownManager, spinner?: PhaseSpinner): Promise<PhaseResult & {
19
56
  sessionId?: string;
@@ -34,7 +71,9 @@ declare function executePhase(issueNumber: number, phase: Phase, config: Executi
34
71
  */
35
72
  export declare function executePhaseWithRetry(issueNumber: number, phase: Phase, config: ExecutionConfig, sessionId?: string, worktreePath?: string, shutdownManager?: ShutdownManager, spinner?: PhaseSpinner,
36
73
  /** @internal Injected for testing — defaults to module-level executePhase */
37
- executePhaseFn?: typeof executePhase): Promise<PhaseResult & {
74
+ executePhaseFn?: typeof executePhase,
75
+ /** @internal Injected for testing — defaults to setTimeout-based delay */
76
+ delayFn?: (ms: number) => Promise<void>): Promise<PhaseResult & {
38
77
  sessionId?: string;
39
78
  }>;
40
79
  export {};