Skip to content

Commit d7c63a5

Browse files
committed
feat(mcp): scan-stage tool — Go port of the stage-scan validator
The corezoid-stage-scan skill shipped a 270-line Python validator as a user-machine runtime dependency outside the Go-only CI. It is now the scan-stage MCP tool inside convctl (single-runtime plugin): same five defect classes ([1] inactive, [1b] empty shells, [2a] broken node links, [2b] broken/inactive conv refs, [2c] api_get_task node missing in the target), same folder-location annotations, quiet and json modes; a parity run on a fixture covering every class produced identical findings to the Python original. Non-object JSON files are skipped silently, exactly like Python's isinstance guard. Deliberate divergences, all safety-positive: zip extraction refuses zip-slip entries and re-roots absolute names (Python's extractall had no guard); the export path is confined to the working directory like every other file tool here; files with duplicate or missing obj_id are each scanned and listed (the Python dict silently dropped duplicates and crashed on several missing-obj_id shapes). The CLI exit code reflects tool errors only — the skill's CI recipe gates on the 'No blockers found.' verdict line instead. The skill drives the tool; the Python script is deleted and the checks run as ordinary go tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent adc026f commit d7c63a5

8 files changed

Lines changed: 895 additions & 283 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Feat: `scan-stage` MCP tool — the corezoid-stage-scan validator ported from the skill's Python script to Go inside convctl (single-runtime plugin, zip-slip-safe extraction, deterministic output; `quiet` and `json` modes). The skill now drives the tool; `scripts/scan_stage.py` is gone and the checks are covered by go tests.
56
- Feat: code-enforced node placement on `push-process` — new nodes added with placeholder coordinates (`x: 0, y: 0`) are auto-placed by the MCP server. Preserve mode is the default: already-placed nodes are never moved, only the new `(0,0)` nodes are slotted near their graph neighbours without overlap; a fully-new process gets a clean layered layout. Disable with the environment variable `COREZOID_AUTOLAYOUT=off`.
67
- Feat: `layout-process` MCP tool — the deterministic auto-layout engine (waterfall for simple trees, sugiyama-lite + error rail for meshes, aligned TABLE/STAR region grids), fully in Go inside convctl. It rewrites only `x`/`y` and the `extra.modeForm` collapse flag, preserves the source file's indentation and trailing newline, and always reports the chosen strategy, canvas size and overlap count; `dry=true` previews without writing, `density=compact|medium|roomy` controls spacing. The corezoid-node-layout skill now drives this tool — its Python scripts are gone (single-runtime plugin), with the 12 layout invariants running as ordinary go tests plus golden coordinate files. Also fixes the hybrid strategy dropping `modeForm=collapse` on residual-graph nodes (they rendered as full blocks shifted by the collapsed offset).
78
- Feature: new `corezoid-node-layout` skill — auto-arranges a process's node x/y into a clean, readable layout and rewrites the `.conv.json` in place (positions + IF/Delay/error collapse only; edges, logic, `conv_id`, aliases and node types are left byte-for-byte intact). Business logic is laid out as a vertical top-to-bottom spine; error handling (escalation → reply → error-final, reachable only via `err_node_id`) is collapsed into a tidy right-hand rail; unreachable orphans go into a compact grid. Guarantees no node overlaps and coordinates within Corezoid's ±10000 canvas (the vertical step shrinks for very deep processes). Simple tree-like processes use a "waterfall" (branches fanned around a central column); large mesh processes use a layered algorithm (dummy nodes for long edges + median crossing-minimisation + priority coordinate straightening). The engine is implemented in Go inside the plugin's MCP server (the `layout-process` tool above — single-runtime plugin, no Python); its clean-layout invariants run as ordinary go tests. Complements the existing `docs/process/node-positioning-best-practices.md`. Run it as the last step before `push-process`.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ validation errors, and summarize what each process does.
213213
| `push-process` | Validate and deploy a `.conv.json` to Corezoid |
214214
| `layout-process` | Auto-arrange node coordinates (waterfall / layered / table-star regions); local, changes only x/y and collapse flags |
215215
| `lint-process` | Validate process structure locally (no API call) |
216+
| `scan-stage` | Static validation of an exported stage .zip/dir: inactive processes, broken node links and conv refs (local, no API) |
216217
| `run-task` | Send a task to a deployed process |
217218
| `list-node-tasks` | List tasks currently sitting in a node |
218219
| `list-task-history` | Show task execution history |

plugins/corezoid/mcp-server/mcp_handlers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var toolHandlers = map[string]toolHandler{
3131
"delete-variable": handleDeleteVariable,
3232
"push-process": handlePushProcess,
3333
"layout-process": handleLayoutProcess,
34+
"scan-stage": handleScanStage,
3435
"lint-process": handleLintProcess,
3536
"run-task": handleRunTask,
3637
"create-process": handleCreateProcess,
@@ -102,6 +103,7 @@ var toolHandlers = map[string]toolHandler{
102103
// occurred before or during the login flow.
103104
var noAuthTools = map[string]struct{}{
104105
"layout-process": {},
106+
"scan-stage": {},
105107
"lint-process": {},
106108
"login": {},
107109
"logout": {},

0 commit comments

Comments
 (0)