@codewalla_india/openspec 1.3.1 → 1.3.3

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 (333) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +214 -133
  3. package/bin/openspec.js +5 -5
  4. package/dist/cli/index.js +99 -62
  5. package/dist/commands/change.d.ts +0 -2
  6. package/dist/commands/change.js +107 -86
  7. package/dist/commands/config.js +14 -16
  8. package/dist/commands/doctor.js +9 -4
  9. package/dist/commands/feedback.js +79 -30
  10. package/dist/commands/modify.d.ts +26 -0
  11. package/dist/commands/modify.js +147 -0
  12. package/dist/commands/schema.js +170 -91
  13. package/dist/commands/show.js +5 -2
  14. package/dist/commands/spec.js +49 -29
  15. package/dist/commands/store.js +15 -21
  16. package/dist/commands/validate.d.ts +8 -0
  17. package/dist/commands/validate.js +43 -20
  18. package/dist/commands/workflow/index.d.ts +2 -2
  19. package/dist/commands/workflow/index.js +1 -1
  20. package/dist/commands/workflow/instructions.d.ts +6 -26
  21. package/dist/commands/workflow/instructions.js +183 -376
  22. package/dist/commands/workflow/new-change.d.ts +0 -4
  23. package/dist/commands/workflow/new-change.js +10 -28
  24. package/dist/commands/workflow/shared.d.ts +34 -19
  25. package/dist/commands/workflow/shared.js +34 -4
  26. package/dist/commands/workflow/status.js +10 -32
  27. package/dist/commands/workflow/templates.js +15 -5
  28. package/dist/commands/workset.d.ts +2 -2
  29. package/dist/commands/workset.js +19 -22
  30. package/dist/comprehension-quiz/fingerprint.d.ts +39 -0
  31. package/dist/comprehension-quiz/fingerprint.js +84 -0
  32. package/dist/comprehension-quiz/index.d.ts +42 -0
  33. package/dist/comprehension-quiz/index.js +47 -0
  34. package/dist/comprehension-quiz/pass-record.d.ts +44 -0
  35. package/dist/comprehension-quiz/pass-record.js +98 -0
  36. package/dist/comprehension-quiz/providers/anthropic.d.ts +35 -0
  37. package/dist/comprehension-quiz/providers/anthropic.js +69 -0
  38. package/dist/comprehension-quiz/providers/factory.d.ts +44 -0
  39. package/dist/comprehension-quiz/providers/factory.js +174 -0
  40. package/dist/comprehension-quiz/providers/interface.d.ts +98 -0
  41. package/dist/comprehension-quiz/providers/interface.js +150 -0
  42. package/dist/comprehension-quiz/providers/local.d.ts +35 -0
  43. package/dist/comprehension-quiz/providers/local.js +69 -0
  44. package/dist/comprehension-quiz/providers/ollama.d.ts +35 -0
  45. package/dist/comprehension-quiz/providers/ollama.js +69 -0
  46. package/dist/comprehension-quiz/providers/openai.d.ts +35 -0
  47. package/dist/comprehension-quiz/providers/openai.js +72 -0
  48. package/dist/comprehension-quiz/question-generator.d.ts +117 -0
  49. package/dist/comprehension-quiz/question-generator.js +203 -0
  50. package/dist/comprehension-quiz/quiz-executor.d.ts +75 -0
  51. package/dist/comprehension-quiz/quiz-executor.js +181 -0
  52. package/dist/comprehension-quiz/types.d.ts +137 -0
  53. package/dist/comprehension-quiz/types.js +11 -0
  54. package/dist/core/archive.d.ts +14 -1
  55. package/dist/core/archive.js +1350 -190
  56. package/dist/core/artifact-graph/graph.d.ts +28 -9
  57. package/dist/core/artifact-graph/graph.js +94 -43
  58. package/dist/core/artifact-graph/index.d.ts +1 -1
  59. package/dist/core/artifact-graph/index.js +1 -1
  60. package/dist/core/artifact-graph/instruction-loader.d.ts +30 -3
  61. package/dist/core/artifact-graph/instruction-loader.js +70 -12
  62. package/dist/core/artifact-graph/outputs.d.ts +1 -0
  63. package/dist/core/artifact-graph/outputs.js +67 -5
  64. package/dist/core/artifact-graph/resolver.d.ts +14 -0
  65. package/dist/core/artifact-graph/resolver.js +69 -15
  66. package/dist/core/artifact-graph/types.js +21 -3
  67. package/dist/core/available-tools.d.ts +2 -2
  68. package/dist/core/available-tools.js +14 -3
  69. package/dist/core/change-metadata/schema.d.ts +2 -0
  70. package/dist/core/change-metadata/schema.js +13 -0
  71. package/dist/core/change-status-policy.d.ts +10 -1
  72. package/dist/core/change-status-policy.js +30 -2
  73. package/dist/core/command-generation/adapters/amazon-q.d.ts +4 -0
  74. package/dist/core/command-generation/adapters/amazon-q.js +11 -5
  75. package/dist/core/command-generation/adapters/antigravity.js +6 -5
  76. package/dist/core/command-generation/adapters/auggie.js +7 -6
  77. package/dist/core/command-generation/adapters/bob.d.ts +5 -1
  78. package/dist/core/command-generation/adapters/bob.js +11 -10
  79. package/dist/core/command-generation/adapters/claude.d.ts +1 -1
  80. package/dist/core/command-generation/adapters/claude.js +12 -17
  81. package/dist/core/command-generation/adapters/cline.js +5 -5
  82. package/dist/core/command-generation/adapters/codebuddy.js +8 -7
  83. package/dist/core/command-generation/adapters/continue.js +8 -7
  84. package/dist/core/command-generation/adapters/costrict.js +7 -6
  85. package/dist/core/command-generation/adapters/crush.js +9 -9
  86. package/dist/core/command-generation/adapters/cursor.js +8 -8
  87. package/dist/core/command-generation/adapters/devin.d.ts +19 -0
  88. package/dist/core/command-generation/adapters/devin.js +36 -0
  89. package/dist/core/command-generation/adapters/factory.js +7 -6
  90. package/dist/core/command-generation/adapters/gemini.js +40 -5
  91. package/dist/core/command-generation/adapters/github-copilot.js +6 -5
  92. package/dist/core/command-generation/adapters/iflow.js +9 -8
  93. package/dist/core/command-generation/adapters/index.d.ts +4 -2
  94. package/dist/core/command-generation/adapters/index.js +4 -2
  95. package/dist/core/command-generation/adapters/junie.js +6 -5
  96. package/dist/core/command-generation/adapters/kilocode.js +1 -1
  97. package/dist/core/command-generation/adapters/kiro.js +6 -5
  98. package/dist/core/command-generation/adapters/lingma.js +9 -9
  99. package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
  100. package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
  101. package/dist/core/command-generation/adapters/opencode.js +6 -8
  102. package/dist/core/command-generation/adapters/pi.d.ts +2 -2
  103. package/dist/core/command-generation/adapters/pi.js +7 -10
  104. package/dist/core/command-generation/adapters/qoder.js +9 -9
  105. package/dist/core/command-generation/adapters/qwen.d.ts +7 -3
  106. package/dist/core/command-generation/adapters/qwen.js +14 -9
  107. package/dist/core/command-generation/adapters/roocode.d.ts +4 -4
  108. package/dist/core/command-generation/adapters/roocode.js +9 -9
  109. package/dist/core/command-generation/adapters/trae.d.ts +13 -0
  110. package/dist/core/command-generation/adapters/trae.js +28 -0
  111. package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
  112. package/dist/core/command-generation/adapters/zcode.js +33 -0
  113. package/dist/core/command-generation/generator.d.ts +8 -0
  114. package/dist/core/command-generation/generator.js +15 -1
  115. package/dist/core/command-generation/index.d.ts +1 -1
  116. package/dist/core/command-generation/index.js +1 -1
  117. package/dist/core/command-generation/invocation.d.ts +73 -0
  118. package/dist/core/command-generation/invocation.js +77 -0
  119. package/dist/core/command-generation/registry.js +8 -4
  120. package/dist/core/command-generation/types.d.ts +9 -2
  121. package/dist/core/command-generation/yaml.d.ts +20 -6
  122. package/dist/core/command-generation/yaml.js +31 -21
  123. package/dist/core/command-surface.d.ts +15 -0
  124. package/dist/core/command-surface.js +33 -0
  125. package/dist/core/completions/command-registry.js +16 -61
  126. package/dist/core/completions/generators/bash-generator.js +41 -41
  127. package/dist/core/completions/generators/fish-generator.js +7 -7
  128. package/dist/core/completions/generators/powershell-generator.js +44 -37
  129. package/dist/core/completions/generators/zsh-generator.js +33 -33
  130. package/dist/core/completions/installers/zsh-installer.d.ts +9 -0
  131. package/dist/core/completions/installers/zsh-installer.js +20 -4
  132. package/dist/core/completions/templates/bash-templates.js +24 -24
  133. package/dist/core/completions/templates/fish-templates.js +38 -38
  134. package/dist/core/completions/templates/powershell-templates.js +28 -28
  135. package/dist/core/completions/templates/zsh-templates.js +39 -39
  136. package/dist/core/config-prompts.d.ts +1 -1
  137. package/dist/core/config-prompts.js +14 -1
  138. package/dist/core/config-schema.d.ts +10 -1
  139. package/dist/core/config-schema.js +67 -1
  140. package/dist/core/config.d.ts +15 -0
  141. package/dist/core/config.js +46 -5
  142. package/dist/core/file-state.js +56 -24
  143. package/dist/core/github-copilot/cloud-agent.d.ts +95 -0
  144. package/dist/core/github-copilot/cloud-agent.js +497 -0
  145. package/dist/core/global-config.d.ts +16 -0
  146. package/dist/core/init.d.ts +58 -0
  147. package/dist/core/init.js +474 -73
  148. package/dist/core/legacy-cleanup.d.ts +59 -0
  149. package/dist/core/legacy-cleanup.js +253 -24
  150. package/dist/core/list.js +23 -16
  151. package/dist/core/migration.d.ts +73 -1
  152. package/dist/core/migration.js +360 -11
  153. package/dist/core/modify/conflict-detector.d.ts +26 -0
  154. package/dist/core/modify/conflict-detector.js +62 -0
  155. package/dist/core/modify/dependency-propagator.d.ts +38 -0
  156. package/dist/core/modify/dependency-propagator.js +103 -0
  157. package/dist/core/modify/history-tracker.d.ts +34 -0
  158. package/dist/core/modify/history-tracker.js +114 -0
  159. package/dist/core/modify/index.d.ts +7 -0
  160. package/dist/core/modify/index.js +7 -0
  161. package/dist/core/onboarding-commands.d.ts +30 -0
  162. package/dist/core/onboarding-commands.js +38 -0
  163. package/dist/core/openspec-root.js +18 -15
  164. package/dist/core/parsers/change-parser.d.ts +17 -2
  165. package/dist/core/parsers/change-parser.js +35 -21
  166. package/dist/core/parsers/code-fence.d.ts +15 -0
  167. package/dist/core/parsers/code-fence.js +49 -0
  168. package/dist/core/parsers/markdown-parser.d.ts +0 -3
  169. package/dist/core/parsers/markdown-parser.js +7 -60
  170. package/dist/core/parsers/requirement-blocks.d.ts +29 -0
  171. package/dist/core/parsers/requirement-blocks.js +150 -31
  172. package/dist/core/parsers/requirement-text.d.ts +48 -0
  173. package/dist/core/parsers/requirement-text.js +98 -0
  174. package/dist/core/parsers/spec-structure.d.ts +1 -1
  175. package/dist/core/parsers/spec-structure.js +20 -30
  176. package/dist/core/profile-sync-drift.d.ts +0 -8
  177. package/dist/core/profile-sync-drift.js +49 -50
  178. package/dist/core/profiles.d.ts +2 -2
  179. package/dist/core/profiles.js +2 -2
  180. package/dist/core/project-config.d.ts +27 -18
  181. package/dist/core/project-config.js +101 -34
  182. package/dist/core/references.js +42 -4
  183. package/dist/core/relationship-health.d.ts +8 -0
  184. package/dist/core/relationship-health.js +13 -0
  185. package/dist/core/root-selection.d.ts +9 -6
  186. package/dist/core/root-selection.js +42 -5
  187. package/dist/core/schemas/base.schema.js +7 -2
  188. package/dist/core/shared/allowed-tools.d.ts +12 -0
  189. package/dist/core/shared/allowed-tools.js +12 -0
  190. package/dist/core/shared/index.d.ts +1 -0
  191. package/dist/core/shared/index.js +1 -0
  192. package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
  193. package/dist/core/shared/skill-content-equivalence.js +41 -0
  194. package/dist/core/shared/skill-generation.js +17 -13
  195. package/dist/core/shared/skill-paths.d.ts +13 -0
  196. package/dist/core/shared/skill-paths.js +23 -0
  197. package/dist/core/shared/tool-detection.d.ts +27 -7
  198. package/dist/core/shared/tool-detection.js +167 -37
  199. package/dist/core/shared-skill-target.d.ts +16 -0
  200. package/dist/core/shared-skill-target.js +156 -0
  201. package/dist/core/specs-apply.d.ts +80 -33
  202. package/dist/core/specs-apply.js +667 -145
  203. package/dist/core/store/git.d.ts +13 -0
  204. package/dist/core/store/git.js +24 -0
  205. package/dist/core/store/operations.js +20 -0
  206. package/dist/core/templates/skill-templates.d.ts +3 -2
  207. package/dist/core/templates/skill-templates.js +3 -2
  208. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  209. package/dist/core/templates/workflows/apply-change.js +186 -224
  210. package/dist/core/templates/workflows/archive-change.js +387 -260
  211. package/dist/core/templates/workflows/bulk-archive-change.js +655 -475
  212. package/dist/core/templates/workflows/continue-change.js +210 -219
  213. package/dist/core/templates/workflows/explore.js +479 -443
  214. package/dist/core/templates/workflows/feedback.js +97 -97
  215. package/dist/core/templates/workflows/ff-change.js +200 -191
  216. package/dist/core/templates/workflows/modify-change.d.ts +4 -1
  217. package/dist/core/templates/workflows/modify-change.js +193 -71
  218. package/dist/core/templates/workflows/new-change.js +127 -134
  219. package/dist/core/templates/workflows/onboard.js +548 -542
  220. package/dist/core/templates/workflows/propose.js +273 -217
  221. package/dist/core/templates/workflows/store-selection.d.ts +1 -1
  222. package/dist/core/templates/workflows/store-selection.js +1 -1
  223. package/dist/core/templates/workflows/sync-specs.js +500 -273
  224. package/dist/core/templates/workflows/update-change.d.ts +10 -0
  225. package/dist/core/templates/workflows/update-change.js +177 -0
  226. package/dist/core/templates/workflows/verify-change.js +324 -326
  227. package/dist/core/update.d.ts +40 -5
  228. package/dist/core/update.js +411 -96
  229. package/dist/core/validation/constants.d.ts +4 -1
  230. package/dist/core/validation/constants.js +4 -1
  231. package/dist/core/validation/plan-validator.d.ts +8 -0
  232. package/dist/core/validation/plan-validator.js +45 -0
  233. package/dist/core/validation/task-numbering.d.ts +16 -0
  234. package/dist/core/validation/task-numbering.js +57 -0
  235. package/dist/core/validation/validator.d.ts +27 -3
  236. package/dist/core/validation/validator.js +337 -48
  237. package/dist/core/version-check.d.ts +152 -0
  238. package/dist/core/version-check.js +731 -0
  239. package/dist/core/view.js +13 -18
  240. package/dist/prompts/searchable-multi-select.js +1 -1
  241. package/dist/telemetry/caller-detection.d.ts +27 -0
  242. package/dist/telemetry/caller-detection.js +85 -0
  243. package/dist/telemetry/caller-detection.test.d.ts +5 -0
  244. package/dist/telemetry/config.d.ts +48 -2
  245. package/dist/telemetry/config.js +113 -11
  246. package/dist/telemetry/config.test.d.ts +5 -0
  247. package/dist/telemetry/deduplication.d.ts +35 -0
  248. package/dist/telemetry/deduplication.js +82 -0
  249. package/dist/telemetry/deduplication.test.d.ts +5 -0
  250. package/dist/telemetry/identity.d.ts +62 -22
  251. package/dist/telemetry/identity.js +147 -102
  252. package/dist/telemetry/index.d.ts +126 -15
  253. package/dist/telemetry/index.js +569 -37
  254. package/dist/telemetry/sanitization.d.ts +40 -0
  255. package/dist/telemetry/sanitization.js +114 -0
  256. package/dist/telemetry/sanitization.test.d.ts +5 -0
  257. package/dist/telemetry/throttling.d.ts +20 -0
  258. package/dist/telemetry/throttling.js +70 -0
  259. package/dist/ui/welcome-screen.d.ts +9 -1
  260. package/dist/ui/welcome-screen.js +91 -38
  261. package/dist/utils/change-metadata.d.ts +43 -0
  262. package/dist/utils/change-metadata.js +123 -7
  263. package/dist/utils/change-utils.d.ts +10 -4
  264. package/dist/utils/change-utils.js +20 -13
  265. package/dist/utils/ci.d.ts +12 -0
  266. package/dist/utils/ci.js +16 -0
  267. package/dist/utils/command-references.d.ts +92 -6
  268. package/dist/utils/command-references.js +180 -7
  269. package/dist/utils/date.d.ts +8 -0
  270. package/dist/utils/date.js +13 -0
  271. package/dist/utils/file-system.d.ts +10 -0
  272. package/dist/utils/file-system.js +70 -0
  273. package/dist/utils/index.d.ts +1 -1
  274. package/dist/utils/index.js +1 -1
  275. package/dist/utils/interactive.d.ts +23 -0
  276. package/dist/utils/interactive.js +32 -0
  277. package/dist/utils/item-discovery.d.ts +19 -0
  278. package/dist/utils/item-discovery.js +30 -48
  279. package/dist/utils/shell-detection.d.ts +1 -1
  280. package/dist/utils/shell-detection.js +64 -11
  281. package/dist/utils/spec-discovery.d.ts +40 -0
  282. package/dist/utils/spec-discovery.js +115 -0
  283. package/dist/utils/task-progress.d.ts +29 -1
  284. package/dist/utils/task-progress.js +109 -15
  285. package/package.json +96 -84
  286. package/schemas/spec-driven/schema.yaml +252 -184
  287. package/schemas/spec-driven/templates/design.md +19 -19
  288. package/schemas/spec-driven/templates/plan-template.md +91 -0
  289. package/schemas/spec-driven/templates/proposal.md +29 -24
  290. package/schemas/spec-driven/templates/spec.md +11 -8
  291. package/schemas/spec-driven/templates/tasks.md +9 -9
  292. package/scripts/postinstall.js +83 -83
  293. package/dist/core/command-generation/adapters/codex.d.ts +0 -16
  294. package/dist/core/command-generation/adapters/codex.js +0 -39
  295. package/dist/core/command-generation/adapters/windsurf.d.ts +0 -14
  296. package/dist/core/command-generation/adapters/windsurf.js +0 -38
  297. package/dist/core/comprehension/config.d.ts +0 -20
  298. package/dist/core/comprehension/config.js +0 -23
  299. package/dist/core/comprehension/fingerprint.d.ts +0 -14
  300. package/dist/core/comprehension/fingerprint.js +0 -33
  301. package/dist/core/comprehension/index.d.ts +0 -57
  302. package/dist/core/comprehension/index.js +0 -87
  303. package/dist/core/comprehension/pass-record.d.ts +0 -29
  304. package/dist/core/comprehension/pass-record.js +0 -64
  305. package/dist/core/comprehension/stats.d.ts +0 -35
  306. package/dist/core/comprehension/stats.js +0 -133
  307. package/dist/core/templates/workflows/comprehension-guidance.d.ts +0 -9
  308. package/dist/core/templates/workflows/comprehension-guidance.js +0 -73
  309. package/dist/core/templates/workflows/mcp-guidance.d.ts +0 -13
  310. package/dist/core/templates/workflows/mcp-guidance.js +0 -131
  311. package/dist/core/templates/workflows/user-prompt-guidance.d.ts +0 -16
  312. package/dist/core/templates/workflows/user-prompt-guidance.js +0 -48
  313. package/dist/telemetry/caller.d.ts +0 -5
  314. package/dist/telemetry/caller.js +0 -29
  315. package/dist/telemetry/client.d.ts +0 -27
  316. package/dist/telemetry/client.js +0 -127
  317. package/dist/telemetry/command-context.d.ts +0 -13
  318. package/dist/telemetry/command-context.js +0 -59
  319. package/dist/telemetry/comprehension.d.ts +0 -44
  320. package/dist/telemetry/comprehension.js +0 -105
  321. package/dist/telemetry/content.d.ts +0 -10
  322. package/dist/telemetry/content.js +0 -56
  323. package/dist/telemetry/git-stats.d.ts +0 -12
  324. package/dist/telemetry/git-stats.js +0 -69
  325. package/dist/telemetry/identify-cache.d.ts +0 -7
  326. package/dist/telemetry/identify-cache.js +0 -47
  327. package/dist/telemetry/input.d.ts +0 -17
  328. package/dist/telemetry/input.js +0 -68
  329. package/dist/telemetry/marker.d.ts +0 -37
  330. package/dist/telemetry/marker.js +0 -67
  331. package/dist/telemetry/workflow.d.ts +0 -85
  332. package/dist/telemetry/workflow.js +0 -318
  333. package/schemas/spec-driven/templates/plan.md +0 -19
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Comprehension quiz system main entry point
3
+ *
4
+ * This module provides the main entry point for the comprehension quiz system,
5
+ * which enforces that developers read and understand change artifacts before
6
+ * implementation. The quiz blocks the `/opsx:apply` command until passed with a score
7
+ * of 80% or higher.
8
+ *
9
+ * @module comprehension-quiz
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { QuizExecutor } from './comprehension-quiz/quiz-executor.js';
14
+ * import { QuizQuestionStream, getQuestionCount } from './comprehension-quiz/question-generator.js';
15
+ *
16
+ * // Create on-demand stream — NO questions generated yet
17
+ * const totalQuestions = getQuestionCount(totalArtifactBytes);
18
+ * const stream = await QuizQuestionStream.create(artifactPaths, totalQuestions);
19
+ *
20
+ * // Execute quiz — one question fetched per answer
21
+ * const executor = new QuizExecutor();
22
+ * const result = await executor.executeQuiz(stream, changeName);
23
+ *
24
+ * if (result.passed) {
25
+ * console.log('Quiz passed! Proceeding with implementation.');
26
+ * } else {
27
+ * console.log('Quiz failed. Please review the artifacts and try again.');
28
+ * }
29
+ * ```
30
+ */
31
+ // Types
32
+ export * from './types.js';
33
+ // Providers
34
+ export * from './providers/interface.js';
35
+ export * from './providers/factory.js';
36
+ export { OpenAIProvider } from './providers/openai.js';
37
+ export { AnthropicProvider } from './providers/anthropic.js';
38
+ export { OllamaProvider } from './providers/ollama.js';
39
+ export { LocalProvider } from './providers/local.js';
40
+ // Core utilities
41
+ export { fingerprintFile, fingerprintDirectory, fingerprintArtifacts, isPassRecordValid } from './fingerprint.js';
42
+ export * from './pass-record.js';
43
+ // Quiz execution
44
+ export { QuizExecutor } from './quiz-executor.js';
45
+ // Question generation
46
+ export { generateQuizQuestions, generateQuestionsForArtifact, getQuestionCount, calculateQuestionAllocation, QuizQuestionStream, } from './question-generator.js';
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pass record storage and validation
3
+ *
4
+ * This module handles the storage and retrieval of quiz pass records. Pass records
5
+ * are stored in `.openspec/comprehension-quiz-passes.json` and include fingerprint
6
+ * information to detect when artifacts have changed since the quiz was passed.
7
+ *
8
+ * @module comprehension-quiz/pass-record
9
+ */
10
+ import type { PassRecord } from './types.js';
11
+ /**
12
+ * Get pass record for a specific change
13
+ *
14
+ * @param changeName - Name of the change
15
+ * @returns Pass record or undefined if not found
16
+ */
17
+ export declare function getPassRecord(changeName: string): Promise<PassRecord | undefined>;
18
+ /**
19
+ * Save pass record for a change
20
+ *
21
+ * @param record - Pass record to save
22
+ */
23
+ export declare function savePassRecord(record: PassRecord): Promise<void>;
24
+ /**
25
+ * Increment failure count for a change
26
+ *
27
+ * @param changeName - Name of the change
28
+ */
29
+ export declare function incrementFailureCount(changeName: string): Promise<void>;
30
+ /**
31
+ * Delete pass record for a change
32
+ *
33
+ * @param changeName - Name of the change
34
+ */
35
+ export declare function deletePassRecord(changeName: string): Promise<void>;
36
+ /**
37
+ * Check if a pass record is valid for current artifact fingerprint
38
+ *
39
+ * @param changeName - Name of the change
40
+ * @param currentFingerprint - Current fingerprint of artifacts
41
+ * @returns True if pass record exists and fingerprint matches
42
+ */
43
+ export declare function isPassRecordValid(changeName: string, currentFingerprint: string): Promise<boolean>;
44
+ //# sourceMappingURL=pass-record.d.ts.map
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Pass record storage and validation
3
+ *
4
+ * This module handles the storage and retrieval of quiz pass records. Pass records
5
+ * are stored in `.openspec/comprehension-quiz-passes.json` and include fingerprint
6
+ * information to detect when artifacts have changed since the quiz was passed.
7
+ *
8
+ * @module comprehension-quiz/pass-record
9
+ */
10
+ import { promises as fs } from 'fs';
11
+ import path from 'path';
12
+ /**
13
+ * Path to the pass records file
14
+ */
15
+ const PASS_RECORDS_FILE = '.openspec/comprehension-quiz-passes.json';
16
+ /**
17
+ * Read all pass records from storage
18
+ *
19
+ * @returns Pass records object
20
+ */
21
+ async function readPassRecords() {
22
+ try {
23
+ const content = await fs.readFile(PASS_RECORDS_FILE, 'utf-8');
24
+ return JSON.parse(content);
25
+ }
26
+ catch (error) {
27
+ // File doesn't exist or is invalid, return empty object
28
+ return {};
29
+ }
30
+ }
31
+ /**
32
+ * Write pass records to storage
33
+ *
34
+ * @param records - Pass records to write
35
+ */
36
+ async function writePassRecords(records) {
37
+ const dir = path.dirname(PASS_RECORDS_FILE);
38
+ await fs.mkdir(dir, { recursive: true });
39
+ await fs.writeFile(PASS_RECORDS_FILE, JSON.stringify(records, null, 2), 'utf-8');
40
+ }
41
+ /**
42
+ * Get pass record for a specific change
43
+ *
44
+ * @param changeName - Name of the change
45
+ * @returns Pass record or undefined if not found
46
+ */
47
+ export async function getPassRecord(changeName) {
48
+ const records = await readPassRecords();
49
+ return records[changeName];
50
+ }
51
+ /**
52
+ * Save pass record for a change
53
+ *
54
+ * @param record - Pass record to save
55
+ */
56
+ export async function savePassRecord(record) {
57
+ const records = await readPassRecords();
58
+ records[record.changeName] = record;
59
+ await writePassRecords(records);
60
+ }
61
+ /**
62
+ * Increment failure count for a change
63
+ *
64
+ * @param changeName - Name of the change
65
+ */
66
+ export async function incrementFailureCount(changeName) {
67
+ const records = await readPassRecords();
68
+ const record = records[changeName];
69
+ if (record) {
70
+ record.failureCount = (record.failureCount || 0) + 1;
71
+ await writePassRecords(records);
72
+ }
73
+ }
74
+ /**
75
+ * Delete pass record for a change
76
+ *
77
+ * @param changeName - Name of the change
78
+ */
79
+ export async function deletePassRecord(changeName) {
80
+ const records = await readPassRecords();
81
+ delete records[changeName];
82
+ await writePassRecords(records);
83
+ }
84
+ /**
85
+ * Check if a pass record is valid for current artifact fingerprint
86
+ *
87
+ * @param changeName - Name of the change
88
+ * @param currentFingerprint - Current fingerprint of artifacts
89
+ * @returns True if pass record exists and fingerprint matches
90
+ */
91
+ export async function isPassRecordValid(changeName, currentFingerprint) {
92
+ const record = await getPassRecord(changeName);
93
+ if (!record) {
94
+ return false;
95
+ }
96
+ return record.fingerprint === currentFingerprint;
97
+ }
98
+ //# sourceMappingURL=pass-record.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Anthropic provider implementation
3
+ *
4
+ * This module implements the Anthropic LLM provider for question generation.
5
+ * It uses the Anthropic API to generate quiz questions from artifact content.
6
+ *
7
+ * @module comprehension-quiz/providers/anthropic
8
+ */
9
+ import { BaseProvider } from './interface.js';
10
+ import type { ProviderConfig, Question } from '../types.js';
11
+ /**
12
+ * Anthropic provider for question generation
13
+ *
14
+ * Requires ANTHROPIC_API_KEY environment variable to be set.
15
+ */
16
+ export declare class AnthropicProvider extends BaseProvider {
17
+ constructor(config: ProviderConfig);
18
+ /**
19
+ * Validate Anthropic configuration
20
+ *
21
+ * @throws Error if API key is missing
22
+ */
23
+ validateConfig(): void;
24
+ /**
25
+ * Generate quiz questions using Anthropic API
26
+ *
27
+ * @param artifactContent - The content of the artifact to generate questions from
28
+ * @param questionCount - Number of questions to generate
29
+ * @param artifactType - Type of artifact (proposal, design, specs, plan, tasks)
30
+ * @returns Array of generated questions
31
+ */
32
+ generateQuestions(artifactContent: string, questionCount: number, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks'): Promise<Question[]>;
33
+ generateSingleQuestion(artifactContent: string, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks', questionIndex: number, totalQuestions: number, previousQuestionTexts: string[]): Promise<Question>;
34
+ }
35
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Anthropic provider implementation
3
+ *
4
+ * This module implements the Anthropic LLM provider for question generation.
5
+ * It uses the Anthropic API to generate quiz questions from artifact content.
6
+ *
7
+ * @module comprehension-quiz/providers/anthropic
8
+ */
9
+ import { BaseProvider } from './interface.js';
10
+ /**
11
+ * Anthropic provider for question generation
12
+ *
13
+ * Requires ANTHROPIC_API_KEY environment variable to be set.
14
+ */
15
+ export class AnthropicProvider extends BaseProvider {
16
+ constructor(config) {
17
+ super(config);
18
+ }
19
+ /**
20
+ * Validate Anthropic configuration
21
+ *
22
+ * @throws Error if API key is missing
23
+ */
24
+ validateConfig() {
25
+ if (!this.config.apiKey) {
26
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for Anthropic provider');
27
+ }
28
+ }
29
+ /**
30
+ * Generate quiz questions using Anthropic API
31
+ *
32
+ * @param artifactContent - The content of the artifact to generate questions from
33
+ * @param questionCount - Number of questions to generate
34
+ * @param artifactType - Type of artifact (proposal, design, specs, plan, tasks)
35
+ * @returns Array of generated questions
36
+ */
37
+ async generateQuestions(artifactContent, questionCount, artifactType) {
38
+ const questions = [];
39
+ for (let i = 0; i < questionCount; i++) {
40
+ const q = await this.generateSingleQuestion(artifactContent, artifactType, i, questionCount, questions.map((q) => q.text));
41
+ questions.push(q);
42
+ }
43
+ return questions;
44
+ }
45
+ async generateSingleQuestion(artifactContent, artifactType, questionIndex, totalQuestions, previousQuestionTexts) {
46
+ const { system, user } = this.buildSingleQuestionPrompt(artifactContent, artifactType, questionIndex, totalQuestions, previousQuestionTexts);
47
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
48
+ method: 'POST',
49
+ headers: {
50
+ 'x-api-key': this.config.apiKey,
51
+ 'anthropic-version': '2023-06-01',
52
+ 'content-type': 'application/json',
53
+ },
54
+ body: JSON.stringify({
55
+ model: this.config.model ?? 'claude-3-opus-20240229',
56
+ max_tokens: 512,
57
+ system,
58
+ messages: [{ role: 'user', content: user }],
59
+ }),
60
+ });
61
+ if (!response.ok) {
62
+ throw new Error(`Anthropic API error ${response.status}: ${await response.text()}`);
63
+ }
64
+ const data = (await response.json());
65
+ const raw = data.content.find((b) => b.type === 'text')?.text ?? '';
66
+ return this.parseSingleQuestionResponse(raw, artifactType);
67
+ }
68
+ }
69
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Provider factory for creating LLM provider instances
3
+ *
4
+ * This module handles provider selection via environment variables, configuration
5
+ * loading, and fallback chain management. It supports OpenAI, Anthropic, Ollama, and
6
+ * local model providers with automatic fallback on failure.
7
+ *
8
+ * @module comprehension-quiz/providers/factory
9
+ */
10
+ import type { LLMProvider } from '../types.js';
11
+ /**
12
+ * Supported provider types
13
+ */
14
+ export type ProviderType = 'openai' | 'anthropic' | 'ollama' | 'local';
15
+ /**
16
+ * Create a provider instance
17
+ *
18
+ * @param providerType - Type of provider to create
19
+ * @returns Provider instance
20
+ * @throws Error if provider cannot be loaded
21
+ */
22
+ export declare function createProvider(providerType: ProviderType): Promise<LLMProvider>;
23
+ /**
24
+ * Create a provider with fallback chain
25
+ *
26
+ * Tries each provider in the fallback chain until one succeeds.
27
+ *
28
+ * @returns Provider instance from first available provider in fallback chain
29
+ * @throws Error if all providers fail
30
+ */
31
+ export declare function createProviderWithFallback(): Promise<LLMProvider>;
32
+ /**
33
+ * Get the primary provider type
34
+ *
35
+ * @returns Provider type
36
+ */
37
+ export declare function getPrimaryProviderType(): ProviderType;
38
+ /**
39
+ * Get the fallback chain
40
+ *
41
+ * @returns Array of provider types in fallback order
42
+ */
43
+ export declare function getFallbackChainTypes(): ProviderType[];
44
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Provider factory for creating LLM provider instances
3
+ *
4
+ * This module handles provider selection via environment variables, configuration
5
+ * loading, and fallback chain management. It supports OpenAI, Anthropic, Ollama, and
6
+ * local model providers with automatic fallback on failure.
7
+ *
8
+ * @module comprehension-quiz/providers/factory
9
+ */
10
+ /**
11
+ * Default fallback chain for providers
12
+ *
13
+ * The system will try providers in this order until one succeeds.
14
+ */
15
+ const DEFAULT_FALLBACK_CHAIN = ['openai', 'anthropic', 'ollama', 'local'];
16
+ /**
17
+ * Environment variable names for provider selection
18
+ */
19
+ const ENV_PROVIDER = 'OPENSPEC_LLM_PROVIDER';
20
+ const ENV_FALLBACK = 'OPENSPEC_LLM_FALLBACK';
21
+ /**
22
+ * Provider-specific environment variables
23
+ *
24
+ * Maps each provider to its configuration environment variables.
25
+ */
26
+ const PROVIDER_ENV_VARS = {
27
+ openai: {
28
+ apiKey: 'OPENAI_API_KEY',
29
+ model: 'OPENAI_MODEL',
30
+ },
31
+ anthropic: {
32
+ apiKey: 'ANTHROPIC_API_KEY',
33
+ model: 'ANTHROPIC_MODEL',
34
+ },
35
+ ollama: {
36
+ endpoint: 'OLLAMA_BASE_URL',
37
+ model: 'OLLAMA_MODEL',
38
+ },
39
+ local: {
40
+ modelType: 'LOCAL_MODEL_TYPE',
41
+ model: 'LOCAL_MODEL_PATH',
42
+ },
43
+ };
44
+ /**
45
+ * Default model names for each provider
46
+ *
47
+ * These are used if no specific model is configured via environment variables.
48
+ */
49
+ const DEFAULT_MODELS = {
50
+ openai: 'gpt-4',
51
+ anthropic: 'claude-3-opus',
52
+ ollama: 'llama2',
53
+ local: 'local-model',
54
+ };
55
+ /**
56
+ * Get provider type from environment variable
57
+ *
58
+ * @returns Provider type or default
59
+ */
60
+ function getProviderType() {
61
+ const envValue = process.env[ENV_PROVIDER];
62
+ if (envValue && ['openai', 'anthropic', 'ollama', 'local'].includes(envValue)) {
63
+ return envValue;
64
+ }
65
+ return 'openai'; // Default
66
+ }
67
+ /**
68
+ * Get fallback chain from environment variable
69
+ *
70
+ * @returns Array of provider types in fallback order
71
+ */
72
+ function getFallbackChain() {
73
+ const envValue = process.env[ENV_FALLBACK];
74
+ if (envValue) {
75
+ const providers = envValue.split(',').map((p) => p.trim().toLowerCase());
76
+ const validProviders = providers.filter((p) => ['openai', 'anthropic', 'ollama', 'local'].includes(p));
77
+ if (validProviders.length > 0) {
78
+ return validProviders;
79
+ }
80
+ }
81
+ return DEFAULT_FALLBACK_CHAIN;
82
+ }
83
+ /**
84
+ * Get configuration for a provider type from environment variables
85
+ *
86
+ * @param providerType - Type of provider
87
+ * @returns Provider configuration
88
+ */
89
+ function getProviderConfig(providerType) {
90
+ const envVars = PROVIDER_ENV_VARS[providerType];
91
+ const config = {};
92
+ if (envVars.apiKey && process.env[envVars.apiKey]) {
93
+ config.apiKey = process.env[envVars.apiKey];
94
+ }
95
+ if (envVars.model && process.env[envVars.model]) {
96
+ config.model = process.env[envVars.model];
97
+ }
98
+ else {
99
+ config.model = DEFAULT_MODELS[providerType];
100
+ }
101
+ if (envVars.endpoint && process.env[envVars.endpoint]) {
102
+ config.endpoint = process.env[envVars.endpoint];
103
+ }
104
+ if (envVars.modelType && process.env[envVars.modelType]) {
105
+ config.modelType = process.env[envVars.modelType];
106
+ }
107
+ return config;
108
+ }
109
+ /**
110
+ * Create a provider instance
111
+ *
112
+ * @param providerType - Type of provider to create
113
+ * @returns Provider instance
114
+ * @throws Error if provider cannot be loaded
115
+ */
116
+ export async function createProvider(providerType) {
117
+ const config = getProviderConfig(providerType);
118
+ switch (providerType) {
119
+ case 'openai':
120
+ const { OpenAIProvider } = await import('./openai.js');
121
+ return new OpenAIProvider(config);
122
+ case 'anthropic':
123
+ const { AnthropicProvider } = await import('./anthropic.js');
124
+ return new AnthropicProvider(config);
125
+ case 'ollama':
126
+ const { OllamaProvider } = await import('./ollama.js');
127
+ return new OllamaProvider(config);
128
+ case 'local':
129
+ const { LocalProvider } = await import('./local.js');
130
+ return new LocalProvider(config);
131
+ default:
132
+ throw new Error(`Unknown provider type: ${providerType}`);
133
+ }
134
+ }
135
+ /**
136
+ * Create a provider with fallback chain
137
+ *
138
+ * Tries each provider in the fallback chain until one succeeds.
139
+ *
140
+ * @returns Provider instance from first available provider in fallback chain
141
+ * @throws Error if all providers fail
142
+ */
143
+ export async function createProviderWithFallback() {
144
+ const fallbackChain = getFallbackChain();
145
+ const errors = [];
146
+ for (const providerType of fallbackChain) {
147
+ try {
148
+ const provider = await createProvider(providerType);
149
+ return provider;
150
+ }
151
+ catch (error) {
152
+ const errorMessage = error instanceof Error ? error.message : String(error);
153
+ errors.push(`${providerType}: ${errorMessage}`);
154
+ }
155
+ }
156
+ throw new Error(`All LLM providers failed. Attempted: ${fallbackChain.join(', ')}. Errors: ${errors.join('; ')}`);
157
+ }
158
+ /**
159
+ * Get the primary provider type
160
+ *
161
+ * @returns Provider type
162
+ */
163
+ export function getPrimaryProviderType() {
164
+ return getProviderType();
165
+ }
166
+ /**
167
+ * Get the fallback chain
168
+ *
169
+ * @returns Array of provider types in fallback order
170
+ */
171
+ export function getFallbackChainTypes() {
172
+ return getFallbackChain();
173
+ }
174
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1,98 @@
1
+ /**
2
+ * LLM provider interface for question generation
3
+ *
4
+ * This module defines the abstract base class that all LLM providers must implement.
5
+ * The interface ensures consistent question generation across different backends (OpenAI,
6
+ * Anthropic, Ollama, local models) with validation of generated questions.
7
+ *
8
+ * @module comprehension-quiz/providers/interface
9
+ */
10
+ import type { LLMProvider, ProviderConfig, Question } from '../types.js';
11
+ /**
12
+ * Abstract base class for LLM providers
13
+ *
14
+ * All providers must extend this class and implement the abstract methods.
15
+ * Provides common validation logic for generated questions.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * class MyProvider extends BaseProvider {
20
+ * async generateQuestions(content, count, type) {
21
+ * // Generate questions using your LLM
22
+ * }
23
+ * validateConfig() {
24
+ * // Check your configuration
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ export declare abstract class BaseProvider implements LLMProvider {
30
+ protected config: ProviderConfig;
31
+ constructor(config: ProviderConfig);
32
+ /**
33
+ * Generate quiz questions from artifact content
34
+ * @param artifactContent - The content of the artifact to generate questions from
35
+ * @param questionCount - Number of questions to generate
36
+ * @param artifactType - Type of artifact (proposal, design, specs, plan, tasks)
37
+ * @returns Array of generated questions
38
+ */
39
+ abstract generateQuestions(artifactContent: string, questionCount: number, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks'): Promise<Question[]>;
40
+ /**
41
+ * Generate a single question on-demand.
42
+ * Subclasses MUST call buildSingleQuestionPrompt() to get the messages and
43
+ * parseSingleQuestionResponse() to parse the LLM reply. This guarantees the
44
+ * correct-answer index never leaks into stdout or conversational context.
45
+ */
46
+ abstract generateSingleQuestion(artifactContent: string, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks', questionIndex: number, totalQuestions: number, previousQuestionTexts: string[]): Promise<Question>;
47
+ /**
48
+ * Validate provider configuration
49
+ * @throws Error if configuration is invalid
50
+ */
51
+ abstract validateConfig(): void;
52
+ /**
53
+ * Build the system + user messages for single-question generation.
54
+ *
55
+ * Contract:
56
+ * - System message explicitly forbids listing multiple questions.
57
+ * - User message asks for exactly one question (question N of total).
58
+ * - Response format is strict JSON only — no prose, no explanation, no answer label.
59
+ * - The correct answer index (correctOption) is returned as a number 0-2; its
60
+ * meaning is never explained in the response so the LLM cannot read it back.
61
+ *
62
+ * @returns { system, user } message pair ready to send to the LLM API
63
+ */
64
+ protected buildSingleQuestionPrompt(artifactContent: string, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks', questionIndex: number, totalQuestions: number, previousQuestionTexts: string[]): {
65
+ system: string;
66
+ user: string;
67
+ };
68
+ /**
69
+ * Parse the raw LLM text response into a Question object.
70
+ * Strips markdown fences if present, then JSON-parses and validates.
71
+ *
72
+ * @param rawResponse - Raw text returned by the LLM API
73
+ * @param artifactType - Expected artifact source (used as fallback)
74
+ * @returns Validated Question object
75
+ * @throws Error if the response cannot be parsed or fails validation
76
+ */
77
+ protected parseSingleQuestionResponse(rawResponse: string, artifactType: 'proposal' | 'design' | 'specs' | 'plan' | 'tasks'): Question;
78
+ /**
79
+ * Validate generated questions before returning
80
+ *
81
+ * Ensures all questions have:
82
+ * - Non-empty text
83
+ * - Exactly 3 options
84
+ * - Valid correct option index (0-2)
85
+ * - Valid artifact source
86
+ *
87
+ * @param questions - Questions to validate
88
+ * @throws Error if any question is invalid
89
+ */
90
+ protected validateQuestions(questions: Question[]): void;
91
+ /**
92
+ * Validate a single question object.
93
+ * @param question - Question to validate
94
+ * @throws Error if invalid
95
+ */
96
+ protected validateQuestion(question: Question): void;
97
+ }
98
+ //# sourceMappingURL=interface.d.ts.map