@nforma.ai/nforma 0.2.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 (215) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1024 -0
  3. package/agents/qgsd-codebase-mapper.md +764 -0
  4. package/agents/qgsd-debugger.md +1201 -0
  5. package/agents/qgsd-executor.md +472 -0
  6. package/agents/qgsd-integration-checker.md +443 -0
  7. package/agents/qgsd-phase-researcher.md +502 -0
  8. package/agents/qgsd-plan-checker.md +643 -0
  9. package/agents/qgsd-planner.md +1182 -0
  10. package/agents/qgsd-project-researcher.md +621 -0
  11. package/agents/qgsd-quorum-orchestrator.md +628 -0
  12. package/agents/qgsd-quorum-slot-worker.md +41 -0
  13. package/agents/qgsd-quorum-synthesizer.md +133 -0
  14. package/agents/qgsd-quorum-test-worker.md +37 -0
  15. package/agents/qgsd-quorum-worker.md +161 -0
  16. package/agents/qgsd-research-synthesizer.md +239 -0
  17. package/agents/qgsd-roadmapper.md +660 -0
  18. package/agents/qgsd-verifier.md +628 -0
  19. package/bin/accept-debug-invariant.cjs +165 -0
  20. package/bin/account-manager.cjs +719 -0
  21. package/bin/aggregate-requirements.cjs +466 -0
  22. package/bin/analyze-assumptions.cjs +757 -0
  23. package/bin/analyze-state-space.cjs +921 -0
  24. package/bin/attribute-trace-divergence.cjs +150 -0
  25. package/bin/auth-drivers/gh-cli.cjs +93 -0
  26. package/bin/auth-drivers/index.cjs +46 -0
  27. package/bin/auth-drivers/pool.cjs +67 -0
  28. package/bin/auth-drivers/simple.cjs +95 -0
  29. package/bin/autoClosePtoF.cjs +110 -0
  30. package/bin/blessed-terminal.cjs +350 -0
  31. package/bin/build-phase-index.cjs +472 -0
  32. package/bin/call-quorum-slot.cjs +541 -0
  33. package/bin/ccr-secure-config.cjs +99 -0
  34. package/bin/ccr-secure-start.cjs +83 -0
  35. package/bin/check-bundled-sdks.cjs +177 -0
  36. package/bin/check-coverage-guard.cjs +112 -0
  37. package/bin/check-liveness-fairness.cjs +95 -0
  38. package/bin/check-mcp-health.cjs +123 -0
  39. package/bin/check-provider-health.cjs +395 -0
  40. package/bin/check-results-exit.cjs +24 -0
  41. package/bin/check-spec-sync.cjs +360 -0
  42. package/bin/check-trace-redaction.cjs +271 -0
  43. package/bin/check-trace-schema-drift.cjs +99 -0
  44. package/bin/compareDrift.cjs +21 -0
  45. package/bin/conformance-schema.cjs +12 -0
  46. package/bin/count-scenarios.cjs +420 -0
  47. package/bin/debt-dedup.cjs +144 -0
  48. package/bin/debt-ledger.cjs +61 -0
  49. package/bin/debt-retention.cjs +76 -0
  50. package/bin/debt-state-machine.cjs +80 -0
  51. package/bin/detect-coverage-gaps.cjs +204 -0
  52. package/bin/detect-project-intent.cjs +362 -0
  53. package/bin/export-prism-constants.cjs +164 -0
  54. package/bin/extract-annotations.cjs +633 -0
  55. package/bin/extractFormalExpected.cjs +104 -0
  56. package/bin/fingerprint-drift.cjs +24 -0
  57. package/bin/fingerprint-issue.cjs +46 -0
  58. package/bin/formal-core.cjs +519 -0
  59. package/bin/formal-ref-linker.cjs +141 -0
  60. package/bin/formal-test-sync.cjs +788 -0
  61. package/bin/generate-formal-specs.cjs +588 -0
  62. package/bin/generate-petri-net.cjs +397 -0
  63. package/bin/generate-phase-spec.cjs +249 -0
  64. package/bin/generate-proposed-changes.cjs +194 -0
  65. package/bin/generate-tla-cfg.cjs +122 -0
  66. package/bin/generate-traceability-matrix.cjs +701 -0
  67. package/bin/generate-triage-bundle.cjs +300 -0
  68. package/bin/gh-account-rotate.cjs +34 -0
  69. package/bin/initialize-model-registry.cjs +105 -0
  70. package/bin/install-formal-tools.cjs +382 -0
  71. package/bin/install.js +2424 -0
  72. package/bin/isNumericThreshold.cjs +34 -0
  73. package/bin/issue-classifier.cjs +151 -0
  74. package/bin/levenshtein.cjs +74 -0
  75. package/bin/lint-formal-models.cjs +580 -0
  76. package/bin/load-baseline-requirements.cjs +275 -0
  77. package/bin/manage-agents-core.cjs +815 -0
  78. package/bin/migrate-formal-dir.cjs +172 -0
  79. package/bin/migrate-planning.cjs +206 -0
  80. package/bin/migrate-to-slots.cjs +255 -0
  81. package/bin/nForma.cjs +2726 -0
  82. package/bin/observe-config.cjs +353 -0
  83. package/bin/observe-debt-writer.cjs +140 -0
  84. package/bin/observe-handler-grafana.cjs +128 -0
  85. package/bin/observe-handler-internal.cjs +301 -0
  86. package/bin/observe-handler-logstash.cjs +153 -0
  87. package/bin/observe-handler-prometheus.cjs +185 -0
  88. package/bin/observe-handlers.cjs +436 -0
  89. package/bin/observe-registry.cjs +131 -0
  90. package/bin/observe-render.cjs +168 -0
  91. package/bin/planning-paths.cjs +167 -0
  92. package/bin/polyrepo.cjs +560 -0
  93. package/bin/prism-priority.cjs +153 -0
  94. package/bin/probe-quorum-slots.cjs +167 -0
  95. package/bin/promote-model.cjs +225 -0
  96. package/bin/propose-debug-invariants.cjs +165 -0
  97. package/bin/providers.json +392 -0
  98. package/bin/pty-proxy.py +129 -0
  99. package/bin/qgsd-solve.cjs +2477 -0
  100. package/bin/quorum-consensus-gate.cjs +238 -0
  101. package/bin/quorum-formal-context.cjs +183 -0
  102. package/bin/quorum-slot-dispatch.cjs +934 -0
  103. package/bin/read-policy.cjs +60 -0
  104. package/bin/requirement-map.cjs +63 -0
  105. package/bin/requirements-core.cjs +247 -0
  106. package/bin/resolve-cli.cjs +101 -0
  107. package/bin/review-mcp-logs.cjs +294 -0
  108. package/bin/run-account-manager-tlc.cjs +188 -0
  109. package/bin/run-account-pool-alloy.cjs +158 -0
  110. package/bin/run-alloy.cjs +153 -0
  111. package/bin/run-audit-alloy.cjs +187 -0
  112. package/bin/run-breaker-tlc.cjs +181 -0
  113. package/bin/run-formal-check.cjs +395 -0
  114. package/bin/run-formal-verify.cjs +701 -0
  115. package/bin/run-installer-alloy.cjs +188 -0
  116. package/bin/run-oauth-rotation-prism.cjs +132 -0
  117. package/bin/run-oscillation-tlc.cjs +202 -0
  118. package/bin/run-phase-tlc.cjs +228 -0
  119. package/bin/run-prism.cjs +446 -0
  120. package/bin/run-protocol-tlc.cjs +201 -0
  121. package/bin/run-quorum-composition-alloy.cjs +155 -0
  122. package/bin/run-sensitivity-sweep.cjs +231 -0
  123. package/bin/run-stop-hook-tlc.cjs +188 -0
  124. package/bin/run-tlc.cjs +467 -0
  125. package/bin/run-transcript-alloy.cjs +173 -0
  126. package/bin/run-uppaal.cjs +264 -0
  127. package/bin/secrets.cjs +134 -0
  128. package/bin/sensitivity-report.cjs +219 -0
  129. package/bin/sensitivity-sweep-feedback.cjs +194 -0
  130. package/bin/set-secret.cjs +29 -0
  131. package/bin/setup-telemetry-cron.sh +36 -0
  132. package/bin/sweepPtoF.cjs +63 -0
  133. package/bin/sync-baseline-requirements.cjs +290 -0
  134. package/bin/task-envelope.cjs +360 -0
  135. package/bin/telemetry-collector.cjs +229 -0
  136. package/bin/unified-mcp-server.mjs +735 -0
  137. package/bin/update-agents.cjs +369 -0
  138. package/bin/update-scoreboard.cjs +1134 -0
  139. package/bin/validate-debt-entry.cjs +207 -0
  140. package/bin/validate-invariant.cjs +419 -0
  141. package/bin/validate-memory.cjs +389 -0
  142. package/bin/validate-requirements-haiku.cjs +435 -0
  143. package/bin/validate-traces.cjs +438 -0
  144. package/bin/verify-formal-results.cjs +124 -0
  145. package/bin/verify-quorum-health.cjs +273 -0
  146. package/bin/write-check-result.cjs +106 -0
  147. package/bin/xstate-to-tla.cjs +483 -0
  148. package/bin/xstate-trace-walker.cjs +205 -0
  149. package/commands/qgsd/add-phase.md +43 -0
  150. package/commands/qgsd/add-requirement.md +24 -0
  151. package/commands/qgsd/add-todo.md +47 -0
  152. package/commands/qgsd/audit-milestone.md +37 -0
  153. package/commands/qgsd/check-todos.md +45 -0
  154. package/commands/qgsd/cleanup.md +18 -0
  155. package/commands/qgsd/close-formal-gaps.md +33 -0
  156. package/commands/qgsd/complete-milestone.md +136 -0
  157. package/commands/qgsd/debug.md +166 -0
  158. package/commands/qgsd/discuss-phase.md +83 -0
  159. package/commands/qgsd/execute-phase.md +117 -0
  160. package/commands/qgsd/fix-tests.md +27 -0
  161. package/commands/qgsd/formal-test-sync.md +32 -0
  162. package/commands/qgsd/health.md +22 -0
  163. package/commands/qgsd/help.md +22 -0
  164. package/commands/qgsd/insert-phase.md +32 -0
  165. package/commands/qgsd/join-discord.md +18 -0
  166. package/commands/qgsd/list-phase-assumptions.md +46 -0
  167. package/commands/qgsd/map-codebase.md +71 -0
  168. package/commands/qgsd/map-requirements.md +20 -0
  169. package/commands/qgsd/mcp-restart.md +176 -0
  170. package/commands/qgsd/mcp-set-model.md +134 -0
  171. package/commands/qgsd/mcp-setup.md +1371 -0
  172. package/commands/qgsd/mcp-status.md +274 -0
  173. package/commands/qgsd/mcp-update.md +238 -0
  174. package/commands/qgsd/new-milestone.md +44 -0
  175. package/commands/qgsd/new-project.md +42 -0
  176. package/commands/qgsd/observe.md +260 -0
  177. package/commands/qgsd/pause-work.md +38 -0
  178. package/commands/qgsd/plan-milestone-gaps.md +34 -0
  179. package/commands/qgsd/plan-phase.md +44 -0
  180. package/commands/qgsd/polyrepo.md +50 -0
  181. package/commands/qgsd/progress.md +24 -0
  182. package/commands/qgsd/queue.md +54 -0
  183. package/commands/qgsd/quick.md +133 -0
  184. package/commands/qgsd/quorum-test.md +275 -0
  185. package/commands/qgsd/quorum.md +707 -0
  186. package/commands/qgsd/reapply-patches.md +110 -0
  187. package/commands/qgsd/remove-phase.md +31 -0
  188. package/commands/qgsd/research-phase.md +189 -0
  189. package/commands/qgsd/resume-work.md +40 -0
  190. package/commands/qgsd/set-profile.md +34 -0
  191. package/commands/qgsd/settings.md +39 -0
  192. package/commands/qgsd/solve.md +565 -0
  193. package/commands/qgsd/sync-baselines.md +119 -0
  194. package/commands/qgsd/triage.md +233 -0
  195. package/commands/qgsd/update.md +37 -0
  196. package/commands/qgsd/verify-work.md +38 -0
  197. package/hooks/dist/config-loader.js +297 -0
  198. package/hooks/dist/conformance-schema.cjs +12 -0
  199. package/hooks/dist/gsd-context-monitor.js +64 -0
  200. package/hooks/dist/qgsd-check-update.js +62 -0
  201. package/hooks/dist/qgsd-circuit-breaker.js +682 -0
  202. package/hooks/dist/qgsd-precompact.js +156 -0
  203. package/hooks/dist/qgsd-prompt.js +653 -0
  204. package/hooks/dist/qgsd-session-start.js +122 -0
  205. package/hooks/dist/qgsd-slot-correlator.js +58 -0
  206. package/hooks/dist/qgsd-spec-regen.js +86 -0
  207. package/hooks/dist/qgsd-statusline.js +91 -0
  208. package/hooks/dist/qgsd-stop.js +553 -0
  209. package/hooks/dist/qgsd-token-collector.js +133 -0
  210. package/hooks/dist/unified-mcp-server.mjs +669 -0
  211. package/package.json +95 -0
  212. package/scripts/build-hooks.js +46 -0
  213. package/scripts/postinstall.js +48 -0
  214. package/scripts/secret-audit.sh +45 -0
  215. package/templates/qgsd.json +49 -0
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ /**
8
+ * Load baseline requirements filtered by project profile.
9
+ *
10
+ * @param {string} profile - One of: web, mobile, desktop, api, cli, library
11
+ * @param {string} [basePath] - Path to baseline-requirements directory, defaults to qgsd-core/defaults/baseline-requirements
12
+ * @returns {Object} { profile, label, description, categories: [...], total }
13
+ */
14
+ function loadBaselineRequirements(profile, basePath) {
15
+ const defaultBasePath = path.resolve(__dirname, '../qgsd-core/defaults/baseline-requirements');
16
+ const basePathToUse = basePath || defaultBasePath;
17
+
18
+ // Read index.json
19
+ const indexPath = path.join(basePathToUse, 'index.json');
20
+ const indexContent = fs.readFileSync(indexPath, 'utf8');
21
+ const index = JSON.parse(indexContent);
22
+
23
+ // Validate profile
24
+ if (!index.profiles[profile]) {
25
+ throw new Error(`Invalid profile: ${profile}. Supported profiles: ${Object.keys(index.profiles).join(', ')}`);
26
+ }
27
+
28
+ const profileConfig = index.profiles[profile];
29
+ const profileLabel = profileConfig.label;
30
+ const profileDescription = profileConfig.description;
31
+
32
+ // Process categories
33
+ const categories = [];
34
+ let totalRequirements = 0;
35
+
36
+ for (const categoryMeta of index.categories) {
37
+ const categoryFile = categoryMeta.file;
38
+ const categoryPath = path.join(basePathToUse, categoryFile);
39
+
40
+ // Check if we should load this category at all
41
+ if (profileConfig.includes_only && !profileConfig.includes_only.includes(categoryFile.replace('.json', ''))) {
42
+ continue; // Skip categories not in includes_only
43
+ }
44
+
45
+ const categoryContent = fs.readFileSync(categoryPath, 'utf8');
46
+ const category = JSON.parse(categoryContent);
47
+
48
+ // Filter requirements based on profile
49
+ let filteredRequirements = category.requirements;
50
+
51
+ if (!profileConfig.includes_all) {
52
+ // Filter based on per-requirement profiles array
53
+ filteredRequirements = category.requirements.filter(req => req.profiles.includes(profile));
54
+ }
55
+
56
+ if (filteredRequirements.length === 0) {
57
+ continue; // Skip empty categories
58
+ }
59
+
60
+ // Assign sequential IDs per category using id_template
61
+ // Extract prefix from id_template (e.g., "UX-{N}" -> "UX")
62
+ const idTemplate = filteredRequirements[0].id_template;
63
+ const prefix = idTemplate.split('-')[0];
64
+
65
+ const categoryRequirements = filteredRequirements.map((req, index) => {
66
+ const reqId = `${prefix}-${String(index + 1).padStart(2, '0')}`;
67
+ return {
68
+ id: reqId,
69
+ text: req.text,
70
+ intent: req.intent,
71
+ verifiable_by: req.verifiable_by,
72
+ };
73
+ });
74
+
75
+ categories.push({
76
+ name: category.category,
77
+ description: category.description,
78
+ requirements: categoryRequirements,
79
+ });
80
+
81
+ totalRequirements += categoryRequirements.length;
82
+ }
83
+
84
+ return {
85
+ profile,
86
+ label: profileLabel,
87
+ description: profileDescription,
88
+ categories,
89
+ total: totalRequirements,
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Load baseline requirements filtered by intent object.
95
+ * Supports conditional packs activated by intent dimensions.
96
+ *
97
+ * @param {Object} intent - Intent object with base_profile and optional dimensions
98
+ * @param {string} intent.base_profile - Required: one of web, mobile, desktop, api, cli, library
99
+ * @param {boolean} [intent.iac] - Optional: include IaC pack if true
100
+ * @param {boolean} [intent.deploy] - Optional: deployment target (for future use)
101
+ * @param {boolean} [intent.sensitive] - Optional: handles sensitive data
102
+ * @param {boolean} [intent.oss] - Optional: open source project
103
+ * @param {boolean} [intent.monorepo] - Optional: monorepo setup
104
+ * @param {string} [basePath] - Path to baseline-requirements directory
105
+ * @returns {Object} { profile, label, intent, categories, packs_applied, total }
106
+ */
107
+ function loadBaselineRequirementsFromIntent(intent, basePath) {
108
+ const defaultBasePath = path.resolve(__dirname, '../qgsd-core/defaults/baseline-requirements');
109
+ const basePathToUse = basePath || defaultBasePath;
110
+
111
+ // Validate base_profile
112
+ if (!intent || !intent.base_profile) {
113
+ throw new Error('intent.base_profile is required');
114
+ }
115
+
116
+ // Read index.json
117
+ const indexPath = path.join(basePathToUse, 'index.json');
118
+ const indexContent = fs.readFileSync(indexPath, 'utf8');
119
+ const index = JSON.parse(indexContent);
120
+
121
+ // Validate base_profile exists
122
+ if (!index.profiles[intent.base_profile]) {
123
+ throw new Error(`Invalid base_profile: ${intent.base_profile}. Supported profiles: ${Object.keys(index.profiles).join(', ')}`);
124
+ }
125
+
126
+ const baseProfile = intent.base_profile;
127
+ const profileConfig = index.profiles[baseProfile];
128
+ const profileLabel = profileConfig.label;
129
+
130
+ // Derive has_ui from base_profile
131
+ const has_ui = ['web', 'mobile', 'desktop'].includes(baseProfile);
132
+
133
+ // Build enriched intent with defaults
134
+ const defaultIntent = {
135
+ iac: false,
136
+ deploy: 'none',
137
+ sensitive: false,
138
+ oss: false,
139
+ monorepo: false,
140
+ };
141
+
142
+ const enrichedIntent = {
143
+ ...defaultIntent,
144
+ ...intent,
145
+ has_ui,
146
+ };
147
+
148
+ // Process packs
149
+ const categories = [];
150
+ let totalRequirements = 0;
151
+ const packsApplied = [];
152
+
153
+ if (!index.packs) {
154
+ throw new Error('index.json missing packs section');
155
+ }
156
+
157
+ for (const [packName, packConfig] of Object.entries(index.packs)) {
158
+ let shouldIncludePack = false;
159
+
160
+ if (packConfig.activation === 'always') {
161
+ shouldIncludePack = true;
162
+ } else if (packConfig.activation === 'conditional') {
163
+ const intentKey = packConfig.intent_key;
164
+ const intentValue = packConfig.intent_value;
165
+ shouldIncludePack = enrichedIntent[intentKey] === intentValue;
166
+ }
167
+
168
+ if (!shouldIncludePack) {
169
+ continue;
170
+ }
171
+
172
+ const categoryFile = packConfig.file;
173
+ const categoryPath = path.join(basePathToUse, categoryFile);
174
+
175
+ // Check if we should load this category based on profile config
176
+ if (profileConfig.includes_only && !profileConfig.includes_only.includes(categoryFile.replace('.json', ''))) {
177
+ continue;
178
+ }
179
+
180
+ const categoryContent = fs.readFileSync(categoryPath, 'utf8');
181
+ const category = JSON.parse(categoryContent);
182
+
183
+ // Filter requirements based on profile
184
+ let filteredRequirements = category.requirements;
185
+
186
+ if (!profileConfig.includes_all) {
187
+ // Filter based on per-requirement profiles array
188
+ filteredRequirements = category.requirements.filter(req => req.profiles.includes(baseProfile));
189
+ }
190
+
191
+ if (filteredRequirements.length === 0) {
192
+ continue;
193
+ }
194
+
195
+ // Assign sequential IDs per category using id_template
196
+ const idTemplate = filteredRequirements[0].id_template;
197
+ const prefix = idTemplate.split('-')[0];
198
+
199
+ const categoryRequirements = filteredRequirements.map((req, index) => {
200
+ const reqId = `${prefix}-${String(index + 1).padStart(2, '0')}`;
201
+ return {
202
+ id: reqId,
203
+ text: req.text,
204
+ intent: req.intent,
205
+ verifiable_by: req.verifiable_by,
206
+ };
207
+ });
208
+
209
+ categories.push({
210
+ name: category.category,
211
+ description: category.description,
212
+ requirements: categoryRequirements,
213
+ });
214
+
215
+ totalRequirements += categoryRequirements.length;
216
+ packsApplied.push(packName);
217
+ }
218
+
219
+ return {
220
+ profile: baseProfile,
221
+ label: profileLabel,
222
+ intent: enrichedIntent,
223
+ categories,
224
+ packs_applied: packsApplied,
225
+ total: totalRequirements,
226
+ };
227
+ }
228
+
229
+ // CLI mode
230
+ if (require.main === module) {
231
+ const args = process.argv.slice(2);
232
+
233
+ if (args.includes('--list-profiles')) {
234
+ const indexPath = path.resolve(__dirname, '../qgsd-core/defaults/baseline-requirements/index.json');
235
+ const indexContent = fs.readFileSync(indexPath, 'utf8');
236
+ const index = JSON.parse(indexContent);
237
+ const profiles = Object.entries(index.profiles).map(([key, val]) => ({
238
+ key,
239
+ label: val.label,
240
+ description: val.description,
241
+ }));
242
+ console.log(JSON.stringify(profiles, null, 2));
243
+ process.exit(0);
244
+ }
245
+
246
+ // Check for --intent-file flag
247
+ const intentFileIdx = args.indexOf('--intent-file');
248
+ if (intentFileIdx !== -1 && args[intentFileIdx + 1]) {
249
+ const intentFilePath = args[intentFileIdx + 1];
250
+ try {
251
+ const intentContent = fs.readFileSync(intentFilePath, 'utf8');
252
+ const intent = JSON.parse(intentContent);
253
+ const result = loadBaselineRequirementsFromIntent(intent);
254
+ console.log(JSON.stringify(result, null, 2));
255
+ process.exit(0);
256
+ } catch (err) {
257
+ console.error(`Error loading intent file: ${err.message}`);
258
+ process.exit(1);
259
+ }
260
+ }
261
+
262
+ const profileIdx = args.indexOf('--profile');
263
+ if (profileIdx === -1 || !args[profileIdx + 1]) {
264
+ console.error('Usage: node bin/load-baseline-requirements.cjs --profile <web|mobile|desktop|api|cli|library>');
265
+ console.error(' node bin/load-baseline-requirements.cjs --intent-file <path>');
266
+ console.error(' node bin/load-baseline-requirements.cjs --list-profiles');
267
+ process.exit(1);
268
+ }
269
+
270
+ const profile = args[profileIdx + 1];
271
+ const result = loadBaselineRequirements(profile);
272
+ console.log(JSON.stringify(result, null, 2));
273
+ }
274
+
275
+ module.exports = { loadBaselineRequirements, loadBaselineRequirementsFromIntent };