sequant 2.7.0 → 2.9.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 +18 -2
- package/dist/bin/cli.d.ts +1 -1
- package/dist/bin/cli.js +12 -2
- package/dist/bin/preflight.d.ts +21 -0
- package/dist/bin/preflight.js +45 -0
- package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
- package/dist/marketplace/external_plugins/sequant/README.md +2 -0
- package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +18 -3
- package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +330 -57
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/force-push.md +34 -0
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +117 -19
- package/dist/marketplace/external_plugins/sequant/skills/assess/references/predicted-collision-detection.md +9 -6
- package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +29 -0
- package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +100 -2
- package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +24 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/anti-pattern-detection.md +285 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/call-site-review.md +202 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +287 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/test-quality-checklist.md +272 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +40 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +95 -11
- package/dist/marketplace/external_plugins/sequant/skills/references/shared/framework-gotchas.md +186 -0
- package/dist/marketplace/external_plugins/sequant/skills/reflect/SKILL.md +27 -13
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/documentation-tiers.md +80 -68
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/phase-reflection.md +31 -15
- package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +669 -0
- package/dist/marketplace/external_plugins/sequant/skills/spec/references/verification-criteria.md +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/test/references/browser-testing-patterns.md +423 -0
- package/dist/marketplace/external_plugins/sequant/skills/upstream/SKILL.md +419 -0
- package/dist/src/commands/logs.js +6 -1
- package/dist/src/commands/run-display.d.ts +20 -0
- package/dist/src/commands/run-display.js +80 -1
- package/dist/src/commands/stats.js +47 -0
- package/dist/src/lib/assess-collision-detect.d.ts +19 -2
- package/dist/src/lib/assess-collision-detect.js +68 -4
- package/dist/src/lib/cli-ui/run-renderer.js +17 -9
- package/dist/src/lib/errors.d.ts +91 -0
- package/dist/src/lib/errors.js +118 -0
- package/dist/src/lib/manifest.js +1 -17
- package/dist/src/lib/version-check.d.ts +19 -0
- package/dist/src/lib/version-check.js +45 -5
- package/dist/src/lib/workflow/batch-executor.d.ts +13 -0
- package/dist/src/lib/workflow/batch-executor.js +142 -24
- package/dist/src/lib/workflow/chain-preflight.d.ts +89 -0
- package/dist/src/lib/workflow/chain-preflight.js +199 -0
- package/dist/src/lib/workflow/chain-resume.d.ts +116 -0
- package/dist/src/lib/workflow/chain-resume.js +166 -0
- package/dist/src/lib/workflow/dependency-markers.d.ts +29 -0
- package/dist/src/lib/workflow/dependency-markers.js +79 -0
- package/dist/src/lib/workflow/drivers/agent-driver.d.ts +17 -0
- package/dist/src/lib/workflow/drivers/claude-code.d.ts +29 -0
- package/dist/src/lib/workflow/drivers/claude-code.js +136 -8
- package/dist/src/lib/workflow/error-classifier.d.ts +9 -2
- package/dist/src/lib/workflow/error-classifier.js +14 -1
- package/dist/src/lib/workflow/log-writer.d.ts +1 -1
- package/dist/src/lib/workflow/log-writer.js +6 -8
- package/dist/src/lib/workflow/metrics-schema.d.ts +39 -0
- package/dist/src/lib/workflow/metrics-schema.js +16 -0
- package/dist/src/lib/workflow/metrics-writer.d.ts +2 -1
- package/dist/src/lib/workflow/phase-executor.d.ts +50 -0
- package/dist/src/lib/workflow/phase-executor.js +151 -17
- package/dist/src/lib/workflow/run-log-schema.d.ts +26 -0
- package/dist/src/lib/workflow/run-log-schema.js +52 -1
- package/dist/src/lib/workflow/run-orchestrator.d.ts +14 -0
- package/dist/src/lib/workflow/run-orchestrator.js +291 -30
- package/dist/src/lib/workflow/state-manager.d.ts +1 -0
- package/dist/src/lib/workflow/state-manager.js +6 -0
- package/dist/src/lib/workflow/state-schema.d.ts +3 -0
- package/dist/src/lib/workflow/state-schema.js +7 -0
- package/dist/src/lib/workflow/status-derivation.d.ts +30 -0
- package/dist/src/lib/workflow/status-derivation.js +27 -0
- package/dist/src/lib/workflow/types.d.ts +40 -0
- package/dist/src/lib/workflow/worktree-manager.d.ts +43 -1
- package/dist/src/lib/workflow/worktree-manager.js +103 -33
- package/dist/src/mcp/tools/run.d.ts +2 -0
- package/dist/src/mcp/tools/run.js +2 -0
- package/dist/src/ui/tui/theme.d.ts +18 -4
- package/dist/src/ui/tui/theme.js +18 -4
- package/package.json +5 -6
- package/templates/hooks/post-tool.sh +18 -3
- package/templates/hooks/pre-tool.sh +330 -57
- package/templates/scripts/cleanup-worktree.sh +103 -14
- package/templates/skills/_shared/references/force-push.md +34 -0
- package/templates/skills/assess/SKILL.md +117 -19
- package/templates/skills/assess/references/predicted-collision-detection.md +9 -6
- package/templates/skills/exec/SKILL.md +29 -0
- package/templates/skills/fullsolve/SKILL.md +1 -1
- package/templates/skills/loop/SKILL.md +100 -2
- package/templates/skills/qa/SKILL.md +24 -0
- package/templates/skills/qa/references/anti-pattern-detection.md +285 -0
- package/templates/skills/qa/references/call-site-review.md +202 -0
- package/templates/skills/qa/references/quality-gates.md +287 -0
- package/templates/skills/qa/references/test-quality-checklist.md +272 -0
- package/templates/skills/qa/references/testing-requirements.md +40 -0
- package/templates/skills/qa/scripts/quality-checks.sh +95 -11
- package/templates/skills/references/shared/framework-gotchas.md +186 -0
- package/templates/skills/reflect/SKILL.md +27 -13
- package/templates/skills/reflect/references/documentation-tiers.md +80 -68
- package/templates/skills/reflect/references/phase-reflection.md +31 -15
- package/templates/skills/release/SKILL.md +669 -0
- package/templates/skills/spec/references/verification-criteria.md +1 -1
- package/templates/skills/test/references/browser-testing-patterns.md +423 -0
- package/templates/skills/upstream/SKILL.md +419 -0
|
@@ -43,6 +43,19 @@ export interface RebaseResult {
|
|
|
43
43
|
/** Error message if rebase failed */
|
|
44
44
|
error?: string;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Result of rebasing a worktree onto a local branch (chain successor → predecessor).
|
|
48
|
+
*/
|
|
49
|
+
export interface LocalRebaseResult {
|
|
50
|
+
/** Whether the rebase was attempted */
|
|
51
|
+
performed: boolean;
|
|
52
|
+
/** Whether the rebase succeeded (branch now contains `ontoBranch`'s commits) */
|
|
53
|
+
success: boolean;
|
|
54
|
+
/** Whether a merge conflict caused the rebase to be aborted */
|
|
55
|
+
conflict: boolean;
|
|
56
|
+
/** Error message if the rebase failed */
|
|
57
|
+
error?: string;
|
|
58
|
+
}
|
|
46
59
|
/**
|
|
47
60
|
* Result of PR creation
|
|
48
61
|
*/
|
|
@@ -176,6 +189,17 @@ export declare function createCheckpointCommit(worktreePath: string, issueNumber
|
|
|
176
189
|
* @internal Exported for testing
|
|
177
190
|
*/
|
|
178
191
|
export declare function reinstallIfLockfileChanged(worktreePath: string, packageManager: string | undefined, verbose: boolean, preRebaseRef?: string): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Rebase a worktree's branch onto a *local* branch ref (e.g. a chain
|
|
194
|
+
* predecessor's feature branch), NOT origin/main. Used to chain a successor
|
|
195
|
+
* onto its predecessor's committed work at execution time (#748), and to
|
|
196
|
+
* re-chain a pre-existing worktree onto its chain base.
|
|
197
|
+
*
|
|
198
|
+
* On conflict, aborts the rebase to restore the original branch state and
|
|
199
|
+
* returns `{ success: false, conflict: true }` so callers can warn rather than
|
|
200
|
+
* silently treat a broken link as healthy.
|
|
201
|
+
*/
|
|
202
|
+
export declare function rebaseOntoLocalBranch(worktreePath: string, ontoBranch: string, verbose?: boolean): LocalRebaseResult;
|
|
179
203
|
/**
|
|
180
204
|
* Rebase the worktree branch onto the base branch before PR creation.
|
|
181
205
|
* This ensures the branch is up-to-date and prevents lockfile drift.
|
|
@@ -189,6 +213,24 @@ export declare function reinstallIfLockfileChanged(worktreePath: string, package
|
|
|
189
213
|
* @internal Exported for testing
|
|
190
214
|
*/
|
|
191
215
|
export declare function rebaseBeforePR(worktreePath: string, issueNumber: number, packageManager: string | undefined, verbose: boolean, baseBranch?: string): RebaseResult;
|
|
216
|
+
/**
|
|
217
|
+
* Build the automated PR body for `sequant run`.
|
|
218
|
+
*
|
|
219
|
+
* Pure and I/O-free, kept separate from {@link createPR} (which shells out to
|
|
220
|
+
* `gh`) so the body — including the non-A+ QA note (#749) — is unit-testable
|
|
221
|
+
* directly.
|
|
222
|
+
*
|
|
223
|
+
* @param issueNumber Issue the PR closes
|
|
224
|
+
* @param opts.stackManifest Appended before the trailer under --stacked (#605)
|
|
225
|
+
* @param opts.qaVerdict QA verdict for the run; a non-A+ stopping state
|
|
226
|
+
* (anything other than `READY_FOR_MERGE`) surfaces a note so a human reviewer
|
|
227
|
+
* sees why the run broke to PR without reaching A+ (#749).
|
|
228
|
+
* @internal Exported for testing
|
|
229
|
+
*/
|
|
230
|
+
export declare function buildAutomatedPRBody(issueNumber: number, opts?: {
|
|
231
|
+
stackManifest?: string;
|
|
232
|
+
qaVerdict?: string;
|
|
233
|
+
}): string;
|
|
192
234
|
/**
|
|
193
235
|
* Push branch and create a PR after successful QA.
|
|
194
236
|
*
|
|
@@ -210,4 +252,4 @@ export declare function rebaseBeforePR(worktreePath: string, issueNumber: number
|
|
|
210
252
|
export declare function createPR(worktreePath: string, issueNumber: number, issueTitle: string, branch: string, verbose: boolean, labels?: string[], stackOptions?: {
|
|
211
253
|
prBase?: string;
|
|
212
254
|
stackManifest?: string;
|
|
213
|
-
}): PRCreationResult;
|
|
255
|
+
}, qaVerdict?: string): PRCreationResult;
|
|
@@ -365,21 +365,14 @@ export async function ensureWorktree(issueNumber, title, verbose, packageManager
|
|
|
365
365
|
if (verbose) {
|
|
366
366
|
console.log(chalk.gray(` Rebasing existing worktree onto chain base (${baseBranch})...`));
|
|
367
367
|
}
|
|
368
|
-
const
|
|
369
|
-
if (
|
|
370
|
-
|
|
371
|
-
// Check if it's a conflict
|
|
372
|
-
if (rebaseError.includes("CONFLICT") ||
|
|
373
|
-
rebaseError.includes("could not apply")) {
|
|
368
|
+
const rebase = rebaseOntoLocalBranch(existingPath, baseBranch, verbose);
|
|
369
|
+
if (!rebase.success) {
|
|
370
|
+
if (rebase.conflict) {
|
|
374
371
|
console.log(chalk.yellow(` ! Rebase conflict detected. Aborting rebase and keeping original branch state.`));
|
|
375
372
|
console.log(chalk.yellow(` ℹ️ Branch ${branch} is not properly chained. Manual rebase may be required.`));
|
|
376
|
-
// Abort the rebase to restore branch state
|
|
377
|
-
spawnSync("git", ["-C", existingPath, "rebase", "--abort"], {
|
|
378
|
-
stdio: "pipe",
|
|
379
|
-
});
|
|
380
373
|
}
|
|
381
374
|
else {
|
|
382
|
-
console.log(chalk.yellow(` ! Rebase failed: ${
|
|
375
|
+
console.log(chalk.yellow(` ! Rebase failed: ${rebase.error ?? ""}`));
|
|
383
376
|
console.log(chalk.yellow(` ℹ️ Continuing with branch in its original state.`));
|
|
384
377
|
}
|
|
385
378
|
return {
|
|
@@ -390,9 +383,6 @@ export async function ensureWorktree(issueNumber, title, verbose, packageManager
|
|
|
390
383
|
rebased: false,
|
|
391
384
|
};
|
|
392
385
|
}
|
|
393
|
-
if (verbose) {
|
|
394
|
-
console.log(chalk.green(` ✔ Existing worktree rebased onto ${baseBranch}`));
|
|
395
|
-
}
|
|
396
386
|
return {
|
|
397
387
|
issue: issueNumber,
|
|
398
388
|
path: existingPath,
|
|
@@ -700,9 +690,10 @@ passed QA in chain mode. It serves as a recovery point if later issues fail.`;
|
|
|
700
690
|
const commitResult = spawnSync("git", ["-C", worktreePath, "commit", "-m", commitMessage], { stdio: "pipe" });
|
|
701
691
|
if (commitResult.status !== 0) {
|
|
702
692
|
const error = commitResult.stderr.toString();
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
693
|
+
// #760: chain resume rebases the next link onto this checkpoint, so a
|
|
694
|
+
// commit failure is surfaced regardless of --verbose (the call site adds
|
|
695
|
+
// the resume-impact warning; here we show the underlying git error).
|
|
696
|
+
console.log(chalk.yellow(` ! Could not create checkpoint commit for #${issueNumber}: ${error.trim()}`));
|
|
706
697
|
return false;
|
|
707
698
|
}
|
|
708
699
|
console.log(chalk.green(` 📌 Checkpoint commit created for #${issueNumber}`));
|
|
@@ -766,6 +757,39 @@ export function reinstallIfLockfileChanged(worktreePath, packageManager, verbose
|
|
|
766
757
|
console.log(chalk.green(` ✔ Dependencies reinstalled`));
|
|
767
758
|
return true;
|
|
768
759
|
}
|
|
760
|
+
/**
|
|
761
|
+
* Rebase a worktree's branch onto a *local* branch ref (e.g. a chain
|
|
762
|
+
* predecessor's feature branch), NOT origin/main. Used to chain a successor
|
|
763
|
+
* onto its predecessor's committed work at execution time (#748), and to
|
|
764
|
+
* re-chain a pre-existing worktree onto its chain base.
|
|
765
|
+
*
|
|
766
|
+
* On conflict, aborts the rebase to restore the original branch state and
|
|
767
|
+
* returns `{ success: false, conflict: true }` so callers can warn rather than
|
|
768
|
+
* silently treat a broken link as healthy.
|
|
769
|
+
*/
|
|
770
|
+
export function rebaseOntoLocalBranch(worktreePath, ontoBranch, verbose = false) {
|
|
771
|
+
const rebaseResult = spawnSync("git", ["-C", worktreePath, "rebase", ontoBranch], { stdio: "pipe" });
|
|
772
|
+
if (rebaseResult.status === 0) {
|
|
773
|
+
if (verbose) {
|
|
774
|
+
console.log(chalk.green(` ✔ Rebased worktree onto ${ontoBranch}`));
|
|
775
|
+
}
|
|
776
|
+
return { performed: true, success: true, conflict: false };
|
|
777
|
+
}
|
|
778
|
+
const rebaseError = rebaseResult.stderr.toString();
|
|
779
|
+
const isConflict = rebaseError.includes("CONFLICT") || rebaseError.includes("could not apply");
|
|
780
|
+
if (isConflict) {
|
|
781
|
+
// Abort to restore the original branch state.
|
|
782
|
+
spawnSync("git", ["-C", worktreePath, "rebase", "--abort"], {
|
|
783
|
+
stdio: "pipe",
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
performed: true,
|
|
788
|
+
success: false,
|
|
789
|
+
conflict: isConflict,
|
|
790
|
+
error: rebaseError.trim(),
|
|
791
|
+
};
|
|
792
|
+
}
|
|
769
793
|
/**
|
|
770
794
|
* Rebase the worktree branch onto the base branch before PR creation.
|
|
771
795
|
* This ensures the branch is up-to-date and prevents lockfile drift.
|
|
@@ -832,6 +856,63 @@ export function rebaseBeforePR(worktreePath, issueNumber, packageManager, verbos
|
|
|
832
856
|
reinstalled,
|
|
833
857
|
};
|
|
834
858
|
}
|
|
859
|
+
/**
|
|
860
|
+
* Render a non-A+ QA verdict as a PR-body note, or `null` for an A+ / absent
|
|
861
|
+
* verdict.
|
|
862
|
+
*
|
|
863
|
+
* Only stopping states that still break to a PR reach this path
|
|
864
|
+
* (`AC_MET_BUT_NOT_A_PLUS`, `NEEDS_VERIFICATION`); `READY_FOR_MERGE` and an
|
|
865
|
+
* absent verdict produce no note. (#749)
|
|
866
|
+
*/
|
|
867
|
+
function qaVerdictNote(verdict) {
|
|
868
|
+
if (!verdict || verdict === "READY_FOR_MERGE")
|
|
869
|
+
return null;
|
|
870
|
+
switch (verdict) {
|
|
871
|
+
case "AC_MET_BUT_NOT_A_PLUS":
|
|
872
|
+
return `> **QA verdict: AC_MET_BUT_NOT_A_PLUS** — acceptance criteria met, but not A+. The run broke to this PR for review rather than entering the quality loop; see the QA review comment for improvement notes.`;
|
|
873
|
+
case "NEEDS_VERIFICATION":
|
|
874
|
+
return `> **QA verdict: NEEDS_VERIFICATION** — acceptance criteria met, pending external verification (e.g. CI or a manual test). See the QA review comment.`;
|
|
875
|
+
default:
|
|
876
|
+
return `> **QA verdict: ${verdict}** — see the QA review comment.`;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Build the automated PR body for `sequant run`.
|
|
881
|
+
*
|
|
882
|
+
* Pure and I/O-free, kept separate from {@link createPR} (which shells out to
|
|
883
|
+
* `gh`) so the body — including the non-A+ QA note (#749) — is unit-testable
|
|
884
|
+
* directly.
|
|
885
|
+
*
|
|
886
|
+
* @param issueNumber Issue the PR closes
|
|
887
|
+
* @param opts.stackManifest Appended before the trailer under --stacked (#605)
|
|
888
|
+
* @param opts.qaVerdict QA verdict for the run; a non-A+ stopping state
|
|
889
|
+
* (anything other than `READY_FOR_MERGE`) surfaces a note so a human reviewer
|
|
890
|
+
* sees why the run broke to PR without reaching A+ (#749).
|
|
891
|
+
* @internal Exported for testing
|
|
892
|
+
*/
|
|
893
|
+
export function buildAutomatedPRBody(issueNumber, opts) {
|
|
894
|
+
const bodyLines = [
|
|
895
|
+
`## Summary`,
|
|
896
|
+
``,
|
|
897
|
+
`Automated PR for issue #${issueNumber}.`,
|
|
898
|
+
``,
|
|
899
|
+
`Fixes #${issueNumber}`,
|
|
900
|
+
``,
|
|
901
|
+
];
|
|
902
|
+
// #749: surface a non-A+ QA verdict in the PR body (not just the run log) so
|
|
903
|
+
// a reviewer sees why the run broke to PR rather than reaching A+.
|
|
904
|
+
const note = qaVerdictNote(opts?.qaVerdict);
|
|
905
|
+
if (note) {
|
|
906
|
+
bodyLines.push(note, ``);
|
|
907
|
+
}
|
|
908
|
+
// #605 AC-4: emit stack manifest before the trailer so reviewers see the
|
|
909
|
+
// chain at the top of the body. Manifest is only set under --stacked.
|
|
910
|
+
if (opts?.stackManifest) {
|
|
911
|
+
bodyLines.push(opts.stackManifest, ``);
|
|
912
|
+
}
|
|
913
|
+
bodyLines.push(`---`, `🤖 Generated by \`sequant run\``);
|
|
914
|
+
return bodyLines.join("\n");
|
|
915
|
+
}
|
|
835
916
|
/**
|
|
836
917
|
* Push branch and create a PR after successful QA.
|
|
837
918
|
*
|
|
@@ -850,7 +931,7 @@ export function rebaseBeforePR(worktreePath, issueNumber, packageManager, verbos
|
|
|
850
931
|
* @returns PRCreationResult with PR info or error
|
|
851
932
|
* @internal Exported for testing
|
|
852
933
|
*/
|
|
853
|
-
export function createPR(worktreePath, issueNumber, issueTitle, branch, verbose, labels, stackOptions) {
|
|
934
|
+
export function createPR(worktreePath, issueNumber, issueTitle, branch, verbose, labels, stackOptions, qaVerdict) {
|
|
854
935
|
const github = new GitHubProvider();
|
|
855
936
|
// Step 1: Check for existing PR on this branch
|
|
856
937
|
const existingPRInfo = github.viewPRByBranchSync(branch, worktreePath);
|
|
@@ -886,21 +967,10 @@ export function createPR(worktreePath, issueNumber, issueTitle, branch, verbose,
|
|
|
886
967
|
const isBug = labels?.some((l) => /^bug/i.test(l));
|
|
887
968
|
const prefix = isBug ? "fix" : "feat";
|
|
888
969
|
const prTitle = `${prefix}(#${issueNumber}): ${issueTitle}`;
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
``,
|
|
894
|
-
`Fixes #${issueNumber}`,
|
|
895
|
-
``,
|
|
896
|
-
];
|
|
897
|
-
// #605 AC-4: emit stack manifest before the trailer so reviewers see the
|
|
898
|
-
// chain at the top of the body. Manifest is only set under --stacked.
|
|
899
|
-
if (stackOptions?.stackManifest) {
|
|
900
|
-
bodyLines.push(stackOptions.stackManifest, ``);
|
|
901
|
-
}
|
|
902
|
-
bodyLines.push(`---`, `🤖 Generated by \`sequant run\``);
|
|
903
|
-
const prBody = bodyLines.join("\n");
|
|
970
|
+
const prBody = buildAutomatedPRBody(issueNumber, {
|
|
971
|
+
stackManifest: stackOptions?.stackManifest,
|
|
972
|
+
qaVerdict,
|
|
973
|
+
});
|
|
904
974
|
const prResult = github.createPRCliSync(prTitle, prBody, branch, worktreePath, stackOptions?.prBase);
|
|
905
975
|
if (prResult.exitCode !== 0) {
|
|
906
976
|
const prError = prResult.stderr.trim() || "Unknown error";
|
|
@@ -182,6 +182,7 @@ export function buildStructuredResponse(runLog, rawOutput, overallStatus, exitCo
|
|
|
182
182
|
total: runLog.summary.totalIssues,
|
|
183
183
|
passed: runLog.summary.passed,
|
|
184
184
|
failed: runLog.summary.failed,
|
|
185
|
+
partial: runLog.summary.partial ?? 0,
|
|
185
186
|
durationSeconds: runLog.summary.totalDurationSeconds,
|
|
186
187
|
},
|
|
187
188
|
phases: phasesRan || runLog.config.phases.join(","),
|
|
@@ -232,6 +233,7 @@ function buildFallbackResponse(stdout, issueNumbers, overallStatus, phases, exit
|
|
|
232
233
|
total: issueNumbers.length,
|
|
233
234
|
passed: overallStatus === "success" ? issueNumbers.length : 0,
|
|
234
235
|
failed: overallStatus === "failure" ? issueNumbers.length : 0,
|
|
236
|
+
partial: 0,
|
|
235
237
|
durationSeconds: 0,
|
|
236
238
|
},
|
|
237
239
|
phases,
|
|
@@ -12,8 +12,10 @@ import type { IssueStatus, PhaseStatus } from "../../lib/workflow/run-state.js";
|
|
|
12
12
|
* - `BRAND_GREEN` is the accent/success green (`--color-accent`).
|
|
13
13
|
*
|
|
14
14
|
* Used to brand the two color signals that matter most at a glance — the
|
|
15
|
-
* live/active phase and success — while issue-distinction (border rotation)
|
|
16
|
-
* failure (red)
|
|
15
|
+
* live/active phase and success — while issue-distinction (border rotation)
|
|
16
|
+
* and failure (red) stay on robust named ANSI colors. The muted gray for
|
|
17
|
+
* secondary chrome is a fixed mid-gray (`DIVIDER_COLOR`) chosen for WCAG
|
|
18
|
+
* contrast rather than the too-dim ANSI bright-black.
|
|
17
19
|
*
|
|
18
20
|
* Ink/chalk auto-downsamples hex to the nearest ANSI color on terminals
|
|
19
21
|
* without truecolor, and `NO_COLOR` still strips all color, so these degrade
|
|
@@ -24,8 +26,20 @@ export declare const BRAND_GREEN: "#10b981";
|
|
|
24
26
|
/** Border-color palette rotated by issue start order. */
|
|
25
27
|
export declare const BORDER_ROTATION: readonly ["cyan", "magenta", "blue", "yellow"];
|
|
26
28
|
export type BorderColor = (typeof BORDER_ROTATION)[number] | typeof BRAND_GREEN | typeof BRAND_ORANGE | "red" | "gray";
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Muted gray for secondary chrome: dividers, field labels (`branch`/`now`/
|
|
31
|
+
* `log`), the `phase N/total` + elapsed line, the `last activity` stamp, and
|
|
32
|
+
* the terminal status line.
|
|
33
|
+
*
|
|
34
|
+
* Lifted off ANSI `"gray"` (bright-black), which the brand's own dark theme
|
|
35
|
+
* renders at ~2.4:1 — below WCAG AA (4.5) and even the 3.0 large-text/UI floor.
|
|
36
|
+
* This fixed mid-gray clears AA (~4.9:1) on the dark theme while staying above
|
|
37
|
+
* 3.0 on light terminals (~3.4:1). It still degrades gracefully: chalk
|
|
38
|
+
* downsamples the hex to the nearest ANSI color on non-truecolor terminals, and
|
|
39
|
+
* `NO_COLOR` strips it entirely. The not-yet-started phase glyph stays on ANSI
|
|
40
|
+
* `"gray"` (see `phaseStatusColor`) so pending work remains the most recessed.
|
|
41
|
+
*/
|
|
42
|
+
export declare const DIVIDER_COLOR: "#8B8B9A";
|
|
29
43
|
/** Brand orange for the live/active phase spinner — the one element the eye
|
|
30
44
|
* tracks. Border rotation still distinguishes concurrent issues. */
|
|
31
45
|
export declare const ACTIVE_PHASE_COLOR: "#FF8012";
|
package/dist/src/ui/tui/theme.js
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
* - `BRAND_GREEN` is the accent/success green (`--color-accent`).
|
|
12
12
|
*
|
|
13
13
|
* Used to brand the two color signals that matter most at a glance — the
|
|
14
|
-
* live/active phase and success — while issue-distinction (border rotation)
|
|
15
|
-
* failure (red)
|
|
14
|
+
* live/active phase and success — while issue-distinction (border rotation)
|
|
15
|
+
* and failure (red) stay on robust named ANSI colors. The muted gray for
|
|
16
|
+
* secondary chrome is a fixed mid-gray (`DIVIDER_COLOR`) chosen for WCAG
|
|
17
|
+
* contrast rather than the too-dim ANSI bright-black.
|
|
16
18
|
*
|
|
17
19
|
* Ink/chalk auto-downsamples hex to the nearest ANSI color on terminals
|
|
18
20
|
* without truecolor, and `NO_COLOR` still strips all color, so these degrade
|
|
@@ -22,8 +24,20 @@ export const BRAND_ORANGE = "#FF8012";
|
|
|
22
24
|
export const BRAND_GREEN = "#10b981";
|
|
23
25
|
/** Border-color palette rotated by issue start order. */
|
|
24
26
|
export const BORDER_ROTATION = ["cyan", "magenta", "blue", "yellow"];
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Muted gray for secondary chrome: dividers, field labels (`branch`/`now`/
|
|
29
|
+
* `log`), the `phase N/total` + elapsed line, the `last activity` stamp, and
|
|
30
|
+
* the terminal status line.
|
|
31
|
+
*
|
|
32
|
+
* Lifted off ANSI `"gray"` (bright-black), which the brand's own dark theme
|
|
33
|
+
* renders at ~2.4:1 — below WCAG AA (4.5) and even the 3.0 large-text/UI floor.
|
|
34
|
+
* This fixed mid-gray clears AA (~4.9:1) on the dark theme while staying above
|
|
35
|
+
* 3.0 on light terminals (~3.4:1). It still degrades gracefully: chalk
|
|
36
|
+
* downsamples the hex to the nearest ANSI color on non-truecolor terminals, and
|
|
37
|
+
* `NO_COLOR` strips it entirely. The not-yet-started phase glyph stays on ANSI
|
|
38
|
+
* `"gray"` (see `phaseStatusColor`) so pending work remains the most recessed.
|
|
39
|
+
*/
|
|
40
|
+
export const DIVIDER_COLOR = "#8B8B9A";
|
|
27
41
|
/** Brand orange for the live/active phase spinner — the one element the eye
|
|
28
42
|
* tracks. Border rotation still distinguishes concurrent issues. */
|
|
29
43
|
export const ACTIVE_PHASE_COLOR = BRAND_ORANGE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sequant",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "AI coding agent orchestrator — resolve GitHub issues end-to-end with isolated git worktrees, quality gates, and an MCP server. Works with Claude Code or Aider.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,10 +25,11 @@
|
|
|
25
25
|
"dev": "tsx bin/cli.ts",
|
|
26
26
|
"test": "vitest run",
|
|
27
27
|
"lint": "eslint src/ bin/ --max-warnings 0",
|
|
28
|
-
"sync:skills": "
|
|
28
|
+
"sync:skills": "npx tsx scripts/check-skill-sync.ts --fix",
|
|
29
29
|
"sync:hooks": "bash scripts/sync-hooks.sh",
|
|
30
|
-
"validate:skills": "for skill in templates/skills/*/; do npx skills-ref validate \"$skill\"; done",
|
|
30
|
+
"validate:skills": "for skill in templates/skills/*/; do case \"$skill\" in *_shared*|*/references/*) continue;; esac; npx skills-ref validate \"$skill\"; done",
|
|
31
31
|
"lint:skill-calls": "npx tsx scripts/lint-skill-calls.ts",
|
|
32
|
+
"lint:skill-sync": "npx tsx scripts/check-skill-sync.ts",
|
|
32
33
|
"prepare:marketplace": "npx tsx scripts/prepare-marketplace.ts",
|
|
33
34
|
"validate:marketplace": "npx tsx scripts/prepare-marketplace.ts --validate-only",
|
|
34
35
|
"prepublishOnly": "npm run build"
|
|
@@ -96,7 +97,6 @@
|
|
|
96
97
|
"cli-table3": "^0.6.5",
|
|
97
98
|
"commander": "^14.0.3",
|
|
98
99
|
"diff": "^9.0.0",
|
|
99
|
-
"gradient-string": "^3.0.0",
|
|
100
100
|
"hono": "^4.12.1",
|
|
101
101
|
"ink": "^7.0.1",
|
|
102
102
|
"inquirer": "^14.0.1",
|
|
@@ -111,9 +111,8 @@
|
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@eslint/js": "^10.0.1",
|
|
114
|
-
"@types/gradient-string": "^1.1.6",
|
|
115
114
|
"@types/inquirer": "^9.0.7",
|
|
116
|
-
"@types/node": "^
|
|
115
|
+
"@types/node": "^26.0.1",
|
|
117
116
|
"@types/react": "^19.2.14",
|
|
118
117
|
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
119
118
|
"@typescript-eslint/parser": "^8.58.0",
|
|
@@ -51,13 +51,28 @@ fi
|
|
|
51
51
|
|
|
52
52
|
_TMPDIR="${TMPDIR:-/tmp}"
|
|
53
53
|
|
|
54
|
-
#
|
|
55
|
-
|
|
54
|
+
# Log sink (#763 AC-5c: blocked-command history must survive to be a useful
|
|
55
|
+
# regression corpus, so $TMPDIR — which macOS purges — is a last resort only).
|
|
56
|
+
#
|
|
57
|
+
# This block MUST stay identical to the one in pre-tool.sh. The two hooks
|
|
58
|
+
# write the *same* claude-timing.log (START there, END here) and the same
|
|
59
|
+
# claude-quality.log, so any divergence silently splits every START/END pair
|
|
60
|
+
# across two files.
|
|
61
|
+
#
|
|
62
|
+
# Every candidate is absolute and lives outside the repo. A repo-local or
|
|
63
|
+
# relative path is wrong three times over: it resolves against the hook's cwd
|
|
64
|
+
# (which Claude Code does not pin), it yields one sink per directory instead
|
|
65
|
+
# of the single corpus AC-5 asks for, and — worst — creating it inside a repo
|
|
66
|
+
# makes `git status --porcelain` non-empty, which silently defeats pre-tool.sh's
|
|
67
|
+
# no-changes guard that reads exactly that output.
|
|
68
|
+
if [[ -n "${CLAUDE_PLUGIN_DATA:-}" ]]; then
|
|
56
69
|
_LOG_DIR="${CLAUDE_PLUGIN_DATA}/logs"
|
|
57
|
-
|
|
70
|
+
elif [[ -n "${HOME:-}" ]]; then
|
|
71
|
+
_LOG_DIR="${HOME}/.sequant/logs"
|
|
58
72
|
else
|
|
59
73
|
_LOG_DIR="${_TMPDIR}"
|
|
60
74
|
fi
|
|
75
|
+
mkdir -p "$_LOG_DIR" 2>/dev/null || _LOG_DIR="${_TMPDIR}"
|
|
61
76
|
|
|
62
77
|
TIMING_LOG="${_LOG_DIR}/claude-timing.log"
|
|
63
78
|
QUALITY_LOG="${_LOG_DIR}/claude-quality.log"
|