lemmafit 0.2.0 → 0.2.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/README.md +6 -3
- package/blank-template/package.json +1 -1
- package/cli/generate-guarantees-md.js +2 -2
- package/cli/lemmafit.js +2 -1
- package/cli/sync.js +0 -13
- package/docs/CLAUDE_INSTRUCTIONS.md +4 -0
- package/package.json +4 -3
- package/skills/lemmafit-dafny/SKILL.md +1 -1
- package/{commands/guarantees.md → skills/lemmafit-guarantees/SKILL.md} +12 -7
- package/skills/lemmafit-spec/SKILL.md +3 -2
package/README.md
CHANGED
|
@@ -31,9 +31,9 @@ claude
|
|
|
31
31
|
|
|
32
32
|
## Use Cases / Considerations
|
|
33
33
|
|
|
34
|
-
- lemmafit works with greenfield projects
|
|
34
|
+
- lemmafit works with greenfield projects. You typically begin a project with `lemmafit init` though `lemmafit add` provides rudimentary support for existing codebases.
|
|
35
35
|
|
|
36
|
-
- lemmafit compiles Dafny to Typescript which then hooks into a React app. In the future, we will support other languages
|
|
36
|
+
- lemmafit compiles Dafny to Javascript/Typescript which then hooks into a runtime like a React app. In the future, we will support other languages.
|
|
37
37
|
|
|
38
38
|
- lemmafit is optimized to work with Claude Code. In the future, lemmafit will be agent-agnostic.
|
|
39
39
|
|
|
@@ -44,7 +44,7 @@ claude
|
|
|
44
44
|
2. The agent will write a `SPEC.yaml` and write verified logic in `lemmafit/dafny/Domain.dfy`
|
|
45
45
|
3. The **daemon** watches `.dfy` files, runs `dafny verify`, and on success compiles to `src/dafny/Domain.cjs` + `src/dafny/app.ts`
|
|
46
46
|
4. The agent will hook the generated TypeScript API into a React app — the logic is proven correct
|
|
47
|
-
5. After proofs complete, run
|
|
47
|
+
5. After proofs complete, run the `/guarantees` skill to activate claimcheck and generate a guarantees report
|
|
48
48
|
|
|
49
49
|
## Project Structure
|
|
50
50
|
|
|
@@ -57,6 +57,7 @@ my-app/
|
|
|
57
57
|
│ │ └── Replay.dfy # Generic Replay kernel
|
|
58
58
|
│ ├── .vibe/
|
|
59
59
|
│ │ ├── config.json # Project config
|
|
60
|
+
│ │ ├── modules.json # Module registry (for multi-module projects)
|
|
60
61
|
│ │ ├── status.json # Verification status (generated)
|
|
61
62
|
│ │ └── claims.json # Proof obligations (generated)
|
|
62
63
|
│ └── reports/
|
|
@@ -75,6 +76,7 @@ my-app/
|
|
|
75
76
|
|
|
76
77
|
```bash
|
|
77
78
|
lemmafit init [dir] # Create project from template
|
|
79
|
+
lemmafit add [Name] # Add a verified module to an existing project
|
|
78
80
|
lemmafit sync [dir] # Re-sync system files (.claude/, hooks)
|
|
79
81
|
lemmafit daemon [dir] # Run verification daemon standalone
|
|
80
82
|
lemmafit logs [dir] # View daemon log
|
|
@@ -94,5 +96,6 @@ npm update lemmafit
|
|
|
94
96
|
|
|
95
97
|
- Node.js 18+
|
|
96
98
|
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI
|
|
99
|
+
- [claimcheck](https://github.com/metareflection/claimcheck) (`npm install -g claimcheck`) — needed for the `/guarantees` skill
|
|
97
100
|
|
|
98
101
|
Dafny and dafny2js are downloaded automatically during `npm install` to `~/.lemmafit/`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Generates
|
|
4
|
-
* -
|
|
3
|
+
* Generates reports/guarantees.md deterministically from:
|
|
4
|
+
* - reports/guarantees.json (claim-to-spec mapping)
|
|
5
5
|
* - lemmafit/.vibe/claimcheck.json (claimcheck results, optional)
|
|
6
6
|
* - SPEC.yaml (for trusted entries and group info)
|
|
7
7
|
*
|
package/cli/lemmafit.js
CHANGED
|
@@ -99,7 +99,8 @@ function initProject(targetDir, templateName, serverBase) {
|
|
|
99
99
|
}
|
|
100
100
|
config.secret = secret;
|
|
101
101
|
if (serverBase.toLowerCase() !== 'none') {
|
|
102
|
-
const
|
|
102
|
+
const sep = serverBase.includes('?') ? '&' : '?';
|
|
103
|
+
const serverWsUrl = `${serverBase}${sep}project=${encodeURIComponent(projectName)}`;
|
|
103
104
|
config.server = serverWsUrl;
|
|
104
105
|
}
|
|
105
106
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
package/cli/sync.js
CHANGED
|
@@ -110,19 +110,6 @@ function syncProject(targetDir) {
|
|
|
110
110
|
fs.writeFileSync(claudeMdPath, POINTER_LINE + '\n');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
// Sync .claude/commands/ from package
|
|
114
|
-
const srcCommands = path.join(__dirname, '..', 'commands');
|
|
115
|
-
if (fs.existsSync(srcCommands)) {
|
|
116
|
-
const commandsDir = path.join(claudeDir, 'commands');
|
|
117
|
-
fs.mkdirSync(commandsDir, { recursive: true });
|
|
118
|
-
for (const file of fs.readdirSync(srcCommands)) {
|
|
119
|
-
fs.copyFileSync(
|
|
120
|
-
path.join(srcCommands, file),
|
|
121
|
-
path.join(commandsDir, file)
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
113
|
// Sync .claude/skills/ from package
|
|
127
114
|
const srcSkills = path.join(__dirname, '..', 'skills');
|
|
128
115
|
if (fs.existsSync(srcSkills)) {
|
|
@@ -60,6 +60,10 @@ When `modules.json` exists:
|
|
|
60
60
|
- `lemmafit-proofs`: Load this skill before writing or editing lemmas
|
|
61
61
|
- `lemmafit-react-pattern`: Load this skill before writing React
|
|
62
62
|
- `lemmafit-spec`: Load this skill when user asks to add or edit feature, and before writing or editing the spec.yaml file
|
|
63
|
+
- `lemmafit-guarantees`: Load this skill to generate a human-readable guarantees report from proven Dafny code and verify claims with claimcheck
|
|
64
|
+
- `lemmafit-pre-react-audits`: Load this skill before writing React to audit proof strength and catch unverified logic
|
|
65
|
+
- `lemmafit-post-react-audit`: Load this skill after writing React to catch effect-free logic that should be in Dafny
|
|
66
|
+
|
|
63
67
|
|
|
64
68
|
If you try to read any of these files and they are missing, alert the user.
|
|
65
69
|
|
package/package.json
CHANGED
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
"verified",
|
|
16
16
|
"proof"
|
|
17
17
|
],
|
|
18
|
-
"version": "0.2.
|
|
18
|
+
"version": "0.2.2",
|
|
19
19
|
"type": "commonjs",
|
|
20
20
|
"files": [
|
|
21
21
|
"cli/",
|
|
22
22
|
"lib/",
|
|
23
23
|
"docs/",
|
|
24
24
|
"skills/",
|
|
25
|
-
"commands/",
|
|
26
25
|
"kernels/",
|
|
27
26
|
"blank-template/"
|
|
28
27
|
],
|
|
@@ -40,10 +39,12 @@
|
|
|
40
39
|
"postinstall": "node ./cli/sync.js && node ./cli/download-dafny2js.js && node ./lib/download-dafny.js"
|
|
41
40
|
},
|
|
42
41
|
"dependencies": {
|
|
43
|
-
"claimcheck": "^0.2.0",
|
|
44
42
|
"js-yaml": "^4.1.1",
|
|
45
43
|
"ws": "^8.18.0"
|
|
46
44
|
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"claimcheck": "^0.2.0"
|
|
47
|
+
},
|
|
47
48
|
"engines": {
|
|
48
49
|
"node": ">=18.0.0"
|
|
49
50
|
},
|
|
@@ -6,7 +6,7 @@ description: Dafny code patterns and reference for lemmafit apps. Use when writi
|
|
|
6
6
|
# Lemmafit Dafny
|
|
7
7
|
|
|
8
8
|
## When to Write Code in Dafny
|
|
9
|
-
- ALL `verifiable:true` entries in the spec MUST be written in Dafny (do not write verifiable code directly in JavaScript or
|
|
9
|
+
- ALL `verifiable:true` entries in the spec MUST be written in Dafny (do not write verifiable code directly in JavaScript or TypeScript)
|
|
10
10
|
|
|
11
11
|
## Dafny Pattern Example
|
|
12
12
|
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lemmafit-guarantees
|
|
3
|
+
description: Generate human-readable guarantees from proven Dafny code and verify them with claimcheck. Use after verification succeeds and SPEC.yaml is in sync with Dafny. Produces guarantees.json, claimcheck-mapping.json, runs claimcheck-multi, and generates guarantees.md report.
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Generate Guarantees and Run Claimcheck
|
|
2
7
|
|
|
3
8
|
You are generating human-readable guarantees from proven Dafny code and verifying them with claimcheck.
|
|
4
9
|
|
|
5
10
|
## Step 0: Make sure the state of the project is verified
|
|
6
11
|
|
|
7
|
-
Check
|
|
12
|
+
Check your context for verification status of the project.
|
|
8
13
|
|
|
9
14
|
## Step 1: Read project data
|
|
10
15
|
|
|
@@ -35,7 +40,7 @@ Analyze the claims from `claims.json` and map them to spec entries from `SPEC.ya
|
|
|
35
40
|
|
|
36
41
|
## Step 3: Write guarantees.json
|
|
37
42
|
|
|
38
|
-
Write `
|
|
43
|
+
Write `reports/guarantees.json` with this format:
|
|
39
44
|
|
|
40
45
|
```json
|
|
41
46
|
{
|
|
@@ -117,15 +122,15 @@ Parse the claimcheck results and report:
|
|
|
117
122
|
- **Disputed** — a discrepancy was found. Show the `discrepancy` text and `weakeningType` (tautology, weakened-postcondition, narrowed-scope, wrong-property).
|
|
118
123
|
- **Error** — lemma not found in source. Check the lemmaName.
|
|
119
124
|
|
|
120
|
-
**If any claims are disputed:** Suggest specific fixes to the Dafny code or the requirement text. If the user agrees, make the fixes, wait for re-verification, and re-run the guarantees process.
|
|
125
|
+
**If any claims are disputed:** Suggest specific fixes to the Dafny code or the requirement text. If the user agrees, make the fixes, wait for re-verification, and re-run the guarantees process.
|
|
121
126
|
|
|
122
127
|
## Step 8: Ensure all files up to date
|
|
123
128
|
|
|
124
|
-
Once iteration is complete, compare `claimcheck-mapping.json` with `guarantees.json` to ensure they contain equivalent information. If there's a discrepancy, trace back to the Dafny code to find which is most accurate. Adjust the relevant file accordingly and re-run `/guarantees` command. Once confirmed, report that the files are in sync.
|
|
129
|
+
Once iteration is complete, compare `claimcheck-mapping.json` with `guarantees.json` to ensure they contain equivalent information. If there's a discrepancy, trace back to the Dafny code to find which is most accurate. Adjust the relevant file accordingly and re-run `/guarantees` command. Once confirmed, report that the files are in sync.
|
|
125
130
|
|
|
126
131
|
## Step 9: Generate guarantees.md via the script
|
|
127
132
|
|
|
128
|
-
Do this only after Step
|
|
133
|
+
Do this only after Step 8 confirms that `claimcheck-mapping.json` and `guarantees.json` are in sync.
|
|
129
134
|
|
|
130
135
|
Run the deterministic report generator:
|
|
131
136
|
|
|
@@ -133,6 +138,6 @@ Run the deterministic report generator:
|
|
|
133
138
|
npx lemmafit-generate-guarantees
|
|
134
139
|
```
|
|
135
140
|
|
|
136
|
-
This reads `
|
|
141
|
+
This reads `reports/guarantees.json`, `reports/claimcheck.json`, and `SPEC.yaml` and writes `reports/guarantees.md`. Do NOT write this file manually — always use the script so the report matches the JSON exactly.
|
|
137
142
|
|
|
138
|
-
Report to the user: "A report of your app's guarantees has been generated in lemmafit/reports/guarantees.md"
|
|
143
|
+
Report to the user: "A report of your app's guarantees has been generated in lemmafit/reports/guarantees.md"
|
|
@@ -39,7 +39,7 @@ SPEC.yaml is a structured YAML file with an `entries` list. Each entry has:
|
|
|
39
39
|
- `depends_on` — list of spec IDs this entry depends on
|
|
40
40
|
- `verifiable` — whether this can be proven in Dafny
|
|
41
41
|
- `guarantee_type` — `verified`, `assumed`, or `trusted`
|
|
42
|
-
- `state` - `DRAFT`, `ADDRESSED`, `null
|
|
42
|
+
- `state` - `DRAFT`, `ADDRESSED`, `null` — only use `ADDRESSED` if the corresponding Dafny module or property have been verified. Use `null` for `verifiable: false`
|
|
43
43
|
|
|
44
44
|
### Example
|
|
45
45
|
```yaml
|
|
@@ -54,7 +54,8 @@ entries:
|
|
|
54
54
|
module: AppCore
|
|
55
55
|
depends_on: []
|
|
56
56
|
verifiable: true
|
|
57
|
-
|
|
57
|
+
guarantee_type: verified
|
|
58
|
+
state: ADDRESSED
|
|
58
59
|
- id: spec-002
|
|
59
60
|
req_id: null
|
|
60
61
|
title: The increment button displays the current count
|