@fission-ai/openspec 1.2.0 → 1.3.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 (54) hide show
  1. package/README.md +8 -13
  2. package/dist/commands/workflow/instructions.js +18 -72
  3. package/dist/commands/workflow/shared.d.ts +6 -1
  4. package/dist/commands/workflow/shared.js +21 -16
  5. package/dist/commands/workflow/status.js +21 -4
  6. package/dist/commands/workflow/templates.js +5 -4
  7. package/dist/core/artifact-graph/index.d.ts +1 -0
  8. package/dist/core/artifact-graph/index.js +1 -0
  9. package/dist/core/artifact-graph/instruction-loader.js +6 -4
  10. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  11. package/dist/core/artifact-graph/outputs.js +39 -0
  12. package/dist/core/artifact-graph/state.js +2 -25
  13. package/dist/core/available-tools.d.ts +3 -2
  14. package/dist/core/available-tools.js +15 -2
  15. package/dist/core/command-generation/adapters/bob.d.ts +14 -0
  16. package/dist/core/command-generation/adapters/bob.js +45 -0
  17. package/dist/core/command-generation/adapters/index.d.ts +3 -0
  18. package/dist/core/command-generation/adapters/index.js +3 -0
  19. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  20. package/dist/core/command-generation/adapters/junie.js +26 -0
  21. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  22. package/dist/core/command-generation/adapters/lingma.js +30 -0
  23. package/dist/core/command-generation/adapters/opencode.d.ts +1 -1
  24. package/dist/core/command-generation/adapters/opencode.js +2 -2
  25. package/dist/core/command-generation/adapters/pi.d.ts +4 -0
  26. package/dist/core/command-generation/adapters/pi.js +15 -1
  27. package/dist/core/command-generation/registry.js +6 -0
  28. package/dist/core/completions/installers/powershell-installer.d.ts +14 -0
  29. package/dist/core/completions/installers/powershell-installer.js +69 -9
  30. package/dist/core/config.d.ts +1 -0
  31. package/dist/core/config.js +5 -1
  32. package/dist/core/init.js +6 -10
  33. package/dist/core/legacy-cleanup.d.ts +1 -1
  34. package/dist/core/legacy-cleanup.js +22 -10
  35. package/dist/core/parsers/change-parser.js +7 -3
  36. package/dist/core/parsers/markdown-parser.d.ts +4 -0
  37. package/dist/core/parsers/markdown-parser.js +41 -1
  38. package/dist/core/parsers/spec-structure.d.ts +9 -0
  39. package/dist/core/parsers/spec-structure.js +88 -0
  40. package/dist/core/specs-apply.js +8 -0
  41. package/dist/core/templates/workflows/apply-change.js +4 -4
  42. package/dist/core/templates/workflows/bulk-archive-change.js +2 -2
  43. package/dist/core/templates/workflows/explore.js +25 -25
  44. package/dist/core/templates/workflows/onboard.js +24 -24
  45. package/dist/core/templates/workflows/verify-change.js +6 -6
  46. package/dist/core/update.js +2 -2
  47. package/dist/core/validation/validator.js +9 -0
  48. package/dist/telemetry/config.d.ts +7 -1
  49. package/dist/telemetry/config.js +87 -19
  50. package/dist/telemetry/index.js +19 -0
  51. package/dist/utils/file-system.d.ts +5 -0
  52. package/dist/utils/file-system.js +21 -1
  53. package/package.json +1 -1
  54. package/scripts/postinstall.js +8 -72
@@ -16,8 +16,21 @@ import { getTelemetryConfig, updateTelemetryConfig } from './config.js';
16
16
  const POSTHOG_API_KEY = 'phc_Hthu8YvaIJ9QaFKyTG4TbVwkbd5ktcAFzVTKeMmoW2g';
17
17
  // Using reverse proxy to avoid ad blockers and keep traffic on our domain
18
18
  const POSTHOG_HOST = 'https://edge.openspec.dev';
19
+ const TELEMETRY_REQUEST_TIMEOUT_MS = 1000;
19
20
  let posthogClient = null;
20
21
  let anonymousId = null;
22
+ async function safeTelemetryFetch(url, options) {
23
+ try {
24
+ const response = await fetch(url, options);
25
+ if (response.ok) {
26
+ return response;
27
+ }
28
+ }
29
+ catch {
30
+ // Silent failure - telemetry should never surface network noise
31
+ }
32
+ return new Response(null, { status: 204 });
33
+ }
21
34
  /**
22
35
  * Check if telemetry is enabled.
23
36
  *
@@ -71,6 +84,12 @@ function getClient() {
71
84
  host: POSTHOG_HOST,
72
85
  flushAt: 1, // Send immediately, don't batch
73
86
  flushInterval: 0, // No timer-based flushing
87
+ fetchRetryCount: 0,
88
+ requestTimeout: TELEMETRY_REQUEST_TIMEOUT_MS,
89
+ preloadFeatureFlags: false,
90
+ disableRemoteConfig: true,
91
+ disableSurveys: true,
92
+ fetch: safeTelemetryFetch,
74
93
  });
75
94
  }
76
95
  return posthogClient;
@@ -4,6 +4,11 @@ export declare class FileSystemUtils {
4
4
  * Essential for cross-platform compatibility with glob libraries like fast-glob.
5
5
  */
6
6
  static toPosixPath(p: string): string;
7
+ /**
8
+ * Returns a canonical absolute path when the target exists.
9
+ * Falls back to path.resolve() so callers can still produce a stable absolute path.
10
+ */
11
+ static canonicalizeExistingPath(targetPath: string): string;
7
12
  private static isWindowsBasePath;
8
13
  private static normalizeSegments;
9
14
  static joinPath(basePath: string, ...segments: string[]): string;
@@ -1,5 +1,7 @@
1
- import { promises as fs, constants as fsConstants } from 'fs';
1
+ import * as nodeFs from 'fs';
2
2
  import path from 'path';
3
+ const fs = nodeFs.promises;
4
+ const { constants: fsConstants } = nodeFs;
3
5
  function isMarkerOnOwnLine(content, markerIndex, markerLength) {
4
6
  let leftIndex = markerIndex - 1;
5
7
  while (leftIndex >= 0 && content[leftIndex] !== '\n') {
@@ -37,6 +39,24 @@ export class FileSystemUtils {
37
39
  static toPosixPath(p) {
38
40
  return p.replace(/\\/g, '/');
39
41
  }
42
+ /**
43
+ * Returns a canonical absolute path when the target exists.
44
+ * Falls back to path.resolve() so callers can still produce a stable absolute path.
45
+ */
46
+ static canonicalizeExistingPath(targetPath) {
47
+ try {
48
+ // Prefer the native resolver so Windows short-path aliases are expanded.
49
+ return nodeFs.realpathSync.native(targetPath);
50
+ }
51
+ catch {
52
+ try {
53
+ return nodeFs.realpathSync(targetPath);
54
+ }
55
+ catch {
56
+ return path.resolve(targetPath);
57
+ }
58
+ }
59
+ }
40
60
  static isWindowsBasePath(basePath) {
41
61
  return /^[A-Za-z]:[\\/]/.test(basePath) || basePath.startsWith('\\');
42
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fission-ai/openspec",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "AI-native system for spec-driven development",
5
5
  "keywords": [
6
6
  "openspec",
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Postinstall script for auto-installing shell completions
4
+ * Postinstall script that hints about shell completions
5
5
  *
6
- * This script runs automatically after npm install unless:
6
+ * Completion installation is opt-in: the user must run
7
+ * `openspec completion install` explicitly. This script only
8
+ * prints a one-line tip after npm install.
9
+ *
10
+ * The tip is suppressed when:
7
11
  * - CI=true environment variable is set
8
12
  * - OPENSPEC_NO_COMPLETIONS=1 environment variable is set
9
13
  * - dist/ directory doesn't exist (dev setup scenario)
@@ -48,65 +52,6 @@ async function distExists() {
48
52
  }
49
53
  }
50
54
 
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 'openspec 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 'openspec completion install' for shell completions`);
103
- }
104
- } catch (error) {
105
- // Fail gracefully - show tip for manual install
106
- console.log(`\nTip: Run 'openspec completion install' for shell completions`);
107
- }
108
- }
109
-
110
55
  /**
111
56
  * Main function
112
57
  */
@@ -124,19 +69,10 @@ async function main() {
124
69
  return;
125
70
  }
126
71
 
127
- // Detect shell
128
- const shell = await detectShell();
129
- if (!shell) {
130
- console.log(`\nTip: Run 'openspec completion install' for shell completions`);
131
- return;
132
- }
133
-
134
- // Install completions
135
- await installCompletions(shell);
72
+ // Completions are opt-in — just print a hint
73
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
136
74
  } catch (error) {
137
75
  // Fail gracefully - never break npm install
138
- // Show tip for manual install
139
- console.log(`\nTip: Run 'openspec completion install' for shell completions`);
140
76
  }
141
77
  }
142
78