Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tool descriptor — --describe

Every Vyges engine can describe itself: run vyges-<engine> --describe and it prints one JSON object saying what it is, how to call it, what it produces, and what claim its result may establish about your design.

vyges-drc --describe

One probe is enough to drive an engine you have never seen. That is what lets vyges mcp hand an AI IDE a typed tool for each engine — real per-parameter schemas rather than an opaque argument string — and it is equally usable from your own orchestrator, CI job, or script.

The descriptor is emitted by the binary, so it cannot drift from the code that implements it. If an engine gains a flag, its descriptor gains it in the same build.

The schema field

Every descriptor names the format it speaks:

"schema": "vyges-tool-descriptor/1.1"

Check the major, ignore the minor. The format grows additively, so a reader that understands 1.x can consume a 1.7 payload by ignoring fields it does not recognise; a 2.x payload is the one that needs attention. This is deliberately not the engine’s release version — engines release from their own repos, and a newer engine driven by an older caller is fine as long as both speak the same descriptor format.

A payload with no schema predates the convention. Treat it as an older build rather than a broken one: read what you recognise and carry on. vyges modules reports this per engine in its CONTRACT column, where pre means exactly that.

Who this page is for: anyone driving the engines programmatically — flow authors, orchestrators, CI, and agent tooling. If you just want to run an engine by hand, --help is the friendlier surface.

A complete descriptor

This is the real output of vyges-em-ir --describe:

{
  "schema": "vyges-tool-descriptor/1.1",   // the descriptor format this payload speaks
  "name": "em-ir",
  "summary": "EM / IR-drop power-integrity sign-off (PDN -> report)",
  "maturity": "workflow-validated",
  "provenance_limitations": [
    "The job names the PDN or DEF/LEF and any power and decap maps; input_hash covers the job path and arguments, not their contents."
  ],
  "invocation": {
    "args_template": ["run", "{job}"],
    "optional": [ { "arg": "out", "flag": "-o" } ],
    "emits_json": true
  },
  "inputs": {
    "type": "object",
    "required": ["job"],
    "properties": {
      "job": { "type": "string", "description": "Path to the EM/IR-drop job file (PDN + limits)." },
      "out": { "type": "string", "description": "Write output to FILE instead of stdout." }
    }
  },
  "artifacts": [ { "role": "emir_report", "field": "report_path" } ],
  "assertion": {
    "id": "power-integrity-met",
    "field": "pi_met",
    "pass_when": { "is_true": true }
  },
  "consumes": ["pdn", "power_report", "spef", "emgeom"]
}

Given only that, a caller can build the command, validate arguments before spending a run, find the report afterwards, and read a pass/fail verdict — without knowing anything else about power integrity.

Top-level fields

FieldRequiredWhat it is
nameyesStable tool id (drc, sta-si, …). The MCP tool takes this name.
summaryyesOne line, shown as the tool’s description.
invocationyesHow to build the command — see below.
inputsnoJSON Schema for the callable parameters. Defaults to an empty object schema.
artifactsnoThe files the run produces, and how to locate them.
assertionnoHow to derive the engineering verdict. Omitted → the result is unknown.
maturitynoHow far the evidence has been proven. Omitted → discovered, which suppresses the verdict.
provenance_limitationsyesWhat input_hash does not cover, in the engine’s own words.
consumesnoInput artifact roles the engine expects (e.g. ["netlist","liberty","spef"]). Declarative today — published for flow authors, not interpreted by the CLI.

A payload without a usable invocation.args_template is not a descriptor; callers should fall back to passing raw CLI arguments.

invocation — building the command

"invocation": {
  "args_template": ["check", "{gds}", "--rules", "{deck}"],
  "optional": [ { "arg": "top", "flag": "--top" } ],
  "emits_json": true
}
  • args_template — the argument vector. A {name} token is substituted with the caller’s value for name. Tokens are required: a missing one is a caller error, not a default.
  • optional — appended only when supplied. With flag, the pair --top TOP is appended; without one, the bare value is appended.
  • emits_json — when true (the default), callers append --json if it is not already present, so the engine’s machine-readable output comes back.

For the descriptor above, {job: "block.emir", out: "emir.rpt"} builds:

vyges-em-ir run block.emir -o emir.rpt --json

inputs — the parameter schema

A standard JSON Schema object describing the callable parameters. vyges mcp passes it through as the MCP tool’s inputSchema, which is why an engine’s parameters appear individually named and documented in an AI IDE. Use it to validate a call before running anything.

Keep name and inputs in mind as the compatibility surface: changing either changes how every existing caller must invoke the tool.

artifacts — finding what the run produced

Each entry names a role and says where the path comes from:

"artifacts": [
  { "role": "timing_report", "field": "report_path" },  // path comes from the engine's --json
  { "role": "sdf", "from_arg": "sdf" }             // path is the value of an input argument
]

An entry needs a source. role alone says a file exists but not where to find it, so the registry drops it — the role then has no effect and the file never appears in the result. Pair every role with a field or a from_arg, and expose the output argument in invocation.optional so a caller can ask for it in the first place.

Prefer field for anything the engine writes. A sign-off engine given -o FILE reports the path back as report_path in its --json, so the artifact is located from the result rather than by echoing an input. That also means the payload still arrives on stdout when -o is used — -o writes the report, it does not redirect the machine output — so one call yields both the verdict and the artifact. Use from_arg where the path really is just an input the engine wrote to and does not echo back (sta-si’s --sdf, for instance).

KeyMeaning
roleWhat the file isdrc_report, timing_report, lvs_report, netlist, svg, …
fieldKey in the engine’s --json output holding the path.
from_argInput-argument name whose value is the path (for -o-style outputs).

Roles are not just labels. vyges mcp derives a tool’s read-only vs mutating classification from them — an engine that produces a netlist edits your design, one that produces a drc_report does not — which is what the VYGES_MCP_PROFILE tiers gate on. See read-only vs mutating tools.

assertion — the design verdict

An engine run has two independent outcomes: whether the process succeeded, and what the evidence says about your design. assertion declares how to derive the second from the engine’s own --json output.

"assertion": {
  "id": "drc-clean",          // stable name for the claim
  "field": "clean",           // key in the engine's --json output
  "pass_when": { "is_true": true },
  "summary_field": "summary"  // optional: a human-readable line to surface
}
pass_whenPasses when the field is
{ "is_true": true }boolean true
{ "eq": <value> }equal to that value (numbers compare numerically)
{ "lte": <number> }a number less than or equal to it

Alternatively { "id": "...", "not_applicable": true } declares that the operation makes no engineering claim — a viewer or format converter — which is different from having one and not reaching it.

The derived verdict lands in the loom-result envelope as engineering.status (pass | fail | unknown | not_applicable), separate from the execution status — see the result envelope. The rules are deliberately conservative: no declared assertion, a run that did not complete, or a verdict field that is missing, null, or the wrong type all yield unknown — never pass, and never fail. Nothing is reported as passing on absent evidence, and a tooling defect is never reported as a design defect. See the two status axes.

Declaring one well

The verdict field must cover the whole check. Two traps are worth naming, because both occurred in this suite and both would have overstated the result:

  • A partial verdict. Timing has setup and hold; power integrity has IR drop and electromigration. Asserting on a field that covers only one half passes designs that fail the other. Where an engine reports several partial verdicts, assert on a combined field.
  • A genuinely inconclusive state. Some checks can finish without reaching a conclusion — a layout-vs-schematic MATCH the bounded search could not confirm, or a timing run with no endpoints to analyze. Emit the verdict field as null in those cases rather than forcing a boolean; null resolves to unknown, which is the honest answer.

maturity — how far the evidence has been proven

Separate from what a verdict says is how much it can be relied on. maturity is that second axis, and it is deliberately about the engine, not the design.

LevelMeans
discoveredThe binary resolves and reports a version. Nothing about its output is guaranteed.
structuredIt publishes a versioned operation and a normalized result — a descriptor like this one.
workflow-validatedIts repository additionally carries a pinned design or fixture that the test suite runs end to end and asserts against, so the operation is proven on a real input, not merely described.

It gates the verdict, it is not decoration. At discovered there is no validated result shape behind an assertion, so the claim is not reportedengineering.status stays unknown however well-formed the assertion is. Absent or unrecognized means discovered: an engine has to say more to claim more, the same principle as an absent assertion.

The level also rides along in the generated MCP tool description, so an agent weighing a result sees it without a second call.

Where the Loom engines stand

Published because publishing your own gaps is the point — a ladder nobody is ever on the bottom rung of would say nothing.

LevelEngines
workflow-validatedsta-si · em-ir · lvs · extract · thermal · power
structureddrc · cdc · glitch · lec · char · gds-view · resize · vt-swap · buffer-insert · hold-fix

The structured engines are not less correct — several carry substantial unit-test suites. They simply do not yet ship a pinned end-to-end case in-repo, and the ladder reports what is proven there, not what is believed.

provenance_limitations — the boundary of the hash

Required. Every descriptor must state what input_hash does not cover.

The reason it is required rather than encouraged: the boundary is easy to leave implicit and expensive to discover later. input_hash is taken over the resolved binary identity, version, declared environment and the argument vectornot the content of any file those arguments name, and not anything those files in turn reference. A job file that points at a netlist, a Liberty and a SPEF contributes only its own path to the hash. Edit the netlist in place and the hash does not move.

"provenance_limitations": [
  "The job names the netlist, Liberty and SPEF; input_hash covers the job path and arguments, not their contents, and Liberty `include` files are not enumerated."
]

The declared strings travel with the evidence they qualify — they appear as provenance.limitations in every result envelope, beside the input_hash they are about, so a consumer reads the caveat where it matters rather than having to go looking for it.

Stability

A descriptor carries no version of its own — it is whatever the binary you invoked emits, so pin the engine version if you need a fixed contract (vyges-<engine> --version).

name and inputs form the compatibility surface: treat a change to either as a breaking change for callers. New optional fields may appear over time — ignore what you do not recognize, and never infer a passing verdict from a field you cannot interpret.