fv-skills-baif 2.0.2 → 2.1.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/CHANGELOG.md +35 -0
- package/README.md +21 -7
- package/agents/fvs-crypto-executor.md +138 -0
- package/agents/fvs-crypto-thinker.md +12 -1
- package/agents/fvs-executor.md +23 -0
- package/agents/fvs-researcher.md +6 -2
- package/bin/install.js +81 -16
- package/commands/fvs/crypto-eval.md +4 -3
- package/commands/fvs/crypto-execute.md +75 -35
- package/commands/fvs/crypto-followup.md +18 -6
- package/commands/fvs/crypto-plan.md +22 -7
- package/commands/fvs/crypto-review.md +181 -0
- package/commands/fvs/formalise.md +6 -2
- package/commands/fvs/help.md +25 -2
- package/commands/fvs/lean-specify.md +83 -11
- package/commands/fvs/lean-verify.md +91 -11
- package/commands/fvs/sync-aeneas-verif.md +33 -0
- package/fv-skills/VERSION +1 -1
- package/fv-skills/references/crypto-plan-review.md +195 -0
- package/fv-skills/references/lean-spec-conventions.md +37 -0
- package/fv-skills/references/model-profiles.md +30 -3
- package/fv-skills/templates/config.json +4 -2
- package/fv-skills/workflows/crypto-execute.md +25 -27
- package/fv-skills/workflows/crypto-followup.md +5 -0
- package/fv-skills/workflows/crypto-plan.md +7 -1
- package/fv-skills/workflows/crypto-review.md +80 -0
- package/fv-skills/workflows/lean-specify.md +44 -3
- package/fv-skills/workflows/lean-verify.md +48 -4
- package/fv-skills/workflows/sync-aeneas-verif.md +24 -0
- package/hooks/dist/fvs-statusline.js +1 -1
- package/package.json +1 -1
- package/scripts/fvs-codex-think.mjs +315 -23
- package/scripts/fvs-lean-style-check.mjs +486 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,41 @@ 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.1.0] - 2026-07-26
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- `/fvs:crypto-review` sends an initial or follow-up crypto plan to authenticated Codex for an
|
|
11
|
+
independent pre-execution adversarial review. Codex runs xhigh, effort-only, ephemeral, and
|
|
12
|
+
read-only; the FVS wrapper persists one validated review artifact and the primary planning seat
|
|
13
|
+
records its evidence-backed response. Codex-authored/unknown-provenance plans and non-APPROVE
|
|
14
|
+
verdicts fail closed before execution.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `/fvs:lean-specify` and `/fvs:lean-verify` now discover and fully load the target repository's
|
|
18
|
+
style guide (configurable with `project.style_guide_path`) into both research and execution
|
|
19
|
+
prompts. A shipped post-write checker enforces the repository line limit (100-column fallback)
|
|
20
|
+
and rejects new ordinary identifiers with three or more namespace dots; verification preserves
|
|
21
|
+
legacy debt only through an explicit baseline and requires full compliance for statement edits.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- FVS installs now verify the shipped Aeneas `_sync-meta.json` mapping and the sync command reports
|
|
25
|
+
real update/reinstall recovery instead of a nonexistent Aeneas installer option.
|
|
26
|
+
- The config template now uses the top-level model schema consumed by commands and defaults
|
|
27
|
+
`fvs-crypto-thinker` to `inherit`.
|
|
28
|
+
|
|
29
|
+
## [2.0.3] - 2026-07-04
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- The crypto formalisation loop now drives a dedicated crypto executor with an `implement -> check -> complete -> escalate -> BLOCKED` discipline, replacing the borrowed functional-correctness one-sorry-at-a-time proof-attempt grind that did not fit crypto work.
|
|
33
|
+
- `/fvs:crypto-execute` gained a runtime-agnostic executor model/effort knob resolved at dispatch time (explicit flag, then a config `model_overrides` entry, then an interactive ask, then inherit the default) so the executor is never hard-pinned to one model.
|
|
34
|
+
- The crypto thinker's plan mode is fenced to producing statements rather than proofs, with an added escalate-to-user tier when a step exceeds its remit.
|
|
35
|
+
- Guidance now treats `lake build` as the style authority for crypto work, and isolation checks skip the package's own style linters to avoid contradictory signals.
|
|
36
|
+
- `/fvs:lean-verify` received a minimal refresh keeping proof-attempt behavior functional-correctness-scoped, decoupling it from the crypto executor without a rewrite.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Codex `hooks.json` is now written in the nested `{ hooks: { ... } }` shape that current Codex expects; pre-existing flat hook files are migrated on reinstall while foreign entries are preserved.
|
|
40
|
+
- Corrected the crypto-plan knowledge-base invocation path so KB querying resolves the intended interpreter and script location.
|
|
41
|
+
|
|
7
42
|
## [2.0.2] - 2026-07-02
|
|
8
43
|
|
|
9
44
|
### Fixed
|
package/README.md
CHANGED
|
@@ -121,12 +121,18 @@ Commands are grouped into five bundles. Each bundle has a **router** command tha
|
|
|
121
121
|
| Command | Description |
|
|
122
122
|
|---------|-------------|
|
|
123
123
|
| `/fvs:fc-plan` | Pick next verification targets via greedy dependency graph traversal |
|
|
124
|
-
| `/fvs:lean-specify` | Generate Lean spec skeleton with `@[step]` theorem pattern |
|
|
125
|
-
| `/fvs:lean-verify` | Attempt proof
|
|
124
|
+
| `/fvs:lean-specify` | Generate a style-checked Lean spec skeleton with `@[step]` theorem pattern |
|
|
125
|
+
| `/fvs:lean-verify` | Attempt proof with domain tactics while blocking new target-style violations |
|
|
126
126
|
| `/fvs:natural-language` | Generate natural language explanation of module or function with pre/post conditions |
|
|
127
127
|
| `/fvs:lean-refactor` | Refactor, simplify, and decompose verified proofs (dead code removal, simp sharpening, tactic golf) — *also in Formalise* |
|
|
128
128
|
| `/fvs:trust-audit` | Build-backed audit of every sorry/axiom affecting a target layer; `#print axioms` classification, fail-if-unjustified gate, dependency-ordered table |
|
|
129
129
|
|
|
130
|
+
`lean-specify` and `lean-verify` load a target style guide from
|
|
131
|
+
`.formalising/fvs-config.json` (`project.style_guide_path`) or discover standard files such as
|
|
132
|
+
`doc/STYLE_GUIDE`. With no guide they enforce a 100-column fallback. Their post-write gate also
|
|
133
|
+
rejects ordinary Lean identifiers with three or more namespace dots, steering generated code
|
|
134
|
+
toward scoped namespaces, `open`, and local names.
|
|
135
|
+
|
|
130
136
|
### Formalise (Paper Track) — `/fvs:formalise`
|
|
131
137
|
|
|
132
138
|
| Command | Description |
|
|
@@ -134,6 +140,7 @@ Commands are grouped into five bundles. Each bundle has a **router** command tha
|
|
|
134
140
|
| `/fvs:lean-formalise` | Formalise paper/math content into Lean 4 specs and definitions (one-shot) |
|
|
135
141
|
| `/fvs:lean-refactor` | Refactor, simplify, and decompose verified proofs — *also in Formal-Core* |
|
|
136
142
|
| `/fvs:crypto-plan` | Author the next bounded, runtime-neutral plan for a topic-based crypto formalisation iteration (KB-grounded, cached under `sources/`) |
|
|
143
|
+
| `/fvs:crypto-review` | Send an initial or follow-up crypto plan to authenticated Codex for independent, read-only adversarial review before execution |
|
|
137
144
|
| `/fvs:crypto-execute` | Run the current iteration's bounded plan under the green-build guard |
|
|
138
145
|
| `/fvs:crypto-eval` | Adversarially evaluate the iteration; ends in one of ACCEPT / FOLLOWUP / HUMAN_RULING / BLOCKED |
|
|
139
146
|
| `/fvs:crypto-followup` | Convert eval findings into the next follow-up plan; HALTs on HUMAN_RULING |
|
|
@@ -184,11 +191,18 @@ This track verifies Rust that Aeneas has lowered to Lean 4. Starting from a Rust
|
|
|
184
191
|
The paper track formalises papers directly into Lean 4 — no Rust, no Aeneas. Two entry points:
|
|
185
192
|
|
|
186
193
|
- **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
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
194
|
+
- **Iterative crypto loop:** for larger crypto formalisations, a topic-based, restartable loop with
|
|
195
|
+
an independent pre-execution review gate:
|
|
196
|
+
|
|
197
|
+
`/fvs:crypto-plan` → `/fvs:crypto-review` → `/fvs:crypto-execute` → `/fvs:crypto-eval` → `/fvs:crypto-followup` → `/fvs:crypto-review` → repeat
|
|
198
|
+
|
|
199
|
+
A high-effort thinker authors each bounded plan. Before execution, authenticated Codex
|
|
200
|
+
independently attacks the plan or follow-up under a read-only sandbox and returns an
|
|
201
|
+
evidence-backed APPROVE / APPROVE-WITH-EDITS / REJECT verdict. The executor runs an approved plan
|
|
202
|
+
under a green-build guard; the post-execution adversarial eval tries to refute the spec, proof,
|
|
203
|
+
and assumptions and ends in exactly one of ACCEPT / FOLLOWUP / HUMAN_RULING / BLOCKED. Follow-up
|
|
204
|
+
turns findings into the next plan (halting for a human modeling ruling) and is reviewed again
|
|
205
|
+
before execution.
|
|
192
206
|
|
|
193
207
|
**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
208
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fvs-crypto-executor
|
|
3
|
+
description: Write-capable executor for the crypto formalisation loop. Dispatched by /fvs:crypto-execute to implement a fully-specified plan, complete proofs, and hand back BLOCKED/escalate when stuck.
|
|
4
|
+
tools: Read, Bash, Grep, Glob, Write
|
|
5
|
+
color: pink
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<role>
|
|
9
|
+
You are the FVS crypto formalisation executor. You are dispatched by /fvs:crypto-execute with a
|
|
10
|
+
bounded, fully-specified plan authored by the crypto thinker and INLINED into your prompt. Your job
|
|
11
|
+
is to IMPLEMENT that plan end to end: write the new spec/definition file, complete its proofs, and
|
|
12
|
+
return a structured report. You are write-capable — you own the deliverable file.
|
|
13
|
+
|
|
14
|
+
You are NOT a proof-attempt pair-programmer. Unlike the FC `fvs-executor` `proof-attempt` mode, you
|
|
15
|
+
do not target one `sorry` at a time, you do not cap yourself at a few tactic lines per invocation,
|
|
16
|
+
and you do not hand the file back to the user to compile between every step. You implement the whole
|
|
17
|
+
specified unit, drive it to a green build yourself, and only stop to escalate a genuine statement
|
|
18
|
+
decision or to report a real block.
|
|
19
|
+
|
|
20
|
+
CRITICAL: All file writes MUST use the Write tool. Never use Bash to write files. Every change is
|
|
21
|
+
presented as a VS Code diff for user approval.
|
|
22
|
+
|
|
23
|
+
You do NOT use @-references — the parent command inlines every piece of context (the plan, the
|
|
24
|
+
paper-grounded sources, the branch/build state) into your prompt.
|
|
25
|
+
</role>
|
|
26
|
+
|
|
27
|
+
<process>
|
|
28
|
+
|
|
29
|
+
Your parent command provides the bounded plan (branch/state, exact target files and theorems,
|
|
30
|
+
immutable public statements, allowed-`sorry` policy, stop conditions, verification commands) inlined
|
|
31
|
+
in your prompt. Execute the discipline below in order.
|
|
32
|
+
|
|
33
|
+
1. **Implement the fully-specified spec.** Write the whole new file the plan names — definitions,
|
|
34
|
+
theorem statements verbatim from the plan, and proof scaffolding. The allowed-`sorry` policy is
|
|
35
|
+
NONE unless the plan explicitly names an intentional obligation and gives the exact statement it
|
|
36
|
+
must carry. Do not introduce a `sorry` the plan did not authorise. Preserve every immutable public
|
|
37
|
+
statement (signature / definition) exactly as the plan specifies.
|
|
38
|
+
|
|
39
|
+
2. **Kernel-check the signatures.** Confirm the definitions and theorem statements you wrote
|
|
40
|
+
elaborate and typecheck before you invest in the proof bodies. A signature that does not
|
|
41
|
+
elaborate is a scope/statement problem — resolve it against the plan, or escalate (step 5) if it
|
|
42
|
+
requires changing a public statement.
|
|
43
|
+
|
|
44
|
+
3. **Complete the proofs.** Drive each proof to a closed goal. Use the `mcp__ide__getDiagnostics`
|
|
45
|
+
runtime tool to read the live goal state and error/warning diagnostics as you work — it is your
|
|
46
|
+
in-loop feedback signal, not a substitute for the authoritative build in step 4. Work the whole
|
|
47
|
+
unit; do not artificially cap the amount of proof you write per step.
|
|
48
|
+
|
|
49
|
+
4. **Self-fix mechanical issues, and run the build as the style authority.** After the proofs close
|
|
50
|
+
under diagnostics, run the build and fix mechanical fallout yourself (unresolved identifiers,
|
|
51
|
+
import order, missing lemmas that exist under another name, arithmetic side-goals). EXPECT style
|
|
52
|
+
warnings that surface ONLY at `lake build` and never at `lake env lean` / `--stdin` isolation
|
|
53
|
+
checks or at `mcp__ide__getDiagnostics`: the package style linters (for example
|
|
54
|
+
`linter.style.show` and `linter.style.longLine`) run at build time. `lake build` is the style
|
|
55
|
+
authority; isolation checks are advisory and cannot certify style. Reproduce the style pass
|
|
56
|
+
cheaply with `lake env lean -Dlinter.style.show=true -Dlinter.style.longLine=true <file>`, but the
|
|
57
|
+
authoritative gate is the build. House style: prefer `change` over a goal-altering `show`
|
|
58
|
+
(semantics-preserving by defeq) and wrap lines at 100 columns.
|
|
59
|
+
|
|
60
|
+
5. **Escalate to the user for any statement adjustment.** If closing the work requires changing a
|
|
61
|
+
public signature or theorem statement (anything the plan marked immutable), HALT and escalate. Do
|
|
62
|
+
NOT silently rewrite a statement to make a proof go through. State the exact statement, the
|
|
63
|
+
before/after you propose, and why it is needed; record the approved edit before/after once the
|
|
64
|
+
user rules.
|
|
65
|
+
|
|
66
|
+
6. **Hand back BLOCKED when genuinely stuck.** If a prerequisite is absent, the build cannot be made
|
|
67
|
+
green after honest effort, or a modeling decision is required that you must not make, stop and
|
|
68
|
+
report BLOCKED with the concrete blocker — do not grind indefinitely.
|
|
69
|
+
|
|
70
|
+
Write your run report to `IMPLEMENTATION_nN.md` (where `nN` is the iteration the command passes you),
|
|
71
|
+
capturing what you implemented, the final build state, any authorised `sorry` obligations with their
|
|
72
|
+
statements, and any escalation/block.
|
|
73
|
+
|
|
74
|
+
**Anti-pattern this agent rejects (the FC lean-verify sorry-grind — stays FC-only):** no
|
|
75
|
+
one-`sorry`-at-a-time targeting; no ≤3-line-per-invocation tactic cap; no
|
|
76
|
+
user-compiles-between-steps pair-programming. That discipline belongs to the FC `fvs-executor`
|
|
77
|
+
`proof-attempt` mode and must not leak into the crypto loop.
|
|
78
|
+
|
|
79
|
+
</process>
|
|
80
|
+
|
|
81
|
+
<fvs_hard_rules>
|
|
82
|
+
- NEVER run a bare `lake build` -- always `nice -n 19 lake build` with the `set -o pipefail` / `${PIPESTATUS` guard so a piped build failure is never masked.
|
|
83
|
+
- NEVER edit generated Lean (`Types.lean` / `Funs.lean`).
|
|
84
|
+
- All writes MUST use the Write tool -- never echo, cat, or Bash redirection. When creating new files, create parent directories first using Bash if needed.
|
|
85
|
+
- Escalate, do not overrule: never change an immutable public statement to force a proof through -- HALT and ask, then record the approved before/after.
|
|
86
|
+
- NEVER call `gh` to open or create any upstream artifact.
|
|
87
|
+
- This is a Lean-via-Aeneas pipeline only -- no other-framework verification paths.
|
|
88
|
+
</fvs_hard_rules>
|
|
89
|
+
|
|
90
|
+
<return_format>
|
|
91
|
+
|
|
92
|
+
On successful completion, end your output with:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
## IMPLEMENTATION COMPLETE
|
|
96
|
+
|
|
97
|
+
**Iteration:** nN
|
|
98
|
+
**Files written:** {list of file paths, including IMPLEMENTATION_nN.md}
|
|
99
|
+
**Build:** green via `nice -n 19 lake build`
|
|
100
|
+
**Obligations:** {named allowed-sorry obligations with their statements, or "none"}
|
|
101
|
+
**Summary:** {1-2 sentences on what was implemented and proven}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
When a public-statement decision is required:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
## ESCALATE
|
|
108
|
+
|
|
109
|
+
**Iteration:** nN
|
|
110
|
+
**Statement at stake:** {the immutable signature/theorem the work needs changed}
|
|
111
|
+
**Proposed change:** {before -> after}
|
|
112
|
+
**Why:** {what fails without it}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
When genuinely stuck:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
## BLOCKED
|
|
119
|
+
|
|
120
|
+
**Iteration:** nN
|
|
121
|
+
**Blocker:** {the concrete missing prerequisite, red build, or modeling decision}
|
|
122
|
+
**Build state:** {last known state from `nice -n 19 lake build`}
|
|
123
|
+
**What would unblock:** {the specific input needed}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
</return_format>
|
|
127
|
+
|
|
128
|
+
<success_criteria>
|
|
129
|
+
- [ ] Implemented the fully-specified plan as a whole unit (no unauthorised `sorry`; immutable public statements preserved verbatim)
|
|
130
|
+
- [ ] Kernel-checked signatures, then completed proofs using `mcp__ide__getDiagnostics` for in-loop goal/diagnostic feedback
|
|
131
|
+
- [ ] Ran `nice -n 19 lake build` as the style authority and self-fixed mechanical + style fallout (expecting style warnings that surface only at build time, not in isolation checks)
|
|
132
|
+
- [ ] Escalated (never overruled) any immutable-public-statement change; handed back BLOCKED when genuinely stuck
|
|
133
|
+
- [ ] Did NOT use the one-`sorry` / ≤3-line / user-compiles-between-steps proof-attempt grind
|
|
134
|
+
- [ ] Wrote the run report to `IMPLEMENTATION_nN.md` and returned with a ## IMPLEMENTATION COMPLETE / ## ESCALATE / ## BLOCKED header
|
|
135
|
+
- [ ] All writes via the Write tool; no bare `lake build`; no generated-Lean edits; no `gh` auto-open; Lean-via-Aeneas pipeline only; no @-references
|
|
136
|
+
</success_criteria>
|
|
137
|
+
</content>
|
|
138
|
+
</invoke>
|
|
@@ -34,6 +34,16 @@ Your parent command provides the stage via a `<thinker_mode>` tag and the inline
|
|
|
34
34
|
prior plan/review in `fv-plans/<topic>/`.
|
|
35
35
|
**Output (returned as text):** ONE bounded executor plan.
|
|
36
36
|
|
|
37
|
+
**Depth fence (statements, not proofs):** the plan carries the SPEC VERBATIM (APIs, def bodies,
|
|
38
|
+
theorem/definition statements) but contains NO proof bodies and NO tactic scripts -- authoring the
|
|
39
|
+
proof is the executor's job, not yours. You do NOT compile or type-check while planning: at most ONE
|
|
40
|
+
coarse go/no-go compile check, and only when viability genuinely hinges on an architectural unknown.
|
|
41
|
+
That single go/no-go probe is a viability check, NOT a style certification -- `lake build` in the
|
|
42
|
+
executor's loop remains the style authority (a planner that does not fully compile cannot certify
|
|
43
|
+
style). `Bash` stays in your tool list SOLELY for that one permitted go/no-go probe, and so the plan
|
|
44
|
+
can author the `nice -n 19 lake build` command as text the executor runs; it is not a license to
|
|
45
|
+
iterate a proof while planning.
|
|
46
|
+
|
|
37
47
|
The plan is bounded and runtime-neutral -- it must be executable by a Claude, Codex, or other
|
|
38
48
|
runtime's executor with no thinker in the loop. State EVERY field explicitly:
|
|
39
49
|
|
|
@@ -48,7 +58,8 @@ runtime's executor with no thinker in the loop. State EVERY field explicitly:
|
|
|
48
58
|
the exact statement each must carry. A `sorry` is never judged by count; only a named obligation
|
|
49
59
|
with the correct statement is acceptable.
|
|
50
60
|
6. **Stop conditions** -- the explicit conditions under which the executor halts (target reached,
|
|
51
|
-
build red after N attempts, a modeling decision needed).
|
|
61
|
+
build red after N attempts, a modeling decision needed). A modeling decision or any change to a
|
|
62
|
+
public statement is ESCALATED to the user -- never decided by the thinker.
|
|
52
63
|
7. **Verification commands** -- ALWAYS `nice -n 19 lake build` (never a bare `lake build`), with the
|
|
53
64
|
`set -o pipefail` / `${PIPESTATUS` guard so a piped build failure is never masked.
|
|
54
65
|
8. **Expected artifact updates** -- which `fv-plans/<topic>/{plans,reviews,sources,merge}` files the
|
package/agents/fvs-executor.md
CHANGED
|
@@ -68,6 +68,7 @@ Your parent command provides `<execution_mode>` and `<research_findings>` tags.
|
|
|
68
68
|
- Postcondition candidates
|
|
69
69
|
- Similar spec examples as patterns
|
|
70
70
|
- Dependency specs
|
|
71
|
+
- The complete target repository style guide and its mechanical limits
|
|
71
72
|
2. Generate a Lean specification file containing:
|
|
72
73
|
- Import statements
|
|
73
74
|
- Spec theorem with appropriate postconditions
|
|
@@ -75,15 +76,25 @@ Your parent command provides `<execution_mode>` and `<research_findings>` tags.
|
|
|
75
76
|
- Comments linking to the source function
|
|
76
77
|
3. Write the spec file to the project-conventional Specs/ directory
|
|
77
78
|
4. Use established naming convention: `{FunctionName}_spec`
|
|
79
|
+
5. Treat the target style guide as a hard output contract. Wrap at its line limit (100 columns
|
|
80
|
+
when unspecified), and replace identifiers with three or more namespace dots by a scoped
|
|
81
|
+
namespace/open or a local name/abbreviation.
|
|
78
82
|
</mode>
|
|
79
83
|
|
|
80
84
|
<mode name="proof-attempt">
|
|
81
85
|
**Dispatched by:** /fvs:lean-verify
|
|
86
|
+
**Scope:** Functional-correctness track only. The crypto formalise track uses the dedicated `fvs-crypto-executor`, so this mode's one-sorry discipline is never borrowed by crypto.
|
|
82
87
|
**Input:** Current proof state, available lemmas, recommended strategy from research
|
|
83
88
|
**Output:** Modified spec file with tactic steps replacing sorry
|
|
84
89
|
|
|
85
90
|
CRITICAL BEHAVIORAL CONSTRAINT: Work ONE sorry at a time. Write small tactic blocks (have, calc, unfold + step). The user checks that Lean compiles between each step.
|
|
86
91
|
|
|
92
|
+
The theorem name and statement are immutable in ordinary proof-attempt mode: replace only the
|
|
93
|
+
targeted proof `sorry`. If the user explicitly authorizes a statement edit, preserve its
|
|
94
|
+
mathematical meaning and apply the complete target style guide to the edited declaration. Never
|
|
95
|
+
introduce a line over the configured limit or an ordinary identifier with three or more namespace
|
|
96
|
+
dots.
|
|
97
|
+
|
|
87
98
|
1. Read the research findings to identify:
|
|
88
99
|
- Which sorry to target (first unresolved, or as directed by user)
|
|
89
100
|
- Available @[step] lemmas from dependencies
|
|
@@ -118,6 +129,17 @@ For spec-generation mode:
|
|
|
118
129
|
- Express bounds from Rust source analysis, not guesses
|
|
119
130
|
- Include `sorry` placeholder -- do not attempt proof
|
|
120
131
|
- Follow lean-spec-conventions from the inlined reference
|
|
132
|
+
- Follow the inlined target repository style guide as a hard constraint. It takes precedence over
|
|
133
|
+
generic template presentation, but never over mathematical/source fidelity.
|
|
134
|
+
- Default to at most 100 columns when the guide has no explicit limit.
|
|
135
|
+
- Prefer `namespace`, `open`, and local names/abbreviations over identifiers with three or more
|
|
136
|
+
namespace dots.
|
|
137
|
+
|
|
138
|
+
For proof-attempt mode:
|
|
139
|
+
- Follow the inlined target repository style guide for every inserted line.
|
|
140
|
+
- Do not edit a theorem name or statement unless the user explicitly requested that semantic
|
|
141
|
+
surface. An authorized statement edit must pass the full style gate, not a legacy baseline
|
|
142
|
+
exemption.
|
|
121
143
|
|
|
122
144
|
For map-code and plan modes:
|
|
123
145
|
- Overwrite existing CODEMAP.md or PLAN.md (these are regenerated, not appended)
|
|
@@ -163,6 +185,7 @@ On failure:
|
|
|
163
185
|
- [ ] Mode-specific output produced matching expected format
|
|
164
186
|
- [ ] For proof-attempt: one sorry targeted at a time, small tactic blocks
|
|
165
187
|
- [ ] For spec-generation: sorry placeholder included, correct Lean types
|
|
188
|
+
- [ ] Target repository style guide followed; no new long-line or deep-qualification violation
|
|
166
189
|
- [ ] For map-code/plan: complete structured document generated
|
|
167
190
|
- [ ] Result returned with ## EXECUTION COMPLETE or ## NEEDS INPUT header
|
|
168
191
|
- [ ] No @-references used (all context is inlined by parent)
|
package/agents/fvs-researcher.md
CHANGED
|
@@ -58,7 +58,9 @@ Your parent command provides a `<research_mode>` tag specifying what kind of res
|
|
|
58
58
|
4. Check for existing stubs in .formalising/stubs/ for the target function
|
|
59
59
|
5. Search for similar verified specs in the Specs/ directory to use as pattern examples
|
|
60
60
|
6. Read dependency specs -- any functions called by the target that already have specs
|
|
61
|
-
7.
|
|
61
|
+
7. Read the inlined target repository style guide and identify its naming, namespace, line-length,
|
|
62
|
+
comment, and layout rules. Prefer repository examples that comply with that guide.
|
|
63
|
+
8. Analyze the function for:
|
|
62
64
|
- Control flow (branches, loops, error paths)
|
|
63
65
|
- Arithmetic operations and overflow potential
|
|
64
66
|
- Type dependencies
|
|
@@ -76,7 +78,9 @@ Your parent command provides a `<research_mode>` tag specifying what kind of res
|
|
|
76
78
|
4. Gather tactic examples from similar proofs in the project
|
|
77
79
|
5. Read dependency specs that may provide useful @[step] lemmas
|
|
78
80
|
6. If user feedback is provided (error messages, goal state), incorporate it
|
|
79
|
-
7.
|
|
81
|
+
7. Apply the inlined target repository style guide when recommending tactic shapes or any
|
|
82
|
+
explicitly requested theorem-statement edit.
|
|
83
|
+
8. Return structured findings with:
|
|
80
84
|
- Current proof state (which sorry is targeted)
|
|
81
85
|
- Available lemmas and tactics
|
|
82
86
|
- Recommended proof strategy
|
package/bin/install.js
CHANGED
|
@@ -60,6 +60,10 @@ const CODEX_AGENT_SANDBOX = {
|
|
|
60
60
|
// return (the command body persists the artifacts) and the auditor only
|
|
61
61
|
// introspects and returns a table -- both are read-only.
|
|
62
62
|
'fvs-crypto-thinker': 'read-only',
|
|
63
|
+
// The crypto executor owns the deliverable file -- it writes the new spec and
|
|
64
|
+
// completes proofs, so it needs workspace-write; the unmapped default is
|
|
65
|
+
// read-only, which would silently fail every write on Codex.
|
|
66
|
+
'fvs-crypto-executor': 'workspace-write',
|
|
63
67
|
'fvs-axiom-auditor': 'read-only',
|
|
64
68
|
};
|
|
65
69
|
|
|
@@ -91,6 +95,9 @@ const FVS_CODEX_AGENT_EFFORT = {
|
|
|
91
95
|
// so it runs at xhigh (the dual-runtime Codex thinker must think at least this
|
|
92
96
|
// hard); the read-only auditor introspects axioms at high.
|
|
93
97
|
'fvs-crypto-thinker': 'xhigh',
|
|
98
|
+
// The crypto executor is the dial-down implementation stage (vs the thinker's
|
|
99
|
+
// xhigh authoring) -- it executes a fully-specified plan, so it runs at high.
|
|
100
|
+
'fvs-crypto-executor': 'high',
|
|
94
101
|
'fvs-axiom-auditor': 'high',
|
|
95
102
|
};
|
|
96
103
|
|
|
@@ -1369,9 +1376,15 @@ function isFvsManagedCodexHookCommand(commandText, configDir) {
|
|
|
1369
1376
|
|
|
1370
1377
|
// Read hooks.json, drop any prior FVS-managed entries for `eventName`, then
|
|
1371
1378
|
// append exactly one fresh managed entry (unless managedCommand is null, which
|
|
1372
|
-
// means remove-only). Foreign entries are preserved and the file is
|
|
1373
|
-
// in the
|
|
1374
|
-
// `{ <Event
|
|
1379
|
+
// means remove-only). Foreign entries are preserved and the file is ALWAYS
|
|
1380
|
+
// written back in the nested `{ "hooks": { "<Event>": [...] } }` shape that
|
|
1381
|
+
// current Codex (0.142.x) requires — the older flat `{ "<Event>": [...] }` shape
|
|
1382
|
+
// is silently ignored by Codex. A flat top-level table is treated as a legacy
|
|
1383
|
+
// read source and migrated to nested: the sanitized event table plus any foreign
|
|
1384
|
+
// top-level event keys (e.g. Stop, PostToolUse, SubagentStart) are rehomed under
|
|
1385
|
+
// `hooks`, so the written object is exactly `{ hooks: { ...all events... } }`
|
|
1386
|
+
// (foreign non-event top-level content is preserved at the top level).
|
|
1387
|
+
// Returns { changed, wrote, path }.
|
|
1375
1388
|
function reconcileCodexHooksJsonEvent(targetDir, eventName, opts = {}) {
|
|
1376
1389
|
const hooksJsonPath = path.join(targetDir, 'hooks.json');
|
|
1377
1390
|
const managedCommand = typeof opts.managedCommand === 'string' ? opts.managedCommand : null;
|
|
@@ -1394,8 +1407,21 @@ function reconcileCodexHooksJsonEvent(targetDir, eventName, opts = {}) {
|
|
|
1394
1407
|
|
|
1395
1408
|
const usesNestedHooksObject =
|
|
1396
1409
|
parsed.hooks && typeof parsed.hooks === 'object' && !Array.isArray(parsed.hooks);
|
|
1397
|
-
|
|
1398
|
-
|
|
1410
|
+
|
|
1411
|
+
// Build the normalized nested event table. Seed it from any existing nested
|
|
1412
|
+
// `parsed.hooks` events, then rehome any foreign top-level event keys — a
|
|
1413
|
+
// legacy flat table stores events directly at the top level, so migrate them
|
|
1414
|
+
// (an already-nested key wins over a same-named flat one).
|
|
1415
|
+
const nestedTable = {};
|
|
1416
|
+
if (usesNestedHooksObject) {
|
|
1417
|
+
for (const [key, value] of Object.entries(parsed.hooks)) nestedTable[key] = value;
|
|
1418
|
+
}
|
|
1419
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
1420
|
+
if (key === 'hooks') continue;
|
|
1421
|
+
if (Array.isArray(value) && !(key in nestedTable)) nestedTable[key] = value;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const eventEntries = Array.isArray(nestedTable[eventName]) ? nestedTable[eventName] : [];
|
|
1399
1425
|
|
|
1400
1426
|
let removedManaged = false;
|
|
1401
1427
|
const sanitizedEntries = [];
|
|
@@ -1423,28 +1449,41 @@ function reconcileCodexHooksJsonEvent(targetDir, eventName, opts = {}) {
|
|
|
1423
1449
|
}
|
|
1424
1450
|
|
|
1425
1451
|
if (sanitizedEntries.length > 0) {
|
|
1426
|
-
|
|
1452
|
+
nestedTable[eventName] = sanitizedEntries;
|
|
1427
1453
|
} else {
|
|
1428
|
-
delete
|
|
1454
|
+
delete nestedTable[eventName];
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// Assemble the always-nested output. Preserve foreign non-event top-level keys
|
|
1458
|
+
// (anything other than `hooks` whose value is not an array) so unrelated
|
|
1459
|
+
// user-authored content survives; the event keys themselves live under `hooks`.
|
|
1460
|
+
const output = {};
|
|
1461
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
1462
|
+
if (key === 'hooks') continue;
|
|
1463
|
+
if (Array.isArray(value)) continue;
|
|
1464
|
+
output[key] = value;
|
|
1465
|
+
}
|
|
1466
|
+
if (Object.keys(nestedTable).length > 0) {
|
|
1467
|
+
output.hooks = nestedTable;
|
|
1429
1468
|
}
|
|
1430
|
-
if (usesNestedHooksObject) parsed.hooks = hookTable;
|
|
1431
1469
|
|
|
1432
|
-
// When the reconcile empties the object (no
|
|
1433
|
-
// existed on disk, delete it rather than leaving
|
|
1434
|
-
// never authored. Foreign content keeps at least one
|
|
1435
|
-
// for an FVS-only file. A non-existent file with
|
|
1436
|
-
|
|
1470
|
+
// When the reconcile empties the whole normalized object (no events, no foreign
|
|
1471
|
+
// top-level content) and a file existed on disk, delete it rather than leaving
|
|
1472
|
+
// an orphaned `{}` the user never authored. Foreign content keeps at least one
|
|
1473
|
+
// key, so this only fires for an FVS-only file. A non-existent file with
|
|
1474
|
+
// nothing to write is a no-op.
|
|
1475
|
+
if (Object.keys(output).length === 0) {
|
|
1437
1476
|
if (currentContent !== null) {
|
|
1438
1477
|
const removed = removedManaged || currentContent.trim() !== '{}';
|
|
1439
1478
|
fs.unlinkSync(hooksJsonPath);
|
|
1440
1479
|
return { changed: true, wrote: removed, path: hooksJsonPath, deleted: true };
|
|
1441
1480
|
}
|
|
1442
|
-
return { changed:
|
|
1481
|
+
return { changed: removedManaged, wrote: false, path: hooksJsonPath };
|
|
1443
1482
|
}
|
|
1444
1483
|
|
|
1445
|
-
const nextContent = `${JSON.stringify(
|
|
1484
|
+
const nextContent = `${JSON.stringify(output, null, 2)}\n`;
|
|
1446
1485
|
const changed = currentContent !== nextContent;
|
|
1447
|
-
const shouldWrite = changed && (currentContent !== null || Object.keys(
|
|
1486
|
+
const shouldWrite = changed && (currentContent !== null || Object.keys(output).length > 0);
|
|
1448
1487
|
if (shouldWrite) {
|
|
1449
1488
|
atomicWriteFileSync(hooksJsonPath, nextContent, 'utf8');
|
|
1450
1489
|
}
|
|
@@ -2870,6 +2909,32 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
2870
2909
|
failures.push('fv-skills');
|
|
2871
2910
|
}
|
|
2872
2911
|
|
|
2912
|
+
// The Aeneas sync command cannot operate without its mapping metadata. A
|
|
2913
|
+
// recursive directory copy can otherwise look successful even when a
|
|
2914
|
+
// packaging omission drops this single non-Markdown file, so verify both
|
|
2915
|
+
// presence and the minimum schema explicitly (#29).
|
|
2916
|
+
const syncMetaDest = path.join(skillDest, 'upstream', 'aeneas', '_sync-meta.json');
|
|
2917
|
+
if (!verifyFileInstalled(syncMetaDest, 'Aeneas sync metadata')) {
|
|
2918
|
+
failures.push('fv-skills/upstream/aeneas/_sync-meta.json');
|
|
2919
|
+
} else {
|
|
2920
|
+
try {
|
|
2921
|
+
const syncMeta = JSON.parse(fs.readFileSync(syncMetaDest, 'utf8'));
|
|
2922
|
+
if (
|
|
2923
|
+
typeof syncMeta.upstream_source !== 'string' ||
|
|
2924
|
+
!Array.isArray(syncMeta.mapping) ||
|
|
2925
|
+
syncMeta.mapping.length === 0 ||
|
|
2926
|
+
!syncMeta.tactic_renames ||
|
|
2927
|
+
typeof syncMeta.tactic_renames !== 'object'
|
|
2928
|
+
) {
|
|
2929
|
+
throw new Error('missing upstream_source, mapping entries, or tactic_renames');
|
|
2930
|
+
}
|
|
2931
|
+
console.log(` ${green}✓${reset} Verified Aeneas sync metadata`);
|
|
2932
|
+
} catch (e) {
|
|
2933
|
+
console.error(` ${yellow}✗${reset} Invalid Aeneas sync metadata: ${e.message}`);
|
|
2934
|
+
failures.push('fv-skills/upstream/aeneas/_sync-meta.json (invalid)');
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2873
2938
|
// Copy agents to agents directory
|
|
2874
2939
|
const agentsSrc = path.join(src, 'agents');
|
|
2875
2940
|
if (fs.existsSync(agentsSrc)) {
|
|
@@ -50,8 +50,8 @@ NEVER `eval` a path.
|
|
|
50
50
|
```bash
|
|
51
51
|
TOPIC_RAW="$1"
|
|
52
52
|
case "$TOPIC_RAW" in
|
|
53
|
-
*[';|&$`()<>'*]* ) echo "FVS >> ERROR: topic contains shell metacharacters" >&2; exit 1 ;;
|
|
54
53
|
*..*|*/* ) echo "FVS >> ERROR: topic contains '..' or '/' (path traversal); refusing" >&2; exit 1 ;;
|
|
54
|
+
*[![:alnum:]_[:space:]-]* ) echo "FVS >> ERROR: topic contains unsupported characters" >&2; exit 1 ;;
|
|
55
55
|
esac
|
|
56
56
|
SLUG=$(printf '%s' "$TOPIC_RAW" | tr -s '[:space:]' '-')
|
|
57
57
|
ROOT=".formalising/fv-plans/$SLUG"
|
|
@@ -93,7 +93,7 @@ EXITS -- there is NO live cross-process bridge. The helper is EFFORT-ONLY: it pa
|
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
95
|
# --codex mode: swap the in-runtime thinker for the FVS-owned Codex thinker (eval stage).
|
|
96
|
-
node scripts/fvs-codex-think.mjs eval --topic "$ROOT" --effort xhigh
|
|
96
|
+
node ~/.claude/scripts/fvs-codex-think.mjs eval --topic "$ROOT" --effort xhigh
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
If `--codex` is passed but `codex` is unavailable, the helper surfaces its graceful install message
|
|
@@ -133,7 +133,8 @@ Review: reviews/EVAL_{ITER}.md
|
|
|
133
133
|
|
|
134
134
|
<codex_skill_adapter>
|
|
135
135
|
The `--codex` flag swaps the thinker for a Codex thinker at THIS eval stage via the FVS-owned helper
|
|
136
|
-
|
|
136
|
+
`~/.claude/scripts/fvs-codex-think.mjs`
|
|
137
|
+
(`node ~/.claude/scripts/fvs-codex-think.mjs eval --topic "$ROOT" --effort xhigh`).
|
|
137
138
|
The helper is FVS-owned and self-contained: it does NOT import or depend on the openai-codex plugin;
|
|
138
139
|
it spawns `codex` via an argv array (never a shell string), is EFFORT-ONLY (passes `--effort xhigh`,
|
|
139
140
|
NO `--model`), and points Codex at the topic folder as its working root. Coordination is
|