agent-formal-verify 0.4.1 → 0.4.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/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changes
2
2
 
3
+ ## 0.4.2 - OpenCode skips stray folders and rejects incomplete skills
4
+
5
+ The OpenCode plugin read every folder under `skills/` as a skill, so one folder without a `SKILL.md`, such as a scratch folder in a local checkout, failed the plugin and registered neither skill. It now skips such folders, as Pi does. A `SKILL.md` without a `name` or `description` used to register with that field undefined; the plugin now fails with the file's path and the missing field. A single-quoted `description` lost nothing but kept its quotes; it now reads as YAML does. The two bundled skills register exactly as before.
6
+
3
7
  ## 0.4.1 - install from npm
4
8
 
5
9
  The package is publishable to npm as `agent-formal-verify`, so Pi installs it with `pi install npm:agent-formal-verify` and OpenCode with `opencode plugin add agent-formal-verify`. A `files` allowlist limits the tarball to `opencode.mjs`, `skills/`, the license, the README and the changelog, which drops it from 77 files and 2.86 MB to 34 files and 59 kB; it leaves out the README artwork, tests, CI configuration and the Claude Code and Codex manifests. A Lean build cache under `skills/` stays out. The metadata test pins the allowlist and fails when a new root file is neither shipped nor listed as repository-only. Pushing a `v*` tag runs a workflow that checks the tag against the package version, runs the metadata tests and publishes with npm trusted publishing and provenance; it skips a version that is already on npm. The skills, the OpenCode plugin and the Git installs are unchanged.
package/opencode.mjs CHANGED
@@ -5,27 +5,33 @@ import { fileURLToPath } from "node:url";
5
5
 
6
6
  const skills = new URL("./skills/", import.meta.url);
7
7
 
8
- function parse(text) {
8
+ function parse(text, path) {
9
9
  const match = text.replaceAll("\r\n", "\n").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
10
- if (!match) throw new Error("SKILL.md has no frontmatter");
10
+ if (!match) throw new Error(`${path} has no frontmatter`);
11
11
  const field = (key) => {
12
12
  const value = match[1].match(new RegExp(`^${key}: (.+)$`, "m"))?.[1];
13
- return value?.startsWith('"') ? JSON.parse(value) : value;
13
+ if (value === undefined) throw new Error(`${path} has no ${key}`);
14
+ if (value.startsWith('"')) return JSON.parse(value);
15
+ if (value.startsWith("'")) return value.slice(1, -1).replaceAll("''", "'");
16
+ return value;
14
17
  };
15
18
  return { name: field("name"), description: field("description"), content: match[2] };
16
19
  }
17
20
 
18
21
  async function load() {
19
22
  const entries = await readdir(skills, { withFileTypes: true });
20
- return Promise.all(
23
+ const found = await Promise.all(
21
24
  entries
22
25
  .filter((entry) => entry.isDirectory())
23
26
  .map(async ({ name }) => {
24
- const file = new URL(`${name}/SKILL.md`, skills);
25
- const skill = parse(await readFile(file, "utf8"));
26
- return { id: name, ...skill, autoinvoke: true, path: fileURLToPath(file) };
27
+ const path = fileURLToPath(new URL(`${name}/SKILL.md`, skills));
28
+ const text = await readFile(path, "utf8").catch((error) => {
29
+ if (error.code !== "ENOENT") throw error;
30
+ });
31
+ return text && { id: name, ...parse(text, path), autoinvoke: true, path };
27
32
  }),
28
33
  );
34
+ return found.filter(Boolean);
29
35
  }
30
36
 
31
37
  export default {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-formal-verify",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Model-check protocols with TLA+, prove invariants with Lean 4, and check bounded Rust functions with Kani.",
5
5
  "author": {
6
6
  "name": "Michael Denyer",