You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+67-63Lines changed: 67 additions & 63 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@
14
14
15
15
**Formal specs, meet your pull requests.**
16
16
17
-
A GitHub App that turns diffs into structured specification suggestions—powered by LLMs, grounded in AST analysis, and wired for Lean 4 when you want proofs to compile.
17
+
A GitHub App that turns PR diffs into structured specification suggestions—powered by LLMs when configured, grounded in tree-sitter AST analysis, and able to write Lean 4 **spec-as-contract** modules under `.specsync/` (opaque stubs + closed proofs where possible; labeled unfinished goals otherwise — not claimed complete).
|**Event-driven**| Listens on GitHub for pull requests, pushes, and comments—then runs the analysis pipeline. |
35
-
|**Multi-language diffs**| Parses changes across common languages using Tree-sitter–backed extraction. |
36
-
|**LLM-assisted specs**| Proposes preconditions, postconditions, invariants, and rationale where API keys are configured. |
37
-
|**Lean-ready output**| Generated modules can target your Lake `specs/` tree so `lake build` stays honest. |
38
-
|**Operator-friendly**| Health and readiness routes on the Probot router, Docker image, and CI for Node + Lean. |
32
+
| Capability | Description |
33
+
| --- | --- |
34
+
|**Async PR analysis**| Webhooks enqueue work on an in-process `AnalysisJobQueue` (idempotent per PR head SHA) so GitHub gets a fast ack. Optional `SPECSYNC_JOB_MARKERS_DIR` shares completion markers across instances on a volume (not committed to the target repo). |
35
+
|**Multi-language diffs**| Tree-sitter AST for JavaScript, TypeScript, Python, Java, and Rust (no Go/C/C++ parsers). Review comments use `RIGHT` for adds/modifies and `LEFT` for pure deletions. |
36
+
|**LLM-assisted specs**| Proposes preconditions, postconditions, invariants, and rationale when API keys are set. Production denies silent mock output unless `SPECSYNC_ALLOW_MOCK_LLM=true`. |
37
+
|**`.specsync/` store**|`/specsync accept` commits JSON contracts (and Lean stubs) under `.specsync/` on the PR branch. Mutating commands require write AuthZ and are rate-limited per actor/PR. |
38
+
|**Soft proof gate**| Default `SPECSYNC_PROOF_GATE=soft`: Lean CI **reports**`sorry` count (comments stripped). Set `strict` to **fail** on any remaining `sorry` in `specs/`. Closed fragments use real proofs (`trivial`, `Nat.zero_le`); unfinished LLM obligations stay labeled — this is not end-to-end formal verification. |
39
+
|**Drift on push**| Compares changed functions against accepted `.specsync/` specs on main/master pushes. |
The optional [VS Code extension](vscode-extension/)adds editor-side commands and local proof hooks; the server-side app lives in this repository’s `src/` tree.
42
+
The optional [VS Code extension](vscode-extension/)reads the same `.specsync/` store; compile it with `npm run compile` in that folder.
41
43
42
44
---
43
45
44
46
## Architecture
45
47
46
-
At a glance: GitHub sends webhooks to**Probot**; the app parses diffs, walks ASTs, asks the **spec analyzer**(and**LLM client** when configured), then posts back via the **GitHub UI** layer. Lean artifacts and CI are first-class paths, not an afterthought.
48
+
GitHub webhooks hit**Probot**; handlers enqueue analysis, then the worker parses diffs, walks ASTs, calls the **spec analyzer**/**LLM client**, and posts review comments plus coverage checks. Accepted specs live under **`.specsync/`**; Lake-built Lean sources for this repo also live under [`specs/`](specs/).
47
49
48
50
```mermaid
49
51
flowchart TB
50
52
subgraph ingest [GitHub]
51
53
E[Webhooks]
52
54
end
53
55
subgraph pipeline [Analysis]
56
+
Q[AnalysisJobQueue]
54
57
D[Diff parser]
55
58
T[AST extractor]
56
59
N[Spec analyzer]
57
60
L[LLM client]
58
61
end
59
62
subgraph surface [Surfaces]
60
63
G[PR comments and checks]
61
-
K[Lean specs under specs/]
62
-
S[Slack and dashboards]
64
+
S[".specsync/ store"]
65
+
K[Lean stubs / Lake specs]
63
66
end
64
-
E --> D --> T --> N
67
+
E --> Q --> D --> T --> N
65
68
N --> L
66
69
N --> G
67
-
N --> K
68
-
N --> S
70
+
G --> S
71
+
S --> K
69
72
```
70
73
71
-
Formal modules consumed by Lake live under [`specs/`](specs/), with [`lakefile.lean`](lakefile.lean) and [`lean-toolchain`](lean-toolchain) pinning the toolchain.
74
+
Formal modules consumed by Lake live under [`specs/`](specs/), with [`lakefile.lean`](lakefile.lean) and [`lean-toolchain`](lean-toolchain) pinning the toolchain. Generated accept-path Lean may also land under `.specsync/lean/` depending on configuration.
SPECSYNC_JOB_MARKERS_DIR= # optional shared FS for multi-instance job idempotency
141
+
SPECSYNC_COMMAND_RATE_LIMIT=10
142
+
SPECSYNC_COMMAND_RATE_WINDOW_MS=60000
143
+
SPECSYNC_DASHBOARD=0
144
+
SPECSYNC_DASHBOARD_SECRET=
132
145
```
133
146
147
+
See [`env.example`](env.example) and [`app.yml`](app.yml) for the full App permission set (`checks: write`, `contents: write` for accept commits, etc.).
148
+
134
149
### GitHub App manifest (reference)
135
150
136
-
Use this shape when registering the app; point the webhook URL at your deployed Probot instance.
Use [`app.yml`](app.yml) when registering the app; point the webhook URL at your deployed Probot instance. Replace org/domain placeholders with your deployment.
158
152
159
153
---
160
154
@@ -180,28 +174,35 @@ default_events:
180
174
When the Probot server exposes a router, the app registers:
181
175
182
176
-`GET /health` — liveness
183
-
- `GET /ready`— readiness (extend when you add databases or queues)
177
+
-`GET /ready` — readiness, including analysis-queue stats and in-process metrics counters
184
178
185
179
The [`Dockerfile`](Dockerfile) healthcheck expects `GET /health` on the process port (default `3000`).
186
180
187
181
---
188
182
189
183
## Lean and Lake
190
184
191
-
- **CI:** [`lean4-ci.yml`](.github/workflows/lean4-ci.yml) runs `lake build` via [lean-action](https://github.com/leanprover/lean-action) when Lean-related paths change.
192
-
- **Local:** From the repo root, `lake build` after installing Elan/Lean.
193
-
- **Generator contract:** Output from [`src/lean4-generator.ts`](src/lean4-generator.ts) should respect `SPECS_DIR` (default `specs`) so files sit in the same Lake library as [`lakefile.lean`](lakefile.lean).
185
+
-**CI:**[`lean4-ci.yml`](.github/workflows/lean4-ci.yml) runs `lake build` via [lean-action](https://github.com/leanprover/lean-action) when Lean-related paths or `src/lean4-generator.ts` change.
186
+
-**Local:** From the repo root, `lake build` after installing Elan/Lean (see `lean-toolchain`).
187
+
-**Committed baseline:**[`specs/Specs.lean`](specs/Specs.lean) + [`specs/Specs/ClosedNatContract.lean`](specs/Specs/ClosedNatContract.lean) are Std-only and **contain zero `sorry`** (opaque + closed proofs).
188
+
-**Generator contract:**[`src/lean4-generator.ts`](src/lean4-generator.ts) emits Std-only Lake modules:
189
+
- Function under contract → `opaque` (no unfinished proof for missing bodies)
190
+
- Smoke / Nat nonneg / other decidable fragments → real proofs (`trivial`, `Nat.zero_le`, …)
-**Proof gate:**`SPECSYNC_PROOF_GATE=soft` (default) reports counts; `strict` fails if any `sorry` remains. SpecSync does **not** claim completed formal verification while open obligations exist.
193
+
-**Accept path:** Artifacts for target repos are stored under `.specsync/` (separate from this repo’s `specs/` library).
|[`lean4-ci.yml`](.github/workflows/lean4-ci.yml)|`lake build` for Lean specs |
203
+
|[`codeql.yml`](.github/workflows/codeql.yml)| CodeQL analysis for JavaScript/TypeScript |
203
204
204
-
[`dependabot.yml`](.github/dependabot.yml) schedules weekly npm updates for the root package and [`vscode-extension/`](vscode-extension/).
205
+
[`dependabot.yml`](.github/dependabot.yml) schedules weekly npm and GitHub Actions updates.
205
206
206
207
---
207
208
@@ -217,10 +218,12 @@ docker run -p 3000:3000 \
217
218
-e APP_ID=<id> \
218
219
-e PRIVATE_KEY=<pem-or-base64> \
219
220
-e WEBHOOK_SECRET=<secret> \
221
+
-e NODE_ENV=production \
222
+
-e SPECSYNC_ALLOW_MOCK_LLM=false \
220
223
specsync
221
224
```
222
225
223
-
Add LLM keys the same way if you use live models in production.
226
+
Add LLM keys the same way if you use live models in production. Without keys (and without `SPECSYNC_ALLOW_MOCK_LLM=true`), the app posts an LLM-unavailable notice instead of fake specs.
224
227
225
228
### Other platforms
226
229
@@ -230,17 +233,18 @@ Any environment that provides Node, `PORT`, Probot env vars, and a **public HTTP
230
233
231
234
## Usage notes
232
235
236
+
-**Accept / ignore / edit:** Comment `/specsync accept` (or ignore/edit) on a suggestion; AuthZ requires a collaborator (or stronger) or PR committer. Accept writes `.specsync/specs/` + Lean stubs on the PR branch.
233
237
-**Demos:** After `npm run build`, run `npm run demo` or `npm run ui-demo`.
234
-
- **VS Code:** See [`vscode-extension/README.md`](vscode-extension/README.md) for building the extension (`npx tsc -p .` inside that folder).
235
-
- **Lean:** Modules under `specs/` should pass `lake build`; proof sketches may use `sorry` until completed.
238
+
-**VS Code:** See [`vscode-extension/README.md`](vscode-extension/README.md); CI runs `npm run compile` in that package.
239
+
-**Lean:**Committed modules under `specs/` pass `lake build` with zero `sorry`. Accept-path sketches may still use labeled unfinished proofs until a human (or stronger autoformalization) closes them.
236
240
237
241
---
238
242
239
243
## Quality and security
240
244
241
-
- Pull requests run lint, format, typecheck, build, and tests; Lean CI validates the Lake project.
242
-
- Prefer Dependabot PRs and periodic `npm audit` before releases.
243
-
- Probot uses structured logging; see [`src/health.ts`](src/health.ts) for optional standalone health HTTP.
245
+
-PRs run lint, format, typecheck, build, coverage-gated tests, production `npm audit`, Docker image smoke, and extension compile; CodeQL runs on push/PR/schedule.
246
+
-Structured logs (Probot `context.log` / shared pino) include job id, PR, latency, and LLM mock|live soft-cost fields where available.
247
+
-Prefer Dependabot PRs; treat audit failures as blocking unless an exception is documented in the workflow.
0 commit comments