sequant 1.15.2 → 1.15.4

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 (43) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/bin/cli.js +4 -0
  3. package/dist/src/commands/logs.js +15 -0
  4. package/dist/src/commands/run.d.ts +150 -1
  5. package/dist/src/commands/run.js +642 -31
  6. package/dist/src/commands/stats.js +48 -0
  7. package/dist/src/lib/scope/index.d.ts +1 -0
  8. package/dist/src/lib/scope/index.js +2 -0
  9. package/dist/src/lib/scope/settings-converter.d.ts +28 -0
  10. package/dist/src/lib/scope/settings-converter.js +53 -0
  11. package/dist/src/lib/settings.d.ts +45 -0
  12. package/dist/src/lib/settings.js +30 -0
  13. package/dist/src/lib/test-tautology-detector.d.ts +122 -0
  14. package/dist/src/lib/test-tautology-detector.js +488 -0
  15. package/dist/src/lib/workflow/git-diff-utils.d.ts +39 -0
  16. package/dist/src/lib/workflow/git-diff-utils.js +142 -0
  17. package/dist/src/lib/workflow/log-writer.d.ts +13 -2
  18. package/dist/src/lib/workflow/log-writer.js +25 -3
  19. package/dist/src/lib/workflow/metrics-schema.d.ts +9 -0
  20. package/dist/src/lib/workflow/metrics-schema.js +10 -1
  21. package/dist/src/lib/workflow/phase-detection.d.ts +3 -0
  22. package/dist/src/lib/workflow/phase-detection.js +27 -1
  23. package/dist/src/lib/workflow/qa-cache.d.ts +3 -1
  24. package/dist/src/lib/workflow/qa-cache.js +2 -0
  25. package/dist/src/lib/workflow/run-log-schema.d.ts +90 -3
  26. package/dist/src/lib/workflow/run-log-schema.js +44 -2
  27. package/dist/src/lib/workflow/state-utils.d.ts +46 -0
  28. package/dist/src/lib/workflow/state-utils.js +167 -0
  29. package/dist/src/lib/workflow/token-utils.d.ts +92 -0
  30. package/dist/src/lib/workflow/token-utils.js +170 -0
  31. package/dist/src/lib/workflow/types.d.ts +10 -0
  32. package/dist/src/lib/workflow/types.js +1 -0
  33. package/package.json +1 -1
  34. package/templates/hooks/pre-tool.sh +4 -0
  35. package/templates/skills/assess/SKILL.md +1 -1
  36. package/templates/skills/exec/SKILL.md +6 -4
  37. package/templates/skills/improve/SKILL.md +37 -24
  38. package/templates/skills/loop/SKILL.md +3 -3
  39. package/templates/skills/qa/references/code-review-checklist.md +10 -11
  40. package/templates/skills/qa/scripts/quality-checks.sh +16 -0
  41. package/templates/skills/security-review/references/security-checklists.md +89 -36
  42. package/templates/skills/solve/SKILL.md +3 -1
  43. package/templates/skills/spec/SKILL.md +8 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sequant",
3
3
  "description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases",
4
- "version": "1.15.2",
4
+ "version": "1.15.4",
5
5
  "author": {
6
6
  "name": "sequant-io",
7
7
  "email": "hello@sequant.io"
package/dist/bin/cli.js CHANGED
@@ -139,7 +139,11 @@ program
139
139
  .option("--qa-gate", "Wait for QA pass before starting next issue in chain (requires --chain)")
140
140
  .option("--base <branch>", "Base branch for worktree creation (default: main or settings.run.defaultBase)")
141
141
  .option("--no-mcp", "Disable MCP server injection in headless mode")
142
+ .option("--no-retry", "Disable automatic retry with MCP fallback (useful for debugging)")
142
143
  .option("--resume", "Resume from last completed phase (reads phase markers from GitHub)")
144
+ .option("--no-rebase", "Skip pre-PR rebase onto origin/main (use when you want to handle rebasing manually)")
145
+ .option("--no-pr", "Skip PR creation after successful QA (manual PR workflow)")
146
+ .option("-f, --force", "Force re-execution of completed issues (bypass pre-flight state guard)")
143
147
  .action(runCommand);
144
148
  program
145
149
  .command("logs")
@@ -112,6 +112,21 @@ function displayLogSummary(log, filename) {
112
112
  const phaseDuration = chalk.gray(`(${formatDuration(phase.durationSeconds)})`);
113
113
  const error = phase.error ? chalk.red(` - ${phase.error}`) : "";
114
114
  console.log(` ${phaseStatus} ${phase.phase} ${phaseDuration}${error}`);
115
+ // Show observability data (AC-9)
116
+ if (phase.commitHash) {
117
+ console.log(chalk.gray(` commit: ${phase.commitHash.slice(0, 8)}`));
118
+ }
119
+ if (phase.filesModified && phase.filesModified.length > 0) {
120
+ console.log(chalk.gray(` files: ${phase.filesModified.length} modified`));
121
+ }
122
+ if (phase.fileDiffStats && phase.fileDiffStats.length > 0) {
123
+ const totalAdditions = phase.fileDiffStats.reduce((sum, f) => sum + f.additions, 0);
124
+ const totalDeletions = phase.fileDiffStats.reduce((sum, f) => sum + f.deletions, 0);
125
+ console.log(chalk.gray(` diff: +${totalAdditions}/-${totalDeletions} lines`));
126
+ }
127
+ if (phase.cacheMetrics) {
128
+ console.log(chalk.gray(` cache: ${phase.cacheMetrics.hits} hits, ${phase.cacheMetrics.misses} misses, ${phase.cacheMetrics.skipped} skipped`));
129
+ }
115
130
  }
116
131
  }
117
132
  }
@@ -4,7 +4,9 @@
4
4
  * Runs the Sequant workflow (/spec → /exec → /qa) for one or more issues
5
5
  * using the Claude Agent SDK for proper skill invocation.
6
6
  */
7
- import { Phase, QaVerdict } from "../lib/workflow/types.js";
7
+ import { Phase, ExecutionConfig, PhaseResult, QaVerdict } from "../lib/workflow/types.js";
8
+ import { ShutdownManager } from "../lib/shutdown.js";
9
+ import { PhaseSpinner } from "../lib/phase-spinner.js";
8
10
  /**
9
11
  * Parse QA verdict from phase output
10
12
  *
@@ -17,6 +19,36 @@ import { Phase, QaVerdict } from "../lib/workflow/types.js";
17
19
  * @returns The parsed verdict or null if not found
18
20
  */
19
21
  export declare function parseQaVerdict(output: string): QaVerdict | null;
22
+ /**
23
+ * Result of worktree freshness check
24
+ */
25
+ interface WorktreeFreshnessResult {
26
+ /** True if worktree is stale (significantly behind main) */
27
+ isStale: boolean;
28
+ /** Number of commits behind origin/main */
29
+ commitsBehind: number;
30
+ /** True if worktree has uncommitted changes */
31
+ hasUncommittedChanges: boolean;
32
+ /** True if worktree has unpushed commits */
33
+ hasUnpushedCommits: boolean;
34
+ }
35
+ /**
36
+ * Check if a worktree is stale (behind origin/main) and should be recreated
37
+ *
38
+ * @param worktreePath - Path to the worktree
39
+ * @param verbose - Enable verbose output
40
+ * @returns Freshness check result
41
+ */
42
+ export declare function checkWorktreeFreshness(worktreePath: string, verbose: boolean): WorktreeFreshnessResult;
43
+ /**
44
+ * Remove and recreate a stale worktree
45
+ *
46
+ * @param existingPath - Path to existing worktree
47
+ * @param branch - Branch name
48
+ * @param verbose - Enable verbose output
49
+ * @returns true if worktree was removed
50
+ */
51
+ export declare function removeStaleWorktree(existingPath: string, branch: string, verbose: boolean): boolean;
20
52
  /**
21
53
  * List all active worktrees with their branches
22
54
  */
@@ -59,6 +91,75 @@ export declare function filterResumedPhases(issueNumber: number, phases: Phase[]
59
91
  * @internal Exported for testing
60
92
  */
61
93
  export declare function createCheckpointCommit(worktreePath: string, issueNumber: number, verbose: boolean): boolean;
94
+ /**
95
+ * Check if any lockfile changed during a rebase and re-run install if needed.
96
+ * This prevents dependency drift when the lockfile was updated on main.
97
+ * @param worktreePath Path to the worktree
98
+ * @param packageManager Package manager to use for install
99
+ * @param verbose Whether to show verbose output
100
+ * @param preRebaseRef Git ref pointing to pre-rebase HEAD (defaults to ORIG_HEAD,
101
+ * which git sets automatically after rebase). Using ORIG_HEAD captures all
102
+ * lockfile changes across multi-commit rebases, unlike HEAD~1 which only
103
+ * checks the last commit.
104
+ * @returns true if reinstall was performed, false otherwise
105
+ * @internal Exported for testing
106
+ */
107
+ export declare function reinstallIfLockfileChanged(worktreePath: string, packageManager: string | undefined, verbose: boolean, preRebaseRef?: string): boolean;
108
+ /**
109
+ * Result of a pre-PR rebase operation
110
+ */
111
+ export interface RebaseResult {
112
+ /** Whether the rebase was performed */
113
+ performed: boolean;
114
+ /** Whether the rebase succeeded */
115
+ success: boolean;
116
+ /** Whether dependencies were reinstalled */
117
+ reinstalled: boolean;
118
+ /** Error message if rebase failed */
119
+ error?: string;
120
+ }
121
+ /**
122
+ * Rebase the worktree branch onto origin/main before PR creation.
123
+ * This ensures the branch is up-to-date and prevents lockfile drift.
124
+ *
125
+ * @param worktreePath Path to the worktree
126
+ * @param issueNumber Issue number (for logging)
127
+ * @param packageManager Package manager to use if reinstall needed
128
+ * @param verbose Whether to show verbose output
129
+ * @returns RebaseResult indicating success/failure and whether reinstall was performed
130
+ * @internal Exported for testing
131
+ */
132
+ export declare function rebaseBeforePR(worktreePath: string, issueNumber: number, packageManager: string | undefined, verbose: boolean): RebaseResult;
133
+ /**
134
+ * Result of PR creation
135
+ */
136
+ export interface PRCreationResult {
137
+ /** Whether PR creation was attempted */
138
+ attempted: boolean;
139
+ /** Whether PR was created successfully (or already existed) */
140
+ success: boolean;
141
+ /** PR number */
142
+ prNumber?: number;
143
+ /** PR URL */
144
+ prUrl?: string;
145
+ /** Error message if failed */
146
+ error?: string;
147
+ }
148
+ /**
149
+ * Push branch and create a PR after successful QA.
150
+ *
151
+ * Handles both fresh PR creation and detection of existing PRs.
152
+ * Failures are warnings — they don't fail the run.
153
+ *
154
+ * @param worktreePath Path to the worktree
155
+ * @param issueNumber Issue number
156
+ * @param issueTitle Issue title (for PR title)
157
+ * @param branch Branch name
158
+ * @param verbose Whether to show verbose output
159
+ * @returns PRCreationResult with PR info or error
160
+ * @internal Exported for testing
161
+ */
162
+ export declare function createPR(worktreePath: string, issueNumber: number, issueTitle: string, branch: string, verbose: boolean, labels?: string[]): PRCreationResult;
62
163
  /**
63
164
  * Detect phases based on issue labels (like /solve logic)
64
165
  */
@@ -124,7 +225,55 @@ interface RunOptions {
124
225
  * Reads phase markers from GitHub issue comments and skips completed phases.
125
226
  */
126
227
  resume?: boolean;
228
+ /**
229
+ * Disable automatic retry with MCP fallback.
230
+ * When true, no retry attempts are made on phase failure.
231
+ * Useful for debugging to see the actual failure without retry masking it.
232
+ */
233
+ noRetry?: boolean;
234
+ /**
235
+ * Skip pre-PR rebase onto origin/main.
236
+ * When true, branches are not rebased before creating the PR.
237
+ * Use when you want to preserve branch state or handle rebasing manually.
238
+ */
239
+ noRebase?: boolean;
240
+ /**
241
+ * Skip PR creation after successful QA.
242
+ * When true, branches are pushed but no PR is created.
243
+ * Useful for manual workflows where PRs are created separately.
244
+ */
245
+ noPr?: boolean;
246
+ /**
247
+ * Force re-execution of issues even if they have completed status.
248
+ * Bypasses the pre-flight state guard that skips ready_for_merge/merged issues.
249
+ */
250
+ force?: boolean;
127
251
  }
252
+ /**
253
+ * Execute a single phase for an issue using Claude Agent SDK
254
+ */
255
+ declare function executePhase(issueNumber: number, phase: Phase, config: ExecutionConfig, sessionId?: string, worktreePath?: string, shutdownManager?: ShutdownManager, spinner?: PhaseSpinner): Promise<PhaseResult & {
256
+ sessionId?: string;
257
+ }>;
258
+ /**
259
+ * Execute a phase with automatic retry for cold-start failures and MCP fallback.
260
+ *
261
+ * Retry strategy:
262
+ * 1. If phase fails within COLD_START_THRESHOLD_SECONDS, retry up to COLD_START_MAX_RETRIES times
263
+ * 2. If still failing and MCP is enabled, retry once with MCP disabled (npx-based MCP servers
264
+ * can fail on first run due to cold-cache issues)
265
+ *
266
+ * The MCP fallback is safe because MCP servers are optional enhancements, not required
267
+ * for core functionality.
268
+ */
269
+ /**
270
+ * @internal Exported for testing only
271
+ */
272
+ export declare function executePhaseWithRetry(issueNumber: number, phase: Phase, config: ExecutionConfig, sessionId?: string, worktreePath?: string, shutdownManager?: ShutdownManager, spinner?: PhaseSpinner,
273
+ /** @internal Injected for testing — defaults to module-level executePhase */
274
+ executePhaseFn?: typeof executePhase): Promise<PhaseResult & {
275
+ sessionId?: string;
276
+ }>;
128
277
  /**
129
278
  * Main run command
130
279
  */