@fission-ai/openspec 0.18.0 → 0.20.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/README.md +59 -0
- package/dist/cli/index.js +32 -2
- package/dist/commands/artifact-workflow.js +11 -1
- package/dist/commands/completion.js +42 -6
- package/dist/core/completions/command-registry.js +7 -1
- package/dist/core/completions/factory.d.ts +15 -2
- package/dist/core/completions/factory.js +19 -1
- 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 +0 -14
- package/dist/core/completions/generators/zsh-generator.js +55 -124
- 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 +1 -12
- 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/config.js +1 -0
- package/dist/core/configurators/slash/codebuddy.js +6 -9
- package/dist/core/configurators/slash/continue.d.ts +9 -0
- package/dist/core/configurators/slash/continue.js +46 -0
- package/dist/core/configurators/slash/registry.js +3 -0
- package/dist/core/templates/agents-template.d.ts +1 -1
- package/dist/core/templates/agents-template.js +7 -7
- package/dist/core/templates/skill-templates.d.ts +19 -0
- package/dist/core/templates/skill-templates.js +817 -20
- package/dist/core/templates/slash-command-templates.js +2 -2
- 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 +145 -0
- package/dist/utils/file-system.d.ts +6 -0
- package/dist/utils/file-system.js +43 -2
- package/package.json +3 -2
|
@@ -11,7 +11,7 @@ const proposalSteps = `**Steps**
|
|
|
11
11
|
4. Capture architectural reasoning in \`design.md\` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
|
|
12
12
|
5. Draft spec deltas in \`changes/<id>/specs/<capability>/spec.md\` (one folder per capability) using \`## ADDED|MODIFIED|REMOVED Requirements\` with at least one \`#### Scenario:\` per requirement and cross-reference related capabilities when relevant.
|
|
13
13
|
6. Draft \`tasks.md\` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
|
|
14
|
-
7. Validate with \`openspec validate <id> --strict\` and resolve every issue before sharing the proposal.`;
|
|
14
|
+
7. Validate with \`openspec validate <id> --strict --no-interactive\` and resolve every issue before sharing the proposal.`;
|
|
15
15
|
const proposalReferences = `**Reference**
|
|
16
16
|
- Use \`openspec show <id> --json --deltas-only\` or \`openspec show <spec> --type spec\` to inspect details when validation fails.
|
|
17
17
|
- Search existing requirements with \`rg -n "Requirement:|Scenario:" openspec/specs\` before writing new ones.
|
|
@@ -34,7 +34,7 @@ const archiveSteps = `**Steps**
|
|
|
34
34
|
2. Validate the change ID by running \`openspec list\` (or \`openspec show <id>\`) and stop if the change is missing, already archived, or otherwise not ready to archive.
|
|
35
35
|
3. Run \`openspec archive <id> --yes\` so the CLI moves the change and applies spec updates without prompts (use \`--skip-specs\` only for tooling-only work).
|
|
36
36
|
4. Review the command output to confirm the target specs were updated and the change landed in \`changes/archive/\`.
|
|
37
|
-
5. Validate with \`openspec validate --strict\` and inspect with \`openspec show <id>\` if anything looks off.`;
|
|
37
|
+
5. Validate with \`openspec validate --strict --no-interactive\` and inspect with \`openspec show <id>\` if anything looks off.`;
|
|
38
38
|
const archiveReferences = `**Reference**
|
|
39
39
|
- Use \`openspec list\` to confirm change IDs before archiving.
|
|
40
40
|
- Inspect refreshed specs with \`openspec list --specs\` and address any validation issues before handing off.`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface TelemetryConfig {
|
|
2
|
+
anonymousId?: string;
|
|
3
|
+
noticeSeen?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface GlobalConfig {
|
|
6
|
+
telemetry?: TelemetryConfig;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get the path to the global config file.
|
|
11
|
+
* Uses ~/.config/openspec/config.json on all platforms.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getConfigPath(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Read the global config file.
|
|
16
|
+
* Returns an empty object if the file doesn't exist.
|
|
17
|
+
*/
|
|
18
|
+
export declare function readConfig(): Promise<GlobalConfig>;
|
|
19
|
+
/**
|
|
20
|
+
* Write to the global config file.
|
|
21
|
+
* Preserves existing fields and merges in new values.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeConfig(updates: Partial<GlobalConfig>): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Get the telemetry config section.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getTelemetryConfig(): Promise<TelemetryConfig>;
|
|
28
|
+
/**
|
|
29
|
+
* Update the telemetry config section.
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateTelemetryConfig(updates: Partial<TelemetryConfig>): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global configuration for telemetry state.
|
|
3
|
+
* Stores anonymous ID and notice-seen flag in ~/.config/openspec/config.json
|
|
4
|
+
*/
|
|
5
|
+
import { promises as fs } from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
/**
|
|
9
|
+
* Get the path to the global config file.
|
|
10
|
+
* Uses ~/.config/openspec/config.json on all platforms.
|
|
11
|
+
*/
|
|
12
|
+
export function getConfigPath() {
|
|
13
|
+
const configDir = path.join(os.homedir(), '.config', 'openspec');
|
|
14
|
+
return path.join(configDir, 'config.json');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read the global config file.
|
|
18
|
+
* Returns an empty object if the file doesn't exist.
|
|
19
|
+
*/
|
|
20
|
+
export async function readConfig() {
|
|
21
|
+
const configPath = getConfigPath();
|
|
22
|
+
try {
|
|
23
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
24
|
+
return JSON.parse(content);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error.code === 'ENOENT') {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
// If parse fails or other error, return empty config
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Write to the global config file.
|
|
36
|
+
* Preserves existing fields and merges in new values.
|
|
37
|
+
*/
|
|
38
|
+
export async function writeConfig(updates) {
|
|
39
|
+
const configPath = getConfigPath();
|
|
40
|
+
const configDir = path.dirname(configPath);
|
|
41
|
+
// Ensure directory exists
|
|
42
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
43
|
+
// Read existing config and merge
|
|
44
|
+
const existing = await readConfig();
|
|
45
|
+
const merged = { ...existing, ...updates };
|
|
46
|
+
// Deep merge for telemetry object
|
|
47
|
+
if (updates.telemetry && existing.telemetry) {
|
|
48
|
+
merged.telemetry = { ...existing.telemetry, ...updates.telemetry };
|
|
49
|
+
}
|
|
50
|
+
await fs.writeFile(configPath, JSON.stringify(merged, null, 2) + '\n');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the telemetry config section.
|
|
54
|
+
*/
|
|
55
|
+
export async function getTelemetryConfig() {
|
|
56
|
+
const config = await readConfig();
|
|
57
|
+
return config.telemetry ?? {};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Update the telemetry config section.
|
|
61
|
+
*/
|
|
62
|
+
export async function updateTelemetryConfig(updates) {
|
|
63
|
+
const existing = await getTelemetryConfig();
|
|
64
|
+
await writeConfig({
|
|
65
|
+
telemetry: { ...existing, ...updates },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if telemetry is enabled.
|
|
3
|
+
*
|
|
4
|
+
* Disabled when:
|
|
5
|
+
* - OPENSPEC_TELEMETRY=0
|
|
6
|
+
* - DO_NOT_TRACK=1
|
|
7
|
+
* - CI=true (any CI environment)
|
|
8
|
+
*/
|
|
9
|
+
export declare function isTelemetryEnabled(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get or create the anonymous user ID.
|
|
12
|
+
* Lazily generates a UUID on first call and persists it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getOrCreateAnonymousId(): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Track a command execution.
|
|
17
|
+
*
|
|
18
|
+
* @param commandName - The command name (e.g., 'init', 'change:apply')
|
|
19
|
+
* @param version - The OpenSpec version
|
|
20
|
+
*/
|
|
21
|
+
export declare function trackCommand(commandName: string, version: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Show first-run telemetry notice if not already seen.
|
|
24
|
+
*/
|
|
25
|
+
export declare function maybeShowTelemetryNotice(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Shutdown the PostHog client and flush pending events.
|
|
28
|
+
* Call this before CLI exit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function shutdown(): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry module for anonymous usage analytics.
|
|
3
|
+
*
|
|
4
|
+
* Privacy-first design:
|
|
5
|
+
* - Only tracks command name and version
|
|
6
|
+
* - No arguments, file paths, or content
|
|
7
|
+
* - Opt-out via OPENSPEC_TELEMETRY=0 or DO_NOT_TRACK=1
|
|
8
|
+
* - Auto-disabled in CI environments
|
|
9
|
+
* - Anonymous ID is a random UUID with no relation to the user
|
|
10
|
+
*/
|
|
11
|
+
import { PostHog } from 'posthog-node';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
import { getTelemetryConfig, updateTelemetryConfig } from './config.js';
|
|
14
|
+
// PostHog API key - public key for client-side analytics
|
|
15
|
+
// This is safe to embed as it only allows sending events, not reading data
|
|
16
|
+
const POSTHOG_API_KEY = 'phc_Hthu8YvaIJ9QaFKyTG4TbVwkbd5ktcAFzVTKeMmoW2g';
|
|
17
|
+
// Using reverse proxy to avoid ad blockers and keep traffic on our domain
|
|
18
|
+
const POSTHOG_HOST = 'https://edge.openspec.dev';
|
|
19
|
+
let posthogClient = null;
|
|
20
|
+
let anonymousId = null;
|
|
21
|
+
/**
|
|
22
|
+
* Check if telemetry is enabled.
|
|
23
|
+
*
|
|
24
|
+
* Disabled when:
|
|
25
|
+
* - OPENSPEC_TELEMETRY=0
|
|
26
|
+
* - DO_NOT_TRACK=1
|
|
27
|
+
* - CI=true (any CI environment)
|
|
28
|
+
*/
|
|
29
|
+
export function isTelemetryEnabled() {
|
|
30
|
+
// Check explicit opt-out
|
|
31
|
+
if (process.env.OPENSPEC_TELEMETRY === '0') {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Respect DO_NOT_TRACK standard
|
|
35
|
+
if (process.env.DO_NOT_TRACK === '1') {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Auto-disable in CI environments
|
|
39
|
+
if (process.env.CI === 'true') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get or create the anonymous user ID.
|
|
46
|
+
* Lazily generates a UUID on first call and persists it.
|
|
47
|
+
*/
|
|
48
|
+
export async function getOrCreateAnonymousId() {
|
|
49
|
+
// Return cached value if available
|
|
50
|
+
if (anonymousId) {
|
|
51
|
+
return anonymousId;
|
|
52
|
+
}
|
|
53
|
+
// Try to load from config
|
|
54
|
+
const config = await getTelemetryConfig();
|
|
55
|
+
if (config.anonymousId) {
|
|
56
|
+
anonymousId = config.anonymousId;
|
|
57
|
+
return anonymousId;
|
|
58
|
+
}
|
|
59
|
+
// Generate new UUID and persist
|
|
60
|
+
anonymousId = randomUUID();
|
|
61
|
+
await updateTelemetryConfig({ anonymousId });
|
|
62
|
+
return anonymousId;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the PostHog client instance.
|
|
66
|
+
* Creates it on first call with CLI-optimized settings.
|
|
67
|
+
*/
|
|
68
|
+
function getClient() {
|
|
69
|
+
if (!posthogClient) {
|
|
70
|
+
posthogClient = new PostHog(POSTHOG_API_KEY, {
|
|
71
|
+
host: POSTHOG_HOST,
|
|
72
|
+
flushAt: 1, // Send immediately, don't batch
|
|
73
|
+
flushInterval: 0, // No timer-based flushing
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return posthogClient;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Track a command execution.
|
|
80
|
+
*
|
|
81
|
+
* @param commandName - The command name (e.g., 'init', 'change:apply')
|
|
82
|
+
* @param version - The OpenSpec version
|
|
83
|
+
*/
|
|
84
|
+
export async function trackCommand(commandName, version) {
|
|
85
|
+
if (!isTelemetryEnabled()) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const userId = await getOrCreateAnonymousId();
|
|
90
|
+
const client = getClient();
|
|
91
|
+
client.capture({
|
|
92
|
+
distinctId: userId,
|
|
93
|
+
event: 'command_executed',
|
|
94
|
+
properties: {
|
|
95
|
+
command: commandName,
|
|
96
|
+
version: version,
|
|
97
|
+
surface: 'cli',
|
|
98
|
+
$ip: null, // Explicitly disable IP tracking
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Silent failure - telemetry should never break CLI
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Show first-run telemetry notice if not already seen.
|
|
108
|
+
*/
|
|
109
|
+
export async function maybeShowTelemetryNotice() {
|
|
110
|
+
if (!isTelemetryEnabled()) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const config = await getTelemetryConfig();
|
|
115
|
+
if (config.noticeSeen) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Display notice
|
|
119
|
+
console.log('Note: OpenSpec collects anonymous usage stats. Opt out: OPENSPEC_TELEMETRY=0');
|
|
120
|
+
// Mark as seen
|
|
121
|
+
await updateTelemetryConfig({ noticeSeen: true });
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Silent failure - telemetry should never break CLI
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Shutdown the PostHog client and flush pending events.
|
|
129
|
+
* Call this before CLI exit.
|
|
130
|
+
*/
|
|
131
|
+
export async function shutdown() {
|
|
132
|
+
if (!posthogClient) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await posthogClient.shutdown();
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Silent failure - telemetry should never break CLI exit
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
posthogClient = null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -9,6 +9,12 @@ export declare class FileSystemUtils {
|
|
|
9
9
|
static joinPath(basePath: string, ...segments: string[]): string;
|
|
10
10
|
static createDirectory(dirPath: string): Promise<void>;
|
|
11
11
|
static fileExists(filePath: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Finds the first existing parent directory by walking up the directory tree.
|
|
14
|
+
* @param dirPath Starting directory path
|
|
15
|
+
* @returns The first existing directory path, or null if root is reached without finding one
|
|
16
|
+
*/
|
|
17
|
+
private static findFirstExistingDirectory;
|
|
12
18
|
static canWriteFile(filePath: string): Promise<boolean>;
|
|
13
19
|
static directoryExists(dirPath: string): Promise<boolean>;
|
|
14
20
|
static writeFile(filePath: string, content: string): Promise<void>;
|
|
@@ -73,6 +73,41 @@ export class FileSystemUtils {
|
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Finds the first existing parent directory by walking up the directory tree.
|
|
78
|
+
* @param dirPath Starting directory path
|
|
79
|
+
* @returns The first existing directory path, or null if root is reached without finding one
|
|
80
|
+
*/
|
|
81
|
+
static async findFirstExistingDirectory(dirPath) {
|
|
82
|
+
let currentDir = dirPath;
|
|
83
|
+
while (true) {
|
|
84
|
+
try {
|
|
85
|
+
const stats = await fs.stat(currentDir);
|
|
86
|
+
if (stats.isDirectory()) {
|
|
87
|
+
return currentDir;
|
|
88
|
+
}
|
|
89
|
+
// Path component exists but is not a directory (edge case)
|
|
90
|
+
console.debug(`Path component ${currentDir} exists but is not a directory`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (error.code === 'ENOENT') {
|
|
95
|
+
// Directory doesn't exist, move up one level
|
|
96
|
+
const parentDir = path.dirname(currentDir);
|
|
97
|
+
if (parentDir === currentDir) {
|
|
98
|
+
// Reached filesystem root without finding existing directory
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
currentDir = parentDir;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Unexpected error (permissions, I/O error, etc.)
|
|
105
|
+
console.debug(`Error checking directory ${currentDir}: ${error.message}`);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
76
111
|
static async canWriteFile(filePath) {
|
|
77
112
|
try {
|
|
78
113
|
const stats = await fs.stat(filePath);
|
|
@@ -91,10 +126,16 @@ export class FileSystemUtils {
|
|
|
91
126
|
}
|
|
92
127
|
catch (error) {
|
|
93
128
|
if (error.code === 'ENOENT') {
|
|
94
|
-
// File doesn't exist
|
|
129
|
+
// File doesn't exist - find first existing parent directory and check its permissions
|
|
95
130
|
const parentDir = path.dirname(filePath);
|
|
131
|
+
const existingDir = await this.findFirstExistingDirectory(parentDir);
|
|
132
|
+
if (existingDir === null) {
|
|
133
|
+
// No existing parent directory found (edge case)
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
// Check if the existing parent directory is writable
|
|
96
137
|
try {
|
|
97
|
-
await fs.access(
|
|
138
|
+
await fs.access(existingDir, fsConstants.W_OK);
|
|
98
139
|
return true;
|
|
99
140
|
}
|
|
100
141
|
catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fission-ai/openspec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "AI-native system for spec-driven development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openspec",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"node": ">=20.19.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
+
"@changesets/changelog-github": "^0.5.2",
|
|
45
46
|
"@changesets/cli": "^2.27.7",
|
|
46
47
|
"@types/node": "^24.2.0",
|
|
47
48
|
"@vitest/ui": "^3.2.4",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"commander": "^14.0.0",
|
|
58
59
|
"fast-glob": "^3.3.3",
|
|
59
60
|
"ora": "^8.2.0",
|
|
61
|
+
"posthog-node": "^5.20.0",
|
|
60
62
|
"yaml": "^2.8.2",
|
|
61
63
|
"zod": "^4.0.17"
|
|
62
64
|
},
|
|
@@ -74,7 +76,6 @@
|
|
|
74
76
|
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
75
77
|
"release": "pnpm run release:ci",
|
|
76
78
|
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
77
|
-
"release:local": "pnpm exec changeset version && pnpm run check:pack-version && pnpm exec changeset publish",
|
|
78
79
|
"changeset": "changeset"
|
|
79
80
|
}
|
|
80
81
|
}
|