sequant 2.2.0 → 2.3.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 +73 -0
- package/dist/bin/cli.js +94 -9
- package/dist/src/commands/doctor.d.ts +25 -0
- package/dist/src/commands/doctor.js +36 -1
- package/dist/src/commands/locks.d.ts +67 -0
- package/dist/src/commands/locks.js +290 -0
- package/dist/src/commands/merge.js +11 -0
- package/dist/src/commands/prompt.d.ts +39 -0
- package/dist/src/commands/prompt.js +179 -0
- package/dist/src/commands/run-display.d.ts +11 -2
- package/dist/src/commands/run-display.js +62 -28
- package/dist/src/commands/run-progress.d.ts +32 -0
- package/dist/src/commands/run-progress.js +76 -0
- package/dist/src/commands/run.js +80 -18
- package/dist/src/commands/stats.d.ts +2 -0
- package/dist/src/commands/stats.js +94 -8
- package/dist/src/commands/status.js +12 -0
- package/dist/src/commands/watch.d.ts +16 -0
- package/dist/src/commands/watch.js +147 -0
- package/dist/src/lib/ac-linter.d.ts +1 -1
- package/dist/src/lib/ac-linter.js +81 -0
- package/dist/src/lib/assess-collision-detect.d.ts +91 -0
- package/dist/src/lib/assess-collision-detect.js +217 -0
- package/dist/src/lib/assess-comment-parser.d.ts +59 -1
- package/dist/src/lib/assess-comment-parser.js +124 -2
- package/dist/src/lib/cli-ui/format.d.ts +19 -0
- package/dist/src/lib/cli-ui/format.js +34 -0
- package/dist/src/lib/cli-ui/run-renderer-types.d.ts +181 -0
- package/dist/src/lib/cli-ui/run-renderer-types.js +7 -0
- package/dist/src/lib/cli-ui/run-renderer.d.ts +239 -0
- package/dist/src/lib/cli-ui/run-renderer.js +1173 -0
- package/dist/src/lib/heuristics/behavior-rule-detector.d.ts +94 -0
- package/dist/src/lib/heuristics/behavior-rule-detector.js +467 -0
- package/dist/src/lib/locks/index.d.ts +7 -0
- package/dist/src/lib/locks/index.js +5 -0
- package/dist/src/lib/locks/lock-manager.d.ts +168 -0
- package/dist/src/lib/locks/lock-manager.js +433 -0
- package/dist/src/lib/locks/types.d.ts +59 -0
- package/dist/src/lib/locks/types.js +31 -0
- package/dist/src/lib/qa/markdown-only-ci.d.ts +46 -0
- package/dist/src/lib/qa/markdown-only-ci.js +74 -0
- package/dist/src/lib/relay/activation.d.ts +60 -0
- package/dist/src/lib/relay/activation.js +122 -0
- package/dist/src/lib/relay/archive.d.ts +34 -0
- package/dist/src/lib/relay/archive.js +106 -0
- package/dist/src/lib/relay/frame.d.ts +20 -0
- package/dist/src/lib/relay/frame.js +76 -0
- package/dist/src/lib/relay/index.d.ts +13 -0
- package/dist/src/lib/relay/index.js +13 -0
- package/dist/src/lib/relay/paths.d.ts +43 -0
- package/dist/src/lib/relay/paths.js +59 -0
- package/dist/src/lib/relay/pid.d.ts +34 -0
- package/dist/src/lib/relay/pid.js +72 -0
- package/dist/src/lib/relay/reader.d.ts +35 -0
- package/dist/src/lib/relay/reader.js +115 -0
- package/dist/src/lib/relay/types.d.ts +68 -0
- package/dist/src/lib/relay/types.js +76 -0
- package/dist/src/lib/relay/writer.d.ts +48 -0
- package/dist/src/lib/relay/writer.js +113 -0
- package/dist/src/lib/settings.d.ts +31 -1
- package/dist/src/lib/settings.js +18 -3
- package/dist/src/lib/version-check.d.ts +60 -5
- package/dist/src/lib/version-check.js +97 -9
- package/dist/src/lib/workflow/batch-executor.d.ts +20 -1
- package/dist/src/lib/workflow/batch-executor.js +248 -175
- package/dist/src/lib/workflow/config-resolver.js +4 -0
- package/dist/src/lib/workflow/heartbeat.d.ts +71 -0
- package/dist/src/lib/workflow/heartbeat.js +194 -0
- package/dist/src/lib/workflow/phase-executor.d.ts +62 -8
- package/dist/src/lib/workflow/phase-executor.js +157 -16
- package/dist/src/lib/workflow/phase-mapper.d.ts +3 -2
- package/dist/src/lib/workflow/phase-mapper.js +17 -20
- package/dist/src/lib/workflow/platforms/github.d.ts +1 -1
- package/dist/src/lib/workflow/platforms/github.js +20 -3
- package/dist/src/lib/workflow/pr-status.d.ts +18 -2
- package/dist/src/lib/workflow/pr-status.js +41 -9
- package/dist/src/lib/workflow/qa-stagnation.d.ts +117 -0
- package/dist/src/lib/workflow/qa-stagnation.js +179 -0
- package/dist/src/lib/workflow/run-orchestrator.d.ts +39 -0
- package/dist/src/lib/workflow/run-orchestrator.js +340 -15
- package/dist/src/lib/workflow/run-reflect.js +1 -1
- package/dist/src/lib/workflow/run-state.d.ts +71 -0
- package/dist/src/lib/workflow/run-state.js +14 -0
- package/dist/src/lib/workflow/state-cleanup.d.ts +13 -5
- package/dist/src/lib/workflow/state-cleanup.js +17 -5
- package/dist/src/lib/workflow/state-manager.d.ts +12 -1
- package/dist/src/lib/workflow/state-manager.js +37 -0
- package/dist/src/lib/workflow/state-schema.d.ts +62 -0
- package/dist/src/lib/workflow/state-schema.js +35 -1
- package/dist/src/lib/workflow/types.d.ts +74 -1
- package/dist/src/lib/workflow/worktree-manager.d.ts +8 -1
- package/dist/src/lib/workflow/worktree-manager.js +15 -6
- package/dist/src/mcp/tools/run.d.ts +44 -0
- package/dist/src/mcp/tools/run.js +104 -13
- package/dist/src/ui/tui/App.d.ts +14 -0
- package/dist/src/ui/tui/App.js +41 -0
- package/dist/src/ui/tui/ElapsedTimer.d.ts +10 -0
- package/dist/src/ui/tui/ElapsedTimer.js +31 -0
- package/dist/src/ui/tui/Header.d.ts +6 -0
- package/dist/src/ui/tui/Header.js +15 -0
- package/dist/src/ui/tui/IssueBox.d.ts +16 -0
- package/dist/src/ui/tui/IssueBox.js +68 -0
- package/dist/src/ui/tui/Spinner.d.ts +9 -0
- package/dist/src/ui/tui/Spinner.js +18 -0
- package/dist/src/ui/tui/index.d.ts +15 -0
- package/dist/src/ui/tui/index.js +29 -0
- package/dist/src/ui/tui/theme.d.ts +29 -0
- package/dist/src/ui/tui/theme.js +52 -0
- package/dist/src/ui/tui/truncate.d.ts +11 -0
- package/dist/src/ui/tui/truncate.js +31 -0
- package/package.json +10 -3
- package/templates/agents/sequant-explorer.md +1 -0
- package/templates/agents/sequant-qa-checker.md +2 -1
- package/templates/agents/sequant-testgen.md +1 -0
- package/templates/hooks/post-tool.sh +11 -0
- package/templates/hooks/pre-tool.sh +18 -9
- package/templates/hooks/relay-check.sh +107 -0
- package/templates/relay/frame.txt +11 -0
- package/templates/scripts/cleanup-worktree.sh +25 -3
- package/templates/scripts/new-feature.sh +6 -0
- package/templates/skills/_shared/references/behavior-rule-detection.md +205 -0
- package/templates/skills/_shared/references/subagent-types.md +21 -8
- package/templates/skills/assess/SKILL.md +103 -49
- package/templates/skills/assess/references/predicted-collision-detection.md +109 -0
- package/templates/skills/docs/SKILL.md +141 -22
- package/templates/skills/exec/SKILL.md +10 -8
- package/templates/skills/fullsolve/SKILL.md +79 -5
- package/templates/skills/loop/SKILL.md +28 -0
- package/templates/skills/merger/SKILL.md +621 -0
- package/templates/skills/qa/SKILL.md +727 -8
- package/templates/skills/setup/SKILL.md +6 -0
- package/templates/skills/spec/SKILL.md +52 -0
- package/templates/skills/spec/references/parallel-groups.md +7 -0
- package/templates/skills/spec/references/recommended-workflow.md +4 -2
- package/templates/skills/testgen/SKILL.md +24 -17
package/dist/src/lib/settings.js
CHANGED
|
@@ -57,6 +57,7 @@ export const RunSettingsSchema = z.object({
|
|
|
57
57
|
devUrl: z.string().optional(),
|
|
58
58
|
agent: z.string().optional(),
|
|
59
59
|
aider: AiderSettingsSchema.optional(),
|
|
60
|
+
relay: z.boolean().default(true),
|
|
60
61
|
});
|
|
61
62
|
/** Zod schema for ScopeThreshold (base — fields required, no defaults) */
|
|
62
63
|
export const ScopeThresholdSchema = z.object({
|
|
@@ -121,6 +122,10 @@ export const ScopeAssessmentSettingsSchema = z.object({
|
|
|
121
122
|
/** Zod schema for QASettings */
|
|
122
123
|
export const QASettingsSchema = z.object({
|
|
123
124
|
smallDiffThreshold: z.number().default(100),
|
|
125
|
+
markdownOnlyCiRelaxed: z.boolean().default(true),
|
|
126
|
+
markdownOnlySafeCiPatterns: z
|
|
127
|
+
.array(z.string())
|
|
128
|
+
.default(["build (*)", "Plugin Structure Validation"]),
|
|
124
129
|
});
|
|
125
130
|
/**
|
|
126
131
|
* Zod schema for the full SequantSettings (AC-1, AC-5).
|
|
@@ -167,6 +172,7 @@ const KNOWN_KEYS = {
|
|
|
167
172
|
"devUrl",
|
|
168
173
|
"agent",
|
|
169
174
|
"aider",
|
|
175
|
+
"relay",
|
|
170
176
|
]),
|
|
171
177
|
agents: new Set(["parallel", "model", "isolateParallel"]),
|
|
172
178
|
scopeAssessment: new Set([
|
|
@@ -175,7 +181,11 @@ const KNOWN_KEYS = {
|
|
|
175
181
|
"trivialThresholds",
|
|
176
182
|
"thresholds",
|
|
177
183
|
]),
|
|
178
|
-
qa: new Set([
|
|
184
|
+
qa: new Set([
|
|
185
|
+
"smallDiffThreshold",
|
|
186
|
+
"markdownOnlyCiRelaxed",
|
|
187
|
+
"markdownOnlySafeCiPatterns",
|
|
188
|
+
]),
|
|
179
189
|
"run.rotation": new Set(["enabled", "maxSizeMB", "maxFiles"]),
|
|
180
190
|
"run.aider": new Set(["model", "editFormat", "extraArgs"]),
|
|
181
191
|
"scopeAssessment.trivialThresholds": new Set([
|
|
@@ -310,6 +320,8 @@ export const DEFAULT_SCOPE_ASSESSMENT_SETTINGS = {
|
|
|
310
320
|
*/
|
|
311
321
|
export const DEFAULT_QA_SETTINGS = {
|
|
312
322
|
smallDiffThreshold: 100,
|
|
323
|
+
markdownOnlyCiRelaxed: true,
|
|
324
|
+
markdownOnlySafeCiPatterns: ["build (*)", "Plugin Structure Validation"],
|
|
313
325
|
};
|
|
314
326
|
/**
|
|
315
327
|
* Default settings
|
|
@@ -331,6 +343,7 @@ export const DEFAULT_SETTINGS = {
|
|
|
331
343
|
retry: true, // Enable automatic retry with MCP fallback by default
|
|
332
344
|
staleBranchThreshold: 5, // Block QA/test if feature is >5 commits behind main
|
|
333
345
|
resolvedIssueTTL: 7, // Auto-prune resolved issues after 7 days
|
|
346
|
+
relay: true, // Enable interactive relay (#383) by default
|
|
334
347
|
},
|
|
335
348
|
agents: DEFAULT_AGENT_SETTINGS,
|
|
336
349
|
scopeAssessment: DEFAULT_SCOPE_ASSESSMENT_SETTINGS,
|
|
@@ -482,7 +495,7 @@ export function generateSettingsJsonc(settings) {
|
|
|
482
495
|
lines.push(` "agents": {`);
|
|
483
496
|
lines.push(` // Run agents in parallel (faster, higher token usage)`);
|
|
484
497
|
lines.push(` "parallel": ${JSON.stringify(settings.agents.parallel)},`);
|
|
485
|
-
lines.push(` // Default model for sub-agents ("haiku", "sonnet", "opus")`);
|
|
498
|
+
lines.push(` // Default model for sub-agents ("haiku", "sonnet", "opus") — currently inert per anthropics/claude-code#43869`);
|
|
486
499
|
lines.push(` "model": ${JSON.stringify(settings.agents.model)},`);
|
|
487
500
|
lines.push(` // Isolate parallel agent groups in separate worktrees`);
|
|
488
501
|
lines.push(` "isolateParallel": ${JSON.stringify(settings.agents.isolateParallel)}`);
|
|
@@ -597,7 +610,7 @@ Generated by \`sequant init\`. See defaults below.
|
|
|
597
610
|
| Key | Type | Default | Description |
|
|
598
611
|
|-----|------|---------|-------------|
|
|
599
612
|
| \`parallel\` | boolean | \`false\` | Run agents in parallel (faster, higher token usage) |
|
|
600
|
-
| \`model\` | enum | \`"haiku"\` | Default model: \`"haiku"\`, \`"sonnet"\`, or \`"opus"
|
|
613
|
+
| \`model\` | enum | \`"haiku"\` | Default model: \`"haiku"\`, \`"sonnet"\`, or \`"opus"\`. **Currently inert** per [anthropics/claude-code#43869](https://github.com/anthropics/claude-code/issues/43869) — subagents inherit the parent session's model. Kept for forward compatibility. |
|
|
601
614
|
| \`isolateParallel\` | boolean | \`false\` | Isolate parallel agents in separate worktrees |
|
|
602
615
|
|
|
603
616
|
## \`scopeAssessment\` — Scope Assessment Settings
|
|
@@ -630,6 +643,8 @@ Each threshold has \`yellow\` (warning) and \`red\` (split recommended) values:
|
|
|
630
643
|
| Key | Type | Default | Description |
|
|
631
644
|
|-----|------|---------|-------------|
|
|
632
645
|
| \`smallDiffThreshold\` | number | \`100\` | Diff size threshold for small-diff fast path |
|
|
646
|
+
| \`markdownOnlyCiRelaxed\` | boolean | \`true\` | When diff touches only \`.md\` files, treat pending CI checks matching \`markdownOnlySafeCiPatterns\` as informational |
|
|
647
|
+
| \`markdownOnlySafeCiPatterns\` | string[] | \`["build (*)", "Plugin Structure Validation"]\` | Glob patterns for CI checks that are safe to ignore when pending on a markdown-only diff |
|
|
633
648
|
|
|
634
649
|
---
|
|
635
650
|
|
|
@@ -28,16 +28,71 @@ export declare function getCachePath(): string;
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function getCurrentVersion(): string;
|
|
30
30
|
/**
|
|
31
|
-
* Check if running from a
|
|
31
|
+
* Check if running from a global install (npm root -g).
|
|
32
|
+
*
|
|
33
|
+
* On POSIX, npm's global root convention puts packages under
|
|
34
|
+
* `<prefix>/lib/node_modules/` (e.g. `/usr/local/lib/node_modules`,
|
|
35
|
+
* `/opt/homebrew/lib/node_modules`, `~/.nvm/versions/node/<v>/lib/node_modules`).
|
|
36
|
+
*
|
|
37
|
+
* On Windows, the default global root is `%AppData%\npm\node_modules\` —
|
|
38
|
+
* sometimes nested under `Roaming\` depending on the npm/Node installer —
|
|
39
|
+
* with no `lib\` segment. Both variants are matched here.
|
|
40
|
+
*
|
|
41
|
+
* Project-local installs live under `<project>/node_modules/` and don't match
|
|
42
|
+
* either pattern.
|
|
43
|
+
*/
|
|
44
|
+
export declare function isGlobalInstall(installPath?: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Check if running from a local node_modules install (vs npx cache or global).
|
|
32
47
|
*
|
|
33
48
|
* Local installs are in: <project>/node_modules/sequant/
|
|
34
49
|
* npx installs are in: ~/.npm/_npx/<hash>/node_modules/sequant/
|
|
50
|
+
* Global installs are in: <prefix>/lib/node_modules/sequant/
|
|
51
|
+
*
|
|
52
|
+
* Only project-local installs return true — npx and globals are excluded so
|
|
53
|
+
* neither receives the project-local "use npm update sequant" warning.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isLocalNodeModulesInstall(installPath?: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Walk up from the given directory to find the directory containing
|
|
58
|
+
* sequant's package.json. Returns null if not found.
|
|
59
|
+
*
|
|
60
|
+
* Mirrors the walk-up in getCurrentVersion() so callers can reason about
|
|
61
|
+
* the install root (the directory that actually holds sequant's package.json),
|
|
62
|
+
* which is needed to distinguish between e.g. project-local installs and the
|
|
63
|
+
* pathological $HOME/node_modules/sequant case.
|
|
64
|
+
*
|
|
65
|
+
* @internal Exported for testability and reuse in bin/cli.ts. Not a stable
|
|
66
|
+
* public API — may change without a major version bump.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getInstallRoot(startDir?: string): string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Check whether sequant is installed in $HOME/node_modules/sequant exactly.
|
|
71
|
+
*
|
|
72
|
+
* This is a known footgun: a stray `npm install sequant` run from $HOME
|
|
73
|
+
* leaves a package.json + node_modules/ at the home root, and Node's module
|
|
74
|
+
* resolution then walks up from any home subdirectory to that stale install
|
|
75
|
+
* before falling back to the npx cache. The result is that `npx sequant`
|
|
76
|
+
* silently runs the home-stray copy instead of the latest version.
|
|
77
|
+
*
|
|
78
|
+
* Project-local installs (anywhere else under node_modules/), global installs,
|
|
79
|
+
* and the npx cache all return false.
|
|
80
|
+
*
|
|
81
|
+
* `installRoot` is accepted as a parameter for testability.
|
|
82
|
+
*/
|
|
83
|
+
export declare function isHomeStrayInstall(installRoot?: string | null): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Render the home-stray warning string for a given install root.
|
|
86
|
+
*
|
|
87
|
+
* Extracted from bin/cli.ts so the rendered output can be asserted in unit
|
|
88
|
+
* tests; the predicate (isHomeStrayInstall) and the emission are then both
|
|
89
|
+
* covered without spawning a child process. Returns the warning text without
|
|
90
|
+
* any chalk styling — the caller decides whether to colorize.
|
|
35
91
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* - npx installs should be updated with: npx sequant@latest
|
|
92
|
+
* @internal Exported for the bin/cli.ts caller and unit tests. Not a stable
|
|
93
|
+
* public API — may change without a major version bump.
|
|
39
94
|
*/
|
|
40
|
-
export declare function
|
|
95
|
+
export declare function buildHomeStrayWarning(installRoot: string): string;
|
|
41
96
|
/**
|
|
42
97
|
* Read the version cache
|
|
43
98
|
*/
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* with the latest version on npm.
|
|
6
6
|
*/
|
|
7
7
|
import fs from "fs";
|
|
8
|
+
import os from "os";
|
|
8
9
|
import path from "path";
|
|
9
10
|
import { fileURLToPath } from "url";
|
|
10
11
|
import { detectPackageManagerSync, getPackageManagerCommands, } from "./stacks.js";
|
|
@@ -56,23 +57,110 @@ export function getCurrentVersion() {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
|
-
* Check if running from a
|
|
60
|
+
* Check if running from a global install (npm root -g).
|
|
61
|
+
*
|
|
62
|
+
* On POSIX, npm's global root convention puts packages under
|
|
63
|
+
* `<prefix>/lib/node_modules/` (e.g. `/usr/local/lib/node_modules`,
|
|
64
|
+
* `/opt/homebrew/lib/node_modules`, `~/.nvm/versions/node/<v>/lib/node_modules`).
|
|
65
|
+
*
|
|
66
|
+
* On Windows, the default global root is `%AppData%\npm\node_modules\` —
|
|
67
|
+
* sometimes nested under `Roaming\` depending on the npm/Node installer —
|
|
68
|
+
* with no `lib\` segment. Both variants are matched here.
|
|
69
|
+
*
|
|
70
|
+
* Project-local installs live under `<project>/node_modules/` and don't match
|
|
71
|
+
* either pattern.
|
|
72
|
+
*/
|
|
73
|
+
export function isGlobalInstall(installPath = __dirname) {
|
|
74
|
+
const normalizedPath = installPath.replace(/\\/g, "/");
|
|
75
|
+
return (normalizedPath.includes("/lib/node_modules/sequant") ||
|
|
76
|
+
/\/AppData\/(Roaming\/)?npm\/node_modules\/sequant/.test(normalizedPath));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if running from a local node_modules install (vs npx cache or global).
|
|
60
80
|
*
|
|
61
81
|
* Local installs are in: <project>/node_modules/sequant/
|
|
62
82
|
* npx installs are in: ~/.npm/_npx/<hash>/node_modules/sequant/
|
|
83
|
+
* Global installs are in: <prefix>/lib/node_modules/sequant/
|
|
63
84
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* - npx installs should be updated with: npx sequant@latest
|
|
85
|
+
* Only project-local installs return true — npx and globals are excluded so
|
|
86
|
+
* neither receives the project-local "use npm update sequant" warning.
|
|
67
87
|
*/
|
|
68
|
-
export function isLocalNodeModulesInstall() {
|
|
69
|
-
|
|
70
|
-
const normalizedPath = __dirname.replace(/\\/g, "/");
|
|
71
|
-
// Running from local node_modules (not npx cache)
|
|
88
|
+
export function isLocalNodeModulesInstall(installPath = __dirname) {
|
|
89
|
+
const normalizedPath = installPath.replace(/\\/g, "/");
|
|
72
90
|
const inNodeModules = normalizedPath.includes("/node_modules/sequant");
|
|
73
91
|
const inNpxCache = normalizedPath.includes("/.npm/_npx/") ||
|
|
74
92
|
normalizedPath.includes("\\.npm\\_npx\\");
|
|
75
|
-
return inNodeModules && !inNpxCache;
|
|
93
|
+
return inNodeModules && !inNpxCache && !isGlobalInstall(normalizedPath);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Walk up from the given directory to find the directory containing
|
|
97
|
+
* sequant's package.json. Returns null if not found.
|
|
98
|
+
*
|
|
99
|
+
* Mirrors the walk-up in getCurrentVersion() so callers can reason about
|
|
100
|
+
* the install root (the directory that actually holds sequant's package.json),
|
|
101
|
+
* which is needed to distinguish between e.g. project-local installs and the
|
|
102
|
+
* pathological $HOME/node_modules/sequant case.
|
|
103
|
+
*
|
|
104
|
+
* @internal Exported for testability and reuse in bin/cli.ts. Not a stable
|
|
105
|
+
* public API — may change without a major version bump.
|
|
106
|
+
*/
|
|
107
|
+
export function getInstallRoot(startDir = __dirname) {
|
|
108
|
+
let dir = startDir;
|
|
109
|
+
while (dir !== path.dirname(dir)) {
|
|
110
|
+
const candidate = path.resolve(dir, "package.json");
|
|
111
|
+
try {
|
|
112
|
+
const content = fs.readFileSync(candidate, "utf8");
|
|
113
|
+
const pkg = JSON.parse(content);
|
|
114
|
+
if (pkg.name === "sequant") {
|
|
115
|
+
return dir;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Not found, continue searching
|
|
120
|
+
}
|
|
121
|
+
dir = path.dirname(dir);
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Check whether sequant is installed in $HOME/node_modules/sequant exactly.
|
|
127
|
+
*
|
|
128
|
+
* This is a known footgun: a stray `npm install sequant` run from $HOME
|
|
129
|
+
* leaves a package.json + node_modules/ at the home root, and Node's module
|
|
130
|
+
* resolution then walks up from any home subdirectory to that stale install
|
|
131
|
+
* before falling back to the npx cache. The result is that `npx sequant`
|
|
132
|
+
* silently runs the home-stray copy instead of the latest version.
|
|
133
|
+
*
|
|
134
|
+
* Project-local installs (anywhere else under node_modules/), global installs,
|
|
135
|
+
* and the npx cache all return false.
|
|
136
|
+
*
|
|
137
|
+
* `installRoot` is accepted as a parameter for testability.
|
|
138
|
+
*/
|
|
139
|
+
export function isHomeStrayInstall(installRoot = getInstallRoot()) {
|
|
140
|
+
if (!installRoot)
|
|
141
|
+
return false;
|
|
142
|
+
const expected = path.join(os.homedir(), "node_modules", "sequant");
|
|
143
|
+
return path.resolve(installRoot) === path.resolve(expected);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Render the home-stray warning string for a given install root.
|
|
147
|
+
*
|
|
148
|
+
* Extracted from bin/cli.ts so the rendered output can be asserted in unit
|
|
149
|
+
* tests; the predicate (isHomeStrayInstall) and the emission are then both
|
|
150
|
+
* covered without spawning a child process. Returns the warning text without
|
|
151
|
+
* any chalk styling — the caller decides whether to colorize.
|
|
152
|
+
*
|
|
153
|
+
* @internal Exported for the bin/cli.ts caller and unit tests. Not a stable
|
|
154
|
+
* public API — may change without a major version bump.
|
|
155
|
+
*/
|
|
156
|
+
export function buildHomeStrayWarning(installRoot) {
|
|
157
|
+
const parent = path.dirname(installRoot);
|
|
158
|
+
return (`! Sequant is running from ${installRoot} — this pollutes\n` +
|
|
159
|
+
` resolution for every subdirectory of your home directory.\n\n` +
|
|
160
|
+
` If accidental (usually is — one stray \`npm install sequant\` from ~ does it):\n` +
|
|
161
|
+
` remove ${parent}\n` +
|
|
162
|
+
` remove $HOME/package.json and $HOME/package-lock.json\n\n` +
|
|
163
|
+
` If intentional: use \`npm install -g sequant\` or the Claude Code plugin.\n`);
|
|
76
164
|
}
|
|
77
165
|
/**
|
|
78
166
|
* Read the version cache
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (including quality-loop retries, checkpoint commits, rebasing, and PR
|
|
8
8
|
* creation).
|
|
9
9
|
*/
|
|
10
|
-
import { PhaseResult, IssueResult, type RunOptions, type IssueExecutionContext, type BatchExecutionContext } from "./types.js";
|
|
10
|
+
import { ExecutionConfig, PhaseResult, IssueResult, type RunOptions, type IssueExecutionContext, type BatchExecutionContext, type ProgressCallback } from "./types.js";
|
|
11
11
|
export type { RunOptions, ProgressCallback, IssueExecutionContext, BatchExecutionContext, } from "./types.js";
|
|
12
12
|
/**
|
|
13
13
|
* Emit a structured progress line to stderr for MCP progress notifications.
|
|
@@ -19,6 +19,16 @@ export type { RunOptions, ProgressCallback, IssueExecutionContext, BatchExecutio
|
|
|
19
19
|
* @param event - Phase lifecycle event: "start", "complete", or "failed"
|
|
20
20
|
* @param extra - Optional fields: durationSeconds (on complete), error (on failed)
|
|
21
21
|
*/
|
|
22
|
+
/**
|
|
23
|
+
* Wrap an `ExecutionConfig` with an `onActivity` hook that re-emits each
|
|
24
|
+
* agent-output ping as a `"activity"` progress event for the dashboard (#543).
|
|
25
|
+
*
|
|
26
|
+
* Returns the input config unchanged when no `onProgress` callback is set,
|
|
27
|
+
* so non-TUI runs pay no overhead.
|
|
28
|
+
*
|
|
29
|
+
* @internal Exported for testing only
|
|
30
|
+
*/
|
|
31
|
+
export declare function withActivityHook(base: ExecutionConfig, issueNumber: number, phase: string, onProgress: ProgressCallback | undefined): ExecutionConfig;
|
|
22
32
|
/**
|
|
23
33
|
* Build enriched prompt context for the /loop phase from a failed phase result (#488).
|
|
24
34
|
* Passes QA verdict, failed ACs, and error directly so the /loop skill doesn't need
|
|
@@ -30,7 +40,16 @@ export declare function buildLoopContext(failedResult: PhaseResult): string;
|
|
|
30
40
|
export declare function emitProgressLine(issue: number, phase: string, event?: "start" | "complete" | "failed", extra?: {
|
|
31
41
|
durationSeconds?: number;
|
|
32
42
|
error?: string;
|
|
43
|
+
iteration?: number;
|
|
33
44
|
}): void;
|
|
45
|
+
/**
|
|
46
|
+
* Emit the current run's UUID on stderr so MCP callers can look up the exact
|
|
47
|
+
* log file produced by this subprocess instead of relying on a fuzzy time
|
|
48
|
+
* filter (#631). Gated on `SEQUANT_ORCHESTRATOR` so CLI users see nothing.
|
|
49
|
+
*
|
|
50
|
+
* Must be called before `emitProgressLine` to satisfy AC-1.
|
|
51
|
+
*/
|
|
52
|
+
export declare function emitRunIdLine(runId: string): void;
|
|
34
53
|
export declare function getIssueInfo(issueNumber: number): Promise<{
|
|
35
54
|
title: string;
|
|
36
55
|
labels: string[];
|