sequant 1.15.1 → 1.15.2

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.
@@ -3,8 +3,8 @@
3
3
  "name": "sequant",
4
4
  "description": "Sequant plugin marketplace - structured workflow system for Claude Code",
5
5
  "owner": {
6
- "name": "admarble",
7
- "email": "github@admarble.com"
6
+ "name": "sequant-io",
7
+ "email": "hello@sequant.io"
8
8
  },
9
9
  "plugins": [
10
10
  {
@@ -12,8 +12,8 @@
12
12
  "description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases. Includes 16 skills for planning, implementation, testing, code review, and quality assurance.",
13
13
  "version": "1.13.0",
14
14
  "author": {
15
- "name": "admarble",
16
- "email": "github@admarble.com"
15
+ "name": "sequant-io",
16
+ "email": "hello@sequant.io"
17
17
  },
18
18
  "source": "./",
19
19
  "category": "workflow"
@@ -1,9 +1,9 @@
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.1",
4
+ "version": "1.15.2",
5
5
  "author": {
6
- "name": "admarble",
7
- "email": "github@admarble.com"
6
+ "name": "sequant-io",
7
+ "email": "hello@sequant.io"
8
8
  }
9
9
  }
package/README.md CHANGED
@@ -238,9 +238,9 @@ Stack guides: [Next.js](docs/stacks/nextjs.md) · [Rust](docs/stacks/rust.md) ·
238
238
 
239
239
  ### Reporting Issues
240
240
 
241
- - **Bug reports:** [Bug template](https://github.com/admarble/sequant/issues/new?template=bug.yml)
242
- - **Feature requests:** [Feature template](https://github.com/admarble/sequant/issues/new?template=feature.yml)
243
- - **Questions:** [GitHub Discussions](https://github.com/admarble/sequant/discussions)
241
+ - **Bug reports:** [Bug template](https://github.com/sequant-io/sequant/issues/new?template=bug.yml)
242
+ - **Feature requests:** [Feature template](https://github.com/sequant-io/sequant/issues/new?template=feature.yml)
243
+ - **Questions:** [GitHub Discussions](https://github.com/sequant-io/sequant/discussions)
244
244
 
245
245
  ### Using `/improve` for Feedback
246
246
 
@@ -407,5 +407,5 @@ export async function initCommand(options) {
407
407
  if (optionalSection) {
408
408
  console.log(optionalSection);
409
409
  }
410
- console.log(chalk.gray("\nDocumentation: https://github.com/admarble/sequant#readme\n"));
410
+ console.log(chalk.gray("\nDocumentation: https://github.com/sequant-io/sequant#readme\n"));
411
411
  }
@@ -201,6 +201,47 @@ async function ensureWorktree(issueNumber, title, verbose, packageManager, baseB
201
201
  if (verbose) {
202
202
  console.log(chalk.gray(` 📂 Reusing existing worktree: ${existingPath}`));
203
203
  }
204
+ // In chain mode, rebase existing worktree onto previous chain link
205
+ if (chainMode && baseBranch) {
206
+ if (verbose) {
207
+ console.log(chalk.gray(` 🔄 Rebasing existing worktree onto chain base (${baseBranch})...`));
208
+ }
209
+ const rebaseResult = spawnSync("git", ["-C", existingPath, "rebase", baseBranch], { stdio: "pipe" });
210
+ if (rebaseResult.status !== 0) {
211
+ const rebaseError = rebaseResult.stderr.toString();
212
+ // Check if it's a conflict
213
+ if (rebaseError.includes("CONFLICT") ||
214
+ rebaseError.includes("could not apply")) {
215
+ console.log(chalk.yellow(` ⚠️ Rebase conflict detected. Aborting rebase and keeping original branch state.`));
216
+ console.log(chalk.yellow(` ℹ️ Branch ${branch} is not properly chained. Manual rebase may be required.`));
217
+ // Abort the rebase to restore branch state
218
+ spawnSync("git", ["-C", existingPath, "rebase", "--abort"], {
219
+ stdio: "pipe",
220
+ });
221
+ }
222
+ else {
223
+ console.log(chalk.yellow(` ⚠️ Rebase failed: ${rebaseError.trim()}`));
224
+ console.log(chalk.yellow(` ℹ️ Continuing with branch in its original state.`));
225
+ }
226
+ return {
227
+ issue: issueNumber,
228
+ path: existingPath,
229
+ branch,
230
+ existed: true,
231
+ rebased: false,
232
+ };
233
+ }
234
+ if (verbose) {
235
+ console.log(chalk.green(` ✅ Existing worktree rebased onto ${baseBranch}`));
236
+ }
237
+ return {
238
+ issue: issueNumber,
239
+ path: existingPath,
240
+ branch,
241
+ existed: true,
242
+ rebased: true,
243
+ };
244
+ }
204
245
  return {
205
246
  issue: issueNumber,
206
247
  path: existingPath,
@@ -444,9 +485,7 @@ export function createCheckpointCommit(worktreePath, issueNumber, verbose) {
444
485
  const commitMessage = `checkpoint(#${issueNumber}): QA passed
445
486
 
446
487
  This is an automatic checkpoint commit created after issue #${issueNumber}
447
- passed QA in chain mode. It serves as a recovery point if later issues fail.
448
-
449
- Co-Authored-By: Sequant <noreply@sequant.dev>`;
488
+ passed QA in chain mode. It serves as a recovery point if later issues fail.`;
450
489
  const commitResult = spawnSync("git", ["-C", worktreePath, "commit", "-m", commitMessage], { stdio: "pipe" });
451
490
  if (commitResult.status !== 0) {
452
491
  const error = commitResult.stderr.toString();
@@ -671,6 +710,11 @@ async function executePhase(issueNumber, phase, config, sessionId, worktreePath,
671
710
  // Get MCP servers config if enabled
672
711
  // Reads from Claude Desktop config and passes to SDK for headless MCP support
673
712
  const mcpServers = config.mcp ? getMcpServersConfig() : undefined;
713
+ // Track whether we're actively streaming verbose output
714
+ // Pausing spinner once per streaming session prevents truncation from rapid pause/resume cycles
715
+ // (Issue #283: ora's stop() clears the current line, which can truncate output when
716
+ // pause/resume is called for every chunk in rapid succession)
717
+ let verboseStreamingActive = false;
674
718
  const queryInstance = query({
675
719
  prompt,
676
720
  options: {
@@ -693,10 +737,14 @@ async function executePhase(issueNumber, phase, config, sessionId, worktreePath,
693
737
  // Capture stderr for debugging (helps diagnose early exit failures)
694
738
  stderr: (data) => {
695
739
  capturedStderr += data;
740
+ // Write stderr in verbose mode
696
741
  if (config.verbose) {
697
- spinner?.pause();
742
+ // Pause spinner once to avoid truncation (Issue #283)
743
+ if (!verboseStreamingActive) {
744
+ spinner?.pause();
745
+ verboseStreamingActive = true;
746
+ }
698
747
  process.stderr.write(chalk.red(data));
699
- spinner?.resume();
700
748
  }
701
749
  },
702
750
  },
@@ -719,10 +767,13 @@ async function executePhase(issueNumber, phase, config, sessionId, worktreePath,
719
767
  capturedOutput += textContent;
720
768
  // Show streaming output in verbose mode
721
769
  if (config.verbose) {
722
- // Pause spinner during verbose streaming to avoid terminal corruption
723
- spinner?.pause();
770
+ // Pause spinner once at start of streaming to avoid truncation
771
+ // (Issue #283: repeated pause/resume causes ora to clear lines between chunks)
772
+ if (!verboseStreamingActive) {
773
+ spinner?.pause();
774
+ verboseStreamingActive = true;
775
+ }
724
776
  process.stdout.write(chalk.gray(textContent));
725
- spinner?.resume();
726
777
  }
727
778
  }
728
779
  }
@@ -731,6 +782,11 @@ async function executePhase(issueNumber, phase, config, sessionId, worktreePath,
731
782
  resultMessage = message;
732
783
  }
733
784
  }
785
+ // Resume spinner after streaming completes (if we paused it)
786
+ if (verboseStreamingActive) {
787
+ spinner?.resume();
788
+ verboseStreamingActive = false;
789
+ }
734
790
  clearTimeout(timeoutId);
735
791
  // Clear abort controller from shutdown manager
736
792
  if (shutdownManager) {
@@ -1190,6 +1246,8 @@ export async function runCommand(issues, options) {
1190
1246
  sequential: config.sequential,
1191
1247
  qualityLoop: config.qualityLoop,
1192
1248
  maxIterations: config.maxIterations,
1249
+ chain: mergedOptions.chain,
1250
+ qaGate: mergedOptions.qaGate,
1193
1251
  };
1194
1252
  logWriter = new LogWriter({
1195
1253
  logPath: mergedOptions.logPath ?? settings.run.logPath,
@@ -57,7 +57,7 @@ async function execCommand(command, args) {
57
57
  /**
58
58
  * Check if a similar upstream issue already exists
59
59
  */
60
- export async function checkForDuplicate(title, owner = "admarble", repo = "sequant") {
60
+ export async function checkForDuplicate(title, owner = "sequant-io", repo = "sequant") {
61
61
  try {
62
62
  validateRepoParams(owner, repo);
63
63
  // Search for existing upstream issues with similar title
@@ -152,7 +152,7 @@ export function isSimilarTitle(title1, title2) {
152
152
  * Create a GitHub issue using a temporary file for the body
153
153
  * This avoids any shell escaping issues with complex markdown content
154
154
  */
155
- export async function createIssue(params, owner = "admarble", repo = "sequant") {
155
+ export async function createIssue(params, owner = "sequant-io", repo = "sequant") {
156
156
  validateRepoParams(owner, repo);
157
157
  // Write body to a temp file to avoid any escaping issues
158
158
  const tempFile = join(tmpdir(), `gh-issue-body-${Date.now()}.md`);
@@ -193,7 +193,7 @@ export async function createIssue(params, owner = "admarble", repo = "sequant")
193
193
  /**
194
194
  * Add a comment to an existing issue
195
195
  */
196
- export async function addIssueComment(issueNumber, comment, owner = "admarble", repo = "sequant") {
196
+ export async function addIssueComment(issueNumber, comment, owner = "sequant-io", repo = "sequant") {
197
197
  validateRepoParams(owner, repo);
198
198
  // Validate issue number
199
199
  if (!Number.isInteger(issueNumber) || issueNumber < 1) {
@@ -226,7 +226,7 @@ export async function addIssueComment(issueNumber, comment, owner = "admarble",
226
226
  /**
227
227
  * Create or link an issue for a finding
228
228
  */
229
- export async function createOrLinkFinding(finding, version, assessmentIssueNumber, dryRun = false, owner = "admarble", repo = "sequant") {
229
+ export async function createOrLinkFinding(finding, version, assessmentIssueNumber, dryRun = false, owner = "sequant-io", repo = "sequant") {
230
230
  // Generate issue content
231
231
  const issueContent = generateFindingIssue(finding, version, assessmentIssueNumber);
232
232
  // Check for duplicate
@@ -254,7 +254,7 @@ export async function createOrLinkFinding(finding, version, assessmentIssueNumbe
254
254
  /**
255
255
  * Create the assessment summary issue
256
256
  */
257
- export async function createAssessmentIssue(title, body, dryRun = false, owner = "admarble", repo = "sequant") {
257
+ export async function createAssessmentIssue(title, body, dryRun = false, owner = "sequant-io", repo = "sequant") {
258
258
  if (dryRun) {
259
259
  return undefined;
260
260
  }
@@ -157,6 +157,8 @@ export declare const RunConfigSchema: z.ZodObject<{
157
157
  sequential: z.ZodBoolean;
158
158
  qualityLoop: z.ZodBoolean;
159
159
  maxIterations: z.ZodNumber;
160
+ chain: z.ZodOptional<z.ZodBoolean>;
161
+ qaGate: z.ZodOptional<z.ZodBoolean>;
160
162
  }, z.core.$strip>;
161
163
  export type RunConfig = z.infer<typeof RunConfigSchema>;
162
164
  /**
@@ -192,6 +194,8 @@ export declare const RunLogSchema: z.ZodObject<{
192
194
  sequential: z.ZodBoolean;
193
195
  qualityLoop: z.ZodBoolean;
194
196
  maxIterations: z.ZodNumber;
197
+ chain: z.ZodOptional<z.ZodBoolean>;
198
+ qaGate: z.ZodOptional<z.ZodBoolean>;
195
199
  }, z.core.$strip>;
196
200
  issues: z.ZodArray<z.ZodObject<{
197
201
  issueNumber: z.ZodNumber;
@@ -109,6 +109,10 @@ export const RunConfigSchema = z.object({
109
109
  qualityLoop: z.boolean(),
110
110
  /** Maximum iterations for fix loops */
111
111
  maxIterations: z.number().int().positive(),
112
+ /** Whether chain mode was enabled (each issue branches from previous) */
113
+ chain: z.boolean().optional(),
114
+ /** Whether QA gate was enabled (chain pauses if QA fails) */
115
+ qaGate: z.boolean().optional(),
112
116
  });
113
117
  /**
114
118
  * Summary statistics for a run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sequant",
3
- "version": "1.15.1",
3
+ "version": "1.15.2",
4
4
  "description": "Quantize your development workflow - Sequential AI phases with quality gates",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,12 +45,12 @@
45
45
  "license": "MIT",
46
46
  "repository": {
47
47
  "type": "git",
48
- "url": "git+https://github.com/admarble/sequant.git"
48
+ "url": "git+https://github.com/sequant-io/sequant.git"
49
49
  },
50
50
  "bugs": {
51
- "url": "https://github.com/admarble/sequant/issues"
51
+ "url": "https://github.com/sequant-io/sequant/issues"
52
52
  },
53
- "homepage": "https://github.com/admarble/sequant#readme",
53
+ "homepage": "https://github.com/sequant-io/sequant#readme",
54
54
  "engines": {
55
55
  "node": ">=18.0.0"
56
56
  },
@@ -369,7 +369,7 @@ fi
369
369
 
370
370
  **If no verification evidence exists:**
371
371
  1. Prompt: "Script changes detected but no execution verification found. Run `/verify <issue> --command \"<test command>\"` before READY_FOR_MERGE verdict."
372
- 2. Do NOT give `READY_FOR_MERGE` verdict until verification is complete
372
+ 2. Do NOT give `READY_FOR_MERGE` verdict until verification is complete (unless an approved override applies — see Section 9a)
373
373
  3. Verdict should be `AC_MET_BUT_NOT_A_PLUS` with note about missing verification
374
374
 
375
375
  **Why this matters:**
@@ -389,6 +389,59 @@ fi
389
389
  /qa 558 # Re-run, now sees verification, can give READY_FOR_MERGE
390
390
  ```
391
391
 
392
+ ### 9a. Script Verification Override
393
+
394
+ In some cases, `/verify` execution can be safely skipped when script changes are purely cosmetic or have no runtime impact. **Overrides require explicit justification and risk assessment.**
395
+
396
+ **Override Format (REQUIRED when skipping /verify):**
397
+
398
+ ```markdown
399
+ ### Script Verification Override
400
+
401
+ **Requirement:** `/verify` before READY_FOR_MERGE
402
+ **Override:** Yes
403
+ **Justification:** [One of the approved categories below]
404
+ **Risk Assessment:** [None/Low/Medium]
405
+ ```
406
+
407
+ **Approved Override Categories:**
408
+
409
+ | Category | Example | Risk |
410
+ |----------|---------|------|
411
+ | Syntax-only refactor | `catch (error)` → `catch` | None |
412
+ | Comment/documentation changes | Adding JSDoc, updating comments | None |
413
+ | Type annotation additions | Adding `: string`, `: number` | None |
414
+ | Import reorganization | Sorting imports, removing unused | None |
415
+ | Variable rename (no logic change) | `foo` → `bar` with no behavioral change | Low |
416
+ | Dead code removal | Removing unreachable branches | Low |
417
+
418
+ **NOT Approved for Override (always require /verify):**
419
+
420
+ | Category | Example | Why |
421
+ |----------|---------|-----|
422
+ | Logic changes | Modified conditionals, new branches | Runtime behavior changes |
423
+ | New functionality | Added functions, new exports | Must verify execution |
424
+ | Dependency changes | Updated imports from new packages | May affect runtime |
425
+ | Error handling changes | Modified catch blocks, new try/catch | Failure paths change |
426
+ | Configuration changes | Modified env vars, config parsing | Environment-dependent |
427
+
428
+ **Risk Assessment Definitions:**
429
+
430
+ | Level | Meaning | Criteria |
431
+ |-------|---------|----------|
432
+ | **None** | Zero runtime impact | Change is invisible at runtime (comments, types, syntax) |
433
+ | **Low** | Negligible runtime impact | Change is cosmetic (rename, dead code) with no logical effect |
434
+ | **Medium** | Possible runtime impact | Change touches executable code but appears safe — **should NOT be overridden** |
435
+
436
+ **Override Decision Flow:**
437
+
438
+ 1. Check if change matches an approved category → If no, `/verify` is required
439
+ 2. Assess risk level → If Medium or higher, `/verify` is required
440
+ 3. Document override using the format above in the QA output
441
+ 4. Include override in the GitHub issue comment for audit trail
442
+
443
+ **CRITICAL:** When in doubt, run `/verify`. Overrides are for clear-cut cases only. If you need to argue that a change is safe, it probably needs verification.
444
+
392
445
  ---
393
446
 
394
447
  ## Output Verification
@@ -399,6 +452,7 @@ fi
399
452
  - [ ] **Verdict** - One of: READY_FOR_MERGE, AC_MET_BUT_NOT_A_PLUS, AC_NOT_MET
400
453
  - [ ] **Quality Metrics** - Type issues, deleted tests, files changed, additions/deletions
401
454
  - [ ] **Code Review Findings** - Strengths, issues, suggestions
455
+ - [ ] **Script Verification Override** - Included if scripts/CLI modified AND /verify was skipped (with justification and risk assessment)
402
456
  - [ ] **Documentation Check** - README/docs updated if feature adds new functionality
403
457
  - [ ] **Next Steps** - Clear, actionable recommendations
404
458
 
@@ -447,6 +501,17 @@ You MUST include these sections:
447
501
 
448
502
  ---
449
503
 
504
+ ### Script Verification Override
505
+
506
+ [Include if scripts/CLI modified AND /verify was skipped, otherwise omit this section]
507
+
508
+ **Requirement:** `/verify` before READY_FOR_MERGE
509
+ **Override:** Yes
510
+ **Justification:** [Approved category from Section 9a]
511
+ **Risk Assessment:** [None/Low/Medium]
512
+
513
+ ---
514
+
450
515
  ### Verdict: [READY_FOR_MERGE | AC_MET_BUT_NOT_A_PLUS | AC_NOT_MET]
451
516
 
452
517
  [Explanation of verdict]