@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
+ ---
2
+ name: qgsd:quorum-test
3
+ description: Run the test suite and submit the full execution bundle to quorum workers for independent quality review. Parallel workers evaluate whether tests genuinely pass and whether assertions are meaningful.
4
+ argument-hint: "[path/to/test.file.js]"
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Bash
9
+ - Task
10
+ - Glob
11
+ ---
12
+
13
+ <objective>
14
+ Run the project test suite, assemble a full execution bundle, and dispatch parallel quorum workers to independently evaluate whether the tests genuinely pass and whether they are real tests.
15
+
16
+ This command extends QGSD quorum from *planning* (consensus on direction) to *verification* (consensus on test quality).
17
+ </objective>
18
+
19
+ <process>
20
+
21
+ **Detect test runner**
22
+
23
+ Read `package.json` if it exists (use the Read tool, not bash). Inspect `devDependencies`, `dependencies`, and `scripts.test`.
24
+
25
+ Determine `$RUNNER` using this priority order:
26
+ 1. If `devDependencies` or `dependencies` contains `"vitest"` → `$RUNNER = vitest`
27
+ 2. Else if `devDependencies` or `dependencies` contains `"jest"` or `"@jest/core"` or `"ts-jest"` or `"babel-jest"` → `$RUNNER = jest`
28
+ 3. Else if `scripts.test` contains `"vitest"` → `$RUNNER = vitest`
29
+ 4. Else if `scripts.test` contains `"jest"` → `$RUNNER = jest`
30
+ 5. Else if `scripts.test` contains `"node --test"` → `$RUNNER = node`
31
+ 6. Else → `$RUNNER = node` (default)
32
+
33
+ Set `$TEST_PATTERNS` based on `$RUNNER`:
34
+ - `jest` or `vitest`: `*.test.ts`, `*.test.tsx`, `*.test.js`, `*.test.jsx`, `*.spec.ts`, `*.spec.tsx`, `*.spec.js`, `*.spec.jsx`
35
+ - `node`: `*.test.js`, `*.test.cjs`, `*.test.mjs`
36
+
37
+ Set `$RUN_CMD` based on `$RUNNER`:
38
+ - `jest`: `npx jest --passWithNoTests`
39
+ - `vitest`: `npx vitest run`
40
+ - `node`: `node --test` (files appended per step 2)
41
+
42
+ Display: `Detected runner: $RUNNER`
43
+
44
+ **Parse and validate target**
45
+
46
+ Parse `$ARGUMENTS`:
47
+ - If non-empty and points to a **file**: use it directly as `$TEST_FILES`
48
+ - If non-empty and points to a **directory**: search within that directory using `$TEST_PATTERNS`
49
+ - If empty: search from repo root using `$TEST_PATTERNS`
50
+
51
+ For directory or root discovery, run one `find` covering all applicable patterns. Example for jest/vitest:
52
+ ```bash
53
+ find <root> \( -name "*.test.ts" -o -name "*.test.tsx" -o -name "*.test.js" \
54
+ -o -name "*.test.jsx" -o -name "*.spec.ts" -o -name "*.spec.tsx" \
55
+ -o -name "*.spec.js" -o -name "*.spec.jsx" \) \
56
+ -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/.next/*"
57
+ ```
58
+
59
+ For node runner:
60
+ ```bash
61
+ find <root> \( -name "*.test.js" -o -name "*.test.cjs" -o -name "*.test.mjs" \) \
62
+ -not -path "*/node_modules/*" -not -path "*/.git/*"
63
+ ```
64
+
65
+ Store the list as `$TEST_FILES`.
66
+
67
+ Empty check:
68
+
69
+ If `$TEST_FILES` is empty, display:
70
+
71
+ ```
72
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
73
+ QGSD ► QUORUM-TEST: No automated tests found
74
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
75
+
76
+ Searched for: <$TEST_PATTERNS>
77
+ Runner detected: <$RUNNER>
78
+
79
+ If this checkpoint requires visual/manual verification, quorum-test does not apply.
80
+ Proceed with human verification or add automated tests before invoking quorum-test.
81
+ ```
82
+
83
+ STOP — do not proceed.
84
+
85
+ File existence check:
86
+
87
+ For each file in `$TEST_FILES`, verify it exists on disk:
88
+ ```bash
89
+ ls $TEST_FILES 2>&1
90
+ ```
91
+
92
+ If any file is missing, display:
93
+
94
+ ```
95
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
96
+ QGSD ► QUORUM-TEST: BLOCK (missing test files)
97
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
98
+
99
+ Missing: <list of missing files>
100
+ Fix: Re-run discovery with `find . -name "*.test.*" | grep -v node_modules`
101
+ ```
102
+
103
+ STOP — do not proceed to test execution.
104
+
105
+ Validation summary:
106
+
107
+ Display:
108
+ ```
109
+ ✓ Runner: $RUNNER
110
+ ✓ N test file(s) found.
111
+ Proceeding to test execution...
112
+ ```
113
+
114
+ **Capture execution bundle**
115
+
116
+ ```bash
117
+ node --version
118
+ ```
119
+ Store as `$NODE_VERSION`.
120
+
121
+ Execute tests using `$RUN_CMD`:
122
+ - **jest**: `npx jest --passWithNoTests $TEST_FILES 2>&1`
123
+ - **vitest**: `npx vitest run $TEST_FILES 2>&1`
124
+ - **node**: `node --test $TEST_FILES 2>&1`
125
+
126
+ Append `echo "EXIT:$?"` to capture exit code. Store full output as `$TEST_OUTPUT`. Extract exit code from the `EXIT:N` line at the end.
127
+
128
+ Read the full source of every file in `$TEST_FILES`. Store as `$TEST_SOURCES` — a combined block with filename headers:
129
+
130
+ ```
131
+ === hooks/qgsd-stop.test.js ===
132
+ <full source>
133
+
134
+ === hooks/config-loader.test.js ===
135
+ <full source>
136
+ ```
137
+
138
+ When reading each test source file:
139
+ - If the file content is empty: include `[WARN] empty source: <filename>` in place of content
140
+ - If the Read tool returns an error: include `[ERROR] read failed: <filename> — <reason>` in place of content
141
+
142
+ This lets quorum workers see exactly what happened per file rather than silently receiving an incomplete bundle.
143
+
144
+ **Immediate BLOCK if exit code is non-zero**
145
+
146
+ If exit code is non-zero, stop immediately and display:
147
+
148
+ ```
149
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
150
+ QGSD ► QUORUM-TEST: BLOCK (test infrastructure failure)
151
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
152
+
153
+ Tests did not run cleanly (exit code: N).
154
+ Fix the infrastructure failure before requesting quorum review.
155
+
156
+ <relevant excerpt from $TEST_OUTPUT>
157
+ ```
158
+
159
+ Do NOT invoke quorum workers. Stop here.
160
+
161
+ **Assemble bundle**
162
+
163
+ Compose `$BUNDLE`:
164
+
165
+ ```
166
+ NODE VERSION: $NODE_VERSION
167
+ TEST FILES: $TEST_FILES
168
+ EXIT CODE: 0
169
+
170
+ === TEST OUTPUT ===
171
+ $TEST_OUTPUT
172
+
173
+ === TEST SOURCES ===
174
+ $TEST_SOURCES
175
+ ```
176
+
177
+ **Dispatch parallel quorum workers**
178
+
179
+ Display:
180
+ ```
181
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
182
+ QGSD ► QUORUM-TEST: Dispatching workers...
183
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
184
+ ```
185
+
186
+ Dispatch all four workers as parallel Task calls (Task subagents are isolated subprocesses — a failing Task does not propagate to sibling Tasks, so this is safe under CLAUDE.md R3.2 which restricts direct sibling MCP calls):
187
+
188
+ Worker prompt template for each:
189
+ ```
190
+ You are a skeptical test reviewer for the QGSD project.
191
+
192
+ <bundle>
193
+ $BUNDLE
194
+ </bundle>
195
+
196
+ Evaluate this test execution bundle.
197
+ Return ONLY:
198
+
199
+ verdict: PASS | BLOCK | REVIEW-NEEDED
200
+ concerns:
201
+ - <most-impactful concern first, or "none" if no concerns>
202
+ - <second concern if applicable, or "none" if only one concern>
203
+
204
+ Your job is NOT to confirm the pass. Read the assertion code and ask: if someone changed the implementation in a meaningful way, would this test catch it? Look for swallowed exceptions, trivially true assertions, mocked internals that bypass real logic.
205
+
206
+ If the bundle contains no test source code, return:
207
+ verdict: REVIEW-NEEDED
208
+ concerns:
209
+ - Bundle missing test sources — cannot verify assertion quality
210
+ ```
211
+
212
+ Dispatch (each call in a single parallel message — Task subagents are isolated subprocesses; a failing Task does not propagate to co-submitted Tasks, unlike direct sibling MCP calls):
213
+ - `Task(subagent_type="general-purpose", prompt="Call mcp__gemini-cli-1__gemini with the following prompt. Pass the full literal text of the bundle inline — do not summarize or truncate: [full worker prompt with $BUNDLE inlined verbatim]")`
214
+ - `Task(subagent_type="general-purpose", prompt="Call mcp__opencode-1__opencode with the following prompt. Pass the full literal text of the bundle inline — do not summarize or truncate: [full worker prompt with $BUNDLE inlined verbatim]")`
215
+ - `Task(subagent_type="general-purpose", prompt="Call mcp__copilot-1__ask with the following prompt. Pass the full literal text of the bundle inline — do not summarize or truncate: [full worker prompt with $BUNDLE inlined verbatim]")`
216
+ - `Task(subagent_type="general-purpose", prompt="Call mcp__codex-cli-1__review with the following prompt. Pass the full literal text of the bundle inline — do not summarize or truncate: [full worker prompt with $BUNDLE inlined verbatim]")`
217
+
218
+ Note: `agents/qgsd-quorum-test-worker.md` defines this same role and output format and can be invoked directly with a bundle as `$ARGUMENTS`. The parallel Task dispatch above is used when targeting specific external models (Gemini, OpenCode, Copilot, Codex) rather than a single agent.
219
+
220
+ **Collect verdicts and render table**
221
+
222
+ Parse each worker response for `verdict:` and `concerns:` lines.
223
+ When parsing concerns: if a bullet reads `none`, treat it as absent and display `—` in the table.
224
+
225
+ If a worker errored or returned unparseable output, mark as `UNAVAIL`.
226
+
227
+ Determine consensus:
228
+ - All available models PASS → consensus `PASS`
229
+ - Any available model BLOCK → consensus `BLOCK`
230
+ - All available models REVIEW-NEEDED (no PASS, no BLOCK) → consensus `REVIEW-NEEDED`
231
+ - Mixed PASS/REVIEW → consensus `REVIEW-NEEDED`
232
+ - All UNAVAIL → stop: "All quorum models unavailable — cannot evaluate."
233
+
234
+ Display:
235
+
236
+ ```
237
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
238
+ QGSD ► QUORUM-TEST RESULTS
239
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
240
+
241
+ ┌──────────────┬──────────────────┬─────────────────────────────────────┐
242
+ │ Model │ Verdict │ Concerns │
243
+ ├──────────────┼──────────────────┼─────────────────────────────────────┤
244
+ │ Gemini │ [verdict] │ [first concern or —] │
245
+ │ OpenCode │ [verdict] │ [first concern or —] │
246
+ │ Copilot │ [verdict] │ [first concern or —] │
247
+ │ Codex │ [verdict] │ [first concern or —] │
248
+ ├──────────────┼──────────────────┼─────────────────────────────────────┤
249
+ │ CONSENSUS │ [consensus] │ [N PASS, N BLOCK, N UNAVAIL] │
250
+ └──────────────┴──────────────────┴─────────────────────────────────────┘
251
+ ```
252
+
253
+ If any model has multiple concerns, list them below the table.
254
+
255
+ **Save artifact**
256
+
257
+ Write `.planning/quick/quorum-test-latest.md`:
258
+
259
+ ```markdown
260
+ # quorum-test artifact
261
+ date: [ISO timestamp]
262
+ files: $TEST_FILES
263
+ exit_code: 0
264
+
265
+ ## verdict
266
+ [consensus verdict]
267
+
268
+ ## worker verdicts
269
+ [table as text]
270
+
271
+ ## execution bundle
272
+ [full $BUNDLE]
273
+ ```
274
+
275
+ </process>