@nforma.ai/nforma 0.2.1 → 0.28.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.
- package/README.md +2 -2
- package/agents/{qgsd-codebase-mapper.md → nf-codebase-mapper.md} +1 -1
- package/agents/{qgsd-debugger.md → nf-debugger.md} +3 -3
- package/agents/{qgsd-executor.md → nf-executor.md} +14 -14
- package/agents/{qgsd-integration-checker.md → nf-integration-checker.md} +1 -1
- package/agents/{qgsd-phase-researcher.md → nf-phase-researcher.md} +6 -6
- package/agents/{qgsd-plan-checker.md → nf-plan-checker.md} +9 -9
- package/agents/{qgsd-planner.md → nf-planner.md} +9 -9
- package/agents/{qgsd-project-researcher.md → nf-project-researcher.md} +2 -2
- package/agents/{qgsd-quorum-orchestrator.md → nf-quorum-orchestrator.md} +33 -33
- package/agents/{qgsd-quorum-slot-worker.md → nf-quorum-slot-worker.md} +3 -3
- package/agents/{qgsd-quorum-synthesizer.md → nf-quorum-synthesizer.md} +3 -3
- package/agents/{qgsd-quorum-test-worker.md → nf-quorum-test-worker.md} +1 -1
- package/agents/{qgsd-quorum-worker.md → nf-quorum-worker.md} +6 -6
- package/agents/{qgsd-research-synthesizer.md → nf-research-synthesizer.md} +5 -5
- package/agents/{qgsd-roadmapper.md → nf-roadmapper.md} +3 -3
- package/agents/{qgsd-verifier.md → nf-verifier.md} +8 -8
- package/bin/accept-debug-invariant.cjs +2 -2
- package/bin/account-manager.cjs +10 -10
- package/bin/aggregate-requirements.cjs +1 -1
- package/bin/analyze-assumptions.cjs +3 -3
- package/bin/analyze-state-space.cjs +14 -14
- package/bin/assumption-register.cjs +146 -0
- package/bin/attribute-trace-divergence.cjs +1 -1
- package/bin/auth-drivers/gh-cli.cjs +1 -1
- package/bin/auth-drivers/pool.cjs +1 -1
- package/bin/autoClosePtoF.cjs +3 -3
- package/bin/budget-tracker.cjs +77 -0
- package/bin/build-layer-manifest.cjs +153 -0
- package/bin/call-quorum-slot.cjs +3 -3
- package/bin/ccr-secure-config.cjs +5 -5
- package/bin/check-bundled-sdks.cjs +1 -1
- package/bin/check-mcp-health.cjs +1 -1
- package/bin/check-provider-health.cjs +6 -6
- package/bin/check-spec-sync.cjs +26 -26
- package/bin/check-trace-schema-drift.cjs +5 -5
- package/bin/conformance-schema.cjs +2 -2
- package/bin/cross-layer-dashboard.cjs +297 -0
- package/bin/design-impact.cjs +377 -0
- package/bin/detect-coverage-gaps.cjs +7 -7
- package/bin/failure-mode-catalog.cjs +227 -0
- package/bin/failure-taxonomy.cjs +177 -0
- package/bin/formal-scope-scan.cjs +179 -0
- package/bin/gate-a-grounding.cjs +334 -0
- package/bin/gate-b-abstraction.cjs +243 -0
- package/bin/gate-c-validation.cjs +166 -0
- package/bin/generate-formal-specs.cjs +17 -17
- package/bin/generate-petri-net.cjs +3 -3
- package/bin/generate-tla-cfg.cjs +5 -5
- package/bin/git-heatmap.cjs +571 -0
- package/bin/harness-diagnostic.cjs +326 -0
- package/bin/hazard-model.cjs +261 -0
- package/bin/install-formal-tools.cjs +1 -1
- package/bin/install.js +184 -139
- package/bin/instrumentation-map.cjs +178 -0
- package/bin/invariant-catalog.cjs +437 -0
- package/bin/issue-classifier.cjs +2 -2
- package/bin/load-baseline-requirements.cjs +4 -4
- package/bin/manage-agents-core.cjs +32 -32
- package/bin/migrate-to-slots.cjs +39 -39
- package/bin/mismatch-register.cjs +217 -0
- package/bin/nForma.cjs +176 -81
- package/bin/{qgsd-solve.cjs → nf-solve.cjs} +327 -14
- package/bin/observe-config.cjs +8 -0
- package/bin/observe-debt-writer.cjs +1 -1
- package/bin/observe-handler-deps.cjs +356 -0
- package/bin/observe-handler-grafana.cjs +2 -17
- package/bin/observe-handler-internal.cjs +5 -5
- package/bin/observe-handler-logstash.cjs +2 -17
- package/bin/observe-handler-prometheus.cjs +2 -17
- package/bin/observe-handler-upstream.cjs +251 -0
- package/bin/observe-handlers.cjs +12 -33
- package/bin/observe-render.cjs +68 -22
- package/bin/observe-utils.cjs +37 -0
- package/bin/observed-fsm.cjs +324 -0
- package/bin/planning-paths.cjs +6 -0
- package/bin/polyrepo.cjs +1 -1
- package/bin/probe-quorum-slots.cjs +1 -1
- package/bin/promote-gate-maturity.cjs +274 -0
- package/bin/promote-model.cjs +1 -1
- package/bin/propose-debug-invariants.cjs +1 -1
- package/bin/quorum-cache.cjs +144 -0
- package/bin/quorum-consensus-gate.cjs +1 -1
- package/bin/quorum-slot-dispatch.cjs +6 -6
- package/bin/requirements-core.cjs +1 -1
- package/bin/review-mcp-logs.cjs +1 -1
- package/bin/risk-heatmap.cjs +151 -0
- package/bin/run-account-manager-tlc.cjs +4 -4
- package/bin/run-account-pool-alloy.cjs +2 -2
- package/bin/run-alloy.cjs +2 -2
- package/bin/run-audit-alloy.cjs +2 -2
- package/bin/run-breaker-tlc.cjs +3 -3
- package/bin/run-formal-check.cjs +9 -9
- package/bin/run-formal-verify.cjs +30 -9
- package/bin/run-installer-alloy.cjs +2 -2
- package/bin/run-oscillation-tlc.cjs +4 -4
- package/bin/run-phase-tlc.cjs +1 -1
- package/bin/run-protocol-tlc.cjs +4 -4
- package/bin/run-quorum-composition-alloy.cjs +2 -2
- package/bin/run-sensitivity-sweep.cjs +2 -2
- package/bin/run-stop-hook-tlc.cjs +3 -3
- package/bin/run-tlc.cjs +21 -21
- package/bin/run-transcript-alloy.cjs +2 -2
- package/bin/secrets.cjs +5 -5
- package/bin/security-sweep.cjs +238 -0
- package/bin/sensitivity-report.cjs +3 -3
- package/bin/set-secret.cjs +5 -5
- package/bin/setup-telemetry-cron.sh +3 -3
- package/bin/stall-detector.cjs +126 -0
- package/bin/state-candidates.cjs +206 -0
- package/bin/sync-baseline-requirements.cjs +1 -1
- package/bin/telemetry-collector.cjs +1 -1
- package/bin/test-changed.cjs +111 -0
- package/bin/test-recipe-gen.cjs +250 -0
- package/bin/trace-corpus-stats.cjs +211 -0
- package/bin/unified-mcp-server.mjs +3 -3
- package/bin/update-scoreboard.cjs +1 -1
- package/bin/validate-memory.cjs +2 -2
- package/bin/validate-traces.cjs +10 -10
- package/bin/verify-quorum-health.cjs +66 -5
- package/bin/xstate-to-tla.cjs +4 -4
- package/bin/xstate-trace-walker.cjs +3 -3
- package/commands/{qgsd → nf}/add-phase.md +3 -3
- package/commands/{qgsd → nf}/add-requirement.md +3 -3
- package/commands/{qgsd → nf}/add-todo.md +3 -3
- package/commands/{qgsd → nf}/audit-milestone.md +4 -4
- package/commands/{qgsd → nf}/check-todos.md +3 -3
- package/commands/{qgsd → nf}/cleanup.md +3 -3
- package/commands/{qgsd → nf}/close-formal-gaps.md +2 -2
- package/commands/{qgsd → nf}/complete-milestone.md +9 -9
- package/commands/{qgsd → nf}/debug.md +9 -9
- package/commands/{qgsd → nf}/discuss-phase.md +3 -3
- package/commands/{qgsd → nf}/execute-phase.md +15 -15
- package/commands/{qgsd → nf}/fix-tests.md +3 -3
- package/commands/{qgsd → nf}/formal-test-sync.md +1 -1
- package/commands/{qgsd → nf}/health.md +3 -3
- package/commands/{qgsd → nf}/help.md +3 -3
- package/commands/{qgsd → nf}/insert-phase.md +3 -3
- package/commands/nf/join-discord.md +18 -0
- package/commands/{qgsd → nf}/list-phase-assumptions.md +2 -2
- package/commands/{qgsd → nf}/map-codebase.md +7 -7
- package/commands/{qgsd → nf}/map-requirements.md +3 -3
- package/commands/{qgsd → nf}/mcp-restart.md +3 -3
- package/commands/{qgsd → nf}/mcp-set-model.md +8 -8
- package/commands/{qgsd → nf}/mcp-setup.md +63 -63
- package/commands/{qgsd → nf}/mcp-status.md +3 -3
- package/commands/{qgsd → nf}/mcp-update.md +7 -7
- package/commands/{qgsd → nf}/new-milestone.md +8 -8
- package/commands/{qgsd → nf}/new-project.md +8 -8
- package/commands/{qgsd → nf}/observe.md +49 -16
- package/commands/{qgsd → nf}/pause-work.md +3 -3
- package/commands/{qgsd → nf}/plan-milestone-gaps.md +5 -5
- package/commands/{qgsd → nf}/plan-phase.md +6 -6
- package/commands/{qgsd → nf}/polyrepo.md +2 -2
- package/commands/{qgsd → nf}/progress.md +3 -3
- package/commands/{qgsd → nf}/queue.md +2 -2
- package/commands/{qgsd → nf}/quick.md +8 -8
- package/commands/{qgsd → nf}/quorum-test.md +10 -10
- package/commands/{qgsd → nf}/quorum.md +40 -40
- package/commands/{qgsd → nf}/reapply-patches.md +2 -2
- package/commands/{qgsd → nf}/remove-phase.md +3 -3
- package/commands/{qgsd → nf}/research-phase.md +12 -12
- package/commands/{qgsd → nf}/resume-work.md +3 -3
- package/commands/nf/review-requirements.md +31 -0
- package/commands/{qgsd → nf}/set-profile.md +3 -3
- package/commands/{qgsd → nf}/settings.md +6 -6
- package/commands/{qgsd → nf}/solve.md +35 -35
- package/commands/{qgsd → nf}/sync-baselines.md +4 -4
- package/commands/{qgsd → nf}/triage.md +10 -10
- package/commands/{qgsd → nf}/update.md +3 -3
- package/commands/{qgsd → nf}/verify-work.md +5 -5
- package/hooks/dist/config-loader.js +188 -32
- package/hooks/dist/conformance-schema.cjs +2 -2
- package/hooks/dist/gsd-context-monitor.js +118 -13
- package/hooks/dist/{qgsd-check-update.js → nf-check-update.js} +5 -5
- package/hooks/dist/{qgsd-circuit-breaker.js → nf-circuit-breaker.js} +35 -24
- package/hooks/dist/nf-circuit-breaker.test.js +1002 -0
- package/hooks/dist/{qgsd-precompact.js → nf-precompact.js} +13 -13
- package/hooks/dist/nf-precompact.test.js +227 -0
- package/hooks/dist/{qgsd-prompt.js → nf-prompt.js} +110 -33
- package/hooks/dist/nf-prompt.test.js +698 -0
- package/hooks/dist/nf-session-start.js +185 -0
- package/hooks/dist/nf-session-start.test.js +354 -0
- package/hooks/dist/{qgsd-slot-correlator.js → nf-slot-correlator.js} +13 -5
- package/hooks/dist/nf-slot-correlator.test.js +85 -0
- package/hooks/dist/{qgsd-spec-regen.js → nf-spec-regen.js} +17 -8
- package/hooks/dist/nf-spec-regen.test.js +73 -0
- package/hooks/dist/{qgsd-statusline.js → nf-statusline.js} +12 -3
- package/hooks/dist/nf-statusline.test.js +157 -0
- package/hooks/dist/{qgsd-stop.js → nf-stop.js} +152 -18
- package/hooks/dist/nf-stop.test.js +1388 -0
- package/hooks/dist/{qgsd-token-collector.js → nf-token-collector.js} +12 -4
- package/hooks/dist/nf-token-collector.test.js +262 -0
- package/hooks/dist/unified-mcp-server.mjs +2 -2
- package/package.json +4 -4
- package/scripts/build-hooks.js +13 -6
- package/scripts/secret-audit.sh +1 -1
- package/scripts/verify-hooks-sync.cjs +90 -0
- package/templates/{qgsd.json → nf.json} +4 -4
- package/commands/qgsd/join-discord.md +0 -18
- package/hooks/dist/qgsd-session-start.js +0 -122
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Answer a question using full quorum consensus (Claude + native CLI agents + all configured claude-mcp-server instances) following
|
|
2
|
+
name: nf:quorum
|
|
3
|
+
description: Answer a question using full quorum consensus (Claude + native CLI agents + all configured claude-mcp-server instances) following nForma quorum protocol. Use when no arguments provided to answer the current conversation's open question.
|
|
4
4
|
argument-hint: "[question or prompt]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -12,7 +12,7 @@ allowed-tools:
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
<objective>
|
|
15
|
-
Run a question or prompt through the full
|
|
15
|
+
Run a question or prompt through the full nForma quorum (R3 protocol): Claude + native CLI agents (Codex, Gemini, OpenCode, Copilot) + all claude-mcp-server instances configured in `~/.claude.json`.
|
|
16
16
|
|
|
17
17
|
**Two modes** based on context:
|
|
18
18
|
- **Mode A — Pure Question**: No commands required. Claude forms its own position first, then dispatches all slot-workers as parallel Tasks, deliberates to consensus.
|
|
@@ -31,7 +31,7 @@ Resolve the question to pass:
|
|
|
31
31
|
- **Priority 1** — Most recent message containing `?` without a substantive answer yet.
|
|
32
32
|
- **Priority 2** — Most recent message describing a choice/trade-off (keywords: "should we", "which approach", "option A vs", "do we", "whether to").
|
|
33
33
|
- **Priority 3** — Most recent open concern or blocker ("not sure", "concern", "blocker", "unclear", "wondering").
|
|
34
|
-
- If none found: stop with `"No open question found. Provide one explicitly: /
|
|
34
|
+
- If none found: stop with `"No open question found. Provide one explicitly: /nf:quorum <question>"`
|
|
35
35
|
|
|
36
36
|
When question is inferred, display before dispatching:
|
|
37
37
|
```
|
|
@@ -62,7 +62,7 @@ If $ARGUMENTS is empty: use the most recent open question or decision from the c
|
|
|
62
62
|
Before any model calls, run a fast HTTP probe of the underlying LLM providers:
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
node "$HOME/.claude/
|
|
65
|
+
node "$HOME/.claude/nf-bin/check-provider-health.cjs" --json
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
Parse the JSON output. Build two structures:
|
|
@@ -73,12 +73,12 @@ Parse the JSON output. Build two structures:
|
|
|
73
73
|
|
|
74
74
|
Any server with `available: false` must be marked UNAVAIL immediately — skip its health_check and inference calls entirely. This prevents hangs from unresponsive provider endpoints.
|
|
75
75
|
|
|
76
|
-
3. **`$QUORUM_ACTIVE`**: read from `~/.claude/
|
|
76
|
+
3. **`$QUORUM_ACTIVE`**: read from `~/.claude/nf.json` (project config takes precedence over global):
|
|
77
77
|
```bash
|
|
78
78
|
node -e "
|
|
79
79
|
const fs = require('fs'), os = require('os'), path = require('path');
|
|
80
|
-
const globalCfg = path.join(os.homedir(), '.claude', '
|
|
81
|
-
const projCfg = path.join(process.cwd(), '.claude', '
|
|
80
|
+
const globalCfg = path.join(os.homedir(), '.claude', 'nf.json');
|
|
81
|
+
const projCfg = path.join(process.cwd(), '.claude', 'nf.json');
|
|
82
82
|
let cfg = {};
|
|
83
83
|
for (const f of [globalCfg, projCfg]) {
|
|
84
84
|
try { Object.assign(cfg, JSON.parse(fs.readFileSync(f, 'utf8'))); } catch(_){}
|
|
@@ -96,12 +96,12 @@ A server in `$QUORUM_ACTIVE` but absent from `$CLAUDE_MCP_SERVERS` = skip silent
|
|
|
96
96
|
- Reorder the remaining working list: healthy servers first (preserving discovery order within each group).
|
|
97
97
|
- Log the final working list as: `Active slots: <slot1>, <slot2>, ...`
|
|
98
98
|
|
|
99
|
-
**max_quorum_size check:** Read `max_quorum_size` from `~/.claude/
|
|
99
|
+
**max_quorum_size check:** Read `max_quorum_size` from `~/.claude/nf.json` (project config takes precedence; default: 3 if absent):
|
|
100
100
|
```bash
|
|
101
101
|
node -e "
|
|
102
102
|
const fs = require('fs'), os = require('os'), path = require('path');
|
|
103
|
-
const globalCfg = path.join(os.homedir(), '.claude', '
|
|
104
|
-
const projCfg = path.join(process.cwd(), '.claude', '
|
|
103
|
+
const globalCfg = path.join(os.homedir(), '.claude', 'nf.json');
|
|
104
|
+
const projCfg = path.join(process.cwd(), '.claude', 'nf.json');
|
|
105
105
|
let cfg = {};
|
|
106
106
|
for (const f of [globalCfg, projCfg]) {
|
|
107
107
|
try { Object.assign(cfg, JSON.parse(fs.readFileSync(f, 'utf8'))); } catch(_){}
|
|
@@ -136,7 +136,7 @@ node -e "
|
|
|
136
136
|
const fs = require('fs'), path = require('path'), os = require('os');
|
|
137
137
|
|
|
138
138
|
const searchPaths = [
|
|
139
|
-
path.join(os.homedir(), '.claude', '
|
|
139
|
+
path.join(os.homedir(), '.claude', 'nf-bin', 'providers.json'),
|
|
140
140
|
];
|
|
141
141
|
try {
|
|
142
142
|
const cj = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude.json'), 'utf8'));
|
|
@@ -150,8 +150,8 @@ for (const p of searchPaths) {
|
|
|
150
150
|
try { providers = JSON.parse(fs.readFileSync(p, 'utf8')).providers; break; } catch(_) {}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
const globalCfg = path.join(os.homedir(), '.claude', '
|
|
154
|
-
const projCfg = path.join(process.cwd(), '.claude', '
|
|
153
|
+
const globalCfg = path.join(os.homedir(), '.claude', 'nf.json');
|
|
154
|
+
const projCfg = path.join(process.cwd(), '.claude', 'nf.json');
|
|
155
155
|
let cfg = {};
|
|
156
156
|
for (const f of [globalCfg, projCfg]) {
|
|
157
157
|
try { Object.assign(cfg, JSON.parse(fs.readFileSync(f, 'utf8'))); } catch(_) {}
|
|
@@ -178,7 +178,7 @@ Detect Claude's model ID from: `CLAUDE_MODEL` env var → `ANTHROPIC_MODEL` env
|
|
|
178
178
|
|
|
179
179
|
Run:
|
|
180
180
|
```bash
|
|
181
|
-
node "$HOME/.claude/
|
|
181
|
+
node "$HOME/.claude/nf-bin/update-scoreboard.cjs" init-team \
|
|
182
182
|
--claude-model "<claude_model_id>" \
|
|
183
183
|
--team '<TEAM_JSON>'
|
|
184
184
|
```
|
|
@@ -236,7 +236,7 @@ echo "Adaptive fan-out: risk_level=${RISK_LEVEL} → fan_out_count=${FAN_OUT_COU
|
|
|
236
236
|
|
|
237
237
|
**Apply cap — build DISPATCH_LIST:** Take the first `FAN_OUT_COUNT - 1` slots from the active working list (healthy-first order from pre-flight). This is the definitive slot cap. Call this `$DISPATCH_LIST`. All subsequent round dispatches (Round 1 and deliberation) use `$DISPATCH_LIST` — never the full working list.
|
|
238
238
|
|
|
239
|
-
> **Why here and not only in the hook:** `
|
|
239
|
+
> **Why here and not only in the hook:** `nf-prompt.js` enforces this cap via `--n` for main-session prompts. But quorum is also dispatched inline from subagents (e.g., `nf-planner` in step 8.5 of `plan-phase.md`) where no UserPromptSubmit hook fires. `quorum.md` must self-enforce the cap for all dispatch contexts.
|
|
240
240
|
|
|
241
241
|
### R6.4 Reduced-Quorum Note (FAN-05)
|
|
242
242
|
|
|
@@ -250,7 +250,7 @@ fi
|
|
|
250
250
|
# When FAN_OUT_COUNT = MAX_QUORUM_SIZE (high/absent): no note emitted.
|
|
251
251
|
```
|
|
252
252
|
|
|
253
|
-
The RISK_LEVEL variable is available downstream for use by Phase v0.18-04 Adaptive Fan-Out. The fan-out logic is now implemented in both quorum.md (above) and
|
|
253
|
+
The RISK_LEVEL variable is available downstream for use by Phase v0.18-04 Adaptive Fan-Out. The fan-out logic is now implemented in both quorum.md (above) and nf-prompt.js (which emits `--n N` for downstream ceiling verification).
|
|
254
254
|
|
|
255
255
|
---
|
|
256
256
|
|
|
@@ -267,7 +267,7 @@ Priority 2 - Pending decision: Find the most recent message that describes a cho
|
|
|
267
267
|
Priority 3 - Open concern or blocker: Find the most recent message that raises a concern, flags a risk, or states something is unclear (keywords: "not sure", "concern", "blocker", "question:", "unclear", "wondering"). Restate it as a question.
|
|
268
268
|
|
|
269
269
|
If none of the above applies: stop with:
|
|
270
|
-
"No open question found. Looked for: explicit '?' question, pending decision, or open concern in recent conversation. Provide a question explicitly: /
|
|
270
|
+
"No open question found. Looked for: explicit '?' question, pending decision, or open concern in recent conversation. Provide a question explicitly: /nf:quorum <question>"
|
|
271
271
|
|
|
272
272
|
When a question is inferred via any priority, Claude MUST display before proceeding:
|
|
273
273
|
"Using conversation context as question (Priority N - [type]):
|
|
@@ -276,7 +276,7 @@ When a question is inferred via any priority, Claude MUST display before proceed
|
|
|
276
276
|
Display:
|
|
277
277
|
```
|
|
278
278
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
279
|
-
|
|
279
|
+
nForma ► QUORUM: Round 1 — N workers dispatched
|
|
280
280
|
Active: gemini-1, opencode-1, copilot-1, codex-1
|
|
281
281
|
Fallback pool: T1 = unused slots with auth_type=sub; T2 = slots with auth_type≠sub (on UNAVAIL)
|
|
282
282
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -296,7 +296,7 @@ Store as `$CLAUDE_POSITION`.
|
|
|
296
296
|
|
|
297
297
|
### Query models (parallel — one Task per slot)
|
|
298
298
|
|
|
299
|
-
Dispatch one `Task(subagent_type="
|
|
299
|
+
Dispatch one `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, ...)` per slot in **`$DISPATCH_LIST`** (capped to `FAN_OUT_COUNT - 1` external slots) as **parallel sibling calls** in one message turn. Do NOT dispatch slots outside `$DISPATCH_LIST`. Build a YAML prompt block per the slot-worker argument spec:
|
|
300
300
|
|
|
301
301
|
```
|
|
302
302
|
slot: <slotName>
|
|
@@ -318,11 +318,11 @@ Set it to the evaluation criteria appropriate for the artifact type, e.g.:
|
|
|
318
318
|
- Audit: "This is a milestone audit. Evaluate whether the work achieves the stated milestone goals."
|
|
319
319
|
|
|
320
320
|
Example dispatch (all Tasks in one message turn):
|
|
321
|
-
- `Task(subagent_type="
|
|
322
|
-
- `Task(subagent_type="
|
|
323
|
-
- `Task(subagent_type="
|
|
324
|
-
- `Task(subagent_type="
|
|
325
|
-
- `Task(subagent_type="
|
|
321
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="gemini-1 [gemini-cli · gemini-3-pro-preview] quorum R1", prompt=<YAML block>)`
|
|
322
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="codex-1 [codex-cli · gpt-5.3-codex] quorum R1", prompt=<YAML block>)`
|
|
323
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="opencode-1 [opencode-cli · grok-code-fast-1] quorum R1", prompt=<YAML block>)`
|
|
324
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="copilot-1 [copilot-cli · gpt-4.1] quorum R1", prompt=<YAML block>)`
|
|
325
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="claude-1 [claude-code-router · deepseek-ai/DeepSeek-V3.2] quorum R1", prompt=<YAML block>)` ← one per claude-mcp server with `available: true`
|
|
326
326
|
(model="haiku" — slot-workers are orchestrators (read files, build prompt, run Bash subprocess), NOT reasoners. The actual reasoning is done by the external CLI. Haiku is faster with zero quality loss.)
|
|
327
327
|
|
|
328
328
|
The slot-worker reads repo context, builds its own prompt from the YAML arguments, calls the slot via `call-quorum-slot.cjs`, and returns a structured result block.
|
|
@@ -369,7 +369,7 @@ If all available models agree → skip to **Consensus output**.
|
|
|
369
369
|
|
|
370
370
|
Run up to 9 deliberation rounds (max 10 total rounds including Round 1).
|
|
371
371
|
|
|
372
|
-
For each round, dispatch one `Task(subagent_type="
|
|
372
|
+
For each round, dispatch one `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, ...)` per slot in **`$DISPATCH_LIST`** as **parallel sibling calls**. Append `prior_positions` to the YAML block for Round 2+ dispatch:
|
|
373
373
|
|
|
374
374
|
```
|
|
375
375
|
slot: <slotName>
|
|
@@ -405,7 +405,7 @@ After 10 total rounds with no consensus → **Escalate**.
|
|
|
405
405
|
|
|
406
406
|
```
|
|
407
407
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
408
|
-
|
|
408
|
+
nForma ► QUORUM CONSENSUS REACHED
|
|
409
409
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
410
410
|
|
|
411
411
|
Question: [question]
|
|
@@ -427,7 +427,7 @@ Update the scoreboard: for each model that voted this round, run:
|
|
|
427
427
|
|
|
428
428
|
```bash
|
|
429
429
|
# For native agents:
|
|
430
|
-
node "$HOME/.claude/
|
|
430
|
+
node "$HOME/.claude/nf-bin/update-scoreboard.cjs" \
|
|
431
431
|
--model <model_name> \
|
|
432
432
|
--result <vote_code> \
|
|
433
433
|
--task "<task_label>" \
|
|
@@ -436,7 +436,7 @@ node "$HOME/.claude/qgsd-bin/update-scoreboard.cjs" \
|
|
|
436
436
|
--task-description "<question or topic being debated>"
|
|
437
437
|
|
|
438
438
|
# For each claude-mcp server (use slot + full model-id, NOT --model):
|
|
439
|
-
node "$HOME/.claude/
|
|
439
|
+
node "$HOME/.claude/nf-bin/update-scoreboard.cjs" \
|
|
440
440
|
--slot <slotName> \
|
|
441
441
|
--model-id <fullModelId> \
|
|
442
442
|
--result <vote_code> \
|
|
@@ -519,7 +519,7 @@ Only write the `## Improvements` section when `request_improvements: true` AND i
|
|
|
519
519
|
|
|
520
520
|
```
|
|
521
521
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
522
|
-
|
|
522
|
+
nForma ► QUORUM ESCALATING — NO CONSENSUS AFTER 10 ROUNDS
|
|
523
523
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
524
524
|
|
|
525
525
|
Question: [question]
|
|
@@ -541,7 +541,7 @@ Update the scoreboard: for each model that voted this round, run:
|
|
|
541
541
|
|
|
542
542
|
```bash
|
|
543
543
|
# For native agents:
|
|
544
|
-
node "$HOME/.claude/
|
|
544
|
+
node "$HOME/.claude/nf-bin/update-scoreboard.cjs" \
|
|
545
545
|
--model <model_name> \
|
|
546
546
|
--result <vote_code> \
|
|
547
547
|
--task "<task_label>" \
|
|
@@ -550,7 +550,7 @@ node "$HOME/.claude/qgsd-bin/update-scoreboard.cjs" \
|
|
|
550
550
|
--task-description "<question or topic being debated>"
|
|
551
551
|
|
|
552
552
|
# For each claude-mcp server (use slot + full model-id, NOT --model):
|
|
553
|
-
node "$HOME/.claude/
|
|
553
|
+
node "$HOME/.claude/nf-bin/update-scoreboard.cjs" \
|
|
554
554
|
--slot <slotName> \
|
|
555
555
|
--model-id <fullModelId> \
|
|
556
556
|
--result <vote_code> \
|
|
@@ -581,7 +581,7 @@ Extract command(s) to run from $ARGUMENTS. If unclear, ask the user to specify.
|
|
|
581
581
|
Display:
|
|
582
582
|
```
|
|
583
583
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
584
|
-
|
|
584
|
+
nForma ► QUORUM: Mode B — Execution + Trace Review
|
|
585
585
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
586
586
|
|
|
587
587
|
Question: [original question]
|
|
@@ -615,7 +615,7 @@ $TRACES
|
|
|
615
615
|
|
|
616
616
|
### Dispatch quorum workers via Task (parallel per round)
|
|
617
617
|
|
|
618
|
-
Dispatch one `Task(subagent_type="
|
|
618
|
+
Dispatch one `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, ...)` per slot in **`$DISPATCH_LIST`** (capped to `FAN_OUT_COUNT - 1` external slots) as **parallel sibling calls** in one message turn. Do NOT dispatch slots outside `$DISPATCH_LIST`. Build a YAML prompt block per the slot-worker argument spec:
|
|
619
619
|
|
|
620
620
|
```
|
|
621
621
|
slot: <slotName>
|
|
@@ -643,11 +643,11 @@ prior_positions: |
|
|
|
643
643
|
Populate `citations:` from the `citations:` field in each model's slot-worker result block. If the result block had no `citations:` field or it was empty, write `(none)`. For Claude's own position, include any file paths or line numbers Claude cited in its reasoning.
|
|
644
644
|
|
|
645
645
|
Example dispatch (all Tasks in one message turn):
|
|
646
|
-
- `Task(subagent_type="
|
|
647
|
-
- `Task(subagent_type="
|
|
648
|
-
- `Task(subagent_type="
|
|
649
|
-
- `Task(subagent_type="
|
|
650
|
-
- `Task(subagent_type="
|
|
646
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="gemini-1 [gemini-cli · gemini-3-pro-preview] quorum R1", prompt=<YAML block>)`
|
|
647
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="codex-1 [codex-cli · gpt-5.3-codex] quorum R1", prompt=<YAML block>)`
|
|
648
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="opencode-1 [opencode-cli · grok-code-fast-1] quorum R1", prompt=<YAML block>)`
|
|
649
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="copilot-1 [copilot-cli · gpt-4.1] quorum R1", prompt=<YAML block>)`
|
|
650
|
+
- `Task(subagent_type="nf-quorum-slot-worker", model="haiku", max_turns=100, description="claude-1 [claude-code-router · deepseek-ai/DeepSeek-V3.2] quorum R1", prompt=<YAML block>)` ← one per claude-mcp server with `available: true`
|
|
651
651
|
(model="haiku" — slot-workers are orchestrators (read files, build prompt, run Bash subprocess), NOT reasoners. The actual reasoning is done by the external CLI. Haiku is faster with zero quality loss.)
|
|
652
652
|
|
|
653
653
|
The slot-worker reads repo context, builds the Mode B prompt (with execution traces) from the YAML arguments, calls the slot via `call-quorum-slot.cjs`, and returns a structured result block with a `verdict: APPROVE | REJECT | FLAG` field.
|
|
@@ -669,7 +669,7 @@ If split: run deliberation (up to 9 deliberation rounds, max 10 total rounds inc
|
|
|
669
669
|
|
|
670
670
|
```
|
|
671
671
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
672
|
-
|
|
672
|
+
nForma ► QUORUM VERDICT
|
|
673
673
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
674
674
|
|
|
675
675
|
┌────────────────────────────────┬──────────────┬──────────────────────────────────────────┐
|
|
@@ -28,7 +28,7 @@ Read `backup-meta.json` from the patches directory.
|
|
|
28
28
|
```
|
|
29
29
|
No local patches found. Nothing to reapply.
|
|
30
30
|
|
|
31
|
-
Local patches are automatically saved when you run /
|
|
31
|
+
Local patches are automatically saved when you run /nf:update
|
|
32
32
|
after modifying any GSD workflow, command, or agent files.
|
|
33
33
|
```
|
|
34
34
|
Exit.
|
|
@@ -76,7 +76,7 @@ For each file in `backup-meta.json`:
|
|
|
76
76
|
After reapplying, regenerate the file manifest so future updates correctly detect these as user modifications:
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
# The manifest will be regenerated on next /
|
|
79
|
+
# The manifest will be regenerated on next /nf:update
|
|
80
80
|
# For now, just note which files were modified
|
|
81
81
|
```
|
|
82
82
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: nf:remove-phase
|
|
3
3
|
description: Remove a future phase from roadmap and renumber subsequent phases
|
|
4
4
|
argument-hint: <phase-number>
|
|
5
5
|
allowed-tools:
|
|
@@ -16,7 +16,7 @@ Output: Phase deleted, all subsequent phases renumbered, git commit as historica
|
|
|
16
16
|
</objective>
|
|
17
17
|
|
|
18
18
|
<execution_context>
|
|
19
|
-
@~/.claude/
|
|
19
|
+
@~/.claude/nf/workflows/remove-phase.md
|
|
20
20
|
</execution_context>
|
|
21
21
|
|
|
22
22
|
<context>
|
|
@@ -26,6 +26,6 @@ Roadmap and state are resolved in-workflow via `init phase-op` and targeted read
|
|
|
26
26
|
</context>
|
|
27
27
|
|
|
28
28
|
<process>
|
|
29
|
-
Execute the remove-phase workflow from @~/.claude/
|
|
29
|
+
Execute the remove-phase workflow from @~/.claude/nf/workflows/remove-phase.md end-to-end.
|
|
30
30
|
Preserve all validation gates (future phase check, work check), renumbering logic, and commit.
|
|
31
31
|
</process>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Research how to implement a phase (standalone - usually use /
|
|
2
|
+
name: nf:research-phase
|
|
3
|
+
description: Research how to implement a phase (standalone - usually use /nf:plan-phase instead)
|
|
4
4
|
argument-hint: "[phase]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -9,9 +9,9 @@ allowed-tools:
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
<objective>
|
|
12
|
-
Research how to implement a phase. Spawns
|
|
12
|
+
Research how to implement a phase. Spawns nf-phase-researcher agent with phase context.
|
|
13
13
|
|
|
14
|
-
**Note:** This is a standalone research command. For most workflows, use `/
|
|
14
|
+
**Note:** This is a standalone research command. For most workflows, use `/nf:plan-phase` which integrates research automatically.
|
|
15
15
|
|
|
16
16
|
**Use this command when:**
|
|
17
17
|
- You want to research without planning yet
|
|
@@ -34,20 +34,20 @@ Normalize phase input in step 1 before any directory lookups.
|
|
|
34
34
|
## 0. Initialize Context
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
INIT=$(node ~/.claude/
|
|
37
|
+
INIT=$(node ~/.claude/nf/bin/gsd-tools.cjs init phase-op "$ARGUMENTS")
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Extract from init JSON: `phase_dir`, `phase_number`, `phase_name`, `phase_found`, `commit_docs`, `has_research`, `state_path`, `requirements_path`, `context_path`, `research_path`.
|
|
41
41
|
|
|
42
42
|
Resolve researcher model:
|
|
43
43
|
```bash
|
|
44
|
-
RESEARCHER_MODEL=$(node ~/.claude/
|
|
44
|
+
RESEARCHER_MODEL=$(node ~/.claude/nf/bin/gsd-tools.cjs resolve-model nf-phase-researcher --raw)
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## 1. Validate Phase
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
PHASE_INFO=$(node ~/.claude/
|
|
50
|
+
PHASE_INFO=$(node ~/.claude/nf/bin/gsd-tools.cjs roadmap get-phase "${phase_number}")
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
**If `found` is false:** Error and exit. **If `found` is true:** Extract `phase_number`, `phase_name`, `goal` from JSON.
|
|
@@ -71,7 +71,7 @@ Use paths from INIT (do not inline file contents in orchestrator context):
|
|
|
71
71
|
|
|
72
72
|
Present summary with phase description and what files the researcher will load.
|
|
73
73
|
|
|
74
|
-
## 4. Spawn
|
|
74
|
+
## 4. Spawn nf-phase-researcher Agent
|
|
75
75
|
|
|
76
76
|
Research modes: ecosystem (default), feasibility, implementation, comparison.
|
|
77
77
|
|
|
@@ -109,7 +109,7 @@ Mode: ecosystem
|
|
|
109
109
|
</additional_context>
|
|
110
110
|
|
|
111
111
|
<downstream_consumer>
|
|
112
|
-
Your RESEARCH.md will be loaded by `/
|
|
112
|
+
Your RESEARCH.md will be loaded by `/nf:plan-phase` which uses specific sections:
|
|
113
113
|
- `## Standard Stack` → Plans use these libraries
|
|
114
114
|
- `## Architecture Patterns` → Task structure follows these
|
|
115
115
|
- `## Don't Hand-Roll` → Tasks NEVER build custom solutions for listed problems
|
|
@@ -135,7 +135,7 @@ Write to: .planning/phases/${PHASE}-{slug}/${PHASE}-RESEARCH.md
|
|
|
135
135
|
|
|
136
136
|
```
|
|
137
137
|
Task(
|
|
138
|
-
prompt="First, read ~/.claude/agents/
|
|
138
|
+
prompt="First, read ~/.claude/agents/nf-phase-researcher.md for your role and instructions.\n\n" + filled_prompt,
|
|
139
139
|
subagent_type="general-purpose",
|
|
140
140
|
model="{researcher_model}",
|
|
141
141
|
description="Research Phase {phase}"
|
|
@@ -171,7 +171,7 @@ Continue research for Phase {phase_number}: {phase_name}
|
|
|
171
171
|
|
|
172
172
|
```
|
|
173
173
|
Task(
|
|
174
|
-
prompt="First, read ~/.claude/agents/
|
|
174
|
+
prompt="First, read ~/.claude/agents/nf-phase-researcher.md for your role and instructions.\n\n" + continuation_prompt,
|
|
175
175
|
subagent_type="general-purpose",
|
|
176
176
|
model="{researcher_model}",
|
|
177
177
|
description="Continue research Phase {phase}"
|
|
@@ -183,7 +183,7 @@ Task(
|
|
|
183
183
|
<success_criteria>
|
|
184
184
|
- [ ] Phase validated against roadmap
|
|
185
185
|
- [ ] Existing research checked
|
|
186
|
-
- [ ]
|
|
186
|
+
- [ ] nf-phase-researcher spawned with context
|
|
187
187
|
- [ ] Checkpoints handled correctly
|
|
188
188
|
- [ ] User knows next steps
|
|
189
189
|
</success_criteria>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: nf:resume-work
|
|
3
3
|
description: Resume work from previous session with full context restoration
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Read
|
|
@@ -22,11 +22,11 @@ Routes to the resume-project workflow which handles:
|
|
|
22
22
|
</objective>
|
|
23
23
|
|
|
24
24
|
<execution_context>
|
|
25
|
-
@~/.claude/
|
|
25
|
+
@~/.claude/nf/workflows/resume-project.md
|
|
26
26
|
</execution_context>
|
|
27
27
|
|
|
28
28
|
<process>
|
|
29
|
-
**Follow the resume-project workflow** from `@~/.claude/
|
|
29
|
+
**Follow the resume-project workflow** from `@~/.claude/nf/workflows/resume-project.md`.
|
|
30
30
|
|
|
31
31
|
The workflow handles all resumption logic including:
|
|
32
32
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nf:review-requirements
|
|
3
|
+
description: Review all requirements for quality — flags specificity issues, redundant overlaps, unmeasurable requirements, and merge candidates
|
|
4
|
+
argument-hint: [--repair] [--dry-run] [--category="Category Name"] [--ids=REQ-01,REQ-02]
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Bash
|
|
10
|
+
- Agent
|
|
11
|
+
- AskUserQuestion
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<objective>
|
|
15
|
+
Scan all requirements in `.planning/formal/requirements.json` for quality issues:
|
|
16
|
+
specificity (too narrow), redundancy (overlaps/duplicates), and measurability (vague/untestable).
|
|
17
|
+
Proposes and optionally applies fixes.
|
|
18
|
+
</objective>
|
|
19
|
+
|
|
20
|
+
<execution_context>
|
|
21
|
+
@~/.claude/nf/workflows/review-requirements.md
|
|
22
|
+
</execution_context>
|
|
23
|
+
|
|
24
|
+
<process>
|
|
25
|
+
Execute the review-requirements workflow from @~/.claude/nf/workflows/review-requirements.md end-to-end.
|
|
26
|
+
Pass through all --flags from arguments:
|
|
27
|
+
--repair Fully autonomous mode — auto-apply safe fixes, skip prompts
|
|
28
|
+
--dry-run Show proposed changes without writing
|
|
29
|
+
--category Focus on a specific category
|
|
30
|
+
--ids Focus on specific requirement IDs
|
|
31
|
+
</process>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: nf:set-profile
|
|
3
3
|
description: Switch model profile for GSD agents (quality/balanced/budget)
|
|
4
4
|
argument-hint: <profile>
|
|
5
5
|
allowed-tools:
|
|
@@ -19,11 +19,11 @@ Routes to the set-profile workflow which handles:
|
|
|
19
19
|
</objective>
|
|
20
20
|
|
|
21
21
|
<execution_context>
|
|
22
|
-
@~/.claude/
|
|
22
|
+
@~/.claude/nf/workflows/set-profile.md
|
|
23
23
|
</execution_context>
|
|
24
24
|
|
|
25
25
|
<process>
|
|
26
|
-
**Follow the set-profile workflow** from `@~/.claude/
|
|
26
|
+
**Follow the set-profile workflow** from `@~/.claude/nf/workflows/set-profile.md`.
|
|
27
27
|
|
|
28
28
|
The workflow handles all logic including:
|
|
29
29
|
1. Profile argument validation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: nf:settings
|
|
3
3
|
description: Project manager hub — dashboard, smart routing, and configuration
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Read
|
|
@@ -14,20 +14,20 @@ allowed-tools:
|
|
|
14
14
|
Guided project manager hub with state-aware dashboard and categorized action menu.
|
|
15
15
|
|
|
16
16
|
Shows project status (milestone, phase, progress, config) then routes to:
|
|
17
|
-
- Continue Working — smart routing based on project state (same as /
|
|
17
|
+
- Continue Working — smart routing based on project state (same as /nf:progress)
|
|
18
18
|
- Project Management — phases, milestones, todos, debug, roadmap
|
|
19
19
|
- Configuration — workflow settings, project profile, baselines, quorum agents
|
|
20
|
-
- Quick Task — ad-hoc tasks via /
|
|
20
|
+
- Quick Task — ad-hoc tasks via /nf:quick
|
|
21
21
|
|
|
22
|
-
Backward compatible: /
|
|
22
|
+
Backward compatible: /nf:settings --config goes directly to workflow settings (original 6-question config form).
|
|
23
23
|
</objective>
|
|
24
24
|
|
|
25
25
|
<execution_context>
|
|
26
|
-
@~/.claude/
|
|
26
|
+
@~/.claude/nf/workflows/settings.md
|
|
27
27
|
</execution_context>
|
|
28
28
|
|
|
29
29
|
<process>
|
|
30
|
-
**Follow the settings workflow** from `@~/.claude/
|
|
30
|
+
**Follow the settings workflow** from `@~/.claude/nf/workflows/settings.md`.
|
|
31
31
|
|
|
32
32
|
The workflow handles all logic including:
|
|
33
33
|
1. Flag check (--config for backward compat)
|