fv-skills-baif 2.0.0 → 2.0.2
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/CHANGELOG.md +14 -0
- package/README.md +25 -5
- package/bin/install.js +222 -67
- package/commands/fvs/help.md +24 -13
- package/fv-skills/VERSION +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to FVS (Formal Verification Skills) will be documented in th
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [2.0.2] - 2026-07-02
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Codex installs now enable hooks with `[features].hooks = true` instead of an invalid root-level `hooks = true`, which current Codex parses as the hooks config table and rejects at startup.
|
|
11
|
+
|
|
12
|
+
## [2.0.1] - 2026-07-01
|
|
13
|
+
|
|
14
|
+
Documentation polish. No code or behavior changes.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- README "How It Works" now documents the Aeneas extraction repair loop, the trust audit, and the paper track's crypto loop -- previously only the v1.x five-stage functional-correctness flow was described; the tagline and Prerequisites now cover both the code and paper tracks
|
|
18
|
+
- `/fvs:help` documents the crypto loop's `--codex` single- vs dual-runtime flag (which stages accept it, what it swaps, and the no-silent-fallback behavior), and Quick Start / Core Workflow now surface the extraction and crypto-loop entry points
|
|
19
|
+
- Install screenshot (`assets/terminal.svg`) version label updated to the v2.0 line
|
|
20
|
+
|
|
7
21
|
## [2.0.0] - 2026-06-30
|
|
8
22
|
|
|
9
23
|
Structural cleanup and bundle architecture. Updating from v1.3 applies all renames, moves, and removals automatically (deleted and renamed commands/agents self-heal on install); the installer prints a one-time summary of the changes below.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# FORMAL VERIFICATION SKILLS
|
|
4
4
|
|
|
5
|
-
**Formal verification
|
|
5
|
+
**Formal verification in Lean 4 with AI-assisted specification and proof — for Rust code (via Aeneas) and for maths/crypto papers. Multi-runtime.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/fv-skills-baif)
|
|
8
8
|
[](LICENSE)
|
|
@@ -54,9 +54,10 @@ Verify with `/fvs:help` inside your chosen runtime.
|
|
|
54
54
|
|
|
55
55
|
### Prerequisites (Lean 4 / Aeneas)
|
|
56
56
|
|
|
57
|
-
- A Lean 4 project with `lakefile.toml` and `lean-toolchain`
|
|
58
|
-
- Aeneas-generated
|
|
59
|
-
-
|
|
57
|
+
- A working Lean 4 toolchain, and a Lean project with `lakefile.toml` and `lean-toolchain`
|
|
58
|
+
- **Functional-correctness track:** Aeneas-generated Lean (`Types.lean`, `Funs.lean`). Produce it from a Rust crate with `/fvs:aeneas-extract`, or supply the output of an existing Aeneas run.
|
|
59
|
+
- **Paper track:** no Rust or Aeneas needed — bring your paper/source material (PDF, LaTeX, images).
|
|
60
|
+
- **Optional:** the Codex CLI, to run the crypto loop's thinking stages dual-runtime (`--codex`).
|
|
60
61
|
|
|
61
62
|
### Recommended: Lean LSP MCP Server
|
|
62
63
|
|
|
@@ -150,7 +151,9 @@ Commands are grouped into five bundles. Each bundle has a **router** command tha
|
|
|
150
151
|
|
|
151
152
|
## How It Works
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
### Functional-correctness track (Rust → Lean 4)
|
|
155
|
+
|
|
156
|
+
This track verifies Rust that Aeneas has lowered to Lean 4. Starting from a Rust crate, `/fvs:aeneas-extract <path>` drives it through the bounded **extraction repair loop** — pin audit → classify → auto-apply / bisect / gate / escalate → reversible records — until you reach a clean build or a documented escalation. It writes reversible source records (`src-modifications.diff` plus a derived `.json`/`.md` and `src-assumptions.md`) at the crate root and never edits generated Lean. Once you have `Types.lean` / `Funs.lean`, the five-stage verification workflow begins:
|
|
154
157
|
|
|
155
158
|
### 1. Map
|
|
156
159
|
|
|
@@ -172,6 +175,23 @@ FVS follows a five-stage workflow. Each stage builds on the previous.
|
|
|
172
175
|
|
|
173
176
|
`/fvs:lean-refactor <spec_path>` — Refactor, simplify, and decompose verified proofs. Applies tiered heuristics (dead code removal, simp sharpening, tactic golf, smart automation) while verifying compilation after every change. Three modes: safe, balanced (default), and aggressive.
|
|
174
177
|
|
|
178
|
+
### 6. Audit
|
|
179
|
+
|
|
180
|
+
`/fvs:trust-audit <target>` — Build-backed audit of the trust surface. Runs a green-build precondition, then uses `#print axioms` to classify every in-scope declaration as verified / `sorry` / axiom. The classical trio (`propext`, `Classical.choice`, `Quot.sound`) is auto-noted as Lean/Mathlib-standard; any project-custom axiom must be justified or the gate reports NOT-CLEAN. Produces a re-runnable, dependency-ordered table under `.formalising/audits/`.
|
|
181
|
+
|
|
182
|
+
### The paper track (maths / crypto)
|
|
183
|
+
|
|
184
|
+
The paper track formalises papers directly into Lean 4 — no Rust, no Aeneas. Two entry points:
|
|
185
|
+
|
|
186
|
+
- **One-shot:** `/fvs:lean-formalise` reads your PDFs / images / LaTeX (optionally grounded in a NotebookLM knowledge base via `/fvs:kb-setup`) and produces Lean definition and spec files in a single pass.
|
|
187
|
+
- **Iterative crypto loop:** for larger crypto formalisations, a topic-based, restartable loop of four stages:
|
|
188
|
+
|
|
189
|
+
`/fvs:crypto-plan` → `/fvs:crypto-execute` → `/fvs:crypto-eval` → `/fvs:crypto-followup` → repeat
|
|
190
|
+
|
|
191
|
+
A high-effort thinker authors each bounded plan; the executor runs it under a green-build guard; an adversarial eval tries to refute the spec, proof, and assumptions and ends in exactly one of ACCEPT / FOLLOWUP / HUMAN_RULING / BLOCKED; follow-up turns findings into the next plan (halting for a human ruling on modeling decisions).
|
|
192
|
+
|
|
193
|
+
**Single- vs dual-runtime (`--codex`).** By default the loop is single-runtime — the thinking stages (`crypto-plan`, `crypto-eval`, `crypto-followup`) run the in-runtime `fvs-crypto-thinker`. Pass `--codex` to hand a stage's thinking to an independent **Codex CLI** thinker instead, so the adversarial planner/evaluator runs on a *different engine* than the executor and blind spots don't correlate. `crypto-execute` is the runtime-neutral executor and takes no `--codex`. Without the Codex CLI installed, a `--codex` stage stops with an install hint rather than silently falling back.
|
|
194
|
+
|
|
175
195
|
---
|
|
176
196
|
|
|
177
197
|
## Uninstalling
|
package/bin/install.js
CHANGED
|
@@ -16,13 +16,20 @@ const reset = '\x1b[0m';
|
|
|
16
16
|
// Codex config.toml constants
|
|
17
17
|
const FVS_CODEX_MARKER = '# FVS Agent Configuration \u2014 managed by fv-skills-baif installer';
|
|
18
18
|
|
|
19
|
-
// Codex hooks feature flag. Current Codex CLI reads
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// over an older config migrates
|
|
19
|
+
// Codex hooks feature flag. Current Codex CLI reads feature flags under the
|
|
20
|
+
// `[features]` table; a root-level `hooks = true` is parsed as the hooks config
|
|
21
|
+
// object itself and is rejected. Emit `[features].hooks`, and treat the legacy
|
|
22
|
+
// alias as equivalent so a reinstall over an older config migrates forward
|
|
23
|
+
// instead of leaving a duplicate.
|
|
23
24
|
const CODEX_HOOKS_FEATURE_KEY = 'hooks';
|
|
24
25
|
const CODEX_HOOKS_FEATURE_LEGACY_KEYS = ['codex_hooks'];
|
|
25
26
|
const CODEX_HOOKS_FEATURE_ALL_KEYS = [CODEX_HOOKS_FEATURE_KEY, ...CODEX_HOOKS_FEATURE_LEGACY_KEYS];
|
|
27
|
+
const CODEX_FEATURES_TABLE = 'features';
|
|
28
|
+
const FVS_CODEX_HOOKS_FEATURE_COMMENT = '# FVS-owned Codex hooks feature flag';
|
|
29
|
+
|
|
30
|
+
function isCodexHooksFeatureKey(key) {
|
|
31
|
+
return CODEX_HOOKS_FEATURE_ALL_KEYS.includes(key);
|
|
32
|
+
}
|
|
26
33
|
|
|
27
34
|
// The only FVS hook script with a Codex event target is the update checker,
|
|
28
35
|
// wired as a SessionStart hook. The statusline has no Codex renderer surface and
|
|
@@ -1083,6 +1090,123 @@ function removeContentRanges(content, ranges) {
|
|
|
1083
1090
|
return cleaned;
|
|
1084
1091
|
}
|
|
1085
1092
|
|
|
1093
|
+
function joinTomlLines(lines) {
|
|
1094
|
+
return lines.map((line) => line.text + line.eol).join('');
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
function parseCodexHooksFeatureAssignment(lineText) {
|
|
1098
|
+
const m = lineText.match(/^\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z0-9_]+))\s*=\s*(true|false)(\s*(?:#.*)?)?$/);
|
|
1099
|
+
if (!m) return null;
|
|
1100
|
+
const key = m[1] || m[2] || m[3];
|
|
1101
|
+
if (!isCodexHooksFeatureKey(key)) return null;
|
|
1102
|
+
return { key, value: m[4], suffix: m[5] || '' };
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function parseRootDottedCodexHooksFeatureAssignment(lineText) {
|
|
1106
|
+
const m = lineText.match(/^\s*features\.(?:"([^"]+)"|'([^']+)'|([A-Za-z0-9_]+))\s*=\s*(true|false)(\s*(?:#.*)?)?$/);
|
|
1107
|
+
if (!m) return null;
|
|
1108
|
+
const key = m[1] || m[2] || m[3];
|
|
1109
|
+
if (!isCodexHooksFeatureKey(key)) return null;
|
|
1110
|
+
return { key, value: m[4], suffix: m[5] || '' };
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
function renderCodexHooksFeatureAssignment(lineText) {
|
|
1114
|
+
const indent = (lineText.match(/^\s*/) || [''])[0];
|
|
1115
|
+
const parsed = parseCodexHooksFeatureAssignment(lineText);
|
|
1116
|
+
return `${indent}${CODEX_HOOKS_FEATURE_KEY} = true${parsed ? parsed.suffix : ''}`;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
function renderRootDottedCodexHooksFeatureAssignment(lineText) {
|
|
1120
|
+
const indent = (lineText.match(/^\s*/) || [''])[0];
|
|
1121
|
+
const parsed = parseRootDottedCodexHooksFeatureAssignment(lineText);
|
|
1122
|
+
return `${indent}features.${CODEX_HOOKS_FEATURE_KEY} = true${parsed ? parsed.suffix : ''}`;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
function removeRootCodexHooksFeatureFlags(content) {
|
|
1126
|
+
const lines = splitTomlLines(content);
|
|
1127
|
+
const firstHeaderIdx = lines.findIndex((line) => parseTomlTableHeader(line.text));
|
|
1128
|
+
let changed = false;
|
|
1129
|
+
const kept = lines.filter((line, index) => {
|
|
1130
|
+
if (firstHeaderIdx !== -1 && index >= firstHeaderIdx) return true;
|
|
1131
|
+
if (!parseCodexHooksFeatureAssignment(line.text)) return true;
|
|
1132
|
+
changed = true;
|
|
1133
|
+
return false;
|
|
1134
|
+
});
|
|
1135
|
+
return { content: changed ? joinTomlLines(kept) : content, changed };
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function getCodexFeaturesSection(content) {
|
|
1139
|
+
return getTomlTableSections(content)
|
|
1140
|
+
.find((section) => !section.array && section.path === CODEX_FEATURES_TABLE);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
function rewriteRootDottedCodexHooksFeature(content) {
|
|
1144
|
+
const lines = splitTomlLines(content);
|
|
1145
|
+
const firstHeaderIdx = lines.findIndex((line) => parseTomlTableHeader(line.text));
|
|
1146
|
+
let found = false;
|
|
1147
|
+
let changed = false;
|
|
1148
|
+
const kept = [];
|
|
1149
|
+
|
|
1150
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
1151
|
+
const line = lines[i];
|
|
1152
|
+
if (firstHeaderIdx !== -1 && i >= firstHeaderIdx) {
|
|
1153
|
+
kept.push(line);
|
|
1154
|
+
continue;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
if (!parseRootDottedCodexHooksFeatureAssignment(line.text)) {
|
|
1158
|
+
kept.push(line);
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
if (!found) {
|
|
1163
|
+
found = true;
|
|
1164
|
+
const rendered = renderRootDottedCodexHooksFeatureAssignment(line.text);
|
|
1165
|
+
if (rendered !== line.text) changed = true;
|
|
1166
|
+
kept.push({ ...line, text: rendered });
|
|
1167
|
+
} else {
|
|
1168
|
+
changed = true;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
return { content: changed ? joinTomlLines(kept) : content, found, changed };
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
function stripFvsManagedCodexHooksFeature(content) {
|
|
1176
|
+
// Self-heal v2.0.1 installs, which wrote the now-invalid root `hooks = true`.
|
|
1177
|
+
let cleaned = removeRootCodexHooksFeatureFlags(content).content;
|
|
1178
|
+
const featuresSection = getCodexFeaturesSection(cleaned);
|
|
1179
|
+
if (!featuresSection) return cleaned;
|
|
1180
|
+
|
|
1181
|
+
const body = cleaned.slice(featuresSection.headerEnd, featuresSection.end);
|
|
1182
|
+
const lines = splitTomlLines(body);
|
|
1183
|
+
const kept = [];
|
|
1184
|
+
let removed = false;
|
|
1185
|
+
|
|
1186
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
1187
|
+
const line = lines[i];
|
|
1188
|
+
if (line.text.trim() === FVS_CODEX_HOOKS_FEATURE_COMMENT) {
|
|
1189
|
+
removed = true;
|
|
1190
|
+
const next = lines[i + 1];
|
|
1191
|
+
if (next && parseCodexHooksFeatureAssignment(next.text)) {
|
|
1192
|
+
i += 1;
|
|
1193
|
+
}
|
|
1194
|
+
continue;
|
|
1195
|
+
}
|
|
1196
|
+
kept.push(line);
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
if (!removed) return cleaned;
|
|
1200
|
+
|
|
1201
|
+
const nextBody = joinTomlLines(kept);
|
|
1202
|
+
const hasRemainingContent = nextBody.split(/\r?\n/).some((line) => line.trim() !== '');
|
|
1203
|
+
if (!hasRemainingContent) {
|
|
1204
|
+
return cleaned.slice(0, featuresSection.start) + cleaned.slice(featuresSection.end);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
return cleaned.slice(0, featuresSection.headerEnd) + nextBody + cleaned.slice(featuresSection.end);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1086
1210
|
/**
|
|
1087
1211
|
* Strip FVS sections from Codex config.toml content.
|
|
1088
1212
|
*
|
|
@@ -1129,21 +1253,11 @@ function stripFvsFromCodexConfig(content) {
|
|
|
1129
1253
|
cleaned = before + after;
|
|
1130
1254
|
}
|
|
1131
1255
|
|
|
1132
|
-
// Remove the FVS-owned
|
|
1133
|
-
//
|
|
1134
|
-
//
|
|
1135
|
-
// orphaned. Only strip it when the FVS marker was present — a flag in a
|
|
1136
|
-
// config that FVS never marked is the user's and must be preserved.
|
|
1256
|
+
// Remove the FVS-owned hooks feature gate. v2.0.1 emitted an invalid root
|
|
1257
|
+
// `hooks = true`; current installs mark their `[features].hooks` insertion so
|
|
1258
|
+
// uninstall can remove only the FVS-owned line and preserve user/GSD flags.
|
|
1137
1259
|
if (hadFvsMarker) {
|
|
1138
|
-
|
|
1139
|
-
const firstHeaderIdx = flagLines.findIndex((l) => /^\s*\[/.test(l));
|
|
1140
|
-
cleaned = flagLines
|
|
1141
|
-
.filter((line, i) => {
|
|
1142
|
-
if (firstHeaderIdx !== -1 && i >= firstHeaderIdx) return true;
|
|
1143
|
-
const m = line.match(/^\s*([A-Za-z0-9_]+)\s*=\s*true\s*$/);
|
|
1144
|
-
return !(m && CODEX_HOOKS_FEATURE_ALL_KEYS.includes(m[1]));
|
|
1145
|
-
})
|
|
1146
|
-
.join('\n');
|
|
1260
|
+
cleaned = stripFvsManagedCodexHooksFeature(cleaned);
|
|
1147
1261
|
}
|
|
1148
1262
|
|
|
1149
1263
|
// Collapse runs of blank lines the removals may have left behind, then
|
|
@@ -1165,9 +1279,9 @@ function stripFvsFromCodexConfig(content) {
|
|
|
1165
1279
|
*
|
|
1166
1280
|
* On reinstall this first strips any previously-emitted FVS tables via the
|
|
1167
1281
|
* TOML-aware strip (so foreign user/GSD tables survive verbatim and stale FVS
|
|
1168
|
-
* tables are removed), then appends the freshly-generated FVS block. The
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1282
|
+
* tables are removed), then appends the freshly-generated FVS agent block. The
|
|
1283
|
+
* hook feature gate is handled separately by ensureCodexHooksFeature so it can
|
|
1284
|
+
* coexist with user/GSD `[features]` settings.
|
|
1171
1285
|
*/
|
|
1172
1286
|
function mergeCodexConfig(configPath, fvsBlock) {
|
|
1173
1287
|
// Case 1: No config.toml -- create fresh.
|
|
@@ -1539,62 +1653,103 @@ function removeCodexHooksJsonSessionStart(targetDir) {
|
|
|
1539
1653
|
return reconcileCodexHooksJsonSessionStart(targetDir, { managedCommand: null });
|
|
1540
1654
|
}
|
|
1541
1655
|
|
|
1542
|
-
// Ensure the Codex hooks feature flag is present
|
|
1543
|
-
//
|
|
1544
|
-
//
|
|
1545
|
-
//
|
|
1656
|
+
// Ensure the Codex hooks feature flag is present as `[features].hooks = true`.
|
|
1657
|
+
// Older FVS versions wrote root-level `hooks = true`, which current Codex parses
|
|
1658
|
+
// as the hooks config table and rejects; remove that stale shape while inserting
|
|
1659
|
+
// the valid feature flag.
|
|
1546
1660
|
function ensureCodexHooksFeature(configContent) {
|
|
1547
|
-
const
|
|
1661
|
+
const original = typeof configContent === 'string' ? configContent : '';
|
|
1662
|
+
const rootStripped = removeRootCodexHooksFeatureFlags(original);
|
|
1663
|
+
let content = rootStripped.content;
|
|
1548
1664
|
const eol = content ? detectLineEnding(content) : '\n';
|
|
1549
|
-
const lines = content.length ? content.split(/\r?\n/) : [];
|
|
1550
1665
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1666
|
+
const featuresSection = getCodexFeaturesSection(content);
|
|
1667
|
+
if (featuresSection) {
|
|
1668
|
+
const body = content.slice(featuresSection.headerEnd, featuresSection.end);
|
|
1669
|
+
const lines = splitTomlLines(body);
|
|
1670
|
+
let found = false;
|
|
1671
|
+
let changed = rootStripped.changed;
|
|
1672
|
+
const kept = [];
|
|
1673
|
+
|
|
1674
|
+
for (const line of lines) {
|
|
1675
|
+
const parsed = parseCodexHooksFeatureAssignment(line.text);
|
|
1676
|
+
if (!parsed) {
|
|
1677
|
+
kept.push(line);
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
if (!found) {
|
|
1682
|
+
found = true;
|
|
1683
|
+
const rendered = renderCodexHooksFeatureAssignment(line.text);
|
|
1684
|
+
if (rendered !== line.text) changed = true;
|
|
1685
|
+
kept.push({ ...line, text: rendered });
|
|
1686
|
+
} else {
|
|
1687
|
+
changed = true;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
if (found) {
|
|
1692
|
+
const next = content.slice(0, featuresSection.headerEnd) +
|
|
1693
|
+
joinTomlLines(kept) +
|
|
1694
|
+
content.slice(featuresSection.end);
|
|
1695
|
+
return { content: next, changed: changed || next !== original };
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
const needsLineBreak = featuresSection.end > 0 &&
|
|
1699
|
+
!content.slice(0, featuresSection.end).endsWith('\n') &&
|
|
1700
|
+
!content.slice(0, featuresSection.end).endsWith('\r\n');
|
|
1701
|
+
const insertText = `${needsLineBreak ? eol : ''}${FVS_CODEX_HOOKS_FEATURE_COMMENT}${eol}${CODEX_HOOKS_FEATURE_KEY} = true${eol}`;
|
|
1702
|
+
const next = content.slice(0, featuresSection.end) + insertText + content.slice(featuresSection.end);
|
|
1703
|
+
return { content: next, changed: true };
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
const dotted = rewriteRootDottedCodexHooksFeature(content);
|
|
1707
|
+
if (dotted.found) {
|
|
1708
|
+
return { content: dotted.content, changed: rootStripped.changed || dotted.changed || dotted.content !== original };
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
const featuresBlock = [
|
|
1712
|
+
`[${CODEX_FEATURES_TABLE}]`,
|
|
1713
|
+
FVS_CODEX_HOOKS_FEATURE_COMMENT,
|
|
1714
|
+
`${CODEX_HOOKS_FEATURE_KEY} = true`,
|
|
1715
|
+
'',
|
|
1716
|
+
].join(eol);
|
|
1717
|
+
|
|
1718
|
+
if (!content) return { content: featuresBlock, changed: true };
|
|
1719
|
+
|
|
1720
|
+
const firstTable = getTomlTableSections(content)[0];
|
|
1721
|
+
if (firstTable) {
|
|
1722
|
+
const before = content.slice(0, firstTable.start);
|
|
1723
|
+
const after = content.slice(firstTable.start);
|
|
1724
|
+
const needsGap = before.length > 0 && !before.endsWith(eol + eol);
|
|
1725
|
+
const next = before + (needsGap ? eol : '') + featuresBlock + eol + after;
|
|
1582
1726
|
return { content: next, changed: true };
|
|
1583
1727
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1728
|
+
|
|
1729
|
+
const base = content.trimEnd();
|
|
1730
|
+
const needsGap = base.length > 0;
|
|
1731
|
+
const next = `${base}${needsGap ? eol + eol : ''}${featuresBlock}`;
|
|
1732
|
+
return { content: next, changed: true };
|
|
1586
1733
|
}
|
|
1587
1734
|
|
|
1588
1735
|
function hasEnabledCodexHooksFeature(configContent) {
|
|
1589
1736
|
if (typeof configContent !== 'string') return false;
|
|
1590
|
-
const
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1737
|
+
const featuresSection = getCodexFeaturesSection(configContent);
|
|
1738
|
+
if (featuresSection) {
|
|
1739
|
+
const body = configContent.slice(featuresSection.headerEnd, featuresSection.end);
|
|
1740
|
+
for (const line of splitTomlLines(body)) {
|
|
1741
|
+
const parsed = parseCodexHooksFeatureAssignment(line.text);
|
|
1742
|
+
if (parsed && parsed.value === 'true') return true;
|
|
1743
|
+
}
|
|
1596
1744
|
}
|
|
1597
|
-
|
|
1745
|
+
|
|
1746
|
+
const lines = splitTomlLines(configContent);
|
|
1747
|
+
const firstHeaderIdx = lines.findIndex((line) => parseTomlTableHeader(line.text));
|
|
1748
|
+
return lines.some((line, index) => {
|
|
1749
|
+
if (firstHeaderIdx !== -1 && index >= firstHeaderIdx) return false;
|
|
1750
|
+
const parsed = parseRootDottedCodexHooksFeatureAssignment(line.text);
|
|
1751
|
+
return Boolean(parsed && parsed.value === 'true');
|
|
1752
|
+
});
|
|
1598
1753
|
}
|
|
1599
1754
|
|
|
1600
1755
|
/**
|
package/commands/fvs/help.md
CHANGED
|
@@ -23,18 +23,25 @@ Commands are grouped into five bundles. Each bundle has a router command (e.g. `
|
|
|
23
23
|
|
|
24
24
|
## Quick Start
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
**From a Rust crate — functional-correctness track:**
|
|
27
|
+
1. `/fvs:aeneas-extract <path>` - Extract Rust → Lean 4 via the bounded Aeneas repair loop
|
|
28
|
+
2. `/fvs:map-code` - Analyze project, build dependency graph
|
|
29
|
+
3. `/fvs:fc-plan` - Select verification targets
|
|
30
|
+
4. `/fvs:lean-specify <function>` - Generate spec with sorry
|
|
31
|
+
5. `/fvs:lean-verify <spec_path>` - Attempt proof interactively
|
|
32
|
+
6. `/fvs:lean-refactor <spec_path>` - Golf and clean up verified proofs
|
|
33
|
+
7. `/fvs:trust-audit <target>` - Audit the sorry/axiom trust surface
|
|
34
|
+
|
|
35
|
+
**From a paper — paper track:**
|
|
36
|
+
- `/fvs:lean-formalise` - One-shot formalisation of paper/math content, or
|
|
37
|
+
- `/fvs:crypto-plan <topic>` - Start the multi-iteration crypto loop (see Formalise below)
|
|
32
38
|
|
|
33
39
|
## Core Workflow
|
|
34
40
|
|
|
35
41
|
```
|
|
36
|
-
/fvs:map-code → /fvs:fc-plan → /fvs:lean-specify → /fvs:lean-verify → /fvs:lean-refactor →
|
|
37
|
-
Paper track:
|
|
42
|
+
Code track: /fvs:aeneas-extract → /fvs:map-code → /fvs:fc-plan → /fvs:lean-specify → /fvs:lean-verify → /fvs:lean-refactor → /fvs:trust-audit
|
|
43
|
+
Paper track: /fvs:lean-formalise → /fvs:lean-verify → /fvs:lean-refactor
|
|
44
|
+
Crypto loop: /fvs:crypto-plan → /fvs:crypto-execute → /fvs:crypto-eval → /fvs:crypto-followup → repeat
|
|
38
45
|
```
|
|
39
46
|
|
|
40
47
|
## Bundles
|
|
@@ -188,24 +195,28 @@ Refactor, simplify, and decompose verified Lean proofs while preserving compilat
|
|
|
188
195
|
|
|
189
196
|
Usage: `/fvs:lean-refactor Specs/Backend/Field/Sub.lean`
|
|
190
197
|
|
|
191
|
-
The crypto formalisation loop (plan -> execute -> eval -> follow-up) is a topic-based, multi-iteration alternative to the one-shot `lean-formalise`. Its four stages share the artifact tree under `fv-plans/<topic>/` and the loop is restartable from those records.
|
|
198
|
+
The crypto formalisation loop (plan -> execute -> eval -> follow-up) is a topic-based, multi-iteration alternative to the one-shot `lean-formalise`. Its four stages share the artifact tree under `fv-plans/<topic>/` and the loop is restartable from those records.
|
|
192
199
|
|
|
193
|
-
|
|
200
|
+
**Single- vs dual-runtime (`--codex`).** By default the loop is *single-runtime*: the high-effort thinking (planning, adversarial eval, follow-up) is done by the in-runtime `fvs-crypto-thinker`. The three *thinking* stages — `crypto-plan`, `crypto-eval`, `crypto-followup` — also accept `--codex`, which hands that stage's thinking to an independent **Codex CLI** thinker instead. That makes the loop *dual-runtime*: the adversarial planner/evaluator runs on a different engine than the executor, reducing correlated blind spots. `crypto-execute` is the runtime-neutral executor and takes no `--codex`. Pass `--codex` without the Codex CLI installed and the stage stops with an install hint (never a silent fallback) — re-run without it to stay single-runtime.
|
|
201
|
+
|
|
202
|
+
**`/fvs:crypto-plan <topic> [nN] [--codex]`**
|
|
194
203
|
Author the next bounded, runtime-neutral executor plan for a topic, grounded in the paper via the NotebookLM knowledge base (answers cached under `sources/`).
|
|
195
204
|
|
|
196
205
|
Usage: `/fvs:crypto-plan "CKA from KEM"`
|
|
206
|
+
Usage: `/fvs:crypto-plan "CKA from KEM" --codex` # hand the planning think-step to Codex
|
|
197
207
|
|
|
198
208
|
**`/fvs:crypto-execute <topic> nN`**
|
|
199
|
-
Run the current iteration's bounded plan under the green-build guard; a failed proof triggers a short interactive redirect early.
|
|
209
|
+
Run the current iteration's bounded plan under the green-build guard; a failed proof triggers a short interactive redirect early. (Executor stage — takes no `--codex`.)
|
|
200
210
|
|
|
201
211
|
Usage: `/fvs:crypto-execute "CKA from KEM" n1`
|
|
202
212
|
|
|
203
|
-
**`/fvs:crypto-eval <topic> nN`**
|
|
213
|
+
**`/fvs:crypto-eval <topic> nN [--codex]`**
|
|
204
214
|
Adversarially evaluate the iteration; ends in exactly one decision (ACCEPT / FOLLOWUP / HUMAN_RULING / BLOCKED).
|
|
205
215
|
|
|
206
216
|
Usage: `/fvs:crypto-eval "CKA from KEM" n1`
|
|
217
|
+
Usage: `/fvs:crypto-eval "CKA from KEM" n1 --codex`
|
|
207
218
|
|
|
208
|
-
**`/fvs:crypto-followup <topic> nN`**
|
|
219
|
+
**`/fvs:crypto-followup <topic> nN [--codex]`**
|
|
209
220
|
Convert eval findings into the next bounded follow-up plan; HALTs for a human ruling on a modeling decision.
|
|
210
221
|
|
|
211
222
|
Usage: `/fvs:crypto-followup "CKA from KEM" n1`
|
package/fv-skills/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.0.
|
|
1
|
+
2.0.2
|
package/package.json
CHANGED