lightspec 0.1.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/LICENSE +22 -0
- package/README.md +435 -0
- package/bin/lightspec.js +3 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +361 -0
- package/dist/commands/change.d.ts +35 -0
- package/dist/commands/change.js +277 -0
- package/dist/commands/completion.d.ts +72 -0
- package/dist/commands/completion.js +257 -0
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.js +198 -0
- package/dist/commands/feedback.d.ts +9 -0
- package/dist/commands/feedback.js +183 -0
- package/dist/commands/show.d.ts +14 -0
- package/dist/commands/show.js +132 -0
- package/dist/commands/spec.d.ts +15 -0
- package/dist/commands/spec.js +225 -0
- package/dist/commands/validate.d.ts +24 -0
- package/dist/commands/validate.js +294 -0
- package/dist/core/archive.d.ts +11 -0
- package/dist/core/archive.js +280 -0
- package/dist/core/completions/command-registry.d.ts +7 -0
- package/dist/core/completions/command-registry.js +456 -0
- package/dist/core/completions/completion-provider.d.ts +60 -0
- package/dist/core/completions/completion-provider.js +102 -0
- package/dist/core/completions/factory.d.ts +64 -0
- package/dist/core/completions/factory.js +75 -0
- package/dist/core/completions/generators/bash-generator.d.ts +32 -0
- package/dist/core/completions/generators/bash-generator.js +174 -0
- package/dist/core/completions/generators/fish-generator.d.ts +32 -0
- package/dist/core/completions/generators/fish-generator.js +157 -0
- package/dist/core/completions/generators/powershell-generator.d.ts +33 -0
- package/dist/core/completions/generators/powershell-generator.js +207 -0
- package/dist/core/completions/generators/zsh-generator.d.ts +44 -0
- package/dist/core/completions/generators/zsh-generator.js +250 -0
- package/dist/core/completions/installers/bash-installer.d.ts +87 -0
- package/dist/core/completions/installers/bash-installer.js +318 -0
- package/dist/core/completions/installers/fish-installer.d.ts +43 -0
- package/dist/core/completions/installers/fish-installer.js +143 -0
- package/dist/core/completions/installers/powershell-installer.d.ts +88 -0
- package/dist/core/completions/installers/powershell-installer.js +327 -0
- package/dist/core/completions/installers/zsh-installer.d.ts +125 -0
- package/dist/core/completions/installers/zsh-installer.js +449 -0
- package/dist/core/completions/templates/bash-templates.d.ts +6 -0
- package/dist/core/completions/templates/bash-templates.js +24 -0
- package/dist/core/completions/templates/fish-templates.d.ts +7 -0
- package/dist/core/completions/templates/fish-templates.js +39 -0
- package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
- package/dist/core/completions/templates/powershell-templates.js +25 -0
- package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
- package/dist/core/completions/templates/zsh-templates.js +36 -0
- package/dist/core/completions/types.d.ts +79 -0
- package/dist/core/completions/types.js +2 -0
- package/dist/core/config-prompts.d.ts +9 -0
- package/dist/core/config-prompts.js +34 -0
- package/dist/core/config-schema.d.ts +76 -0
- package/dist/core/config-schema.js +200 -0
- package/dist/core/config.d.ts +16 -0
- package/dist/core/config.js +30 -0
- package/dist/core/configurators/agents.d.ts +8 -0
- package/dist/core/configurators/agents.js +15 -0
- package/dist/core/configurators/base.d.ts +7 -0
- package/dist/core/configurators/base.js +2 -0
- package/dist/core/configurators/claude.d.ts +8 -0
- package/dist/core/configurators/claude.js +15 -0
- package/dist/core/configurators/cline.d.ts +8 -0
- package/dist/core/configurators/cline.js +15 -0
- package/dist/core/configurators/codebuddy.d.ts +8 -0
- package/dist/core/configurators/codebuddy.js +15 -0
- package/dist/core/configurators/costrict.d.ts +8 -0
- package/dist/core/configurators/costrict.js +15 -0
- package/dist/core/configurators/iflow.d.ts +8 -0
- package/dist/core/configurators/iflow.js +15 -0
- package/dist/core/configurators/qoder.d.ts +30 -0
- package/dist/core/configurators/qoder.js +42 -0
- package/dist/core/configurators/qwen.d.ts +24 -0
- package/dist/core/configurators/qwen.js +37 -0
- package/dist/core/configurators/registry.d.ts +9 -0
- package/dist/core/configurators/registry.js +43 -0
- package/dist/core/configurators/slash/amazon-q.d.ts +9 -0
- package/dist/core/configurators/slash/amazon-q.js +46 -0
- package/dist/core/configurators/slash/antigravity.d.ts +9 -0
- package/dist/core/configurators/slash/antigravity.js +23 -0
- package/dist/core/configurators/slash/auggie.d.ts +9 -0
- package/dist/core/configurators/slash/auggie.js +31 -0
- package/dist/core/configurators/slash/base.d.ts +19 -0
- package/dist/core/configurators/slash/base.js +69 -0
- package/dist/core/configurators/slash/claude.d.ts +9 -0
- package/dist/core/configurators/slash/claude.js +37 -0
- package/dist/core/configurators/slash/cline.d.ts +9 -0
- package/dist/core/configurators/slash/cline.js +23 -0
- package/dist/core/configurators/slash/codebuddy.d.ts +9 -0
- package/dist/core/configurators/slash/codebuddy.js +34 -0
- package/dist/core/configurators/slash/codex.d.ts +14 -0
- package/dist/core/configurators/slash/codex.js +109 -0
- package/dist/core/configurators/slash/continue.d.ts +9 -0
- package/dist/core/configurators/slash/continue.js +46 -0
- package/dist/core/configurators/slash/costrict.d.ts +9 -0
- package/dist/core/configurators/slash/costrict.js +31 -0
- package/dist/core/configurators/slash/crush.d.ts +9 -0
- package/dist/core/configurators/slash/crush.js +37 -0
- package/dist/core/configurators/slash/cursor.d.ts +9 -0
- package/dist/core/configurators/slash/cursor.js +37 -0
- package/dist/core/configurators/slash/factory.d.ts +10 -0
- package/dist/core/configurators/slash/factory.js +35 -0
- package/dist/core/configurators/slash/gemini.d.ts +9 -0
- package/dist/core/configurators/slash/gemini.js +22 -0
- package/dist/core/configurators/slash/github-copilot.d.ts +9 -0
- package/dist/core/configurators/slash/github-copilot.js +34 -0
- package/dist/core/configurators/slash/iflow.d.ts +9 -0
- package/dist/core/configurators/slash/iflow.js +37 -0
- package/dist/core/configurators/slash/kilocode.d.ts +9 -0
- package/dist/core/configurators/slash/kilocode.js +17 -0
- package/dist/core/configurators/slash/opencode.d.ts +12 -0
- package/dist/core/configurators/slash/opencode.js +72 -0
- package/dist/core/configurators/slash/qoder.d.ts +35 -0
- package/dist/core/configurators/slash/qoder.js +76 -0
- package/dist/core/configurators/slash/qwen.d.ts +32 -0
- package/dist/core/configurators/slash/qwen.js +49 -0
- package/dist/core/configurators/slash/registry.d.ts +8 -0
- package/dist/core/configurators/slash/registry.js +78 -0
- package/dist/core/configurators/slash/roocode.d.ts +9 -0
- package/dist/core/configurators/slash/roocode.js +23 -0
- package/dist/core/configurators/slash/toml-base.d.ts +10 -0
- package/dist/core/configurators/slash/toml-base.js +53 -0
- package/dist/core/configurators/slash/windsurf.d.ts +9 -0
- package/dist/core/configurators/slash/windsurf.js +23 -0
- package/dist/core/converters/json-converter.d.ts +6 -0
- package/dist/core/converters/json-converter.js +51 -0
- package/dist/core/global-config.d.ts +39 -0
- package/dist/core/global-config.js +115 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +3 -0
- package/dist/core/init.d.ts +52 -0
- package/dist/core/init.js +644 -0
- package/dist/core/list.d.ts +9 -0
- package/dist/core/list.js +171 -0
- package/dist/core/parsers/change-parser.d.ts +13 -0
- package/dist/core/parsers/change-parser.js +193 -0
- package/dist/core/parsers/markdown-parser.d.ts +22 -0
- package/dist/core/parsers/markdown-parser.js +187 -0
- package/dist/core/parsers/requirement-blocks.d.ts +37 -0
- package/dist/core/parsers/requirement-blocks.js +201 -0
- package/dist/core/project-config.d.ts +64 -0
- package/dist/core/project-config.js +223 -0
- package/dist/core/schemas/base.schema.d.ts +13 -0
- package/dist/core/schemas/base.schema.js +13 -0
- package/dist/core/schemas/change.schema.d.ts +73 -0
- package/dist/core/schemas/change.schema.js +31 -0
- package/dist/core/schemas/index.d.ts +4 -0
- package/dist/core/schemas/index.js +4 -0
- package/dist/core/schemas/spec.schema.d.ts +18 -0
- package/dist/core/schemas/spec.schema.js +15 -0
- package/dist/core/specs-apply.d.ts +73 -0
- package/dist/core/specs-apply.js +384 -0
- package/dist/core/styles/palette.d.ts +7 -0
- package/dist/core/styles/palette.js +8 -0
- package/dist/core/templates/agents-root-stub.d.ts +2 -0
- package/dist/core/templates/agents-root-stub.js +17 -0
- package/dist/core/templates/agents-template.d.ts +2 -0
- package/dist/core/templates/agents-template.js +458 -0
- package/dist/core/templates/claude-template.d.ts +2 -0
- package/dist/core/templates/claude-template.js +2 -0
- package/dist/core/templates/cline-template.d.ts +2 -0
- package/dist/core/templates/cline-template.js +2 -0
- package/dist/core/templates/costrict-template.d.ts +2 -0
- package/dist/core/templates/costrict-template.js +2 -0
- package/dist/core/templates/index.d.ts +17 -0
- package/dist/core/templates/index.js +37 -0
- package/dist/core/templates/project-template.d.ts +8 -0
- package/dist/core/templates/project-template.js +32 -0
- package/dist/core/templates/slash-command-templates.d.ts +4 -0
- package/dist/core/templates/slash-command-templates.js +49 -0
- package/dist/core/update.d.ts +4 -0
- package/dist/core/update.js +88 -0
- package/dist/core/validation/constants.d.ts +34 -0
- package/dist/core/validation/constants.js +40 -0
- package/dist/core/validation/types.d.ts +18 -0
- package/dist/core/validation/types.js +2 -0
- package/dist/core/validation/validator.d.ts +33 -0
- package/dist/core/validation/validator.js +409 -0
- package/dist/core/view.d.ts +8 -0
- package/dist/core/view.js +168 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/telemetry/config.d.ts +32 -0
- package/dist/telemetry/config.js +68 -0
- package/dist/telemetry/index.d.ts +31 -0
- package/dist/telemetry/index.js +103 -0
- package/dist/utils/file-system.d.ts +25 -0
- package/dist/utils/file-system.js +218 -0
- package/dist/utils/interactive.d.ts +18 -0
- package/dist/utils/interactive.js +21 -0
- package/dist/utils/item-discovery.d.ts +4 -0
- package/dist/utils/item-discovery.js +72 -0
- package/dist/utils/match.d.ts +3 -0
- package/dist/utils/match.js +22 -0
- package/dist/utils/shell-detection.d.ts +20 -0
- package/dist/utils/shell-detection.js +41 -0
- package/dist/utils/task-progress.d.ts +8 -0
- package/dist/utils/task-progress.js +36 -0
- package/package.json +82 -0
- package/scripts/postinstall.js +147 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves whether non-interactive mode is requested.
|
|
3
|
+
* Handles both explicit `noInteractive: true` and Commander.js style `interactive: false`.
|
|
4
|
+
* Use this helper instead of manually checking options.noInteractive to avoid bugs.
|
|
5
|
+
*/
|
|
6
|
+
export function resolveNoInteractive(value) {
|
|
7
|
+
if (typeof value === 'boolean')
|
|
8
|
+
return value;
|
|
9
|
+
return value?.noInteractive === true || value?.interactive === false;
|
|
10
|
+
}
|
|
11
|
+
export function isInteractive(value) {
|
|
12
|
+
if (resolveNoInteractive(value))
|
|
13
|
+
return false;
|
|
14
|
+
if (process.env.OPEN_SPEC_INTERACTIVE === '0')
|
|
15
|
+
return false;
|
|
16
|
+
// Respect the standard CI environment variable (set by GitHub Actions, GitLab CI, Travis, etc.)
|
|
17
|
+
if ('CI' in process.env)
|
|
18
|
+
return false;
|
|
19
|
+
return !!process.stdin.isTTY;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=interactive.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getActiveChangeIds(root?: string): Promise<string[]>;
|
|
2
|
+
export declare function getSpecIds(root?: string): Promise<string[]>;
|
|
3
|
+
export declare function getArchivedChangeIds(root?: string): Promise<string[]>;
|
|
4
|
+
//# sourceMappingURL=item-discovery.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export async function getActiveChangeIds(root = process.cwd()) {
|
|
4
|
+
const changesPath = path.join(root, 'lightspec', 'changes');
|
|
5
|
+
try {
|
|
6
|
+
const entries = await fs.readdir(changesPath, { withFileTypes: true });
|
|
7
|
+
const result = [];
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'archive')
|
|
10
|
+
continue;
|
|
11
|
+
const proposalPath = path.join(changesPath, entry.name, 'proposal.md');
|
|
12
|
+
try {
|
|
13
|
+
await fs.access(proposalPath);
|
|
14
|
+
result.push(entry.name);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// skip directories without proposal.md
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result.sort();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function getSpecIds(root = process.cwd()) {
|
|
27
|
+
const specsPath = path.join(root, 'lightspec', 'specs');
|
|
28
|
+
const result = [];
|
|
29
|
+
try {
|
|
30
|
+
const entries = await fs.readdir(specsPath, { withFileTypes: true });
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (!entry.isDirectory() || entry.name.startsWith('.'))
|
|
33
|
+
continue;
|
|
34
|
+
const specFile = path.join(specsPath, entry.name, 'spec.md');
|
|
35
|
+
try {
|
|
36
|
+
await fs.access(specFile);
|
|
37
|
+
result.push(entry.name);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// ignore
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
return result.sort();
|
|
48
|
+
}
|
|
49
|
+
export async function getArchivedChangeIds(root = process.cwd()) {
|
|
50
|
+
const archivePath = path.join(root, 'lightspec', 'changes', 'archive');
|
|
51
|
+
try {
|
|
52
|
+
const entries = await fs.readdir(archivePath, { withFileTypes: true });
|
|
53
|
+
const result = [];
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
if (!entry.isDirectory() || entry.name.startsWith('.'))
|
|
56
|
+
continue;
|
|
57
|
+
const proposalPath = path.join(archivePath, entry.name, 'proposal.md');
|
|
58
|
+
try {
|
|
59
|
+
await fs.access(proposalPath);
|
|
60
|
+
result.push(entry.name);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// skip directories without proposal.md
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result.sort();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=item-discovery.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function nearestMatches(input, candidates, max = 5) {
|
|
2
|
+
const scored = candidates.map(candidate => ({ candidate, distance: levenshtein(input, candidate) }));
|
|
3
|
+
scored.sort((a, b) => a.distance - b.distance);
|
|
4
|
+
return scored.slice(0, max).map(s => s.candidate);
|
|
5
|
+
}
|
|
6
|
+
export function levenshtein(a, b) {
|
|
7
|
+
const m = a.length;
|
|
8
|
+
const n = b.length;
|
|
9
|
+
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
|
10
|
+
for (let i = 0; i <= m; i++)
|
|
11
|
+
dp[i][0] = i;
|
|
12
|
+
for (let j = 0; j <= n; j++)
|
|
13
|
+
dp[0][j] = j;
|
|
14
|
+
for (let i = 1; i <= m; i++) {
|
|
15
|
+
for (let j = 1; j <= n; j++) {
|
|
16
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
17
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return dp[m][n];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=match.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported shell types for completion generation
|
|
3
|
+
*/
|
|
4
|
+
export type SupportedShell = 'zsh' | 'bash' | 'fish' | 'powershell';
|
|
5
|
+
/**
|
|
6
|
+
* Result of shell detection
|
|
7
|
+
*/
|
|
8
|
+
export interface ShellDetectionResult {
|
|
9
|
+
/** The detected shell if supported, otherwise undefined */
|
|
10
|
+
shell: SupportedShell | undefined;
|
|
11
|
+
/** The raw shell name detected (even if unsupported), or undefined if nothing detected */
|
|
12
|
+
detected: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Detects the current user's shell based on environment variables
|
|
16
|
+
*
|
|
17
|
+
* @returns Detection result with supported shell and raw detected name
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectShell(): ShellDetectionResult;
|
|
20
|
+
//# sourceMappingURL=shell-detection.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects the current user's shell based on environment variables
|
|
3
|
+
*
|
|
4
|
+
* @returns Detection result with supported shell and raw detected name
|
|
5
|
+
*/
|
|
6
|
+
export function detectShell() {
|
|
7
|
+
// Try SHELL environment variable first (Unix-like systems)
|
|
8
|
+
const shellPath = process.env.SHELL;
|
|
9
|
+
if (shellPath) {
|
|
10
|
+
const shellName = shellPath.toLowerCase();
|
|
11
|
+
if (shellName.includes('zsh')) {
|
|
12
|
+
return { shell: 'zsh', detected: 'zsh' };
|
|
13
|
+
}
|
|
14
|
+
if (shellName.includes('bash')) {
|
|
15
|
+
return { shell: 'bash', detected: 'bash' };
|
|
16
|
+
}
|
|
17
|
+
if (shellName.includes('fish')) {
|
|
18
|
+
return { shell: 'fish', detected: 'fish' };
|
|
19
|
+
}
|
|
20
|
+
// Shell detected but not supported
|
|
21
|
+
// Extract shell name from path (e.g., /bin/tcsh -> tcsh)
|
|
22
|
+
const match = shellPath.match(/\/([^/]+)$/);
|
|
23
|
+
const detectedName = match ? match[1] : shellPath;
|
|
24
|
+
return { shell: undefined, detected: detectedName };
|
|
25
|
+
}
|
|
26
|
+
// Check for PowerShell on Windows
|
|
27
|
+
// PSModulePath is a reliable PowerShell-specific environment variable
|
|
28
|
+
if (process.env.PSModulePath || process.platform === 'win32') {
|
|
29
|
+
const comspec = process.env.COMSPEC?.toLowerCase();
|
|
30
|
+
// If PSModulePath exists, we're definitely in PowerShell
|
|
31
|
+
if (process.env.PSModulePath) {
|
|
32
|
+
return { shell: 'powershell', detected: 'powershell' };
|
|
33
|
+
}
|
|
34
|
+
// On Windows without PSModulePath, we might be in cmd.exe
|
|
35
|
+
if (comspec?.includes('cmd.exe')) {
|
|
36
|
+
return { shell: undefined, detected: 'cmd.exe' };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { shell: undefined, detected: undefined };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=shell-detection.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TaskProgress {
|
|
2
|
+
total: number;
|
|
3
|
+
completed: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function countTasksFromContent(content: string): TaskProgress;
|
|
6
|
+
export declare function getTaskProgressForChange(changesDir: string, changeName: string): Promise<TaskProgress>;
|
|
7
|
+
export declare function formatTaskStatus(progress: TaskProgress): string;
|
|
8
|
+
//# sourceMappingURL=task-progress.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const TASK_PATTERN = /^[-*]\s+\[[\sx]\]/i;
|
|
4
|
+
const COMPLETED_TASK_PATTERN = /^[-*]\s+\[x\]/i;
|
|
5
|
+
export function countTasksFromContent(content) {
|
|
6
|
+
const lines = content.split('\n');
|
|
7
|
+
let total = 0;
|
|
8
|
+
let completed = 0;
|
|
9
|
+
for (const line of lines) {
|
|
10
|
+
if (line.match(TASK_PATTERN)) {
|
|
11
|
+
total++;
|
|
12
|
+
if (line.match(COMPLETED_TASK_PATTERN)) {
|
|
13
|
+
completed++;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return { total, completed };
|
|
18
|
+
}
|
|
19
|
+
export async function getTaskProgressForChange(changesDir, changeName) {
|
|
20
|
+
const tasksPath = path.join(changesDir, changeName, 'tasks.md');
|
|
21
|
+
try {
|
|
22
|
+
const content = await fs.readFile(tasksPath, 'utf-8');
|
|
23
|
+
return countTasksFromContent(content);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { total: 0, completed: 0 };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function formatTaskStatus(progress) {
|
|
30
|
+
if (progress.total === 0)
|
|
31
|
+
return 'No tasks';
|
|
32
|
+
if (progress.completed === progress.total)
|
|
33
|
+
return '✓ Complete';
|
|
34
|
+
return `${progress.completed}/${progress.total} tasks`;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=task-progress.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lightspec",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "AI-native system for spec-driven development",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lightspec",
|
|
7
|
+
"specs",
|
|
8
|
+
"cli",
|
|
9
|
+
"ai",
|
|
10
|
+
"development"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/augmenter-dev/lightspec",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/augmenter-dev/lightspec.git"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "LightSpec Contributors",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"lightspec": "./bin/lightspec.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"bin",
|
|
35
|
+
"scripts/postinstall.js",
|
|
36
|
+
"!dist/**/*.test.js",
|
|
37
|
+
"!dist/**/__tests__",
|
|
38
|
+
"!dist/**/*.map"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"lint": "eslint src/",
|
|
42
|
+
"build": "node build.js",
|
|
43
|
+
"dev": "tsc --watch",
|
|
44
|
+
"dev:cli": "pnpm build && node bin/lightspec.js",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"test:ui": "vitest --ui",
|
|
48
|
+
"test:coverage": "vitest --coverage",
|
|
49
|
+
"test:postinstall": "node scripts/postinstall.js",
|
|
50
|
+
"prepare": "pnpm run build",
|
|
51
|
+
"prepublishOnly": "pnpm run build",
|
|
52
|
+
"postinstall": "node scripts/postinstall.js",
|
|
53
|
+
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
54
|
+
"release": "pnpm run release:ci",
|
|
55
|
+
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
56
|
+
"changeset": "changeset"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=20.19.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@changesets/changelog-github": "^0.5.2",
|
|
63
|
+
"@changesets/cli": "^2.27.7",
|
|
64
|
+
"@types/node": "^24.2.0",
|
|
65
|
+
"@vitest/ui": "^3.2.4",
|
|
66
|
+
"eslint": "^9.39.2",
|
|
67
|
+
"typescript": "^5.9.3",
|
|
68
|
+
"typescript-eslint": "^8.50.1",
|
|
69
|
+
"vitest": "^3.2.4"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@inquirer/core": "^10.2.2",
|
|
73
|
+
"@inquirer/prompts": "^7.8.0",
|
|
74
|
+
"chalk": "^5.5.0",
|
|
75
|
+
"commander": "^14.0.0",
|
|
76
|
+
"fast-glob": "^3.3.3",
|
|
77
|
+
"ora": "^8.2.0",
|
|
78
|
+
"yaml": "^2.8.2",
|
|
79
|
+
"zod": "^4.0.17"
|
|
80
|
+
},
|
|
81
|
+
"packageManager": "pnpm@10.18.3+sha512.bbd16e6d7286fd7e01f6b3c0b3c932cda2965c06a908328f74663f10a9aea51f1129eea615134bf992831b009eabe167ecb7008b597f40ff9bc75946aadfb08d"
|
|
82
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script for auto-installing shell completions
|
|
5
|
+
*
|
|
6
|
+
* This script runs automatically after npm install unless:
|
|
7
|
+
* - CI=true environment variable is set
|
|
8
|
+
* - LIGHTSPEC_NO_COMPLETIONS=1 environment variable is set
|
|
9
|
+
* - dist/ directory doesn't exist (dev setup scenario)
|
|
10
|
+
*
|
|
11
|
+
* The script never fails npm install - all errors are caught and handled gracefully.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { promises as fs } from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if we should skip installation
|
|
23
|
+
*/
|
|
24
|
+
function shouldSkipInstallation() {
|
|
25
|
+
// Skip in CI environments
|
|
26
|
+
if (process.env.CI === 'true' || process.env.CI === '1') {
|
|
27
|
+
return { skip: true, reason: 'CI environment detected' };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Skip if user opted out
|
|
31
|
+
if (process.env.LIGHTSPEC_NO_COMPLETIONS === '1') {
|
|
32
|
+
return { skip: true, reason: 'LIGHTSPEC_NO_COMPLETIONS=1 set' };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { skip: false };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if dist/ directory exists
|
|
40
|
+
*/
|
|
41
|
+
async function distExists() {
|
|
42
|
+
const distPath = path.join(__dirname, '..', 'dist');
|
|
43
|
+
try {
|
|
44
|
+
const stat = await fs.stat(distPath);
|
|
45
|
+
return stat.isDirectory();
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Detect the user's shell
|
|
53
|
+
*/
|
|
54
|
+
async function detectShell() {
|
|
55
|
+
try {
|
|
56
|
+
const { detectShell } = await import('../dist/utils/shell-detection.js');
|
|
57
|
+
const result = detectShell();
|
|
58
|
+
return result.shell;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
// Fail silently if detection module doesn't exist
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Install completions for the detected shell
|
|
67
|
+
*/
|
|
68
|
+
async function installCompletions(shell) {
|
|
69
|
+
try {
|
|
70
|
+
const { CompletionFactory } = await import('../dist/core/completions/factory.js');
|
|
71
|
+
const { COMMAND_REGISTRY } = await import('../dist/core/completions/command-registry.js');
|
|
72
|
+
|
|
73
|
+
// Check if shell is supported
|
|
74
|
+
if (!CompletionFactory.isSupported(shell)) {
|
|
75
|
+
console.log(`\nTip: Run 'lightspec completion install' for shell completions`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Generate completion script
|
|
80
|
+
const generator = CompletionFactory.createGenerator(shell);
|
|
81
|
+
const script = generator.generate(COMMAND_REGISTRY);
|
|
82
|
+
|
|
83
|
+
// Install completion script
|
|
84
|
+
const installer = CompletionFactory.createInstaller(shell);
|
|
85
|
+
const result = await installer.install(script);
|
|
86
|
+
|
|
87
|
+
if (result.success) {
|
|
88
|
+
// Show success message based on installation type
|
|
89
|
+
if (result.isOhMyZsh) {
|
|
90
|
+
console.log(`✓ Shell completions installed`);
|
|
91
|
+
console.log(` Restart shell: exec zsh`);
|
|
92
|
+
} else if (result.zshrcConfigured) {
|
|
93
|
+
console.log(`✓ Shell completions installed and configured`);
|
|
94
|
+
console.log(` Restart shell: exec zsh`);
|
|
95
|
+
} else {
|
|
96
|
+
console.log(`✓ Shell completions installed to ~/.zsh/completions/`);
|
|
97
|
+
console.log(` Add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)`);
|
|
98
|
+
console.log(` Then: exec zsh`);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// Installation failed, show tip for manual install
|
|
102
|
+
console.log(`\nTip: Run 'lightspec completion install' for shell completions`);
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
// Fail gracefully - show tip for manual install
|
|
106
|
+
console.log(`\nTip: Run 'lightspec completion install' for shell completions`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Main function
|
|
112
|
+
*/
|
|
113
|
+
async function main() {
|
|
114
|
+
try {
|
|
115
|
+
// Check if we should skip
|
|
116
|
+
const skipCheck = shouldSkipInstallation();
|
|
117
|
+
if (skipCheck.skip) {
|
|
118
|
+
// Silent skip - no output
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check if dist/ exists (skip silently if not - expected during dev setup)
|
|
123
|
+
if (!(await distExists())) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Detect shell
|
|
128
|
+
const shell = await detectShell();
|
|
129
|
+
if (!shell) {
|
|
130
|
+
console.log(`\nTip: Run 'lightspec completion install' for shell completions`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Install completions
|
|
135
|
+
await installCompletions(shell);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
// Fail gracefully - never break npm install
|
|
138
|
+
// Show tip for manual install
|
|
139
|
+
console.log(`\nTip: Run 'lightspec completion install' for shell completions`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Run main and handle any unhandled errors
|
|
144
|
+
main().catch(() => {
|
|
145
|
+
// Silent failure - never break npm install
|
|
146
|
+
process.exit(0);
|
|
147
|
+
});
|