@nforma.ai/nforma 0.2.1 → 0.29.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 (193) hide show
  1. package/README.md +2 -2
  2. package/agents/{qgsd-codebase-mapper.md → nf-codebase-mapper.md} +1 -1
  3. package/agents/{qgsd-debugger.md → nf-debugger.md} +3 -3
  4. package/agents/{qgsd-executor.md → nf-executor.md} +14 -14
  5. package/agents/{qgsd-integration-checker.md → nf-integration-checker.md} +1 -1
  6. package/agents/{qgsd-phase-researcher.md → nf-phase-researcher.md} +6 -6
  7. package/agents/{qgsd-plan-checker.md → nf-plan-checker.md} +9 -9
  8. package/agents/{qgsd-planner.md → nf-planner.md} +9 -9
  9. package/agents/{qgsd-project-researcher.md → nf-project-researcher.md} +2 -2
  10. package/agents/{qgsd-quorum-orchestrator.md → nf-quorum-orchestrator.md} +33 -33
  11. package/agents/{qgsd-quorum-slot-worker.md → nf-quorum-slot-worker.md} +3 -3
  12. package/agents/{qgsd-quorum-synthesizer.md → nf-quorum-synthesizer.md} +3 -3
  13. package/agents/{qgsd-quorum-test-worker.md → nf-quorum-test-worker.md} +1 -1
  14. package/agents/{qgsd-quorum-worker.md → nf-quorum-worker.md} +6 -6
  15. package/agents/{qgsd-research-synthesizer.md → nf-research-synthesizer.md} +5 -5
  16. package/agents/{qgsd-roadmapper.md → nf-roadmapper.md} +3 -3
  17. package/agents/{qgsd-verifier.md → nf-verifier.md} +8 -8
  18. package/bin/accept-debug-invariant.cjs +2 -2
  19. package/bin/account-manager.cjs +10 -10
  20. package/bin/aggregate-requirements.cjs +1 -1
  21. package/bin/analyze-assumptions.cjs +3 -3
  22. package/bin/analyze-state-space.cjs +14 -14
  23. package/bin/assumption-register.cjs +146 -0
  24. package/bin/attribute-trace-divergence.cjs +1 -1
  25. package/bin/auth-drivers/gh-cli.cjs +1 -1
  26. package/bin/auth-drivers/pool.cjs +1 -1
  27. package/bin/autoClosePtoF.cjs +3 -3
  28. package/bin/budget-tracker.cjs +77 -0
  29. package/bin/build-layer-manifest.cjs +153 -0
  30. package/bin/call-quorum-slot.cjs +3 -3
  31. package/bin/ccr-secure-config.cjs +5 -5
  32. package/bin/check-bundled-sdks.cjs +1 -1
  33. package/bin/check-mcp-health.cjs +1 -1
  34. package/bin/check-provider-health.cjs +6 -6
  35. package/bin/check-spec-sync.cjs +26 -26
  36. package/bin/check-trace-schema-drift.cjs +5 -5
  37. package/bin/conformance-schema.cjs +2 -2
  38. package/bin/cross-layer-dashboard.cjs +297 -0
  39. package/bin/design-impact.cjs +377 -0
  40. package/bin/detect-coverage-gaps.cjs +7 -7
  41. package/bin/failure-mode-catalog.cjs +227 -0
  42. package/bin/failure-taxonomy.cjs +177 -0
  43. package/bin/formal-scope-scan.cjs +179 -0
  44. package/bin/gate-a-grounding.cjs +334 -0
  45. package/bin/gate-b-abstraction.cjs +243 -0
  46. package/bin/gate-c-validation.cjs +166 -0
  47. package/bin/generate-formal-specs.cjs +17 -17
  48. package/bin/generate-petri-net.cjs +3 -3
  49. package/bin/generate-tla-cfg.cjs +5 -5
  50. package/bin/git-heatmap.cjs +571 -0
  51. package/bin/harness-diagnostic.cjs +326 -0
  52. package/bin/hazard-model.cjs +261 -0
  53. package/bin/install-formal-tools.cjs +1 -1
  54. package/bin/install.js +184 -139
  55. package/bin/instrumentation-map.cjs +178 -0
  56. package/bin/invariant-catalog.cjs +437 -0
  57. package/bin/issue-classifier.cjs +2 -2
  58. package/bin/load-baseline-requirements.cjs +4 -4
  59. package/bin/manage-agents-core.cjs +32 -32
  60. package/bin/migrate-to-slots.cjs +39 -39
  61. package/bin/mismatch-register.cjs +217 -0
  62. package/bin/nForma.cjs +176 -81
  63. package/bin/{qgsd-solve.cjs → nf-solve.cjs} +327 -14
  64. package/bin/observe-config.cjs +8 -0
  65. package/bin/observe-debt-writer.cjs +1 -1
  66. package/bin/observe-handler-deps.cjs +356 -0
  67. package/bin/observe-handler-grafana.cjs +2 -17
  68. package/bin/observe-handler-internal.cjs +5 -5
  69. package/bin/observe-handler-logstash.cjs +2 -17
  70. package/bin/observe-handler-prometheus.cjs +2 -17
  71. package/bin/observe-handler-upstream.cjs +251 -0
  72. package/bin/observe-handlers.cjs +12 -33
  73. package/bin/observe-render.cjs +68 -22
  74. package/bin/observe-utils.cjs +37 -0
  75. package/bin/observed-fsm.cjs +324 -0
  76. package/bin/planning-paths.cjs +6 -0
  77. package/bin/polyrepo.cjs +1 -1
  78. package/bin/probe-quorum-slots.cjs +1 -1
  79. package/bin/promote-gate-maturity.cjs +274 -0
  80. package/bin/promote-model.cjs +1 -1
  81. package/bin/propose-debug-invariants.cjs +1 -1
  82. package/bin/quorum-cache.cjs +144 -0
  83. package/bin/quorum-consensus-gate.cjs +1 -1
  84. package/bin/quorum-preflight.cjs +89 -0
  85. package/bin/quorum-slot-dispatch.cjs +6 -6
  86. package/bin/requirements-core.cjs +1 -1
  87. package/bin/review-mcp-logs.cjs +1 -1
  88. package/bin/risk-heatmap.cjs +151 -0
  89. package/bin/run-account-manager-tlc.cjs +4 -4
  90. package/bin/run-account-pool-alloy.cjs +2 -2
  91. package/bin/run-alloy.cjs +2 -2
  92. package/bin/run-audit-alloy.cjs +2 -2
  93. package/bin/run-breaker-tlc.cjs +3 -3
  94. package/bin/run-formal-check.cjs +9 -9
  95. package/bin/run-formal-verify.cjs +30 -9
  96. package/bin/run-installer-alloy.cjs +2 -2
  97. package/bin/run-oscillation-tlc.cjs +4 -4
  98. package/bin/run-phase-tlc.cjs +1 -1
  99. package/bin/run-protocol-tlc.cjs +4 -4
  100. package/bin/run-quorum-composition-alloy.cjs +2 -2
  101. package/bin/run-sensitivity-sweep.cjs +2 -2
  102. package/bin/run-stop-hook-tlc.cjs +3 -3
  103. package/bin/run-tlc.cjs +21 -21
  104. package/bin/run-transcript-alloy.cjs +2 -2
  105. package/bin/secrets.cjs +5 -5
  106. package/bin/security-sweep.cjs +238 -0
  107. package/bin/sensitivity-report.cjs +3 -3
  108. package/bin/set-secret.cjs +5 -5
  109. package/bin/setup-telemetry-cron.sh +3 -3
  110. package/bin/stall-detector.cjs +126 -0
  111. package/bin/state-candidates.cjs +206 -0
  112. package/bin/sync-baseline-requirements.cjs +1 -1
  113. package/bin/telemetry-collector.cjs +1 -1
  114. package/bin/test-changed.cjs +111 -0
  115. package/bin/test-recipe-gen.cjs +250 -0
  116. package/bin/trace-corpus-stats.cjs +211 -0
  117. package/bin/unified-mcp-server.mjs +3 -3
  118. package/bin/update-scoreboard.cjs +1 -1
  119. package/bin/validate-memory.cjs +2 -2
  120. package/bin/validate-traces.cjs +10 -10
  121. package/bin/verify-quorum-health.cjs +66 -5
  122. package/bin/xstate-to-tla.cjs +4 -4
  123. package/bin/xstate-trace-walker.cjs +3 -3
  124. package/commands/{qgsd → nf}/add-phase.md +3 -3
  125. package/commands/{qgsd → nf}/add-requirement.md +3 -3
  126. package/commands/{qgsd → nf}/add-todo.md +3 -3
  127. package/commands/{qgsd → nf}/audit-milestone.md +4 -4
  128. package/commands/{qgsd → nf}/check-todos.md +3 -3
  129. package/commands/{qgsd → nf}/cleanup.md +3 -3
  130. package/commands/{qgsd → nf}/close-formal-gaps.md +2 -2
  131. package/commands/{qgsd → nf}/complete-milestone.md +9 -9
  132. package/commands/{qgsd → nf}/debug.md +9 -9
  133. package/commands/{qgsd → nf}/discuss-phase.md +3 -3
  134. package/commands/{qgsd → nf}/execute-phase.md +15 -15
  135. package/commands/{qgsd → nf}/fix-tests.md +3 -3
  136. package/commands/{qgsd → nf}/formal-test-sync.md +1 -1
  137. package/commands/{qgsd → nf}/health.md +3 -3
  138. package/commands/{qgsd → nf}/help.md +3 -3
  139. package/commands/{qgsd → nf}/insert-phase.md +3 -3
  140. package/commands/nf/join-discord.md +18 -0
  141. package/commands/{qgsd → nf}/list-phase-assumptions.md +2 -2
  142. package/commands/{qgsd → nf}/map-codebase.md +7 -7
  143. package/commands/{qgsd → nf}/map-requirements.md +3 -3
  144. package/commands/{qgsd → nf}/mcp-restart.md +3 -3
  145. package/commands/{qgsd → nf}/mcp-set-model.md +8 -8
  146. package/commands/{qgsd → nf}/mcp-setup.md +63 -63
  147. package/commands/{qgsd → nf}/mcp-status.md +3 -3
  148. package/commands/{qgsd → nf}/mcp-update.md +7 -7
  149. package/commands/{qgsd → nf}/new-milestone.md +8 -8
  150. package/commands/{qgsd → nf}/new-project.md +8 -8
  151. package/commands/{qgsd → nf}/observe.md +49 -16
  152. package/commands/{qgsd → nf}/pause-work.md +3 -3
  153. package/commands/{qgsd → nf}/plan-milestone-gaps.md +5 -5
  154. package/commands/{qgsd → nf}/plan-phase.md +6 -6
  155. package/commands/{qgsd → nf}/polyrepo.md +2 -2
  156. package/commands/{qgsd → nf}/progress.md +3 -3
  157. package/commands/{qgsd → nf}/queue.md +2 -2
  158. package/commands/{qgsd → nf}/quick.md +8 -8
  159. package/commands/{qgsd → nf}/quorum-test.md +10 -10
  160. package/commands/{qgsd → nf}/quorum.md +36 -86
  161. package/commands/{qgsd → nf}/reapply-patches.md +2 -2
  162. package/commands/{qgsd → nf}/remove-phase.md +3 -3
  163. package/commands/{qgsd → nf}/research-phase.md +12 -12
  164. package/commands/{qgsd → nf}/resume-work.md +3 -3
  165. package/commands/nf/review-requirements.md +31 -0
  166. package/commands/{qgsd → nf}/set-profile.md +3 -3
  167. package/commands/{qgsd → nf}/settings.md +6 -6
  168. package/commands/{qgsd → nf}/solve.md +35 -35
  169. package/commands/{qgsd → nf}/sync-baselines.md +4 -4
  170. package/commands/{qgsd → nf}/triage.md +10 -10
  171. package/commands/{qgsd → nf}/update.md +3 -3
  172. package/commands/{qgsd → nf}/verify-work.md +5 -5
  173. package/hooks/dist/config-loader.js +188 -32
  174. package/hooks/dist/conformance-schema.cjs +2 -2
  175. package/hooks/dist/gsd-context-monitor.js +118 -13
  176. package/hooks/dist/{qgsd-check-update.js → nf-check-update.js} +5 -5
  177. package/hooks/dist/{qgsd-circuit-breaker.js → nf-circuit-breaker.js} +35 -24
  178. package/hooks/dist/{qgsd-precompact.js → nf-precompact.js} +13 -13
  179. package/hooks/dist/{qgsd-prompt.js → nf-prompt.js} +110 -33
  180. package/hooks/dist/nf-session-start.js +185 -0
  181. package/hooks/dist/{qgsd-slot-correlator.js → nf-slot-correlator.js} +13 -5
  182. package/hooks/dist/{qgsd-spec-regen.js → nf-spec-regen.js} +17 -8
  183. package/hooks/dist/{qgsd-statusline.js → nf-statusline.js} +12 -3
  184. package/hooks/dist/{qgsd-stop.js → nf-stop.js} +152 -18
  185. package/hooks/dist/{qgsd-token-collector.js → nf-token-collector.js} +12 -4
  186. package/hooks/dist/unified-mcp-server.mjs +2 -2
  187. package/package.json +6 -4
  188. package/scripts/build-hooks.js +13 -6
  189. package/scripts/secret-audit.sh +1 -1
  190. package/scripts/verify-hooks-sync.cjs +90 -0
  191. package/templates/{qgsd.json → nf.json} +4 -4
  192. package/commands/qgsd/join-discord.md +0 -18
  193. package/hooks/dist/qgsd-session-start.js +0 -122
@@ -1,13 +1,13 @@
1
- <!-- DEPRECATED: This agent is superseded by qgsd-quorum-slot-worker.md as of quick-101. Do not use. The orchestrator now spawns qgsd-quorum-slot-worker for all slot calls. This file is kept for reference only. -->
1
+ <!-- DEPRECATED: This agent is superseded by nf-quorum-slot-worker.md as of quick-101. Do not use. The orchestrator now spawns nf-quorum-slot-worker for all slot calls. This file is kept for reference only. -->
2
2
  ---
3
- name: qgsd-quorum-worker
3
+ name: nf-quorum-worker
4
4
  description: Parallel quorum slot worker — spawned as a parallel Task by the orchestrator. Receives $ARGUMENTS with slot/round config, reads the repository, calls one slot via call-quorum-slot.cjs, and returns structured output.
5
5
  tools: Read, Bash, Glob, Grep
6
6
  color: blue
7
7
  ---
8
8
 
9
9
  <role>
10
- You are a QGSD quorum slot worker. You are spawned as a parallel Task by the orchestrator — one worker per active quorum slot. Your sole job is to call one slot, capture the output, and return a structured result. You do NOT update any scoreboard. You do NOT write any files.
10
+ You are a nForma quorum slot worker. You are spawned as a parallel Task by the orchestrator — one worker per active quorum slot. Your sole job is to call one slot, capture the output, and return a structured result. You do NOT update any scoreboard. You do NOT write any files.
11
11
 
12
12
  **Execution flow:**
13
13
 
@@ -20,7 +20,7 @@ You are a QGSD quorum slot worker. You are spawned as a parallel Task by the orc
20
20
  4. Run the slot call via Bash (where `slot: <slotName>` comes from $ARGUMENTS):
21
21
 
22
22
  ```bash
23
- node "$HOME/.claude/qgsd-bin/call-quorum-slot.cjs" --slot <slot> --timeout <timeout_ms> --cwd <repo_dir> <<'WORKER_PROMPT'
23
+ node "$HOME/.claude/nf-bin/call-quorum-slot.cjs" --slot <slot> --timeout <timeout_ms> --cwd <repo_dir> <<'WORKER_PROMPT'
24
24
  [constructed prompt — see Prompt Construction below]
25
25
  WORKER_PROMPT
26
26
  ```
@@ -34,7 +34,7 @@ WORKER_PROMPT
34
34
 
35
35
  Mode A prompt:
36
36
  ```
37
- QGSD Quorum — Round <round>
37
+ nForma Quorum — Round <round>
38
38
 
39
39
  Repository: <repo_dir>
40
40
 
@@ -75,7 +75,7 @@ Evaluate this question independently. Give your honest answer with reasoning. Be
75
75
 
76
76
  Mode B prompt:
77
77
  ```
78
- QGSD Quorum — Execution Review (Round <round>)
78
+ nForma Quorum — Execution Review (Round <round>)
79
79
 
80
80
  Repository: <repo_dir>
81
81
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: qgsd-research-synthesizer
2
+ name: nf-research-synthesizer
3
3
  description: Synthesizes research outputs from parallel researcher agents into SUMMARY.md. Spawned by /qgsd:new-project after 4 researcher agents complete.
4
4
  tools: Read, Write, Bash
5
5
  color: purple
@@ -27,7 +27,7 @@ If the prompt contains a `<files_to_read>` block, you MUST use the `Read` tool t
27
27
  </role>
28
28
 
29
29
  <downstream_consumer>
30
- Your SUMMARY.md is consumed by the qgsd-roadmapper agent which uses it to:
30
+ Your SUMMARY.md is consumed by the nf-roadmapper agent which uses it to:
31
31
 
32
32
  | Section | How Roadmapper Uses It |
33
33
  |---------|------------------------|
@@ -122,7 +122,7 @@ Identify gaps that couldn't be resolved and need attention during planning.
122
122
 
123
123
  ## Step 6: Write SUMMARY.md
124
124
 
125
- Use template: ~/.claude/qgsd/templates/research-project/SUMMARY.md
125
+ Use template: ~/.claude/nf/templates/research-project/SUMMARY.md
126
126
 
127
127
  Write to `.planning/research/SUMMARY.md`
128
128
 
@@ -131,7 +131,7 @@ Write to `.planning/research/SUMMARY.md`
131
131
  The 4 parallel researcher agents write files but do NOT commit. You commit everything together.
132
132
 
133
133
  ```bash
134
- node ~/.claude/qgsd/bin/gsd-tools.cjs commit "docs: complete project research" --files .planning/research/
134
+ node ~/.claude/nf/bin/gsd-tools.cjs commit "docs: complete project research" --files .planning/research/
135
135
  ```
136
136
 
137
137
  ## Step 8: Return Summary
@@ -142,7 +142,7 @@ Return brief confirmation with key points for the orchestrator.
142
142
 
143
143
  <output_format>
144
144
 
145
- Use template: ~/.claude/qgsd/templates/research-project/SUMMARY.md
145
+ Use template: ~/.claude/nf/templates/research-project/SUMMARY.md
146
146
 
147
147
  Key sections:
148
148
  - Executive Summary (2-3 paragraphs)
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: qgsd-roadmapper
2
+ name: nf-roadmapper
3
3
  description: Creates project roadmaps with phase breakdown, requirement mapping, success criteria derivation, and coverage validation. Spawned by /qgsd:new-project orchestrator.
4
4
  tools: Read, Write, Bash, Glob, Grep
5
5
  color: purple
@@ -328,11 +328,11 @@ After roadmap creation, REQUIREMENTS.md gets updated with phase mappings:
328
328
  | 2. Name | 0/2 | Not started | - |
329
329
  ```
330
330
 
331
- Reference full template: `~/.claude/qgsd/templates/roadmap.md`
331
+ Reference full template: `~/.claude/nf/templates/roadmap.md`
332
332
 
333
333
  ## STATE.md Structure
334
334
 
335
- Use template from `~/.claude/qgsd/templates/state.md`.
335
+ Use template from `~/.claude/nf/templates/state.md`.
336
336
 
337
337
  Key sections:
338
338
  - Project Reference (core value, current focus)
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: qgsd-verifier
2
+ name: nf-verifier
3
3
  description: Verifies phase goal achievement through goal-backward analysis. Checks codebase delivers what phase promised, not just that tasks completed. Creates VERIFICATION.md report.
4
4
  tools: Read, Write, Bash, Grep, Glob
5
5
  color: green
@@ -57,7 +57,7 @@ Set `is_re_verification = false`, proceed with Step 1.
57
57
  ```bash
58
58
  ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null
59
59
  ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null
60
- node ~/.claude/qgsd/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM"
60
+ node ~/.claude/nf/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM"
61
61
  grep -E "^| $PHASE_NUM" .planning/REQUIREMENTS.md 2>/dev/null
62
62
  ```
63
63
 
@@ -94,7 +94,7 @@ must_haves:
94
94
  If no must_haves in frontmatter, check for Success Criteria:
95
95
 
96
96
  ```bash
97
- PHASE_DATA=$(node ~/.claude/qgsd/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM" --raw)
97
+ PHASE_DATA=$(node ~/.claude/nf/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM" --raw)
98
98
  ```
99
99
 
100
100
  Parse the `success_criteria` array from the JSON output. If non-empty:
@@ -137,7 +137,7 @@ For each truth:
137
137
  Use gsd-tools for artifact verification against must_haves in PLAN frontmatter:
138
138
 
139
139
  ```bash
140
- ARTIFACT_RESULT=$(node ~/.claude/qgsd/bin/gsd-tools.cjs verify artifacts "$PLAN_PATH")
140
+ ARTIFACT_RESULT=$(node ~/.claude/nf/bin/gsd-tools.cjs verify artifacts "$PLAN_PATH")
141
141
  ```
142
142
 
143
143
  Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
@@ -186,7 +186,7 @@ Key links are critical connections. If broken, the goal fails even with all arti
186
186
  Use gsd-tools for key link verification against must_haves in PLAN frontmatter:
187
187
 
188
188
  ```bash
189
- LINKS_RESULT=$(node ~/.claude/qgsd/bin/gsd-tools.cjs verify key-links "$PLAN_PATH")
189
+ LINKS_RESULT=$(node ~/.claude/nf/bin/gsd-tools.cjs verify key-links "$PLAN_PATH")
190
190
  ```
191
191
 
192
192
  Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
@@ -268,12 +268,12 @@ Identify files modified in this phase from SUMMARY.md key-files section, or extr
268
268
 
269
269
  ```bash
270
270
  # Option 1: Extract from SUMMARY frontmatter
271
- SUMMARY_FILES=$(node ~/.claude/qgsd/bin/gsd-tools.cjs summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
271
+ SUMMARY_FILES=$(node ~/.claude/nf/bin/gsd-tools.cjs summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
272
272
 
273
273
  # Option 2: Verify commits exist (if commit hashes documented)
274
274
  COMMIT_HASHES=$(grep -oE "[a-f0-9]{7,40}" "$PHASE_DIR"/*-SUMMARY.md | head -10)
275
275
  if [ -n "$COMMIT_HASHES" ]; then
276
- COMMITS_VALID=$(node ~/.claude/qgsd/bin/gsd-tools.cjs verify commits $COMMIT_HASHES)
276
+ COMMITS_VALID=$(node ~/.claude/nf/bin/gsd-tools.cjs verify commits $COMMIT_HASHES)
277
277
  fi
278
278
 
279
279
  # Fallback: grep for files
@@ -502,7 +502,7 @@ Omit this section entirely.
502
502
  ---
503
503
 
504
504
  _Verified: {timestamp}_
505
- _Verifier: Claude (qgsd-verifier)_
505
+ _Verifier: Claude (nf-verifier)_
506
506
  ```
507
507
 
508
508
  ## Return to Orchestrator
@@ -4,7 +4,7 @@
4
4
  // Debug invariant write path (ARCH-03): writes a PROPERTY definition directly
5
5
  // to a canonical .planning/formal/tla/ spec with full provenance tracking.
6
6
  //
7
- // When /qgsd:debug accepts a new invariant candidate, this script writes it to
7
+ // When /nf:debug accepts a new invariant candidate, this script writes it to
8
8
  // the canonical spec and records update_source=debug + session_id in model-registry.json.
9
9
  //
10
10
  // Usage:
@@ -31,7 +31,7 @@ function findProjectRoot(startPath) {
31
31
  if (parent === current) break; // filesystem root
32
32
  current = parent;
33
33
  }
34
- return path.join(__dirname, '..'); // fallback to QGSD project root
34
+ return path.join(__dirname, '..'); // fallback to nForma project root
35
35
  }
36
36
 
37
37
  // ── Parse CLI arguments ───────────────────────────────────────────────────────
@@ -2,11 +2,11 @@
2
2
  'use strict';
3
3
 
4
4
  /**
5
- * account-manager.cjs — OAuth account pool manager for QGSD providers
5
+ * account-manager.cjs — OAuth account pool manager for nForma providers
6
6
  *
7
7
  * Manages multiple OAuth credentials for providers with oauth_rotation config.
8
8
  * The implementation is a state machine that directly mirrors
9
- * .planning/formal/tla/QGSDAccountManager.tla — each TLA+ action is one FSM event.
9
+ * .planning/formal/tla/NFAccountManager.tla — each TLA+ action is one FSM event.
10
10
  *
11
11
  * Usage:
12
12
  * node bin/account-manager.cjs add --login [--name alias] [--provider gemini-1]
@@ -19,7 +19,7 @@
19
19
  * Credential layout (configurable via oauth_rotation in providers.json):
20
20
  * active_file — ~/.gemini/oauth_creds.json (the live credential Gemini CLI reads)
21
21
  * creds_dir — ~/.gemini/accounts/ (pool: one .json per account)
22
- * active_ptr — ~/.gemini/accounts/.qgsd-active (sidecar: name of active account)
22
+ * active_ptr — ~/.gemini/accounts/.nf-active (sidecar: name of active account)
23
23
  */
24
24
 
25
25
  const fs = require('fs');
@@ -27,7 +27,7 @@ const path = require('path');
27
27
  const os = require('os');
28
28
  const { spawn } = require('child_process');
29
29
 
30
- // ─── FSM states and events (mirrors QGSDAccountManager.tla) ──────────────────
30
+ // ─── FSM states and events (mirrors NFAccountManager.tla) ──────────────────
31
31
 
32
32
  const S = Object.freeze({
33
33
  IDLE: 'IDLE',
@@ -53,7 +53,7 @@ const E = Object.freeze({
53
53
  RESET: 'RESET',
54
54
  });
55
55
 
56
- // Transition table derived from QGSDAccountManager.tla Next relation.
56
+ // Transition table derived from NFAccountManager.tla Next relation.
57
57
  // TRANSITIONS[currentState][event] = nextState
58
58
  const TRANSITIONS = {
59
59
  [S.IDLE]: {
@@ -115,7 +115,7 @@ function expandHome(p) {
115
115
  function findProviders() {
116
116
  const search = [
117
117
  path.join(__dirname, 'providers.json'),
118
- path.join(os.homedir(), '.claude', 'qgsd-bin', 'providers.json'),
118
+ path.join(os.homedir(), '.claude', 'nf-bin', 'providers.json'),
119
119
  ];
120
120
  try {
121
121
  const cfg = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude.json'), 'utf8'));
@@ -184,7 +184,7 @@ function getActiveFile(provider) {
184
184
  // Sidecar pointer file — stores just the account name of the current active.
185
185
  // Avoids content-diffing which breaks when tokens are silently refreshed.
186
186
  function getActivePtr(credsDir) {
187
- return path.join(credsDir, '.qgsd-active');
187
+ return path.join(credsDir, '.nf-active');
188
188
  }
189
189
 
190
190
  function listPool(credsDir) {
@@ -402,7 +402,7 @@ const C = {
402
402
 
403
403
 
404
404
  function printAccountsHeader(provider, pool, active) {
405
- const tag = `QGSD · Accounts · ${provider.name} · ${provider.display_provider ?? ''}`;
405
+ const tag = `nForma · Accounts · ${provider.name} · ${provider.display_provider ?? ''}`;
406
406
  const border = '─'.repeat(tag.length + 4);
407
407
  console.log('');
408
408
  console.log(` ${C.cyan}╭${border}╮${C.reset}`);
@@ -657,11 +657,11 @@ function usage(prefix = 'node bin/account-manager.cjs') {
657
657
  ' --login Spawn auth login inline; auto-detect email from id_token',
658
658
  ' --name <email> Account name/email (overrides auto-detection)',
659
659
  '',
660
- 'Formal spec: .planning/formal/tla/QGSDAccountManager.tla',
660
+ 'Formal spec: .planning/formal/tla/NFAccountManager.tla',
661
661
  ].join('\n'));
662
662
  }
663
663
 
664
- // ─── Exported entry point (called by qgsd.cjs) ─────────────────────────
664
+ // ─── Exported entry point (called by nf.cjs) ─────────────────────────
665
665
 
666
666
  async function run(argv, usagePrefix) {
667
667
  const getArg = (f) => { const i = argv.indexOf(f); return i !== -1 && argv[i + 1] ? argv[i + 1] : null; };
@@ -68,7 +68,7 @@ function parseTraceability(content) {
68
68
  }
69
69
 
70
70
  // Extract milestone from document title
71
- // Matches: # Requirements: QGSD vX.XX ... or similar
71
+ // Matches: # Requirements: nForma vX.XX ... or similar
72
72
  function extractMilestone(content) {
73
73
  const match = content.match(/#\s+Requirements:.*?(v[\d.]+)/);
74
74
  return match ? match[1] : 'unknown';
@@ -511,13 +511,13 @@ function generateGapReport(crossRefResults) {
511
511
  const partial = crossRefResults.filter(a => a.coverage === 'partial').length;
512
512
  const uncovered = crossRefResults.filter(a => a.coverage === 'uncovered').length;
513
513
 
514
- // Generate metric names with qgsd_ prefix and collision detection
514
+ // Generate metric names with nf_ prefix and collision detection
515
515
  const metricNameCounts = new Map();
516
516
  const gaps = crossRefResults
517
517
  .filter(a => a.coverage !== 'covered')
518
518
  .map(a => {
519
- // Generate canonical metric name: qgsd_ + lowercase + replace non-alnum with _
520
- const baseName = 'qgsd_' + a.name.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
519
+ // Generate canonical metric name: nf_ + lowercase + replace non-alnum with _
520
+ const baseName = 'nf_' + a.name.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
521
521
  // Track for collision detection
522
522
  const count = metricNameCounts.get(baseName) || 0;
523
523
  metricNameCounts.set(baseName, count + 1);
@@ -59,23 +59,23 @@ const MERGE_BUDGET = {
59
59
 
60
60
  // ── CFG → TLA module mapping ────────────────────────────────────────────────
61
61
  // Reverse map: cfg base name (without .cfg) → TLA module name
62
- // Needed because cfg naming is inconsistent (MCbreaker vs MCQGSDQuorum etc.)
62
+ // Needed because cfg naming is inconsistent (MCbreaker vs MCNFQuorum etc.)
63
63
 
64
64
  const CFG_TO_MODULE = {
65
- 'MCbreaker': 'QGSDCircuitBreaker',
66
- 'MCoscillation': 'QGSDOscillation',
67
- 'MCconvergence': 'QGSDConvergence',
68
- 'MCdeliberation': 'QGSDDeliberation',
69
- 'MCprefilter': 'QGSDPreFilter',
70
- 'MCsafety': 'QGSDQuorum',
71
- 'MCliveness': 'QGSDQuorum',
72
- 'MCQGSDQuorum': 'QGSDQuorum_xstate',
73
- 'MCaccount-manager': 'QGSDAccountManager',
74
- 'MCMCPEnv': 'QGSDMCPEnv',
65
+ 'MCbreaker': 'NFCircuitBreaker',
66
+ 'MCoscillation': 'NFOscillation',
67
+ 'MCconvergence': 'NFConvergence',
68
+ 'MCdeliberation': 'NFDeliberation',
69
+ 'MCprefilter': 'NFPreFilter',
70
+ 'MCsafety': 'NFQuorum',
71
+ 'MCliveness': 'NFQuorum',
72
+ 'MCNFQuorum': 'NFQuorum_xstate',
73
+ 'MCaccount-manager': 'NFAccountManager',
74
+ 'MCMCPEnv': 'NFMCPEnv',
75
75
  'MCTUINavigation': 'TUINavigation',
76
- 'MCStopHook': 'QGSDStopHook',
77
- 'MCrecruiting-safety': 'QGSDRecruiting',
78
- 'MCrecruiting-liveness': 'QGSDRecruiting',
76
+ 'MCStopHook': 'NFStopHook',
77
+ 'MCrecruiting-safety': 'NFRecruiting',
78
+ 'MCrecruiting-liveness': 'NFRecruiting',
79
79
  };
80
80
 
81
81
  // ── Parsing Utilities ───────────────────────────────────────────────────────
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * assumption-register.cjs — Parses assumption-gaps.md into a structured JSON
6
+ * register with validation status and linked L2 states.
7
+ *
8
+ * Requirements: SEM-03
9
+ *
10
+ * Usage:
11
+ * node bin/assumption-register.cjs # print summary to stdout
12
+ * node bin/assumption-register.cjs --json # print full register JSON to stdout
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const ROOT = process.env.PROJECT_ROOT || path.join(__dirname, '..');
19
+ const FORMAL = path.join(ROOT, '.planning', 'formal');
20
+ const GAPS_PATH = path.join(FORMAL, 'assumption-gaps.md');
21
+ const OUT_DIR = path.join(FORMAL, 'semantics');
22
+ const OUT_FILE = path.join(OUT_DIR, 'assumption-register.json');
23
+
24
+ const JSON_FLAG = process.argv.includes('--json');
25
+
26
+ // ── Parser ──────────────────────────────────────────────────────────────────
27
+
28
+ /**
29
+ * Parse a markdown table string into structured assumption entries.
30
+ * @param {string} content - Raw markdown content containing a pipe-delimited table
31
+ * @returns {Array} Parsed assumption entries
32
+ */
33
+ function parseMarkdownTable(content) {
34
+ const lines = content.split('\n');
35
+ const assumptions = [];
36
+ let skipped = 0;
37
+
38
+ for (const line of lines) {
39
+ // Skip non-table lines, header rows, separator rows
40
+ if (!line.startsWith('|')) continue;
41
+ if (line.includes('---')) continue;
42
+
43
+ const cells = line.split('|').map(c => c.trim()).filter(c => c !== '');
44
+ if (cells.length < 7) {
45
+ // Check if this is the header row
46
+ if (cells[0] === '#' || cells[0] === 'Metric') continue;
47
+ skipped++;
48
+ continue;
49
+ }
50
+
51
+ const numCell = cells[0];
52
+ // Skip header row
53
+ if (numCell === '#') continue;
54
+
55
+ const id = parseInt(numCell, 10);
56
+ if (isNaN(id)) {
57
+ skipped++;
58
+ continue;
59
+ }
60
+
61
+ assumptions.push({
62
+ id,
63
+ source: cells[1],
64
+ name: cells[2],
65
+ type: cells[3],
66
+ coverage: cells[4],
67
+ proposed_metric: cells[5].replace(/^`|`$/g, ''),
68
+ metric_type: cells[6],
69
+ validation_status: 'untested',
70
+ linked_l2_states: []
71
+ });
72
+ }
73
+
74
+ if (skipped > 0) {
75
+ process.stderr.write(`Warning: skipped ${skipped} malformed table lines\n`);
76
+ }
77
+
78
+ return assumptions;
79
+ }
80
+
81
+ /**
82
+ * Parse assumption-gaps.md file into structured entries.
83
+ * @param {string} gapsPath - Path to the assumption-gaps.md file
84
+ * @returns {Array} Parsed assumption entries
85
+ */
86
+ function parseAssumptionGaps(gapsPath) {
87
+ const content = fs.readFileSync(gapsPath, 'utf8');
88
+ return parseMarkdownTable(content);
89
+ }
90
+
91
+ // ── Main ────────────────────────────────────────────────────────────────────
92
+
93
+ function main() {
94
+ if (!fs.existsSync(GAPS_PATH)) {
95
+ console.error(`ERROR: assumption-gaps.md not found at ${GAPS_PATH}`);
96
+ process.exit(1);
97
+ }
98
+
99
+ const assumptions = parseAssumptionGaps(GAPS_PATH);
100
+
101
+ if (assumptions.length < 500) {
102
+ console.error(`ERROR: Only parsed ${assumptions.length} assumptions, expected >= 500`);
103
+ process.exit(1);
104
+ }
105
+
106
+ // Build summary
107
+ const byType = {};
108
+ const byCoverage = {};
109
+ for (const a of assumptions) {
110
+ byType[a.type] = (byType[a.type] || 0) + 1;
111
+ byCoverage[a.coverage] = (byCoverage[a.coverage] || 0) + 1;
112
+ }
113
+
114
+ const register = {
115
+ schema_version: '1',
116
+ generated: new Date().toISOString(),
117
+ assumptions,
118
+ summary: {
119
+ total_parsed: assumptions.length,
120
+ by_type: byType,
121
+ by_coverage: byCoverage,
122
+ by_validation_status: {
123
+ untested: assumptions.length,
124
+ validated: 0,
125
+ invalidated: 0
126
+ }
127
+ }
128
+ };
129
+
130
+ if (!fs.existsSync(OUT_DIR)) fs.mkdirSync(OUT_DIR, { recursive: true });
131
+ fs.writeFileSync(OUT_FILE, JSON.stringify(register, null, 2) + '\n');
132
+
133
+ if (JSON_FLAG) {
134
+ process.stdout.write(JSON.stringify(register, null, 2) + '\n');
135
+ } else {
136
+ console.log(`Assumption Register written to ${path.relative(ROOT, OUT_FILE)}`);
137
+ console.log(` Total parsed: ${assumptions.length}`);
138
+ console.log(` By type: ${Object.entries(byType).map(([k,v]) => `${k}=${v}`).join(' ')}`);
139
+ console.log(` By coverage: ${Object.entries(byCoverage).map(([k,v]) => `${k}=${v}`).join(' ')}`);
140
+ }
141
+ }
142
+
143
+ // Export for testing
144
+ module.exports = { parseAssumptionGaps, parseMarkdownTable };
145
+
146
+ if (require.main === module) main();
@@ -70,7 +70,7 @@ function classifyDivergence(ttrace) {
70
70
 
71
71
  const recommendation = implBugConfidence >= specBugConfidence
72
72
  ? `impl-bug: check hook implementation — context field initialization or event payload mapping`
73
- : `spec-bug: review XState guard "${failingGuard || 'unknown'}" in qgsd-workflow.machine.ts`;
73
+ : `spec-bug: review XState guard "${failingGuard || 'unknown'}" in nf-workflow.machine.ts`;
74
74
 
75
75
  return { specBugConfidence, implBugConfidence, failingGuard, recommendation, evidence };
76
76
  }
@@ -6,7 +6,7 @@
6
6
  * Accounts live in the macOS/system keychain managed by gh.
7
7
  * There is no credential file to copy — all operations delegate to gh.
8
8
  * This is the single source of truth for gh auth status parsing,
9
- * replacing duplicated regex in qgsd.cjs and gh-account-rotate.cjs.
9
+ * replacing duplicated regex in nf.cjs and gh-account-rotate.cjs.
10
10
  *
11
11
  * Applies to: copilot-1
12
12
  *
@@ -19,7 +19,7 @@ const acm = require('../account-manager.cjs');
19
19
 
20
20
  /**
21
21
  * list(provider) → [{ name, active }]
22
- * Reads the pool directory and the .qgsd-active pointer — no subprocess.
22
+ * Reads the pool directory and the .nf-active pointer — no subprocess.
23
23
  */
24
24
  function list(provider) {
25
25
  const credsDir = acm.getCredsDir(provider);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * P->F auto-close remediation dispatch
3
- * Dispatches parameter updates via /qgsd:quick for drift entries,
3
+ * Dispatches parameter updates via /nf:quick for drift entries,
4
4
  * flags investigation for issue/invariant entries.
5
5
  *
6
6
  * Requirements: PF-04, PF-05
@@ -63,11 +63,11 @@ function autoClosePtoF(residual, options = {}) {
63
63
  const isParameter = entry.issue_type === 'drift' && isNumericFn(entry.formal_ref, { specDir });
64
64
 
65
65
  if (isParameter) {
66
- // Parameter update track: dispatch /qgsd:quick
66
+ // Parameter update track: dispatch /nf:quick
67
67
  let dispatchOk = false;
68
68
 
69
69
  if (spawnFn) {
70
- const result = spawnFn('qgsd-quick.cjs', [
70
+ const result = spawnFn('nf-quick.cjs', [
71
71
  `Update formal parameter ${entry.formal_ref} to match production`,
72
72
  `Production measurement: ${entry.meta?.measured_value}`,
73
73
  `Current formal: ${div.expected}`,
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+ // bin/budget-tracker.cjs
3
+ // Token budget calculation, profile downgrade logic, and subscription slot exclusion.
4
+ // Uses only node:fs, node:path. No external dependencies.
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ // Profile downgrade sequence: quality -> balanced -> budget -> null (minimum)
10
+ const DOWNGRADE_CHAIN = { quality: 'balanced', balanced: 'budget', budget: null };
11
+
12
+ /**
13
+ * Compute budget status from context window usage percentage.
14
+ * @param {number} usedPct - Context window used percentage (0-100).
15
+ * @param {object} budgetConfig - budget config section from nf.json.
16
+ * @param {object} agentConfig - agent_config section from nf.json (unused for now, reserved for sub exclusion).
17
+ * @returns {object} Budget status object.
18
+ */
19
+ function computeBudgetStatus(usedPct, budgetConfig, agentConfig) {
20
+ if (!budgetConfig || budgetConfig.session_limit_tokens == null) {
21
+ return { active: false };
22
+ }
23
+
24
+ const estimatedTokens = Math.round((usedPct / 100) * 200000);
25
+ const budgetUsedPct = Math.round((estimatedTokens / budgetConfig.session_limit_tokens) * 100);
26
+
27
+ return {
28
+ active: true,
29
+ estimatedTokens,
30
+ budgetUsedPct,
31
+ shouldWarn: budgetUsedPct >= (budgetConfig.warn_pct || 60),
32
+ shouldDowngrade: budgetUsedPct >= (budgetConfig.downgrade_pct || 85),
33
+ };
34
+ }
35
+
36
+ /**
37
+ * Trigger a model profile downgrade by writing to .planning/config.json.
38
+ * @param {string} cwd - Project working directory.
39
+ * @returns {object} Downgrade result.
40
+ */
41
+ function triggerProfileDowngrade(cwd) {
42
+ try {
43
+ const configPath = path.join(cwd, '.planning', 'config.json');
44
+ let config = {};
45
+ if (fs.existsSync(configPath)) {
46
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
47
+ }
48
+ const current = config.model_profile || 'balanced';
49
+ const next = DOWNGRADE_CHAIN[current];
50
+ if (next === undefined || next === null) {
51
+ return { downgraded: false, current };
52
+ }
53
+ config.model_profile = next;
54
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
55
+ return { downgraded: true, from: current, to: next };
56
+ } catch (e) {
57
+ return { downgraded: false, error: e.message };
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Format a budget warning message for additionalContext injection.
63
+ * @param {object} status - Output from computeBudgetStatus.
64
+ * @param {object|null} downgradeResult - Output from triggerProfileDowngrade (or null).
65
+ * @returns {string} Warning message.
66
+ */
67
+ function formatBudgetWarning(status, downgradeResult) {
68
+ if (status.shouldDowngrade && downgradeResult && downgradeResult.downgraded) {
69
+ return `BUDGET ALERT: Context at ${status.budgetUsedPct}% of token budget. Model profile downgraded from '${downgradeResult.from}' to '${downgradeResult.to}'. Consider running /compact.`;
70
+ }
71
+ if (status.shouldWarn) {
72
+ return `BUDGET WARNING: Context at ${status.budgetUsedPct}% of token budget (${status.estimatedTokens} estimated tokens of ${status.active ? (status.budgetUsedPct > 0 ? Math.round(status.estimatedTokens * 100 / status.budgetUsedPct) : 0) : 0} limit). Monitor usage and consider /compact at next clean boundary.`;
73
+ }
74
+ return '';
75
+ }
76
+
77
+ module.exports = { DOWNGRADE_CHAIN, computeBudgetStatus, triggerProfileDowngrade, formatBudgetWarning };