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.
- package/README.md +10 -8
- package/dist/bin/cli.js +19 -9
- package/dist/src/commands/doctor.js +42 -20
- package/dist/src/commands/init.js +152 -65
- package/dist/src/commands/logs.js +7 -6
- package/dist/src/commands/run.d.ts +13 -1
- package/dist/src/commands/run.js +122 -32
- package/dist/src/commands/stats.js +67 -48
- package/dist/src/commands/status.js +30 -12
- package/dist/src/commands/sync.d.ts +28 -0
- package/dist/src/commands/sync.js +102 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +4 -0
- package/dist/src/lib/cli-ui.d.ts +196 -0
- package/dist/src/lib/cli-ui.js +544 -0
- package/dist/src/lib/content-analyzer.d.ts +89 -0
- package/dist/src/lib/content-analyzer.js +437 -0
- package/dist/src/lib/phase-signal.d.ts +94 -0
- package/dist/src/lib/phase-signal.js +171 -0
- package/dist/src/lib/phase-spinner.d.ts +146 -0
- package/dist/src/lib/phase-spinner.js +255 -0
- package/dist/src/lib/solve-comment-parser.d.ts +84 -0
- package/dist/src/lib/solve-comment-parser.js +200 -0
- package/dist/src/lib/stack-config.d.ts +51 -0
- package/dist/src/lib/stack-config.js +77 -0
- package/dist/src/lib/stacks.d.ts +52 -0
- package/dist/src/lib/stacks.js +173 -0
- package/dist/src/lib/templates.d.ts +2 -0
- package/dist/src/lib/templates.js +9 -2
- package/dist/src/lib/upstream/assessment.d.ts +70 -0
- package/dist/src/lib/upstream/assessment.js +385 -0
- package/dist/src/lib/upstream/index.d.ts +11 -0
- package/dist/src/lib/upstream/index.js +14 -0
- package/dist/src/lib/upstream/issues.d.ts +38 -0
- package/dist/src/lib/upstream/issues.js +267 -0
- package/dist/src/lib/upstream/relevance.d.ts +50 -0
- package/dist/src/lib/upstream/relevance.js +209 -0
- package/dist/src/lib/upstream/report.d.ts +29 -0
- package/dist/src/lib/upstream/report.js +391 -0
- package/dist/src/lib/upstream/types.d.ts +207 -0
- package/dist/src/lib/upstream/types.js +5 -0
- package/dist/src/lib/workflow/log-writer.d.ts +1 -1
- package/dist/src/lib/workflow/metrics-schema.d.ts +3 -3
- package/dist/src/lib/workflow/qa-cache.d.ts +199 -0
- package/dist/src/lib/workflow/qa-cache.js +440 -0
- package/dist/src/lib/workflow/run-log-schema.d.ts +34 -6
- package/dist/src/lib/workflow/run-log-schema.js +12 -1
- package/dist/src/lib/workflow/state-schema.d.ts +4 -4
- package/dist/src/lib/workflow/types.d.ts +4 -0
- package/package.json +6 -1
- package/templates/skills/qa/scripts/quality-checks.sh +509 -53
- package/templates/skills/solve/SKILL.md +375 -83
- package/templates/skills/spec/SKILL.md +107 -5
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack configuration persistence
|
|
3
|
+
*
|
|
4
|
+
* Manages user's stack configuration in .sequant/stack.json
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Stack entry with optional path for subdirectory stacks
|
|
8
|
+
*/
|
|
9
|
+
export interface StackEntry {
|
|
10
|
+
name: string;
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Persisted stack configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface StackConfigFile {
|
|
17
|
+
/** Primary stack (determines dev URL and main commands) */
|
|
18
|
+
primary: StackEntry;
|
|
19
|
+
/** Additional stacks to include in constitution notes */
|
|
20
|
+
additional?: StackEntry[];
|
|
21
|
+
/** When this configuration was last updated */
|
|
22
|
+
lastUpdated?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load stack configuration from .sequant/stack.json
|
|
26
|
+
*
|
|
27
|
+
* @returns Stack configuration or null if not found
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadStackConfig(): Promise<StackConfigFile | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Save stack configuration to .sequant/stack.json
|
|
32
|
+
*
|
|
33
|
+
* @param config - Stack configuration to save
|
|
34
|
+
*/
|
|
35
|
+
export declare function saveStackConfig(config: StackConfigFile): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if stack configuration exists
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasStackConfig(): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Get the primary stack name from configuration
|
|
42
|
+
*
|
|
43
|
+
* @returns Primary stack name or null if not configured
|
|
44
|
+
*/
|
|
45
|
+
export declare function getPrimaryStack(): Promise<string | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Get all configured stacks (primary + additional)
|
|
48
|
+
*
|
|
49
|
+
* @returns Array of all stack names
|
|
50
|
+
*/
|
|
51
|
+
export declare function getAllConfiguredStacks(): Promise<string[]>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack configuration persistence
|
|
3
|
+
*
|
|
4
|
+
* Manages user's stack configuration in .sequant/stack.json
|
|
5
|
+
*/
|
|
6
|
+
import { fileExists, readFile, writeFile, ensureDir } from "./fs.js";
|
|
7
|
+
import { dirname } from "path";
|
|
8
|
+
const STACK_CONFIG_PATH = ".sequant/stack.json";
|
|
9
|
+
/**
|
|
10
|
+
* Load stack configuration from .sequant/stack.json
|
|
11
|
+
*
|
|
12
|
+
* @returns Stack configuration or null if not found
|
|
13
|
+
*/
|
|
14
|
+
export async function loadStackConfig() {
|
|
15
|
+
try {
|
|
16
|
+
if (!(await fileExists(STACK_CONFIG_PATH))) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const content = await readFile(STACK_CONFIG_PATH);
|
|
20
|
+
const config = JSON.parse(content);
|
|
21
|
+
// Validate required fields
|
|
22
|
+
if (!config.primary || !config.primary.name) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Save stack configuration to .sequant/stack.json
|
|
33
|
+
*
|
|
34
|
+
* @param config - Stack configuration to save
|
|
35
|
+
*/
|
|
36
|
+
export async function saveStackConfig(config) {
|
|
37
|
+
const configWithTimestamp = {
|
|
38
|
+
...config,
|
|
39
|
+
lastUpdated: new Date().toISOString(),
|
|
40
|
+
};
|
|
41
|
+
await ensureDir(dirname(STACK_CONFIG_PATH));
|
|
42
|
+
await writeFile(STACK_CONFIG_PATH, JSON.stringify(configWithTimestamp, null, 2) + "\n");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if stack configuration exists
|
|
46
|
+
*/
|
|
47
|
+
export async function hasStackConfig() {
|
|
48
|
+
return fileExists(STACK_CONFIG_PATH);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get the primary stack name from configuration
|
|
52
|
+
*
|
|
53
|
+
* @returns Primary stack name or null if not configured
|
|
54
|
+
*/
|
|
55
|
+
export async function getPrimaryStack() {
|
|
56
|
+
const config = await loadStackConfig();
|
|
57
|
+
return config?.primary?.name ?? null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all configured stacks (primary + additional)
|
|
61
|
+
*
|
|
62
|
+
* @returns Array of all stack names
|
|
63
|
+
*/
|
|
64
|
+
export async function getAllConfiguredStacks() {
|
|
65
|
+
const config = await loadStackConfig();
|
|
66
|
+
if (!config)
|
|
67
|
+
return [];
|
|
68
|
+
const stacks = [config.primary.name];
|
|
69
|
+
if (config.additional) {
|
|
70
|
+
for (const entry of config.additional) {
|
|
71
|
+
if (!stacks.includes(entry.name)) {
|
|
72
|
+
stacks.push(entry.name);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return stacks;
|
|
77
|
+
}
|
package/dist/src/lib/stacks.d.ts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stack detection and configuration
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detected stack with location information
|
|
6
|
+
*/
|
|
7
|
+
export interface DetectedStack {
|
|
8
|
+
/** Stack name (e.g., "nextjs", "python") */
|
|
9
|
+
stack: string;
|
|
10
|
+
/** Path relative to project root (empty string for root) */
|
|
11
|
+
path: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Stack configuration for persistence in .sequant/stack.json
|
|
15
|
+
*/
|
|
16
|
+
export interface StackConfig_Persisted {
|
|
17
|
+
/** Primary stack for the project (determines dev URL, commands) */
|
|
18
|
+
primary: {
|
|
19
|
+
name: string;
|
|
20
|
+
path?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Additional stacks to include in constitution notes */
|
|
23
|
+
additional?: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
path?: string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
4
28
|
/**
|
|
5
29
|
* Supported package managers
|
|
6
30
|
*/
|
|
@@ -46,6 +70,23 @@ export interface StackConfig {
|
|
|
46
70
|
}
|
|
47
71
|
export declare const STACKS: Record<string, StackConfig>;
|
|
48
72
|
export declare function detectStack(): Promise<string | null>;
|
|
73
|
+
/**
|
|
74
|
+
* Detect stack in a specific directory
|
|
75
|
+
* Similar to detectStack but operates on a given path
|
|
76
|
+
*
|
|
77
|
+
* @param basePath - Directory path to check (relative to cwd)
|
|
78
|
+
* @returns Stack name or null if not detected
|
|
79
|
+
*/
|
|
80
|
+
export declare function detectStackInDirectory(basePath: string): Promise<string | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Detect all stacks in the repository
|
|
83
|
+
*
|
|
84
|
+
* Traverses root and immediate subdirectories (1 level deep) to find
|
|
85
|
+
* all stacks present in a monorepo or multi-stack project.
|
|
86
|
+
*
|
|
87
|
+
* @returns Array of detected stacks with their paths
|
|
88
|
+
*/
|
|
89
|
+
export declare function detectAllStacks(): Promise<DetectedStack[]>;
|
|
49
90
|
export declare function getStackConfig(stack: string): StackConfig;
|
|
50
91
|
/**
|
|
51
92
|
* Stack-specific notes for constitution templates
|
|
@@ -61,3 +102,14 @@ export declare const STACK_NOTES: Record<string, string>;
|
|
|
61
102
|
* @returns The stack-specific notes markdown content
|
|
62
103
|
*/
|
|
63
104
|
export declare function getStackNotes(stack: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Get combined stack notes for multiple stacks
|
|
107
|
+
*
|
|
108
|
+
* Combines notes from a primary stack and optional additional stacks
|
|
109
|
+
* into a single markdown section for multi-stack projects.
|
|
110
|
+
*
|
|
111
|
+
* @param primary - Primary stack name (determines primary tooling)
|
|
112
|
+
* @param additional - Additional stacks to include notes for
|
|
113
|
+
* @returns Combined stack notes markdown content
|
|
114
|
+
*/
|
|
115
|
+
export declare function getMultiStackNotes(primary: string, additional?: string[]): string;
|
package/dist/src/lib/stacks.js
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stack detection and configuration
|
|
3
3
|
*/
|
|
4
|
+
import { readdir } from "fs/promises";
|
|
4
5
|
import { fileExists, readFile } from "./fs.js";
|
|
6
|
+
/**
|
|
7
|
+
* Directories to skip during multi-stack detection
|
|
8
|
+
*/
|
|
9
|
+
const SKIP_DIRECTORIES = [
|
|
10
|
+
"node_modules",
|
|
11
|
+
".git",
|
|
12
|
+
"vendor",
|
|
13
|
+
"dist",
|
|
14
|
+
"build",
|
|
15
|
+
".next",
|
|
16
|
+
".nuxt",
|
|
17
|
+
".output",
|
|
18
|
+
"__pycache__",
|
|
19
|
+
"target",
|
|
20
|
+
".claude",
|
|
21
|
+
".sequant",
|
|
22
|
+
];
|
|
5
23
|
/**
|
|
6
24
|
* Package manager configurations
|
|
7
25
|
*/
|
|
@@ -307,6 +325,128 @@ export async function detectStack() {
|
|
|
307
325
|
}
|
|
308
326
|
return null;
|
|
309
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Detect stack in a specific directory
|
|
330
|
+
* Similar to detectStack but operates on a given path
|
|
331
|
+
*
|
|
332
|
+
* @param basePath - Directory path to check (relative to cwd)
|
|
333
|
+
* @returns Stack name or null if not detected
|
|
334
|
+
*/
|
|
335
|
+
export async function detectStackInDirectory(basePath) {
|
|
336
|
+
const pathPrefix = basePath ? `${basePath}/` : "";
|
|
337
|
+
// Check for Next.js config files
|
|
338
|
+
for (const file of STACKS.nextjs.detection.files || []) {
|
|
339
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
340
|
+
return "nextjs";
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Check for Astro config files
|
|
344
|
+
for (const file of STACKS.astro.detection.files || []) {
|
|
345
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
346
|
+
return "astro";
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Check for SvelteKit config files
|
|
350
|
+
for (const file of STACKS.sveltekit.detection.files || []) {
|
|
351
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
352
|
+
return "sveltekit";
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// Check for Remix config files
|
|
356
|
+
for (const file of STACKS.remix.detection.files || []) {
|
|
357
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
358
|
+
return "remix";
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Check for Nuxt config files
|
|
362
|
+
for (const file of STACKS.nuxt.detection.files || []) {
|
|
363
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
364
|
+
return "nuxt";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// Check package.json for JS framework dependencies
|
|
368
|
+
const packageJsonPath = `${pathPrefix}package.json`;
|
|
369
|
+
if (await fileExists(packageJsonPath)) {
|
|
370
|
+
try {
|
|
371
|
+
const pkg = JSON.parse(await readFile(packageJsonPath));
|
|
372
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
373
|
+
if (deps.next)
|
|
374
|
+
return "nextjs";
|
|
375
|
+
if (deps.astro)
|
|
376
|
+
return "astro";
|
|
377
|
+
if (deps["@sveltejs/kit"])
|
|
378
|
+
return "sveltekit";
|
|
379
|
+
if (deps["@remix-run/react"])
|
|
380
|
+
return "remix";
|
|
381
|
+
if (deps.nuxt)
|
|
382
|
+
return "nuxt";
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
// Ignore parse errors
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Check for Rust
|
|
389
|
+
if (await fileExists(`${pathPrefix}Cargo.toml`)) {
|
|
390
|
+
return "rust";
|
|
391
|
+
}
|
|
392
|
+
// Check for Go
|
|
393
|
+
if (await fileExists(`${pathPrefix}go.mod`)) {
|
|
394
|
+
return "go";
|
|
395
|
+
}
|
|
396
|
+
// Check for Python
|
|
397
|
+
for (const file of STACKS.python.detection.files || []) {
|
|
398
|
+
if (await fileExists(`${pathPrefix}${file}`)) {
|
|
399
|
+
return "python";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Detect all stacks in the repository
|
|
406
|
+
*
|
|
407
|
+
* Traverses root and immediate subdirectories (1 level deep) to find
|
|
408
|
+
* all stacks present in a monorepo or multi-stack project.
|
|
409
|
+
*
|
|
410
|
+
* @returns Array of detected stacks with their paths
|
|
411
|
+
*/
|
|
412
|
+
export async function detectAllStacks() {
|
|
413
|
+
const results = [];
|
|
414
|
+
// Check root directory
|
|
415
|
+
const rootStack = await detectStackInDirectory("");
|
|
416
|
+
if (rootStack) {
|
|
417
|
+
results.push({ stack: rootStack, path: "" });
|
|
418
|
+
}
|
|
419
|
+
// Check immediate subdirectories (1 level deep)
|
|
420
|
+
try {
|
|
421
|
+
const entries = await readdir(".", { withFileTypes: true });
|
|
422
|
+
for (const entry of entries) {
|
|
423
|
+
if (!entry.isDirectory())
|
|
424
|
+
continue;
|
|
425
|
+
if (SKIP_DIRECTORIES.includes(entry.name))
|
|
426
|
+
continue;
|
|
427
|
+
if (entry.name.startsWith("."))
|
|
428
|
+
continue; // Skip hidden directories
|
|
429
|
+
const subdirStack = await detectStackInDirectory(entry.name);
|
|
430
|
+
if (subdirStack) {
|
|
431
|
+
// Skip if same stack as root (likely a false positive)
|
|
432
|
+
// e.g., both root and /packages/web detect "nextjs"
|
|
433
|
+
// We want distinct stacks, not duplicates
|
|
434
|
+
const isDuplicate = results.some((r) => r.stack === subdirStack && r.path === "");
|
|
435
|
+
// Only skip if root has the same stack AND this is a common mono-repo pattern
|
|
436
|
+
// (like packages/, apps/, etc.)
|
|
437
|
+
if (!isDuplicate ||
|
|
438
|
+
entry.name === "frontend" ||
|
|
439
|
+
entry.name === "backend") {
|
|
440
|
+
results.push({ stack: subdirStack, path: entry.name });
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
// Directory read failed, return what we have
|
|
447
|
+
}
|
|
448
|
+
return results;
|
|
449
|
+
}
|
|
310
450
|
export function getStackConfig(stack) {
|
|
311
451
|
return STACKS[stack] || STACKS.generic;
|
|
312
452
|
}
|
|
@@ -469,3 +609,36 @@ export const STACK_NOTES = {
|
|
|
469
609
|
export function getStackNotes(stack) {
|
|
470
610
|
return STACK_NOTES[stack] || STACK_NOTES.generic;
|
|
471
611
|
}
|
|
612
|
+
/**
|
|
613
|
+
* Get combined stack notes for multiple stacks
|
|
614
|
+
*
|
|
615
|
+
* Combines notes from a primary stack and optional additional stacks
|
|
616
|
+
* into a single markdown section for multi-stack projects.
|
|
617
|
+
*
|
|
618
|
+
* @param primary - Primary stack name (determines primary tooling)
|
|
619
|
+
* @param additional - Additional stacks to include notes for
|
|
620
|
+
* @returns Combined stack notes markdown content
|
|
621
|
+
*/
|
|
622
|
+
export function getMultiStackNotes(primary, additional = []) {
|
|
623
|
+
const sections = [];
|
|
624
|
+
// Add primary stack notes (with "Primary" marker)
|
|
625
|
+
const primaryNotes = STACK_NOTES[primary] || STACK_NOTES.generic;
|
|
626
|
+
if (additional.length > 0) {
|
|
627
|
+
// Replace the first line heading to include "(Primary)"
|
|
628
|
+
const modifiedPrimary = primaryNotes.replace(/^### (.+)$/m, "### $1 (Primary)");
|
|
629
|
+
sections.push(modifiedPrimary);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
sections.push(primaryNotes);
|
|
633
|
+
}
|
|
634
|
+
// Add additional stack notes
|
|
635
|
+
for (const stack of additional) {
|
|
636
|
+
if (stack === primary)
|
|
637
|
+
continue; // Skip if same as primary
|
|
638
|
+
const notes = STACK_NOTES[stack];
|
|
639
|
+
if (notes && notes !== STACK_NOTES.generic) {
|
|
640
|
+
sections.push(notes);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return sections.join("\n\n---\n\n");
|
|
644
|
+
}
|
|
@@ -32,6 +32,8 @@ export interface CopyTemplatesOptions {
|
|
|
32
32
|
noSymlinks?: boolean;
|
|
33
33
|
/** Force replacement of existing files/symlinks */
|
|
34
34
|
force?: boolean;
|
|
35
|
+
/** Additional stacks to include in constitution notes (for multi-stack projects) */
|
|
36
|
+
additionalStacks?: string[];
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
39
|
* Create symlinks for files in a directory, with fallback to copy
|
|
@@ -5,7 +5,9 @@ import { readdir, chmod } from "fs/promises";
|
|
|
5
5
|
import { join, dirname, relative, isAbsolute } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { readFile, writeFile, ensureDir, fileExists, isSymlink, createSymlink, removeFileOrSymlink, } from "./fs.js";
|
|
8
|
-
import {
|
|
8
|
+
import { getPackageVersion } from "./manifest.js";
|
|
9
|
+
const SKILLS_VERSION_PATH = ".claude/skills/.sequant-version";
|
|
10
|
+
import { getStackConfig, getStackNotes, getMultiStackNotes } from "./stacks.js";
|
|
9
11
|
import { isNativeWindows } from "./system.js";
|
|
10
12
|
import { getProjectName } from "./project-name.js";
|
|
11
13
|
// Get the package templates directory
|
|
@@ -161,7 +163,10 @@ export async function copyTemplates(stack, tokens, options = {}) {
|
|
|
161
163
|
// Detect project name from available sources (package.json, Cargo.toml, etc.)
|
|
162
164
|
const projectName = await getProjectName();
|
|
163
165
|
// Get stack-specific notes for constitution template
|
|
164
|
-
|
|
166
|
+
// Use multi-stack notes if additional stacks are provided
|
|
167
|
+
const stackNotes = options.additionalStacks && options.additionalStacks.length > 0
|
|
168
|
+
? getMultiStackNotes(stack, options.additionalStacks)
|
|
169
|
+
: getStackNotes(stack);
|
|
165
170
|
const variables = {
|
|
166
171
|
...stackConfig.variables,
|
|
167
172
|
...tokens,
|
|
@@ -224,5 +229,7 @@ export async function copyTemplates(stack, tokens, options = {}) {
|
|
|
224
229
|
const content = await readFile(settingsPath);
|
|
225
230
|
await writeFile(".claude/settings.json", processTemplate(content, variables));
|
|
226
231
|
}
|
|
232
|
+
// Write skills version marker for sync detection
|
|
233
|
+
await writeFile(SKILLS_VERSION_PATH, getPackageVersion());
|
|
227
234
|
return { scriptsSymlinked, symlinkResults };
|
|
228
235
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main assessment module for upstream analysis
|
|
3
|
+
* Coordinates release fetching, analysis, and output generation
|
|
4
|
+
*/
|
|
5
|
+
import type { AssessmentOptions, Baseline, BatchedAssessment, ReleaseData, UpstreamAssessment } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Validate a version string to prevent command injection
|
|
8
|
+
* @throws Error if version format is invalid
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateVersion(version: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Check if gh CLI is available and authenticated
|
|
13
|
+
* @returns Object with availability status and error message if not available
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkGhCliAvailable(): Promise<{
|
|
16
|
+
available: boolean;
|
|
17
|
+
authenticated: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Fetch release data from Claude Code repository
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchRelease(version?: string): Promise<ReleaseData | null>;
|
|
24
|
+
/**
|
|
25
|
+
* List releases from Claude Code repository
|
|
26
|
+
*/
|
|
27
|
+
export declare function listReleases(limit?: number): Promise<Array<{
|
|
28
|
+
tagName: string;
|
|
29
|
+
publishedAt: string;
|
|
30
|
+
}>>;
|
|
31
|
+
/**
|
|
32
|
+
* Get releases since a specific version
|
|
33
|
+
*/
|
|
34
|
+
export declare function getReleasesSince(sinceVersion: string): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Load baseline from file
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadBaseline(path?: string): Promise<Baseline>;
|
|
39
|
+
/**
|
|
40
|
+
* Save baseline to file
|
|
41
|
+
*/
|
|
42
|
+
export declare function saveBaseline(baseline: Baseline, path?: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Update baseline with new assessed version
|
|
45
|
+
*/
|
|
46
|
+
export declare function updateBaseline(version: string, path?: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Check if a version has already been assessed
|
|
49
|
+
*/
|
|
50
|
+
export declare function isAlreadyAssessed(version: string): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Save local report
|
|
53
|
+
*/
|
|
54
|
+
export declare function saveLocalReport(assessment: UpstreamAssessment): Promise<string>;
|
|
55
|
+
/**
|
|
56
|
+
* Run a single version assessment
|
|
57
|
+
*/
|
|
58
|
+
export declare function assessVersion(version: string, options?: AssessmentOptions): Promise<UpstreamAssessment | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Run assessment for latest release
|
|
61
|
+
*/
|
|
62
|
+
export declare function assessLatest(options?: AssessmentOptions): Promise<UpstreamAssessment | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Run batched assessment for multiple versions
|
|
65
|
+
*/
|
|
66
|
+
export declare function assessSince(sinceVersion: string, options?: AssessmentOptions): Promise<BatchedAssessment | null>;
|
|
67
|
+
/**
|
|
68
|
+
* Main entry point for upstream assessment
|
|
69
|
+
*/
|
|
70
|
+
export declare function runUpstream(options?: AssessmentOptions): Promise<UpstreamAssessment | BatchedAssessment | null>;
|