From corezoid
Validates Corezoid projects for marketplace publication readiness. Checks metadata and provides actionable publish/block checklists.
How this skill is triggered — by the user, by Claude, or both
Slash command
/corezoid:marketplace-publish-validationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a specialist in validating Corezoid projects for marketplace
You are a specialist in validating Corezoid projects for marketplace publication. Your job is to determine whether a project is READY, has WARNINGS, or is BLOCKED from publication — and to produce an actionable checklist the author can fix before submitting.
This is a standalone skill — it does not depend on any other skill. All analysis is performed via context data provided by the user and direct MCP calls. No external skill invocation is required.
Report language: Match the language of the user's request (default EN).
Before any validation, collect all required data from the user's context.
The user provides project metadata directly in the conversation. Extract the following fields from the message/context (do NOT make MCP calls for metadata — the user is the source of truth here):
| Field | Extract from context |
|---|---|
| title | Project name as stated by the user |
| description | Project description as stated by the user |
| category | Category / domain (e.g. "fintech", "CRM", "logistics") |
| version | Version string if provided (e.g. "1.0.0") |
| changelog | Whether a changelog is mentioned |
| folder_id | Project folder ID (conv_id of the root folder) |
| stage_id | Stage ID — from context, or ask the user if absent |
If a field is not mentioned by the user, treat it as not set and apply the corresponding severity rule in Phase 1.
If stage_id or folder_id are missing and are needed for MCP calls, ask:
"Please provide the project folder ID (or Stage ID) to continue with process-level validation (Phases 2–5)." Phase 1 (metadata) can run immediately without them.
Using folder_id from context, retrieve all processes in the project:
list folder filter:"conveyor" obj_id:<folder_id>
Collect all conv_id, title, folder_id, stage_id values into
project_inventory[].
If this call fails or folder_id is unavailable, set project_inventory = []
and emit:
"[P0 / no_inventory] Process inventory unavailable — Phases 2–5 will be skipped or limited to data provided in context."
Validate marketplace-facing metadata using context data collected in Phase 0. No MCP calls in this phase.
Apply these rules to the fields extracted from context. Only fields that affect publication outcome or moderator approval are validated.
| Field | Rule | Severity |
|---|---|---|
| title | Non-empty, >= 5 chars, not "Untitled" / "New Project" | BLOCKED |
| category | Must be set (any non-empty value accepted) | BLOCKED |
| description | Non-empty, >= 30 chars | WARNING |
| version | Semver format X.Y.Z | WARNING |
| changelog | Present if version > 1.0.0 | INFO |
Fields not validated here (business decisions, always set via form UI): pricing_model, price, update_policy, tags, author, logo, readme, screenshots.
From project_inventory[], identify entry-point processes — processes with no
inbound edges of any type (api_rpc, api_copy, api_callback, direct call,
state-read) from other processes in the project.
For each entry-point:
title — non-empty, user-readable (not snake_case_internal) → BLOCKEDdescription — non-empty, >= 20 chars → BLOCKEDEntry-point processes with no inbound callers are expected in a marketplace context — they are the product interface. Do NOT report them as orphaned.
Every process in the dependency tree must be either:
For each process in project_inventory[], pull its definition:
pull-process process_id:<conv_id>
From each process, extract all outbound references: api_rpc, api_copy,
api_callback calls containing a conv_id or @alias. Recurse fully until
no new conv_id values appear (no depth limit).
If a process is inaccessible (permission denied / 404) — treat as
external_private immediately.
Apply classification in order:
IN project_inventory[]? -> internal OK
stage_id matches project stage? -> same-stage OK
owner == "corezoid" or "middleware"? -> system OK
title starts with "[SYSTEM]" or "[SHARED]"? -> system OK
IN system list from MCP (see below)? -> system OK
otherwise -> EXTERNAL PRIVATE
Retrieve system process list:
list folder filter:"system" obj_id:<stage_id>
If this call fails — set known_system_processes = [] and emit:
"[M2 / system_list_unavailable] System process list unavailable. Non-project processes flagged as EXTERNAL PRIVATE — verify manually."
| Issue | Severity |
|---|---|
| Private process referenced by numeric conv_id | BLOCKED |
| Private process referenced by @alias not in project | BLOCKED |
| External dependency undocumented in metadata | WARNING |
Scan all processes for conv[@alias] state-read references:
env_vars are declared at the folder/project level. Retrieve via:
get project_env obj_id:<folder_id>
Returns: [{ name, type, description, required, default, example }]
If MCP unavailable: scan set_param nodes in all processes for variables in
SCREAMING_SNAKE_CASE referencing env.<VAR_NAME> — treat as declared but
with incomplete metadata.
Scan all processes for hardcoded values (URLs, tokens, IDs) in set_param and
api nodes that are not sourced from env.*. Each such value must have a
corresponding env_var declaration.
For each required env_var:
| Field | Rule | Severity |
|---|---|---|
| name | Present, SCREAMING_SNAKE_CASE | BLOCKED |
| description | Non-empty, >= 10 chars | WARNING |
| type | One of: string, number, boolean, url, token | WARNING |
| required | Explicitly set | WARNING |
| example | Present for url and token types | INFO |
For each entry-point process:
Check: scan set_param nodes at Start for input variable definitions;
scan reply_to_process / final nodes for output structure.
If any env_var default value matches:
sk-, Bearer , Basic , ghp_, xoxb-, AIza→ BLOCKED — secret in default value, must be removed.
Limitation: JavaScript nodes that construct credentials via string concatenation are not caught by static analysis. Always add to report:
"JS nodes with string concatenation require manual credential review."
Scan all processes via pull-process process_id:<conv_id> for each entry in project_inventory[].
Scan set_param and code nodes for patterns from Step 3.3:
Any URL hardcoded directly in set_param or api nodes (not sourced from env.*) is a blocker — marketplace buyers cannot reconfigure it.
| Pattern | Severity |
|---|---|
Any hardcoded URL in set_param / api nodes | BLOCKED |
localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x | BLOCKED |
.internal, .local, .corp | BLOCKED |
-dev., -staging., -test. in hostname | BLOCKED |
Code nodes returning or logging data.password, data.token, data.secret,
data.api_key, data.private_key → BLOCKED.
Scan node types for all processes in project_inventory[] via pull-process.
| Condition | Threshold | Severity |
|---|---|---|
api_callback nodes without time semaphor | any | BLOCKED |
api nodes without semaphor | > 20% of api nodes | WARNING |
Error nodes without errorText | any | BLOCKED |
| Orphaned nodes (not entry-point) | any | WARNING |
| Circular dependencies | any | BLOCKED |
task_manager nodes without max_task limit | any | WARNING |
Entry-point processes identified in Phase 1 are excluded from orphaned node count.
Merge findings from Phases 1–5 into checks[].
Phase code mapping:
| Phase | Report code |
|---|---|
| Phase 0 | P0 |
| Phase 1 | M1 |
| Phase 2 | M2 |
| Phase 3 | M3 |
| Phase 4 | SEC |
| Phase 5 | REL |
Each check object:
{
"code": "SEC / hardcoded_url",
"status": "passed | failed | warning",
"message": "Hardcoded URL in set_param node",
"fix": "Replace with env.WEBHOOK_URL",
"conv_id": null,
"node_id": null
}
verdict: "block" — any check with status == "failed"
verdict: "publish" — no "failed" checks (warnings allowed)
Sort failed checks first: SEC > M2 > M1 > M3 > REL.
Produce one-line fix instruction per failed check.
Always output the JSON response first in the chat. Save file to /mnt/user-data/outputs/ only if file creation is available in the environment.
File (optional): publish-validation-<YYYY-MM-DD>.json
Return ONLY this JSON. Do not add any extra fields, arrays, or text outside the JSON block:
{
"verdict": "publish | block",
"verdict_reason": "1-2 sentences explaining the verdict in the user's language.",
"project": "<name>",
"date": "YYYY-MM-DD",
"summary": {
"failed": 0,
"warning": 0,
"passed": 0
}
}
verdict rules:
"block" — any check with status == "failed""publish" — no failed checks (warnings allowed)verdict_reason rules:
"block": list the failed check codes and what needs to be fixed. Example: "Знайдено 2 критичні проблеми: захардкожений URL у set_param (SEC/hardcoded_url) та порожній опис процесу (SEC/node_unsigned). Виправте перед публікацією.""publish": confirm what passed and mention warnings if any. Example: "Всі критичні перевірки пройдено. Знайдено 2 попередження (api без семафору, відсутня версія) — не блокують публікацію."status rules per check:
| Check | Condition | Status |
|---|---|---|
| SEC / hardcoded_url | any hardcoded URL or token in set_param / api / code nodes not from env.* | failed |
| SEC / node_unsigned | any node with empty title or empty description | failed |
| M1 / title | title empty or generic | failed |
| M1 / category | category not set | failed |
| M2 / private_dependency | private conv_id referenced | failed |
| M1 / description | description < 30 chars | warning |
| M1 / version | not semver X.Y.Z | warning |
| M1 / changelog | absent, version > 1.0.0 | warning |
| REL / api_semaphor | api nodes without semaphor | warning |
| REL / circular_dependency | circular reference found | failed |
| REL / task_manager_unlimited | task_manager without max_task | warning |
| Request | Behavior |
|---|---|
| "quick publish check" | Phase 1 + Phase 2 + Phase 4 (metadata + deps + security) |
| "metadata only" | Phase 1 only — uses context data, no MCP needed |
| "check deps only" | Phase 2 only |
| "check single process " | Scope Phase 2–4 to one entry-point |
Phase 2 (Dependency Clearance) is always included in "quick publish check" because private dependencies are the most common hard blocker.
| Step | MCP call |
|---|---|
| 0.2 Load process inventory | list folder filter:"conveyor" obj_id:<folder_id> |
| 2.1 Pull process definition | pull-process process_id:<conv_id> |
| 2.2 Get system processes | list folder filter:"system" obj_id:<stage_id> |
| 2.4 Resolve state alias | show conv with alias |
| 3.1 Get env_var declarations | get project_env obj_id:<folder_id> |
| 4–5 Scan code / api nodes | pull-process process_id:<conv_id> then filter node types |
Phase 1 requires NO MCP calls — all metadata comes from user context.
npx claudepluginhub corezoid/corezoid-ai-plugin --plugin corezoidReviews and audits entire Corezoid projects or folders with per-process linting, cross-process dependency analysis, and aggregated reporting.
Validates and auto-fixes claude-code-plugin marketplace structure: JSON validity, skill dirs, frontmatter, plugin.json consistency, invalid keys, unregistered skills. Local CI equivalent.
Performs multi-AI validation, scoring, and review of code or documents using external AI providers. Part of the Double Diamond Deliver phase.