@specsafe/core 0.5.0 → 0.6.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.
Files changed (81) hide show
  1. package/dist/elicitation/engine.d.ts +75 -0
  2. package/dist/elicitation/engine.d.ts.map +1 -0
  3. package/dist/elicitation/engine.js +174 -0
  4. package/dist/elicitation/engine.js.map +1 -0
  5. package/dist/elicitation/flows.d.ts +18 -0
  6. package/dist/elicitation/flows.d.ts.map +1 -0
  7. package/dist/elicitation/flows.js +331 -0
  8. package/dist/elicitation/flows.js.map +1 -0
  9. package/dist/elicitation/generator.d.ts +20 -0
  10. package/dist/elicitation/generator.d.ts.map +1 -0
  11. package/dist/elicitation/generator.js +260 -0
  12. package/dist/elicitation/generator.js.map +1 -0
  13. package/dist/elicitation/index.d.ts +27 -0
  14. package/dist/elicitation/index.d.ts.map +1 -0
  15. package/dist/elicitation/index.js +29 -0
  16. package/dist/elicitation/index.js.map +1 -0
  17. package/dist/elicitation/types.d.ts +69 -0
  18. package/dist/elicitation/types.d.ts.map +1 -0
  19. package/dist/elicitation/types.js +6 -0
  20. package/dist/elicitation/types.js.map +1 -0
  21. package/dist/extensions/builtins/complexity.d.ts +7 -0
  22. package/dist/extensions/builtins/complexity.d.ts.map +1 -0
  23. package/dist/extensions/builtins/complexity.js +97 -0
  24. package/dist/extensions/builtins/complexity.js.map +1 -0
  25. package/dist/extensions/builtins/owasp.d.ts +7 -0
  26. package/dist/extensions/builtins/owasp.d.ts.map +1 -0
  27. package/dist/extensions/builtins/owasp.js +76 -0
  28. package/dist/extensions/builtins/owasp.js.map +1 -0
  29. package/dist/extensions/index.d.ts +54 -0
  30. package/dist/extensions/index.d.ts.map +1 -0
  31. package/dist/extensions/index.js +72 -0
  32. package/dist/extensions/index.js.map +1 -0
  33. package/dist/extensions/loader.d.ts +28 -0
  34. package/dist/extensions/loader.d.ts.map +1 -0
  35. package/dist/extensions/loader.js +62 -0
  36. package/dist/extensions/loader.js.map +1 -0
  37. package/dist/extensions/registry.d.ts +74 -0
  38. package/dist/extensions/registry.d.ts.map +1 -0
  39. package/dist/extensions/registry.js +159 -0
  40. package/dist/extensions/registry.js.map +1 -0
  41. package/dist/extensions/types.d.ts +70 -0
  42. package/dist/extensions/types.d.ts.map +1 -0
  43. package/dist/extensions/types.js +2 -0
  44. package/dist/extensions/types.js.map +1 -0
  45. package/dist/governance/builtins.d.ts +7 -0
  46. package/dist/governance/builtins.d.ts.map +1 -0
  47. package/dist/governance/builtins.js +105 -0
  48. package/dist/governance/builtins.js.map +1 -0
  49. package/dist/governance/constitution.d.ts +23 -0
  50. package/dist/governance/constitution.d.ts.map +1 -0
  51. package/dist/governance/constitution.js +245 -0
  52. package/dist/governance/constitution.js.map +1 -0
  53. package/dist/governance/index.d.ts +3 -0
  54. package/dist/governance/index.d.ts.map +1 -0
  55. package/dist/governance/index.js +2 -0
  56. package/dist/governance/index.js.map +1 -0
  57. package/dist/governance/template.d.ts +12 -0
  58. package/dist/governance/template.d.ts.map +1 -0
  59. package/dist/governance/template.js +84 -0
  60. package/dist/governance/template.js.map +1 -0
  61. package/dist/governance/types.d.ts +64 -0
  62. package/dist/governance/types.d.ts.map +1 -0
  63. package/dist/governance/types.js +2 -0
  64. package/dist/governance/types.js.map +1 -0
  65. package/dist/index.d.ts +15 -18
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +11 -18
  68. package/dist/index.js.map +1 -1
  69. package/dist/templates/checklist.d.ts +7 -0
  70. package/dist/templates/checklist.d.ts.map +1 -0
  71. package/dist/templates/checklist.js +131 -0
  72. package/dist/templates/checklist.js.map +1 -0
  73. package/dist/templates/engine.d.ts +20 -0
  74. package/dist/templates/engine.d.ts.map +1 -0
  75. package/dist/templates/engine.js +187 -0
  76. package/dist/templates/engine.js.map +1 -0
  77. package/dist/templates/types.d.ts +67 -0
  78. package/dist/templates/types.d.ts.map +1 -0
  79. package/dist/templates/types.js +5 -0
  80. package/dist/templates/types.js.map +1 -0
  81. package/package.json +1 -1
@@ -0,0 +1,54 @@
1
+ /**
2
+ * SpecSafe Extension System
3
+ *
4
+ * Provides a plugin architecture for extending SpecSafe functionality
5
+ * at various lifecycle hooks.
6
+ */
7
+ export type { Extension, ExtensionHook, ExtensionContext, ExtensionResult, HookRegistration, } from './types.js';
8
+ export { ExtensionRegistry } from './registry.js';
9
+ import type { Extension, ExtensionHook, ExtensionContext, ExtensionResult } from './types.js';
10
+ /**
11
+ * Register an extension
12
+ */
13
+ export declare function registerExtension(extension: Extension): void;
14
+ /**
15
+ * Unregister an extension
16
+ */
17
+ export declare function unregisterExtension(extensionId: string): boolean;
18
+ /**
19
+ * Get an extension by ID
20
+ */
21
+ export declare function getExtension(extensionId: string): Extension | undefined;
22
+ /**
23
+ * List all registered extensions
24
+ */
25
+ export declare function listExtensions(): Extension[];
26
+ /**
27
+ * List enabled extensions only
28
+ */
29
+ export declare function listEnabledExtensions(): Extension[];
30
+ /**
31
+ * Check if an extension exists
32
+ */
33
+ export declare function hasExtension(extensionId: string): boolean;
34
+ /**
35
+ * Enable an extension
36
+ */
37
+ export declare function enableExtension(extensionId: string): boolean;
38
+ /**
39
+ * Disable an extension
40
+ */
41
+ export declare function disableExtension(extensionId: string): boolean;
42
+ /**
43
+ * Execute hooks for a phase
44
+ */
45
+ export declare function executeHooks(phase: ExtensionHook, context: ExtensionContext): Promise<ExtensionResult[]>;
46
+ /**
47
+ * Clear all extensions (useful for testing)
48
+ */
49
+ export declare function clearExtensions(): void;
50
+ export { validateExtension, loadExtension, loadExtensions, loadBuiltinExtensions } from './loader.js';
51
+ export type { Extension as ExtensionConfig } from './types.js';
52
+ export type { ExtensionHook as ExtensionPhase } from './types.js';
53
+ export type ExtensionRegistryEntry = Extension;
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9F;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,EAAE,CAEnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAExG;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAGD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGtG,YAAY,EAAE,SAAS,IAAI,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,aAAa,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,MAAM,MAAM,sBAAsB,GAAG,SAAS,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * SpecSafe Extension System
3
+ *
4
+ * Provides a plugin architecture for extending SpecSafe functionality
5
+ * at various lifecycle hooks.
6
+ */
7
+ // Re-export registry methods as standalone functions
8
+ export { ExtensionRegistry } from './registry.js';
9
+ import { ExtensionRegistry } from './registry.js';
10
+ /**
11
+ * Register an extension
12
+ */
13
+ export function registerExtension(extension) {
14
+ ExtensionRegistry.register(extension);
15
+ }
16
+ /**
17
+ * Unregister an extension
18
+ */
19
+ export function unregisterExtension(extensionId) {
20
+ return ExtensionRegistry.unregister(extensionId);
21
+ }
22
+ /**
23
+ * Get an extension by ID
24
+ */
25
+ export function getExtension(extensionId) {
26
+ return ExtensionRegistry.get(extensionId);
27
+ }
28
+ /**
29
+ * List all registered extensions
30
+ */
31
+ export function listExtensions() {
32
+ return ExtensionRegistry.list();
33
+ }
34
+ /**
35
+ * List enabled extensions only
36
+ */
37
+ export function listEnabledExtensions() {
38
+ return ExtensionRegistry.listEnabled();
39
+ }
40
+ /**
41
+ * Check if an extension exists
42
+ */
43
+ export function hasExtension(extensionId) {
44
+ return ExtensionRegistry.has(extensionId);
45
+ }
46
+ /**
47
+ * Enable an extension
48
+ */
49
+ export function enableExtension(extensionId) {
50
+ return ExtensionRegistry.enable(extensionId);
51
+ }
52
+ /**
53
+ * Disable an extension
54
+ */
55
+ export function disableExtension(extensionId) {
56
+ return ExtensionRegistry.disable(extensionId);
57
+ }
58
+ /**
59
+ * Execute hooks for a phase
60
+ */
61
+ export function executeHooks(phase, context) {
62
+ return ExtensionRegistry.executeHooks(phase, context);
63
+ }
64
+ /**
65
+ * Clear all extensions (useful for testing)
66
+ */
67
+ export function clearExtensions() {
68
+ ExtensionRegistry.clear();
69
+ }
70
+ // Loader exports
71
+ export { validateExtension, loadExtension, loadExtensions, loadBuiltinExtensions } from './loader.js';
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,qDAAqD;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,iBAAiB,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,iBAAiB,CAAC,WAAW,EAAE,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,iBAAiB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB,EAAE,OAAyB;IAC1E,OAAO,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,iBAAiB;AACjB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { Extension } from './types.js';
2
+ /**
3
+ * Validate extension structure
4
+ * @param ext - Extension to validate
5
+ * @returns true if extension is valid
6
+ * @throws Error if extension is invalid
7
+ */
8
+ export declare function validateExtension(ext: unknown): ext is Extension;
9
+ /**
10
+ * Load a single extension
11
+ * @param extension - Extension to load
12
+ * @param autoRegister - Whether to automatically register the extension (default: true)
13
+ * @returns The loaded extension
14
+ */
15
+ export declare function loadExtension(extension: Extension, autoRegister?: boolean): Extension;
16
+ /**
17
+ * Load multiple extensions
18
+ * @param extensions - Array of extensions to load
19
+ * @param autoRegister - Whether to automatically register extensions (default: true)
20
+ * @returns Array of loaded extensions
21
+ */
22
+ export declare function loadExtensions(extensions: Extension[], autoRegister?: boolean): Extension[];
23
+ /**
24
+ * Load builtin extensions
25
+ * @returns Array of loaded builtin extensions
26
+ */
27
+ export declare function loadBuiltinExtensions(): Promise<Extension[]>;
28
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/extensions/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,SAAS,CA4BhE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,YAAY,UAAO,GAAG,SAAS,CAQlF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,YAAY,UAAO,GAAG,SAAS,EAAE,CAExF;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAOlE"}
@@ -0,0 +1,62 @@
1
+ import { ExtensionRegistry } from './registry.js';
2
+ /**
3
+ * Validate extension structure
4
+ * @param ext - Extension to validate
5
+ * @returns true if extension is valid
6
+ * @throws Error if extension is invalid
7
+ */
8
+ export function validateExtension(ext) {
9
+ if (!ext || typeof ext !== 'object') {
10
+ throw new Error('Extension must be an object');
11
+ }
12
+ const extension = ext;
13
+ if (!extension.id || typeof extension.id !== 'string') {
14
+ throw new Error('Extension must have a string "id" field');
15
+ }
16
+ if (!extension.name || typeof extension.name !== 'string') {
17
+ throw new Error('Extension must have a string "name" field');
18
+ }
19
+ if (!extension.description || typeof extension.description !== 'string') {
20
+ throw new Error('Extension must have a string "description" field');
21
+ }
22
+ if (!extension.version || typeof extension.version !== 'string') {
23
+ throw new Error('Extension must have a string "version" field');
24
+ }
25
+ if (!extension.hooks || typeof extension.hooks !== 'object') {
26
+ throw new Error('Extension must have a "hooks" object');
27
+ }
28
+ return true;
29
+ }
30
+ /**
31
+ * Load a single extension
32
+ * @param extension - Extension to load
33
+ * @param autoRegister - Whether to automatically register the extension (default: true)
34
+ * @returns The loaded extension
35
+ */
36
+ export function loadExtension(extension, autoRegister = true) {
37
+ validateExtension(extension);
38
+ if (autoRegister) {
39
+ ExtensionRegistry.register(extension);
40
+ }
41
+ return extension;
42
+ }
43
+ /**
44
+ * Load multiple extensions
45
+ * @param extensions - Array of extensions to load
46
+ * @param autoRegister - Whether to automatically register extensions (default: true)
47
+ * @returns Array of loaded extensions
48
+ */
49
+ export function loadExtensions(extensions, autoRegister = true) {
50
+ return extensions.map(ext => loadExtension(ext, autoRegister));
51
+ }
52
+ /**
53
+ * Load builtin extensions
54
+ * @returns Array of loaded builtin extensions
55
+ */
56
+ export async function loadBuiltinExtensions() {
57
+ const { owaspExtension } = await import('./builtins/owasp.js');
58
+ const { complexityExtension } = await import('./builtins/complexity.js');
59
+ const builtins = [owaspExtension, complexityExtension];
60
+ return loadExtensions(builtins, true);
61
+ }
62
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/extensions/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,SAAS,GAAG,GAAyB,CAAC;IAE5C,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAoB,EAAE,YAAY,GAAG,IAAI;IACrE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE7B,IAAI,YAAY,EAAE,CAAC;QACjB,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAAuB,EAAE,YAAY,GAAG,IAAI;IACzE,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC/D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAEzE,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;IAEvD,OAAO,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { Extension, ExtensionHook, ExtensionContext, ExtensionResult, HookRegistration } from './types.js';
2
+ /**
3
+ * Global extension registry
4
+ */
5
+ declare class ExtensionRegistryClass {
6
+ private extensions;
7
+ private hooks;
8
+ /**
9
+ * Register an extension
10
+ * @param extension - Extension to register
11
+ * @throws Error if extension with same ID already exists
12
+ */
13
+ register(extension: Extension): void;
14
+ /**
15
+ * Unregister an extension
16
+ * @param extensionId - ID of extension to unregister
17
+ * @returns true if extension was found and removed
18
+ */
19
+ unregister(extensionId: string): boolean;
20
+ /**
21
+ * Get an extension by ID
22
+ * @param extensionId - Extension ID
23
+ * @returns Extension or undefined if not found
24
+ */
25
+ get(extensionId: string): Extension | undefined;
26
+ /**
27
+ * Get all registered extensions
28
+ * @returns Array of all extensions
29
+ */
30
+ list(): Extension[];
31
+ /**
32
+ * Get enabled extensions only
33
+ * @returns Array of enabled extensions
34
+ */
35
+ listEnabled(): Extension[];
36
+ /**
37
+ * Check if an extension exists
38
+ * @param extensionId - Extension ID
39
+ * @returns true if extension is registered
40
+ */
41
+ has(extensionId: string): boolean;
42
+ /**
43
+ * Enable an extension
44
+ * @param extensionId - Extension ID
45
+ * @returns true if extension was found and enabled
46
+ */
47
+ enable(extensionId: string): boolean;
48
+ /**
49
+ * Disable an extension
50
+ * @param extensionId - Extension ID
51
+ * @returns true if extension was found and disabled
52
+ */
53
+ disable(extensionId: string): boolean;
54
+ /**
55
+ * Get hooks for a specific phase
56
+ * @param phase - Hook phase
57
+ * @returns Array of hook registrations for this phase
58
+ */
59
+ getHooks(phase: ExtensionHook): HookRegistration[];
60
+ /**
61
+ * Execute all hooks for a phase
62
+ * @param phase - Hook phase
63
+ * @param context - Extension context
64
+ * @returns Array of results from all hooks
65
+ */
66
+ executeHooks(phase: ExtensionHook, context: ExtensionContext): Promise<ExtensionResult[]>;
67
+ /**
68
+ * Clear all extensions (useful for testing)
69
+ */
70
+ clear(): void;
71
+ }
72
+ export declare const ExtensionRegistry: ExtensionRegistryClass;
73
+ export {};
74
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/extensions/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhH;;GAEG;AACH,cAAM,sBAAsB;IAC1B,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,KAAK,CAAqD;IAElE;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAyBpC;;;;OAIG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAoBxC;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI/C;;;OAGG;IACH,IAAI,IAAI,SAAS,EAAE;IAInB;;;OAGG;IACH,WAAW,IAAI,SAAS,EAAE;IAI1B;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC;;;;OAIG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IASpC;;;;OAIG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IASrC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,EAAE;IAIlD;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA0B/F;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAGD,eAAO,MAAM,iBAAiB,wBAA+B,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Global extension registry
3
+ */
4
+ class ExtensionRegistryClass {
5
+ extensions = new Map();
6
+ hooks = new Map();
7
+ /**
8
+ * Register an extension
9
+ * @param extension - Extension to register
10
+ * @throws Error if extension with same ID already exists
11
+ */
12
+ register(extension) {
13
+ if (this.extensions.has(extension.id)) {
14
+ throw new Error(`Extension with ID "${extension.id}" is already registered`);
15
+ }
16
+ this.extensions.set(extension.id, extension);
17
+ // Register hooks
18
+ for (const [phase, handler] of Object.entries(extension.hooks)) {
19
+ if (typeof handler === 'function') {
20
+ const registration = {
21
+ extensionId: extension.id,
22
+ phase: phase,
23
+ handler,
24
+ priority: 0,
25
+ };
26
+ const phaseHooks = this.hooks.get(phase) || [];
27
+ phaseHooks.push(registration);
28
+ phaseHooks.sort((a, b) => (a.priority || 0) - (b.priority || 0));
29
+ this.hooks.set(phase, phaseHooks);
30
+ }
31
+ }
32
+ }
33
+ /**
34
+ * Unregister an extension
35
+ * @param extensionId - ID of extension to unregister
36
+ * @returns true if extension was found and removed
37
+ */
38
+ unregister(extensionId) {
39
+ const extension = this.extensions.get(extensionId);
40
+ if (!extension) {
41
+ return false;
42
+ }
43
+ // Remove all hooks for this extension
44
+ for (const [phase, registrations] of this.hooks.entries()) {
45
+ const filtered = registrations.filter(r => r.extensionId !== extensionId);
46
+ if (filtered.length > 0) {
47
+ this.hooks.set(phase, filtered);
48
+ }
49
+ else {
50
+ this.hooks.delete(phase);
51
+ }
52
+ }
53
+ this.extensions.delete(extensionId);
54
+ return true;
55
+ }
56
+ /**
57
+ * Get an extension by ID
58
+ * @param extensionId - Extension ID
59
+ * @returns Extension or undefined if not found
60
+ */
61
+ get(extensionId) {
62
+ return this.extensions.get(extensionId);
63
+ }
64
+ /**
65
+ * Get all registered extensions
66
+ * @returns Array of all extensions
67
+ */
68
+ list() {
69
+ return Array.from(this.extensions.values());
70
+ }
71
+ /**
72
+ * Get enabled extensions only
73
+ * @returns Array of enabled extensions
74
+ */
75
+ listEnabled() {
76
+ return this.list().filter(ext => ext.enabled !== false);
77
+ }
78
+ /**
79
+ * Check if an extension exists
80
+ * @param extensionId - Extension ID
81
+ * @returns true if extension is registered
82
+ */
83
+ has(extensionId) {
84
+ return this.extensions.has(extensionId);
85
+ }
86
+ /**
87
+ * Enable an extension
88
+ * @param extensionId - Extension ID
89
+ * @returns true if extension was found and enabled
90
+ */
91
+ enable(extensionId) {
92
+ const extension = this.extensions.get(extensionId);
93
+ if (!extension) {
94
+ return false;
95
+ }
96
+ extension.enabled = true;
97
+ return true;
98
+ }
99
+ /**
100
+ * Disable an extension
101
+ * @param extensionId - Extension ID
102
+ * @returns true if extension was found and disabled
103
+ */
104
+ disable(extensionId) {
105
+ const extension = this.extensions.get(extensionId);
106
+ if (!extension) {
107
+ return false;
108
+ }
109
+ extension.enabled = false;
110
+ return true;
111
+ }
112
+ /**
113
+ * Get hooks for a specific phase
114
+ * @param phase - Hook phase
115
+ * @returns Array of hook registrations for this phase
116
+ */
117
+ getHooks(phase) {
118
+ return this.hooks.get(phase) || [];
119
+ }
120
+ /**
121
+ * Execute all hooks for a phase
122
+ * @param phase - Hook phase
123
+ * @param context - Extension context
124
+ * @returns Array of results from all hooks
125
+ */
126
+ async executeHooks(phase, context) {
127
+ const phaseHooks = this.getHooks(phase);
128
+ const results = [];
129
+ for (const hook of phaseHooks) {
130
+ const extension = this.extensions.get(hook.extensionId);
131
+ // Skip disabled extensions
132
+ if (!extension || extension.enabled === false) {
133
+ continue;
134
+ }
135
+ try {
136
+ const result = await hook.handler(context);
137
+ results.push(result);
138
+ }
139
+ catch (error) {
140
+ results.push({
141
+ success: false,
142
+ message: `Extension "${hook.extensionId}" failed`,
143
+ errors: [error instanceof Error ? error.message : String(error)],
144
+ });
145
+ }
146
+ }
147
+ return results;
148
+ }
149
+ /**
150
+ * Clear all extensions (useful for testing)
151
+ */
152
+ clear() {
153
+ this.extensions.clear();
154
+ this.hooks.clear();
155
+ }
156
+ }
157
+ // Export singleton instance
158
+ export const ExtensionRegistry = new ExtensionRegistryClass();
159
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/extensions/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { Spec } from '../types.js';
2
+ /**
3
+ * Extension hook phases in the SpecSafe workflow
4
+ */
5
+ export type ExtensionHook = 'pre-validate' | 'post-validate' | 'pre-generate' | 'post-generate' | 'pre-commit';
6
+ /**
7
+ * Context provided to extension hooks
8
+ */
9
+ export interface ExtensionContext {
10
+ /** The spec being processed */
11
+ spec: Spec;
12
+ /** Current phase of execution */
13
+ phase: ExtensionHook;
14
+ /** Additional metadata */
15
+ metadata?: Record<string, unknown>;
16
+ }
17
+ /**
18
+ * Result returned by extension hooks
19
+ */
20
+ export interface ExtensionResult {
21
+ /** Whether the extension check passed */
22
+ success: boolean;
23
+ /** Optional message describing the result */
24
+ message?: string;
25
+ /** Optional suggestions for improvement */
26
+ suggestions?: string[];
27
+ /** Optional warnings (non-blocking) */
28
+ warnings?: string[];
29
+ /** Optional errors (blocking) */
30
+ errors?: string[];
31
+ /** Additional data returned by the extension */
32
+ data?: Record<string, unknown>;
33
+ }
34
+ /**
35
+ * Extension definition
36
+ */
37
+ export interface Extension {
38
+ /** Unique identifier for the extension */
39
+ id: string;
40
+ /** Human-readable name */
41
+ name: string;
42
+ /** Description of what the extension does */
43
+ description: string;
44
+ /** Extension version */
45
+ version: string;
46
+ /** Author/maintainer */
47
+ author?: string;
48
+ /** Hooks this extension provides */
49
+ hooks: {
50
+ [K in ExtensionHook]?: (context: ExtensionContext) => Promise<ExtensionResult> | ExtensionResult;
51
+ };
52
+ /** Whether the extension is enabled */
53
+ enabled?: boolean;
54
+ /** Extension configuration */
55
+ config?: Record<string, unknown>;
56
+ }
57
+ /**
58
+ * Hook registration entry
59
+ */
60
+ export interface HookRegistration {
61
+ /** Extension that registered this hook */
62
+ extensionId: string;
63
+ /** Hook phase */
64
+ phase: ExtensionHook;
65
+ /** Hook handler function */
66
+ handler: (context: ExtensionContext) => Promise<ExtensionResult> | ExtensionResult;
67
+ /** Priority (lower = runs first) */
68
+ priority?: number;
69
+ }
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/extensions/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,eAAe,GACf,cAAc,GACd,eAAe,GACf,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,IAAI,EAAE,IAAI,CAAC;IACX,iCAAiC;IACjC,KAAK,EAAE,aAAa,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE;SACJ,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe;KACjG,CAAC;IACF,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,4BAA4B;IAC5B,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC;IACnF,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/extensions/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { Principle, Gate, GatePhase } from './types.js';
2
+ export declare const BUILTIN_PRINCIPLES: Principle[];
3
+ export declare const BUILTIN_GATES: Gate[];
4
+ export declare function getBuiltinPrinciple(id: string): Principle | undefined;
5
+ export declare function getBuiltinGate(id: string): Gate | undefined;
6
+ export declare function getGatesForPhase(phase: GatePhase): Gate[];
7
+ //# sourceMappingURL=builtins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/governance/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAyB,SAAS,EAAE,MAAM,YAAY,CAAC;AAIpF,eAAO,MAAM,kBAAkB,EAAE,SAAS,EAOzC,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,IAAI,EA4E/B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAErE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,CAEzD"}