sequant 1.12.0 → 1.13.1

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 (53) hide show
  1. package/README.md +10 -8
  2. package/dist/bin/cli.js +19 -9
  3. package/dist/src/commands/doctor.js +42 -20
  4. package/dist/src/commands/init.js +152 -65
  5. package/dist/src/commands/logs.js +7 -6
  6. package/dist/src/commands/run.d.ts +13 -1
  7. package/dist/src/commands/run.js +122 -32
  8. package/dist/src/commands/stats.js +67 -48
  9. package/dist/src/commands/status.js +30 -12
  10. package/dist/src/commands/sync.d.ts +28 -0
  11. package/dist/src/commands/sync.js +102 -0
  12. package/dist/src/index.d.ts +6 -0
  13. package/dist/src/index.js +4 -0
  14. package/dist/src/lib/cli-ui.d.ts +196 -0
  15. package/dist/src/lib/cli-ui.js +544 -0
  16. package/dist/src/lib/content-analyzer.d.ts +89 -0
  17. package/dist/src/lib/content-analyzer.js +437 -0
  18. package/dist/src/lib/phase-signal.d.ts +94 -0
  19. package/dist/src/lib/phase-signal.js +171 -0
  20. package/dist/src/lib/phase-spinner.d.ts +146 -0
  21. package/dist/src/lib/phase-spinner.js +255 -0
  22. package/dist/src/lib/solve-comment-parser.d.ts +84 -0
  23. package/dist/src/lib/solve-comment-parser.js +200 -0
  24. package/dist/src/lib/stack-config.d.ts +51 -0
  25. package/dist/src/lib/stack-config.js +77 -0
  26. package/dist/src/lib/stacks.d.ts +52 -0
  27. package/dist/src/lib/stacks.js +173 -0
  28. package/dist/src/lib/templates.d.ts +2 -0
  29. package/dist/src/lib/templates.js +9 -2
  30. package/dist/src/lib/upstream/assessment.d.ts +70 -0
  31. package/dist/src/lib/upstream/assessment.js +385 -0
  32. package/dist/src/lib/upstream/index.d.ts +11 -0
  33. package/dist/src/lib/upstream/index.js +14 -0
  34. package/dist/src/lib/upstream/issues.d.ts +38 -0
  35. package/dist/src/lib/upstream/issues.js +267 -0
  36. package/dist/src/lib/upstream/relevance.d.ts +50 -0
  37. package/dist/src/lib/upstream/relevance.js +209 -0
  38. package/dist/src/lib/upstream/report.d.ts +29 -0
  39. package/dist/src/lib/upstream/report.js +391 -0
  40. package/dist/src/lib/upstream/types.d.ts +207 -0
  41. package/dist/src/lib/upstream/types.js +5 -0
  42. package/dist/src/lib/workflow/log-writer.d.ts +1 -1
  43. package/dist/src/lib/workflow/metrics-schema.d.ts +3 -3
  44. package/dist/src/lib/workflow/qa-cache.d.ts +199 -0
  45. package/dist/src/lib/workflow/qa-cache.js +440 -0
  46. package/dist/src/lib/workflow/run-log-schema.d.ts +34 -6
  47. package/dist/src/lib/workflow/run-log-schema.js +12 -1
  48. package/dist/src/lib/workflow/state-schema.d.ts +4 -4
  49. package/dist/src/lib/workflow/types.d.ts +4 -0
  50. package/package.json +6 -1
  51. package/templates/skills/qa/scripts/quality-checks.sh +509 -53
  52. package/templates/skills/solve/SKILL.md +375 -83
  53. package/templates/skills/spec/SKILL.md +107 -5
@@ -0,0 +1,102 @@
1
+ /**
2
+ * sequant sync - Fast, non-interactive template sync
3
+ *
4
+ * Syncs skills and other templates from the package to the local project.
5
+ * Designed for plugin users who need to update after upgrading sequant.
6
+ */
7
+ import chalk from "chalk";
8
+ import { getManifest, updateManifest, getPackageVersion, } from "../lib/manifest.js";
9
+ import { copyTemplates } from "../lib/templates.js";
10
+ import { getConfig } from "../lib/config.js";
11
+ import { writeFile, readFile, fileExists } from "../lib/fs.js";
12
+ const SKILLS_VERSION_PATH = ".claude/skills/.sequant-version";
13
+ /**
14
+ * Get the version of skills currently installed
15
+ */
16
+ export async function getSkillsVersion() {
17
+ if (!(await fileExists(SKILLS_VERSION_PATH))) {
18
+ return null;
19
+ }
20
+ try {
21
+ const content = await readFile(SKILLS_VERSION_PATH);
22
+ return content.trim();
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * Check if skills are outdated compared to package version
30
+ */
31
+ export async function areSkillsOutdated() {
32
+ const currentVersion = await getSkillsVersion();
33
+ const packageVersion = getPackageVersion();
34
+ return {
35
+ outdated: currentVersion !== packageVersion,
36
+ currentVersion,
37
+ packageVersion,
38
+ };
39
+ }
40
+ /**
41
+ * Update the skills version marker
42
+ */
43
+ async function updateSkillsVersion() {
44
+ await writeFile(SKILLS_VERSION_PATH, getPackageVersion());
45
+ }
46
+ export async function syncCommand(options = {}) {
47
+ const { force = false, quiet = false } = options;
48
+ if (!quiet) {
49
+ console.log(chalk.blue("\nšŸ”„ Syncing templates...\n"));
50
+ }
51
+ // Check if initialized
52
+ const manifest = await getManifest();
53
+ if (!manifest) {
54
+ console.log(chalk.red("āŒ Sequant is not initialized. Run `sequant init` first."));
55
+ process.exitCode = 1;
56
+ return;
57
+ }
58
+ const packageVersion = getPackageVersion();
59
+ const skillsVersion = await getSkillsVersion();
60
+ if (!quiet) {
61
+ console.log(chalk.gray(`Skills version: ${skillsVersion || "(unknown)"}`));
62
+ console.log(chalk.gray(`Package version: ${packageVersion}`));
63
+ console.log(chalk.gray(`Stack: ${manifest.stack}\n`));
64
+ }
65
+ // Check if sync is needed
66
+ if (!force && skillsVersion === packageVersion) {
67
+ if (!quiet) {
68
+ console.log(chalk.green("āœ… Skills are already up to date!"));
69
+ }
70
+ return;
71
+ }
72
+ // Get config tokens for template processing
73
+ const config = await getConfig();
74
+ const tokens = config?.tokens || {};
75
+ // Copy templates with force to overwrite existing files
76
+ const copyOptions = {
77
+ force: true, // Always overwrite when syncing
78
+ };
79
+ if (!quiet) {
80
+ console.log(chalk.blue("šŸ“„ Copying templates..."));
81
+ }
82
+ await copyTemplates(manifest.stack, tokens, copyOptions);
83
+ // Update version markers
84
+ await updateSkillsVersion();
85
+ await updateManifest();
86
+ if (!quiet) {
87
+ console.log(chalk.green(`\nāœ… Synced to v${packageVersion}`));
88
+ console.log(chalk.gray("\nSkills, hooks, and memory files have been updated."));
89
+ }
90
+ }
91
+ /**
92
+ * Check and warn if skills are outdated (for use by other commands)
93
+ */
94
+ export async function checkAndWarnSkillsOutdated() {
95
+ const { outdated, currentVersion, packageVersion } = await areSkillsOutdated();
96
+ if (outdated) {
97
+ console.log(chalk.yellow(`\nāš ļø Skills are outdated (${currentVersion || "unknown"} → ${packageVersion})`));
98
+ console.log(chalk.yellow(" Run: npx sequant sync\n"));
99
+ return true;
100
+ }
101
+ return false;
102
+ }
@@ -23,3 +23,9 @@ export { createStateHook, isOrchestrated, getOrchestrationContext, } from "./lib
23
23
  export type { StateHook, StateHookOptions } from "./lib/workflow/state-hook.js";
24
24
  export { rebuildStateFromLogs, cleanupStaleEntries, } from "./lib/workflow/state-utils.js";
25
25
  export type { RebuildOptions, RebuildResult, CleanupOptions, CleanupResult, } from "./lib/workflow/state-utils.js";
26
+ export { analyzeTitleForPhases, analyzeBodyForPhases, analyzeContentForPhases, isTrivialWork, formatContentAnalysis, } from "./lib/content-analyzer.js";
27
+ export type { ContentSignal, ContentAnalysisResult, } from "./lib/content-analyzer.js";
28
+ export { mergePhaseSignals, signalFromLabel, signalsFromLabels, formatMergedPhases, SIGNAL_PRIORITY, } from "./lib/phase-signal.js";
29
+ export type { SignalSource, SignalConfidence, PhaseSignal, MergedPhaseResult, } from "./lib/phase-signal.js";
30
+ export { isSolveComment, findSolveComment, parseSolveWorkflow, solveWorkflowToSignals, solveCoversIssue, } from "./lib/solve-comment-parser.js";
31
+ export type { SolveWorkflowResult, IssueComment, } from "./lib/solve-comment-parser.js";
package/dist/src/index.js CHANGED
@@ -16,3 +16,7 @@ export { StateManager, getStateManager } from "./lib/workflow/state-manager.js";
16
16
  export { createEmptyState, createIssueState, createPhaseState, STATE_FILE_PATH, WORKFLOW_PHASES, } from "./lib/workflow/state-schema.js";
17
17
  export { createStateHook, isOrchestrated, getOrchestrationContext, } from "./lib/workflow/state-hook.js";
18
18
  export { rebuildStateFromLogs, cleanupStaleEntries, } from "./lib/workflow/state-utils.js";
19
+ // Content analysis exports
20
+ export { analyzeTitleForPhases, analyzeBodyForPhases, analyzeContentForPhases, isTrivialWork, formatContentAnalysis, } from "./lib/content-analyzer.js";
21
+ export { mergePhaseSignals, signalFromLabel, signalsFromLabels, formatMergedPhases, SIGNAL_PRIORITY, } from "./lib/phase-signal.js";
22
+ export { isSolveComment, findSolveComment, parseSolveWorkflow, solveWorkflowToSignals, solveCoversIssue, } from "./lib/solve-comment-parser.js";
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Centralized CLI UI module for Sequant
3
+ *
4
+ * Provides consistent styling, spinners, boxes, tables, and branding
5
+ * with graceful fallbacks for non-TTY, CI, and legacy terminals.
6
+ */
7
+ /**
8
+ * UI configuration options
9
+ */
10
+ export interface UIConfig {
11
+ /** Disable all colors and styling */
12
+ noColor: boolean;
13
+ /** JSON output mode - suppress decorative output */
14
+ jsonMode: boolean;
15
+ /** Verbose mode - use text-only spinners to avoid overwriting output */
16
+ verbose: boolean;
17
+ /** Whether stdout is a TTY */
18
+ isTTY: boolean;
19
+ /** Running in CI environment */
20
+ isCI: boolean;
21
+ /** Minimal output mode */
22
+ minimal: boolean;
23
+ }
24
+ /**
25
+ * Configure UI settings
26
+ *
27
+ * Call this early in CLI startup to set global options.
28
+ */
29
+ export declare function configureUI(options: Partial<UIConfig>): void;
30
+ /**
31
+ * Get current UI configuration
32
+ */
33
+ export declare function getUIConfig(): Readonly<UIConfig>;
34
+ /**
35
+ * Standardized color palette for consistent styling
36
+ */
37
+ export declare const colors: {
38
+ success: ((s: string) => string) | import("chalk").ChalkInstance;
39
+ error: import("chalk").ChalkInstance | ((s: string) => string);
40
+ warning: import("chalk").ChalkInstance | ((s: string) => string);
41
+ info: import("chalk").ChalkInstance | ((s: string) => string);
42
+ muted: import("chalk").ChalkInstance | ((s: string) => string);
43
+ header: import("chalk").ChalkInstance | ((s: string) => string);
44
+ label: import("chalk").ChalkInstance | ((s: string) => string);
45
+ value: import("chalk").ChalkInstance | ((s: string) => string);
46
+ accent: import("chalk").ChalkInstance | ((s: string) => string);
47
+ bold: import("chalk").ChalkInstance | ((s: string) => string);
48
+ pending: import("chalk").ChalkInstance | ((s: string) => string);
49
+ running: import("chalk").ChalkInstance | ((s: string) => string);
50
+ completed: import("chalk").ChalkInstance | ((s: string) => string);
51
+ failed: import("chalk").ChalkInstance | ((s: string) => string);
52
+ };
53
+ /**
54
+ * Get the ASCII logo with optional gradient
55
+ */
56
+ export declare function logo(): string;
57
+ /**
58
+ * Get the banner (logo + tagline)
59
+ */
60
+ export declare function banner(): string;
61
+ /**
62
+ * Spinner manager interface
63
+ */
64
+ export interface SpinnerManager {
65
+ /** Start the spinner with optional new text */
66
+ start(text?: string): SpinnerManager;
67
+ /** Mark as succeeded with optional message */
68
+ succeed(text?: string): SpinnerManager;
69
+ /** Mark as failed with optional message */
70
+ fail(text?: string): SpinnerManager;
71
+ /** Mark as warning with optional message */
72
+ warn(text?: string): SpinnerManager;
73
+ /** Stop the spinner */
74
+ stop(): SpinnerManager;
75
+ /** Update the spinner text */
76
+ text: string;
77
+ /** Check if spinner is active */
78
+ isSpinning: boolean;
79
+ }
80
+ /**
81
+ * Create a spinner with automatic fallback
82
+ *
83
+ * Returns an animated spinner for TTY, text-only for non-TTY/verbose/CI.
84
+ */
85
+ export declare function spinner(text: string): SpinnerManager;
86
+ /**
87
+ * Box style presets
88
+ */
89
+ export type BoxStyle = "success" | "error" | "warning" | "info" | "header" | "default";
90
+ /**
91
+ * Create a boxed message
92
+ */
93
+ export declare function box(content: string, style?: BoxStyle): string;
94
+ /**
95
+ * Create a success box with title and message
96
+ */
97
+ export declare function successBox(title: string, message: string): string;
98
+ /**
99
+ * Create an error box with title and message
100
+ */
101
+ export declare function errorBox(title: string, message: string): string;
102
+ /**
103
+ * Create a warning box with title and message
104
+ */
105
+ export declare function warningBox(title: string, message: string): string;
106
+ /**
107
+ * Create a header box
108
+ */
109
+ export declare function headerBox(title: string): string;
110
+ /**
111
+ * Table column definition
112
+ */
113
+ export interface TableColumn {
114
+ /** Column header text */
115
+ header: string;
116
+ /** Column width (optional) */
117
+ width?: number;
118
+ /** Text alignment */
119
+ align?: "left" | "center" | "right";
120
+ }
121
+ /**
122
+ * Table options
123
+ */
124
+ export interface TableOptions {
125
+ /** Column definitions */
126
+ columns: TableColumn[];
127
+ /** Table style */
128
+ style?: "default" | "compact" | "borderless";
129
+ }
130
+ /**
131
+ * Create a formatted table
132
+ */
133
+ export declare function table(rows: (string | number)[][], options: TableOptions): string;
134
+ /**
135
+ * Create a simple key-value table
136
+ */
137
+ export declare function keyValueTable(data: Record<string, string | number>): string;
138
+ /**
139
+ * Status indicator types
140
+ */
141
+ export type StatusType = "success" | "error" | "warning" | "pending" | "running";
142
+ /**
143
+ * Get a status icon
144
+ */
145
+ export declare function statusIcon(type: StatusType): string;
146
+ /**
147
+ * Print a status message with icon
148
+ */
149
+ export declare function printStatus(type: StatusType, message: string): void;
150
+ /**
151
+ * Create a horizontal divider
152
+ */
153
+ export declare function divider(width?: number): string;
154
+ /**
155
+ * Create a section header
156
+ */
157
+ export declare function sectionHeader(title: string): string;
158
+ /**
159
+ * Phase status for progress display
160
+ */
161
+ export interface PhaseStatus {
162
+ name: string;
163
+ status: "pending" | "running" | "success" | "failure" | "skipped";
164
+ }
165
+ /**
166
+ * Display phase progress as a visual indicator
167
+ */
168
+ export declare function phaseProgress(phases: PhaseStatus[]): string;
169
+ /**
170
+ * Create a progress bar
171
+ */
172
+ export declare function progressBar(current: number, total: number, width?: number): string;
173
+ /**
174
+ * Unified UI object for convenient access to all utilities
175
+ */
176
+ export declare const ui: {
177
+ configure: typeof configureUI;
178
+ getConfig: typeof getUIConfig;
179
+ logo: typeof logo;
180
+ banner: typeof banner;
181
+ spinner: typeof spinner;
182
+ box: typeof box;
183
+ successBox: typeof successBox;
184
+ errorBox: typeof errorBox;
185
+ warningBox: typeof warningBox;
186
+ headerBox: typeof headerBox;
187
+ table: typeof table;
188
+ keyValueTable: typeof keyValueTable;
189
+ statusIcon: typeof statusIcon;
190
+ printStatus: typeof printStatus;
191
+ divider: typeof divider;
192
+ sectionHeader: typeof sectionHeader;
193
+ phaseProgress: typeof phaseProgress;
194
+ progressBar: typeof progressBar;
195
+ };
196
+ export default ui;