@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.
- 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-preflight.cjs +89 -0
- 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 +36 -86
- 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/{qgsd-precompact.js → nf-precompact.js} +13 -13
- package/hooks/dist/{qgsd-prompt.js → nf-prompt.js} +110 -33
- package/hooks/dist/nf-session-start.js +185 -0
- package/hooks/dist/{qgsd-slot-correlator.js → nf-slot-correlator.js} +13 -5
- package/hooks/dist/{qgsd-spec-regen.js → nf-spec-regen.js} +17 -8
- package/hooks/dist/{qgsd-statusline.js → nf-statusline.js} +12 -3
- package/hooks/dist/{qgsd-stop.js → nf-stop.js} +152 -18
- package/hooks/dist/{qgsd-token-collector.js → nf-token-collector.js} +12 -4
- package/hooks/dist/unified-mcp-server.mjs +2 -2
- package/package.json +6 -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
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* quorum-cache.cjs — Cache infrastructure for quorum results.
|
|
5
|
+
*
|
|
6
|
+
* Provides deterministic cache key computation (SHA-256), file-based read/write
|
|
7
|
+
* with TTL validation, and invalidation logic based on git HEAD and quorum
|
|
8
|
+
* composition changes.
|
|
9
|
+
*
|
|
10
|
+
* Cache files are stored in .planning/.quorum-cache/ (gitignored).
|
|
11
|
+
* All operations fail-open: errors return null/undefined, never throw.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const crypto = require('node:crypto');
|
|
15
|
+
const fs = require('node:fs');
|
|
16
|
+
const path = require('node:path');
|
|
17
|
+
const { spawnSync } = require('node:child_process');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Compute a deterministic SHA-256 cache key from quorum inputs.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} prompt - The user prompt string
|
|
23
|
+
* @param {string} context - Additional context string
|
|
24
|
+
* @param {Array<{slot: string}>} slots - Slot objects with .slot property
|
|
25
|
+
* @param {Array} configQuorumActive - quorum_active array from config
|
|
26
|
+
* @param {string} gitHead - Current git HEAD hash
|
|
27
|
+
* @returns {string} Full hex SHA-256 digest
|
|
28
|
+
*/
|
|
29
|
+
function computeCacheKey(prompt, context, slots, configQuorumActive, gitHead) {
|
|
30
|
+
const sortedSlotNames = (slots || [])
|
|
31
|
+
.map(s => s.slot)
|
|
32
|
+
.sort()
|
|
33
|
+
.join(',');
|
|
34
|
+
|
|
35
|
+
const configHash = crypto
|
|
36
|
+
.createHash('sha256')
|
|
37
|
+
.update(JSON.stringify(configQuorumActive || []))
|
|
38
|
+
.digest('hex')
|
|
39
|
+
.slice(0, 16);
|
|
40
|
+
|
|
41
|
+
const payload = [
|
|
42
|
+
String(prompt || ''),
|
|
43
|
+
String(context || ''),
|
|
44
|
+
sortedSlotNames,
|
|
45
|
+
configHash,
|
|
46
|
+
String(gitHead || ''),
|
|
47
|
+
].join('\x00');
|
|
48
|
+
|
|
49
|
+
return crypto.createHash('sha256').update(payload).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get current git HEAD hash.
|
|
54
|
+
* Runs `git rev-parse HEAD` with a 3s timeout. Fail-open.
|
|
55
|
+
*
|
|
56
|
+
* @returns {string} Trimmed HEAD hash or empty string on failure
|
|
57
|
+
*/
|
|
58
|
+
function getGitHead() {
|
|
59
|
+
try {
|
|
60
|
+
const result = spawnSync('git', ['rev-parse', 'HEAD'], {
|
|
61
|
+
timeout: 3000,
|
|
62
|
+
encoding: 'utf8',
|
|
63
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
64
|
+
});
|
|
65
|
+
return (result.stdout || '').trim();
|
|
66
|
+
} catch (_) {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Read a cache entry from disk.
|
|
73
|
+
* Returns parsed entry if valid (version 1, not expired, has completed field).
|
|
74
|
+
* Fail-open: returns null on any error or invalid state.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} cacheKey - The cache key (hex digest)
|
|
77
|
+
* @param {string} cacheDir - Directory containing cache files
|
|
78
|
+
* @returns {object|null} Parsed cache entry or null
|
|
79
|
+
*/
|
|
80
|
+
function readCache(cacheKey, cacheDir) {
|
|
81
|
+
try {
|
|
82
|
+
const filePath = path.join(cacheDir, `${cacheKey}.json`);
|
|
83
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
84
|
+
const entry = JSON.parse(raw);
|
|
85
|
+
|
|
86
|
+
// Version check
|
|
87
|
+
if (entry.version !== 1) return null;
|
|
88
|
+
|
|
89
|
+
// Must have completed field (pending entries are cache misses)
|
|
90
|
+
if (!entry.completed) return null;
|
|
91
|
+
|
|
92
|
+
// TTL check
|
|
93
|
+
const age = Date.now() - new Date(entry.created).getTime();
|
|
94
|
+
if (age > entry.ttl_ms) return null;
|
|
95
|
+
|
|
96
|
+
return entry;
|
|
97
|
+
} catch (_) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Write a cache entry to disk. Creates cacheDir if needed. Fail-open.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} cacheKey - The cache key (hex digest)
|
|
106
|
+
* @param {object} entry - Cache entry object
|
|
107
|
+
* @param {string} cacheDir - Directory to write cache files
|
|
108
|
+
*/
|
|
109
|
+
function writeCache(cacheKey, entry, cacheDir) {
|
|
110
|
+
try {
|
|
111
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
112
|
+
const filePath = path.join(cacheDir, `${cacheKey}.json`);
|
|
113
|
+
fs.writeFileSync(filePath, JSON.stringify(entry, null, 2), 'utf8');
|
|
114
|
+
} catch (_) {
|
|
115
|
+
// Fail-open: swallow errors
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Validate a cache entry against current state.
|
|
121
|
+
* Returns false if git HEAD changed, quorum composition changed, or TTL expired.
|
|
122
|
+
*
|
|
123
|
+
* @param {object} entry - Cache entry to validate
|
|
124
|
+
* @param {string} currentGitHead - Current git HEAD hash
|
|
125
|
+
* @param {Array} currentQuorumActive - Current quorum_active config
|
|
126
|
+
* @returns {boolean} True if cache entry is still valid
|
|
127
|
+
*/
|
|
128
|
+
function isCacheValid(entry, currentGitHead, currentQuorumActive) {
|
|
129
|
+
if (!entry) return false;
|
|
130
|
+
|
|
131
|
+
// Git HEAD must match
|
|
132
|
+
if (entry.git_head !== currentGitHead) return false;
|
|
133
|
+
|
|
134
|
+
// Quorum composition must match
|
|
135
|
+
if (JSON.stringify(entry.quorum_active) !== JSON.stringify(currentQuorumActive)) return false;
|
|
136
|
+
|
|
137
|
+
// TTL must not be expired
|
|
138
|
+
const age = Date.now() - new Date(entry.created).getTime();
|
|
139
|
+
if (age > entry.ttl_ms) return false;
|
|
140
|
+
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = { computeCacheKey, readCache, writeCache, getGitHead, isCacheValid };
|
|
@@ -154,7 +154,7 @@ function readEarlyEscalationThreshold(configPaths) {
|
|
|
154
154
|
const DEFAULT = 0.10;
|
|
155
155
|
const paths = configPaths || [
|
|
156
156
|
path.join(process.cwd(), '.planning', 'config.json'),
|
|
157
|
-
path.join(process.cwd(), '.planning', '
|
|
157
|
+
path.join(process.cwd(), '.planning', 'nf.json'),
|
|
158
158
|
];
|
|
159
159
|
for (const cfgPath of paths) {
|
|
160
160
|
try {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* quorum-preflight.cjs — extract quorum config and team identity from nf.json + providers.json
|
|
6
|
+
*
|
|
7
|
+
* Replaces three inline `node -e` snippets in quorum.md that caused shell-escaping
|
|
8
|
+
* failures (LLMs escaping `!` as `\!` inside node -e strings).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* node quorum-preflight.cjs --quorum-active # → JSON array of active slot names
|
|
12
|
+
* node quorum-preflight.cjs --max-quorum-size # → integer (default 3)
|
|
13
|
+
* node quorum-preflight.cjs --team # → JSON { slotName: { model } }
|
|
14
|
+
* node quorum-preflight.cjs --all # → JSON { quorum_active, max_quorum_size, team }
|
|
15
|
+
*
|
|
16
|
+
* All modes read from ~/.claude/nf.json (global) merged with $CWD/.claude/nf.json (project).
|
|
17
|
+
* --team and --all also read providers.json (same search logic as call-quorum-slot.cjs).
|
|
18
|
+
*
|
|
19
|
+
* Exit code: always 0. Output: JSON to stdout.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
const os = require('os');
|
|
25
|
+
|
|
26
|
+
// ─── Read merged nf.json config ─────────────────────────────────────────────
|
|
27
|
+
function readConfig() {
|
|
28
|
+
const globalCfg = path.join(os.homedir(), '.claude', 'nf.json');
|
|
29
|
+
const projCfg = path.join(process.cwd(), '.claude', 'nf.json');
|
|
30
|
+
let cfg = {};
|
|
31
|
+
for (const f of [globalCfg, projCfg]) {
|
|
32
|
+
try { Object.assign(cfg, JSON.parse(fs.readFileSync(f, 'utf8'))); } catch (_) {}
|
|
33
|
+
}
|
|
34
|
+
return cfg;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ─── Find providers.json (mirrors call-quorum-slot.cjs / probe-quorum-slots.cjs) ──
|
|
38
|
+
function findProviders() {
|
|
39
|
+
const searchPaths = [
|
|
40
|
+
path.join(__dirname, 'providers.json'),
|
|
41
|
+
path.join(os.homedir(), '.claude', 'nf-bin', 'providers.json'),
|
|
42
|
+
];
|
|
43
|
+
try {
|
|
44
|
+
const claudeJson = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude.json'), 'utf8'));
|
|
45
|
+
const u1args = claudeJson?.mcpServers?.['unified-1']?.args ?? [];
|
|
46
|
+
const serverScript = u1args.find(a => typeof a === 'string' && a.endsWith('unified-mcp-server.mjs'));
|
|
47
|
+
if (serverScript) searchPaths.unshift(path.join(path.dirname(serverScript), 'providers.json'));
|
|
48
|
+
} catch (_) {}
|
|
49
|
+
for (const p of searchPaths) {
|
|
50
|
+
try {
|
|
51
|
+
if (fs.existsSync(p)) return JSON.parse(fs.readFileSync(p, 'utf8')).providers;
|
|
52
|
+
} catch (_) {}
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ─── Build team JSON from providers + config ────────────────────────────────
|
|
58
|
+
function buildTeam(providers, active) {
|
|
59
|
+
const team = {};
|
|
60
|
+
for (const p of providers) {
|
|
61
|
+
if (active.length > 0 && !active.includes(p.name)) continue;
|
|
62
|
+
team[p.name] = { model: p.model };
|
|
63
|
+
}
|
|
64
|
+
return team;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ─── Main ───────────────────────────────────────────────────────────────────
|
|
68
|
+
const mode = process.argv[2] || '--all';
|
|
69
|
+
const cfg = readConfig();
|
|
70
|
+
|
|
71
|
+
if (mode === '--quorum-active') {
|
|
72
|
+
console.log(JSON.stringify(cfg.quorum_active || []));
|
|
73
|
+
} else if (mode === '--max-quorum-size') {
|
|
74
|
+
console.log(cfg.max_quorum_size ?? 3);
|
|
75
|
+
} else if (mode === '--team') {
|
|
76
|
+
const providers = findProviders();
|
|
77
|
+
const active = cfg.quorum_active || [];
|
|
78
|
+
console.log(JSON.stringify(buildTeam(providers, active)));
|
|
79
|
+
} else if (mode === '--all') {
|
|
80
|
+
const providers = findProviders();
|
|
81
|
+
const active = cfg.quorum_active || [];
|
|
82
|
+
const team = buildTeam(providers, active);
|
|
83
|
+
const maxSize = cfg.max_quorum_size ?? 3;
|
|
84
|
+
console.log(JSON.stringify({ quorum_active: active, max_quorum_size: maxSize, team }));
|
|
85
|
+
} else {
|
|
86
|
+
console.error(`Unknown mode: ${mode}`);
|
|
87
|
+
console.error('Usage: node quorum-preflight.cjs [--quorum-active|--max-quorum-size|--team|--all]');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* [--cwd <dir>]
|
|
20
20
|
*
|
|
21
21
|
* Builds the Mode A or Mode B prompt from deterministic JS templates matching
|
|
22
|
-
* agents/
|
|
22
|
+
* agents/nf-quorum-slot-worker.md Step 2, pipes it to call-quorum-slot.cjs via
|
|
23
23
|
* child_process.spawn, parses the output, and emits a structured YAML result block.
|
|
24
24
|
*
|
|
25
25
|
* Exported pure functions (testable without subprocess):
|
|
@@ -118,7 +118,7 @@ const PATH_CATEGORY_MAP = new Map([
|
|
|
118
118
|
*
|
|
119
119
|
* @param {Array} requirements — full requirements array
|
|
120
120
|
* @param {string} question — the question text
|
|
121
|
-
* @param {string|null} artifactPath — optional artifact path (e.g. "hooks/
|
|
121
|
+
* @param {string|null} artifactPath — optional artifact path (e.g. "hooks/nf-stop.js")
|
|
122
122
|
* @returns {Array} — filtered requirements (max 20), sorted by score descending
|
|
123
123
|
*/
|
|
124
124
|
function matchRequirementsByKeywords(requirements, question, artifactPath) {
|
|
@@ -279,7 +279,7 @@ function formatRequirementsSection(requirements) {
|
|
|
279
279
|
/**
|
|
280
280
|
* buildModeAPrompt — constructs the Mode A question prompt.
|
|
281
281
|
*
|
|
282
|
-
* Matches the EXACT template from agents/
|
|
282
|
+
* Matches the EXACT template from agents/nf-quorum-slot-worker.md Step 2 Mode A.
|
|
283
283
|
*
|
|
284
284
|
* @param {object} opts
|
|
285
285
|
* @param {number} opts.round
|
|
@@ -297,7 +297,7 @@ function buildModeAPrompt({ round, repoDir, question, artifactPath, artifactCont
|
|
|
297
297
|
const lines = [];
|
|
298
298
|
|
|
299
299
|
// Header
|
|
300
|
-
lines.push(`
|
|
300
|
+
lines.push(`nForma Quorum — Round ${round}`);
|
|
301
301
|
lines.push('');
|
|
302
302
|
|
|
303
303
|
// Repository + question
|
|
@@ -422,7 +422,7 @@ function buildModeAPrompt({ round, repoDir, question, artifactPath, artifactCont
|
|
|
422
422
|
/**
|
|
423
423
|
* buildModeBPrompt — constructs the Mode B execution review prompt.
|
|
424
424
|
*
|
|
425
|
-
* Matches the EXACT template from agents/
|
|
425
|
+
* Matches the EXACT template from agents/nf-quorum-slot-worker.md Step 2 Mode B.
|
|
426
426
|
*
|
|
427
427
|
* @param {object} opts
|
|
428
428
|
* @param {number} opts.round
|
|
@@ -440,7 +440,7 @@ function buildModeBPrompt({ round, repoDir, question, traces, artifactPath, arti
|
|
|
440
440
|
const lines = [];
|
|
441
441
|
|
|
442
442
|
// Header
|
|
443
|
-
lines.push(`
|
|
443
|
+
lines.push(`nForma Quorum — Execution Review (Round ${round})`);
|
|
444
444
|
lines.push('');
|
|
445
445
|
|
|
446
446
|
// Repository + question
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Pure data functions for requirements management.
|
|
5
5
|
* No blessed dependency — all functions are testable in isolation.
|
|
6
|
-
* Consumers: bin/
|
|
6
|
+
* Consumers: bin/nf.cjs (blessed TUI)
|
|
7
7
|
*
|
|
8
8
|
* Data sources (project-relative paths via process.cwd()):
|
|
9
9
|
* .planning/formal/requirements.json — 210 requirements in frozen envelope
|
package/bin/review-mcp-logs.cjs
CHANGED
|
@@ -192,7 +192,7 @@ const fmtMs = (ms) => {
|
|
|
192
192
|
};
|
|
193
193
|
|
|
194
194
|
console.log(`\n${bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}`);
|
|
195
|
-
console.log(bold('
|
|
195
|
+
console.log(bold(' nForma ► MCP LOG REVIEW'));
|
|
196
196
|
console.log(bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
197
197
|
console.log(dim(` Scanned: ${files.length} debug files | Last ${MAX_DAYS} days | ${DEBUG_DIR}`));
|
|
198
198
|
console.log();
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* risk-heatmap.cjs — Ranked risk transition list for Layer 3 (Reasoning).
|
|
6
|
+
*
|
|
7
|
+
* Combines FMEA RPN scores with L1/L2 coverage gap data to produce a
|
|
8
|
+
* prioritized list of highest-risk transitions. Transitions not modeled
|
|
9
|
+
* in XState receive a 50% risk penalty.
|
|
10
|
+
*
|
|
11
|
+
* Requirements: RSN-03
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node bin/risk-heatmap.cjs # print summary to stdout
|
|
15
|
+
* node bin/risk-heatmap.cjs --json # print full results JSON to stdout
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
const ROOT = process.env.PROJECT_ROOT || path.join(__dirname, '..');
|
|
22
|
+
const FORMAL = path.join(ROOT, '.planning', 'formal');
|
|
23
|
+
const REASONING_DIR = path.join(FORMAL, 'reasoning');
|
|
24
|
+
const OUT_FILE = path.join(REASONING_DIR, 'risk-heatmap.json');
|
|
25
|
+
|
|
26
|
+
const JSON_FLAG = process.argv.includes('--json');
|
|
27
|
+
|
|
28
|
+
// ── Risk tier classification ────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
function classifyRiskTier(riskScore) {
|
|
31
|
+
if (riskScore >= 200) return 'critical';
|
|
32
|
+
if (riskScore >= 100) return 'high';
|
|
33
|
+
if (riskScore >= 40) return 'medium';
|
|
34
|
+
return 'low';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ── Core computation ────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compute composite risk score for a transition.
|
|
41
|
+
* risk_score = RPN * (1 + coverage_gap_penalty)
|
|
42
|
+
* coverage_gap_penalty = 0.5 if transition is in missing_in_model, else 0.0
|
|
43
|
+
*/
|
|
44
|
+
function computeRiskScore(rpn, hasCoverageGap) {
|
|
45
|
+
const penalty = hasCoverageGap ? 0.5 : 0.0;
|
|
46
|
+
return rpn * (1 + penalty);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function generateRiskHeatmap(hazardModel, observedFsm) {
|
|
50
|
+
// Build set of missing_in_model transitions
|
|
51
|
+
const missingInModel = new Set(
|
|
52
|
+
(observedFsm.model_comparison?.missing_in_model || [])
|
|
53
|
+
.map(m => `${m.from}-${m.event}`)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const transitions = [];
|
|
57
|
+
|
|
58
|
+
for (const hazard of (hazardModel?.hazards || [])) {
|
|
59
|
+
const key = `${hazard.state}-${hazard.event}`;
|
|
60
|
+
const hasCoverageGap = missingInModel.has(key);
|
|
61
|
+
const coverageGapPenalty = hasCoverageGap ? 0.5 : 0.0;
|
|
62
|
+
const riskScore = computeRiskScore(hazard.rpn, hasCoverageGap);
|
|
63
|
+
|
|
64
|
+
transitions.push({
|
|
65
|
+
state: hazard.state,
|
|
66
|
+
event: hazard.event,
|
|
67
|
+
to_state: hazard.to_state,
|
|
68
|
+
rpn: hazard.rpn,
|
|
69
|
+
coverage_gap: hasCoverageGap,
|
|
70
|
+
coverage_gap_penalty: coverageGapPenalty,
|
|
71
|
+
risk_score: riskScore,
|
|
72
|
+
risk_tier: classifyRiskTier(riskScore),
|
|
73
|
+
derived_from: [
|
|
74
|
+
{ layer: 'L3', artifact: 'reasoning/hazard-model.json', ref: `hazards[id=${hazard.id}]` },
|
|
75
|
+
{ layer: 'L2', artifact: 'semantics/observed-fsm.json', ref: `observed_transitions.${hazard.state}.${hazard.event}` },
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Sort by risk_score descending
|
|
81
|
+
transitions.sort((a, b) => b.risk_score - a.risk_score);
|
|
82
|
+
|
|
83
|
+
// Summary stats
|
|
84
|
+
const byRiskTier = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
85
|
+
let coverageGapCount = 0;
|
|
86
|
+
for (const t of transitions) {
|
|
87
|
+
byRiskTier[t.risk_tier] = (byRiskTier[t.risk_tier] || 0) + 1;
|
|
88
|
+
if (t.coverage_gap) coverageGapCount++;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
schema_version: '1',
|
|
93
|
+
generated: new Date().toISOString(),
|
|
94
|
+
formula: 'risk_score = RPN * (1 + coverage_gap_penalty); coverage_gap_penalty = 0.5 if missing_in_model, else 0.0',
|
|
95
|
+
risk_tiers: {
|
|
96
|
+
critical: 'risk_score >= 200',
|
|
97
|
+
high: '100 <= risk_score < 200',
|
|
98
|
+
medium: '40 <= risk_score < 100',
|
|
99
|
+
low: 'risk_score < 40',
|
|
100
|
+
},
|
|
101
|
+
transitions,
|
|
102
|
+
summary: {
|
|
103
|
+
total: transitions.length,
|
|
104
|
+
by_risk_tier: byRiskTier,
|
|
105
|
+
coverage_gap_count: coverageGapCount,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── Entry point ─────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
function main() {
|
|
113
|
+
// Load L3 hazard model
|
|
114
|
+
const hazardPath = path.join(REASONING_DIR, 'hazard-model.json');
|
|
115
|
+
if (!fs.existsSync(hazardPath)) {
|
|
116
|
+
console.error('ERROR: hazard-model.json not found at', hazardPath);
|
|
117
|
+
console.error('Run bin/hazard-model.cjs first.');
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
const hazardModel = JSON.parse(fs.readFileSync(hazardPath, 'utf8'));
|
|
121
|
+
|
|
122
|
+
// Load L2 observed FSM
|
|
123
|
+
const fsmPath = path.join(FORMAL, 'semantics', 'observed-fsm.json');
|
|
124
|
+
if (!fs.existsSync(fsmPath)) {
|
|
125
|
+
console.error('ERROR: observed-fsm.json not found at', fsmPath);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
const observedFsm = JSON.parse(fs.readFileSync(fsmPath, 'utf8'));
|
|
129
|
+
|
|
130
|
+
const output = generateRiskHeatmap(hazardModel, observedFsm);
|
|
131
|
+
|
|
132
|
+
// Write output
|
|
133
|
+
fs.mkdirSync(REASONING_DIR, { recursive: true });
|
|
134
|
+
fs.writeFileSync(OUT_FILE, JSON.stringify(output, null, 2) + '\n');
|
|
135
|
+
|
|
136
|
+
if (JSON_FLAG) {
|
|
137
|
+
process.stdout.write(JSON.stringify(output));
|
|
138
|
+
} else {
|
|
139
|
+
console.log(`Risk Heatmap`);
|
|
140
|
+
console.log(` Total transitions: ${output.summary.total}`);
|
|
141
|
+
console.log(` By risk tier: ${JSON.stringify(output.summary.by_risk_tier)}`);
|
|
142
|
+
console.log(` Coverage gaps: ${output.summary.coverage_gap_count}`);
|
|
143
|
+
console.log(` Output: ${OUT_FILE}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (require.main === module) main();
|
|
150
|
+
|
|
151
|
+
module.exports = { computeRiskScore, classifyRiskTier, generateRiskHeatmap, main };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
// bin/run-account-manager-tlc.cjs
|
|
4
|
-
// Invokes TLC model checker for the
|
|
5
|
-
// Source spec: .planning/formal/tla/
|
|
4
|
+
// Invokes TLC model checker for the nForma account manager TLA+ specification.
|
|
5
|
+
// Source spec: .planning/formal/tla/NFAccountManager.tla
|
|
6
6
|
// Source impl: bin/account-manager.cjs
|
|
7
7
|
//
|
|
8
8
|
// Checks:
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// - .planning/formal/tla/tla2tools.jar (see .planning/formal/tla/README.md for download command)
|
|
24
24
|
|
|
25
25
|
const { spawnSync } = require('child_process');
|
|
26
|
-
const JAVA_HEAP_MAX = process.env.
|
|
26
|
+
const JAVA_HEAP_MAX = process.env.NF_JAVA_HEAP_MAX || '512m';
|
|
27
27
|
const fs = require('fs');
|
|
28
28
|
const path = require('path');
|
|
29
29
|
const { writeCheckResult } = require('./write-check-result.cjs');
|
|
@@ -125,7 +125,7 @@ if (!fs.existsSync(jarPath)) {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// ── 4. Invoke TLC ────────────────────────────────────────────────────────────
|
|
128
|
-
const specPath = path.join(ROOT, '.planning', 'formal', 'tla', '
|
|
128
|
+
const specPath = path.join(ROOT, '.planning', 'formal', 'tla', 'NFAccountManager.tla');
|
|
129
129
|
const cfgPath = path.join(ROOT, '.planning', 'formal', 'tla', configName + '.cfg');
|
|
130
130
|
// Use workers=1 for liveness (IdleReachable) — avoids multi-worker liveness bugs in TLC
|
|
131
131
|
const workers = '1';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
// bin/run-account-pool-alloy.cjs
|
|
4
|
-
// Invokes Alloy 6 JAR headless for the
|
|
4
|
+
// Invokes Alloy 6 JAR headless for the nForma account pool structure spec.
|
|
5
5
|
// Requirements: ALY-AM-01
|
|
6
6
|
//
|
|
7
7
|
// Usage:
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// - .planning/formal/alloy/org.alloytools.alloy.dist.jar (see VERIFICATION_TOOLS.md for download)
|
|
20
20
|
|
|
21
21
|
const { spawnSync } = require('child_process');
|
|
22
|
-
const JAVA_HEAP_MAX = process.env.
|
|
22
|
+
const JAVA_HEAP_MAX = process.env.NF_JAVA_HEAP_MAX || '512m';
|
|
23
23
|
const fs = require('fs');
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const { writeCheckResult } = require('./write-check-result.cjs');
|
package/bin/run-alloy.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
// bin/run-alloy.cjs
|
|
4
|
-
// Invokes Alloy 6 JAR headless for the
|
|
4
|
+
// Invokes Alloy 6 JAR headless for the nForma vote-counting model.
|
|
5
5
|
// Requirements: ALY-02
|
|
6
6
|
//
|
|
7
7
|
// Usage:
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// - .planning/formal/alloy/org.alloytools.alloy.dist.jar (see VERIFICATION_TOOLS.md for download)
|
|
13
13
|
|
|
14
14
|
const { spawnSync } = require('child_process');
|
|
15
|
-
const JAVA_HEAP_MAX = process.env.
|
|
15
|
+
const JAVA_HEAP_MAX = process.env.NF_JAVA_HEAP_MAX || '512m';
|
|
16
16
|
const fs = require('fs');
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const { writeCheckResult } = require('./write-check-result.cjs');
|
package/bin/run-audit-alloy.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
// bin/run-audit-alloy.cjs
|
|
4
|
-
// Invokes Alloy 6 JAR headless for
|
|
4
|
+
// Invokes Alloy 6 JAR headless for nForma audit trail specs (GAP-3, GAP-9).
|
|
5
5
|
// Requirements: GAP-3, GAP-9
|
|
6
6
|
//
|
|
7
7
|
// Usage:
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// - .planning/formal/alloy/org.alloytools.alloy.dist.jar (see VERIFICATION_TOOLS.md for download)
|
|
17
17
|
|
|
18
18
|
const { spawnSync } = require('child_process');
|
|
19
|
-
const JAVA_HEAP_MAX = process.env.
|
|
19
|
+
const JAVA_HEAP_MAX = process.env.NF_JAVA_HEAP_MAX || '512m';
|
|
20
20
|
const fs = require('fs');
|
|
21
21
|
const path = require('path');
|
|
22
22
|
const { writeCheckResult } = require('./write-check-result.cjs');
|
package/bin/run-breaker-tlc.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
// bin/run-breaker-tlc.cjs
|
|
4
|
-
// Invokes TLC model checker for the
|
|
4
|
+
// Invokes TLC model checker for the nForma circuit breaker TLA+ specification.
|
|
5
5
|
// Requirements: QT-105
|
|
6
6
|
//
|
|
7
7
|
// Usage:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// - .planning/formal/tla/tla2tools.jar (see .planning/formal/tla/README.md for download command)
|
|
14
14
|
|
|
15
15
|
const { spawnSync } = require('child_process');
|
|
16
|
-
const JAVA_HEAP_MAX = process.env.
|
|
16
|
+
const JAVA_HEAP_MAX = process.env.NF_JAVA_HEAP_MAX || '512m';
|
|
17
17
|
const fs = require('fs');
|
|
18
18
|
const path = require('path');
|
|
19
19
|
const { writeCheckResult } = require('./write-check-result.cjs');
|
|
@@ -117,7 +117,7 @@ if (!fs.existsSync(jarPath)) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// ── 4. Invoke TLC ────────────────────────────────────────────────────────────
|
|
120
|
-
const specPath = path.join(ROOT, '.planning', 'formal', 'tla', '
|
|
120
|
+
const specPath = path.join(ROOT, '.planning', 'formal', 'tla', 'NFCircuitBreaker.tla');
|
|
121
121
|
const cfgPath = path.join(ROOT, '.planning', 'formal', 'tla', configName + '.cfg');
|
|
122
122
|
// Always use 'auto' workers — MCbreaker has a small state space and liveness
|
|
123
123
|
// can safely run with multiple workers (no known multi-worker liveness bugs at this scale).
|
package/bin/run-formal-check.cjs
CHANGED
|
@@ -31,7 +31,7 @@ const MODULE_CHECKS = {
|
|
|
31
31
|
cmd: [
|
|
32
32
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
33
33
|
'-config', '.planning/formal/tla/MCliveness.cfg',
|
|
34
|
-
'.planning/formal/tla/
|
|
34
|
+
'.planning/formal/tla/NFQuorum.tla',
|
|
35
35
|
'-workers', '1'
|
|
36
36
|
]
|
|
37
37
|
},
|
|
@@ -67,7 +67,7 @@ const MODULE_CHECKS = {
|
|
|
67
67
|
cmd: [
|
|
68
68
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
69
69
|
'-config', '.planning/formal/tla/MCbreaker.cfg',
|
|
70
|
-
'.planning/formal/tla/
|
|
70
|
+
'.planning/formal/tla/NFCircuitBreaker.tla',
|
|
71
71
|
'-workers', '1'
|
|
72
72
|
]
|
|
73
73
|
}
|
|
@@ -78,7 +78,7 @@ const MODULE_CHECKS = {
|
|
|
78
78
|
cmd: [
|
|
79
79
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
80
80
|
'-config', '.planning/formal/tla/MCdeliberation.cfg',
|
|
81
|
-
'.planning/formal/tla/
|
|
81
|
+
'.planning/formal/tla/NFDeliberation.tla',
|
|
82
82
|
'-workers', '1'
|
|
83
83
|
]
|
|
84
84
|
}
|
|
@@ -89,7 +89,7 @@ const MODULE_CHECKS = {
|
|
|
89
89
|
cmd: [
|
|
90
90
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
91
91
|
'-config', '.planning/formal/tla/MCoscillation.cfg',
|
|
92
|
-
'.planning/formal/tla/
|
|
92
|
+
'.planning/formal/tla/NFOscillation.tla',
|
|
93
93
|
'-workers', '1'
|
|
94
94
|
]
|
|
95
95
|
}
|
|
@@ -100,7 +100,7 @@ const MODULE_CHECKS = {
|
|
|
100
100
|
cmd: [
|
|
101
101
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
102
102
|
'-config', '.planning/formal/tla/MCconvergence.cfg',
|
|
103
|
-
'.planning/formal/tla/
|
|
103
|
+
'.planning/formal/tla/NFConvergence.tla',
|
|
104
104
|
'-workers', '1'
|
|
105
105
|
]
|
|
106
106
|
}
|
|
@@ -111,7 +111,7 @@ const MODULE_CHECKS = {
|
|
|
111
111
|
cmd: [
|
|
112
112
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
113
113
|
'-config', '.planning/formal/tla/MCprefilter.cfg',
|
|
114
|
-
'.planning/formal/tla/
|
|
114
|
+
'.planning/formal/tla/NFPreFilter.tla',
|
|
115
115
|
'-workers', '1'
|
|
116
116
|
]
|
|
117
117
|
}
|
|
@@ -122,7 +122,7 @@ const MODULE_CHECKS = {
|
|
|
122
122
|
cmd: [
|
|
123
123
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
124
124
|
'-config', '.planning/formal/tla/MCrecruiting-safety.cfg',
|
|
125
|
-
'.planning/formal/tla/
|
|
125
|
+
'.planning/formal/tla/NFRecruiting.tla',
|
|
126
126
|
'-workers', '1'
|
|
127
127
|
]
|
|
128
128
|
}
|
|
@@ -133,7 +133,7 @@ const MODULE_CHECKS = {
|
|
|
133
133
|
cmd: [
|
|
134
134
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
135
135
|
'-config', '.planning/formal/tla/MCaccount-manager.cfg',
|
|
136
|
-
'.planning/formal/tla/
|
|
136
|
+
'.planning/formal/tla/NFAccountManager.tla',
|
|
137
137
|
'-workers', '1'
|
|
138
138
|
]
|
|
139
139
|
}
|
|
@@ -144,7 +144,7 @@ const MODULE_CHECKS = {
|
|
|
144
144
|
cmd: [
|
|
145
145
|
'java', '-cp', '.planning/formal/tla/tla2tools.jar', 'tlc2.TLC',
|
|
146
146
|
'-config', '.planning/formal/tla/MCMCPEnv.cfg',
|
|
147
|
-
'.planning/formal/tla/
|
|
147
|
+
'.planning/formal/tla/NFMCPEnv.tla',
|
|
148
148
|
'-workers', '1'
|
|
149
149
|
]
|
|
150
150
|
}
|