Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "webmcpify",
"source": "./",
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"version": "0.6.1"
"version": "0.7.0"
}
]
}
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "webmcpify",
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"version": "0.6.1",
"version": "0.7.0",
"author": {
"name": "Jonas Tüchler"
}
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "webmcpify",
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"version": "0.6.1",
"version": "0.7.0",
"author": {
"name": "Jonas Tüchler"
}
Expand Down
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ reconstruct them from git history.

## [Unreleased]

## [0.7.0] — 2026-09-19

- Added a dependency-free host-side mutation journal for verification runners.
It acquires the permanent manifest sidecar through `flock(1)` or macOS/FreeBSD
`lockf(1)` descriptor mode, migrates missing journals, and fails closed when no supported
advisory lock is available. A stable manifest/sidecar identity plus inode,
link and journal validation reject replacement or corrupt safety state.
- Wired the Playwright template's valid, invalid and cleanup mutation examples
through durable pre-dispatch and settlement hooks. Atomic manifest replacement
now writes and fsyncs a sibling temporary file, renames it, and fsyncs the
directory while the sidecar lock remains held.
- Added regressions for two-runner exclusion, cleanup linkage, pre-dispatch
persistence failure, runner death with a retained `started` entry,
malformed journals, sidecar attacks, canonical argument fingerprints, and
legacy-manifest migration.

## [0.6.1] — 2026-09-19

- Pinned the verification harness install to the versions the skill is tested with
Expand Down Expand Up @@ -95,4 +111,5 @@ reconstruct them from git history.
[0.5.1]: https://github.com/TueJon/webmcpify/compare/v0.5.0...v0.5.1
[0.6.0]: https://github.com/TueJon/webmcpify/compare/v0.5.1...v0.6.0
[0.6.1]: https://github.com/TueJon/webmcpify/compare/v0.6.0...v0.6.1
[Unreleased]: https://github.com/TueJon/webmcpify/compare/v0.6.1...HEAD
[0.7.0]: https://github.com/TueJon/webmcpify/compare/v0.6.1...v0.7.0
[Unreleased]: https://github.com/TueJon/webmcpify/compare/v0.7.0...HEAD
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ Every phase is a **loop over persistent state**, not a one-shot pass:
examples recorded in the manifest. That includes mutating declarative forms,
where Chrome pauses the execution until a real submit interaction — the
harness performs that submit click mid-execution instead of faking the pass.
- **Crash-safe mutation checks** — a dependency-free host helper journals every
mutating dispatch and cleanup before execution, atomically settles verified
outcomes, and serializes runners with a permanent advisory-lock sidecar on
Linux (`flock`) and macOS/FreeBSD (`lockf -k`).
- **Spec over scoreboard** — WebMCP checkers and inspector extensions grade pages
against a mix of spec features, conventions, and invented checks. webmcpify
classifies their findings instead of chasing them: it never emits
Expand All @@ -161,7 +165,7 @@ Every phase is a **loop over persistent state**, not a one-shot pass:
|---|---|
| [`skills/webmcpify/SKILL.md`](skills/webmcpify/SKILL.md) | The pipeline (what your agent follows) |
| [`skills/webmcpify/references/`](skills/webmcpify/references/) | Phase guides: inventory, integrate, Workbench, runtime, verify, heal, security, discovery |
| [`skills/webmcpify/templates/`](skills/webmcpify/templates/) | Vendorable runtime (TS + JS), temporary visual Workbench, ambient types, Playwright verification template, discovery manifest |
| [`skills/webmcpify/templates/`](skills/webmcpify/templates/) | Vendorable runtime (TS + JS), durable mutation journal, temporary visual Workbench, ambient types, Playwright verification template, discovery manifest |

## Status

Expand Down
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "webmcpify",
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"version": "0.6.1",
"version": "0.7.0",
"author": {
"name": "Jonas Tüchler"
}
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"type": "module",
"license": "MIT",
"version": "0.6.1",
"version": "0.7.0",
"publisher": "TueJon",
"repository": {
"url": "https://github.com/TueJon/webmcpify"
Expand All @@ -26,7 +26,7 @@
},
"scripts": {
"typecheck": "tsc -p tsconfig.templates.json && tsc -p tsconfig.spec.json && tsc -p tsconfig.jsx.json",
"syntaxcheck": "node --check skills/webmcpify/templates/webmcpify.js && node --check skills/webmcpify/templates/webmcp-workbench.js && node --check skills/webmcpify/scripts/workbench.mjs",
"syntaxcheck": "node --check skills/webmcpify/templates/webmcpify.js && node --check skills/webmcpify/templates/webmcp-workbench.js && node --check skills/webmcpify/templates/mutation-journal.js && node --check skills/webmcpify/scripts/workbench.mjs",
"test": "node --test \"tests/*.test.mjs\"",
"check": "npm run typecheck && npm run syntaxcheck && npm test",
"workbench:verify": "node tests/workbench-browser.mjs",
Expand Down
35 changes: 35 additions & 0 deletions release/v0.7.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# webmcpify v0.7.0

Verification runners no longer have to invent their own crash-safety layer for
mutating tools. The skill now ships a dependency-free host-side journal helper
and wires its Playwright template through durable pre-dispatch, cleanup and
settlement hooks.

## What changed

- Acquires the never-replaced `.webmcpify/manifest.lock` sidecar with `flock(1)`
where present or macOS/FreeBSD `lockf(1)` descriptor mode, and fails closed if neither
advisory-lock command is available.
- Binds the manifest to a stable sidecar identity, rejects symlinks, hard links,
inode swaps and malformed journals. The runner retains the locked descriptor,
removing a separately killable holder from the dispatch boundary.
- Records a canonical-arguments fingerprint and a durable `started` entry before
each valid example, invalid example and mutating cleanup action.
- Settles an entry only after an independent read path establishes the effect or
its absence and required cleanup has completed.
- Migrates manifests without `mutationExecutions`, invalidating historical
verification evidence without inventing in-flight calls.
- Covers concurrent runners across atomic manifest replacement, persistence
failure before dispatch, runner death, corrupt safety state, sidecar
replacement and legacy-manifest migration.

## Compatibility and evidence

This is a backward-compatible verification-workflow expansion from v0.6.1. It
does not change the vendored browser runtime or the application-facing WebMCP
contract. The helper requires Node.js 20 and either `flock(1)` or `lockf(1)`;
mutation verification remains safely not-run on platforms without either. The
same portable regression runs on Linux and macOS and declares that prerequisite
as its only platform skip.

Compare: https://github.com/TueJon/webmcpify/compare/v0.6.1...v0.7.0
2 changes: 1 addition & 1 deletion skill.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webmcpify",
"version": "0.6.1",
"version": "0.7.0",
"description": "WebMCP agent skill for curated core coverage or route-by-route parity — inventory an existing web app, integrate approved tools, then verify and heal them in a real browser.",
"license": "MIT",
"author": {
Expand Down
17 changes: 10 additions & 7 deletions skills/webmcpify/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ DETECT ──▶ INVENTORY ──▶ [HUMAN GATE: manifest approval] ──▶ I

Everything you need ships inside this skill directory: phase guides in
`references/`, and vendorable code in `templates/` (runtime, ambient types,
JS variant, React JSX typings, verification spec + compat helper). Never assume files exist
outside the skill dir.
JS variant, React JSX typings, verification spec, compatibility helper and
durable mutation journal). Never assume files exist outside the skill dir.

**Out of scope** (stop and say so): backend-only MCP servers (that's classic MCP,
not WebMCP), automating third-party sites you don't control, and generic SEO work.
Expand Down Expand Up @@ -159,6 +159,8 @@ Manifest schema (Webmcpify Manifest v4):
```jsonc
{
"webmcpify": 4,
// Omit until the helper's first execution-capable open; it then writes and preserves this UUID.
"mutationLockIdentity": "2d734e2d-1537-41a7-b8b5-0af6e932019e",
"app": { "stack": "react-vite", "typescript": true, "entry": "src/main.tsx",
"baseUrl": "https://app.example.test", "startCommand": "npm run dev",
"verificationOrigin": "https://app.example.test",
Expand All @@ -185,7 +187,7 @@ Manifest schema (Webmcpify Manifest v4):
},
"setup": { // PATHS created/modified per one-time setup step ([] = not done yet)
"runtimeVendored": ["src/webmcp/webmcpify.ts", "src/webmcp/webmcp.d.ts"],
"harnessInstalled": [".webmcpify/webmcp.spec.ts", ".webmcpify/webmcp-compat.js"],
"harnessInstalled": [".webmcpify/webmcp.spec.ts", ".webmcpify/webmcp-compat.js", ".webmcpify/mutation-journal.ts", ".webmcpify/mutation-journal.js"],
"originTrialNoted": ["README.md"]
},
"discovery": null, // optional off-page layer (references/discovery.md). Stays null unless
Expand Down Expand Up @@ -407,12 +409,13 @@ and removes it within the same inspection session.

## Phase 3 — VERIFY (loop)

Set up once from `templates/webmcp.spec.ts` per `references/verify.md` (real headed
Chrome; current production `document.modelContext.getTools()`/`executeTool()` surface).
Set up once from `templates/webmcp.spec.ts` plus the shipped host-side
`templates/mutation-journal.{ts,js}` per `references/verify.md` (real headed Chrome;
current production `document.modelContext.getTools()`/`executeTool()` surface).
Before any execution, enforce the durable mutation journal in
`references/reverify.md`: scan unresolved attempts, persist each mutation before
dispatch, and settle only after independent reconciliation and cleanup. Wire the
host-side hooks into the chosen runner; without them, mutations are blocked.
dispatch, and settle only after independent reconciliation and cleanup. Use its
hooks in the chosen runner; without them, mutations are blocked.
Then loop over every `integrated` tool, using its manifest `route`, `auth`,
`examples`, `expect`, and `annotations` fields:

Expand Down
22 changes: 20 additions & 2 deletions skills/webmcpify/references/reverify.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,26 @@ the evidence even when frontend files did not change.

Manifest v4 adds `mutationExecutions: []` on each tool. This is a required
workflow journal for new mutation runs, not a browser API or an automatic feature
of the vendored runtime. Before using a runner, implement its Node/host-side
pre-dispatch and settlement hooks; a browser-only callback is not durable.
of the vendored runtime. Vendor `templates/mutation-journal.{ts,js}` next to the
spec and use its Node/host-side `openMutationJournal`, `beforeDispatch`, `settle`
and `close` operations; a browser-only callback is not durable. The helper prefers
`flock(1)`, falls back to macOS/FreeBSD `lockf(1)` descriptor mode (which implies
`-k`), and fails closed when neither advisory-lock command is available. Other
runners must adapt dispatch through these same hooks rather than reproduce the
locking and durability protocol.

The helper opens the sidecar once without following symlinks, rejects non-regular
or multiply linked files, and passes that verified descriptor to the lock backend.
The short acquisition process exits while the runner retains the locked open-file
description itself, so there is no separately killable holder between a journal
write and dispatch. A competing descriptor verifies that the kernel lock survived
acquisition; device/inode checks at every durable I/O boundary fence pathname
replacement. Existing journals are validated in full before use; only an actually
absent `mutationExecutions` field is migrated, while malformed entries, duplicate
execution IDs and invalid cleanup-parent links fail closed without a rewrite.
On its first execution-capable open it also records one stable
`mutationLockIdentity` in the manifest and sidecar metadata; a missing or different
sidecar identity thereafter cannot become a second operational lock.

Each entry has `executionId`, `tool`, `contractRevision`, `origin`, `role`,
`fixtureRevision`, `argumentsFingerprint` (SHA-256 of canonical JSON with sorted
Expand Down
27 changes: 20 additions & 7 deletions skills/webmcpify/references/verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ as the expected property in the actual target Chrome build.

## Harness

Instantiate `templates/webmcp.spec.ts` + `templates/webmcp-compat.js` (bundled with this skill — vendor both together; the spec imports `parseInputSchema` from the helper on the Node side, and carries an inlined `normalizeResult` copy inside `page.evaluate` because the browser cannot close over imports) — Playwright,
Instantiate `templates/webmcp.spec.ts`, `templates/webmcp-compat.js` and the
`templates/mutation-journal.{ts,js}` pair (bundled with this skill — vendor all
of them together). The spec imports `parseInputSchema` from the compatibility
helper on the Node side, and carries an inlined `normalizeResult` copy inside
`page.evaluate` because the browser cannot close over imports. The mutation
journal is host-side and must never be copied into browser code. Use Playwright,
headed persistent Chrome, one describe-block per tool generated from the manifest,
with real assertions (never commented-out placeholders). Put the generated spec
next to the repo's existing e2e tests.
Expand All @@ -127,6 +132,7 @@ import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: process.env.WEBMCP_SPEC_DIR, // → <target-repo>/.webmcpify
workers: 1, // one shared headed Chrome — never parallelize
retries: 0, // never replay a possibly-mutating call
});
EOF
WEBMCP_SPEC_DIR=<target-repo>/.webmcpify \
Expand Down Expand Up @@ -161,12 +167,19 @@ the page-context Playwright harness above, which was measured against Chrome 150

Before using the spec template, Puppeteer, Workbench, smoke or model runners,
read [the durable journal protocol](reverify.md#durable-mutation-execution-journal).
The supplied browser/runtime helpers do not implement host persistence. Instrument
all mutation dispatches and cleanup with its atomic pre-dispatch/settlement hooks,
acquire its stable sidecar OS lock before the initial manifest scan, and disable
automatic retries. A runner without such hooks is read-only for this
workflow; report mutation checks not-run. Reconcile existing started entries
before selecting tools, including entries on verified/skipped tools.
Use the shipped `templates/mutation-journal.{ts,js}` helper instead of hand-rolling
the lock or write sequence: call `openMutationJournal` before the runner's first
manifest read, `beforeDispatch` immediately before every mutation (invalid examples
and cleanup included), and `settle` only after the effect or proven absence plus
cleanup has been independently established. Keep the journal open until the final
settlement and disable automatic retries. The helper uses `flock(1)` where present,
falls back to macOS/FreeBSD `lockf(1)` descriptor mode without replacing the sidecar, and fails
closed if neither command is available. A runner that cannot expose these hooks is
read-only for this workflow; report mutation checks not-run. Reconcile existing
started entries before selecting tools, including entries on verified/skipped tools.
Do not repair a malformed journal or sidecar in place: the helper deliberately
rejects corrupt entries, symlinks, hard links and lock-identity changes without
authorizing a mutation.

## Agent evals (recommended; required evidence for SaaS-scale readiness claims)

Expand Down
Loading
Loading