Troubleshoot the gate
How to troubleshoot the gate
Section titled “How to troubleshoot the gate”The deterministic gate (node scripts/check.mjs) reports the highest tier a plugin satisfies and lists what blocks the next one. Every finding carries a reqId (for example U5, S3, G2) and an inline Standard sec pointer. This page maps the findings you hit most often to their cause and the exact remediation, so you can read a failing reqId off the gate and go straight to the fix.
The gate is judgment-free: it never decides quality, only conformance to the Standard. Description scoring and behavioral evaluation sit beside it (askit-evaluate / /askit-evaluate) and never gate pass/fail.
First, read the findings
Section titled “First, read the findings”node scripts/check.mjsEach line is [severity] check (reqId): message -> file. Two things matter:
- Severity. An
errorcan fail the gate; awarnnever does (warnings are surfaced, not blocking - Standard sec 4.5).U5,U7, andU8are warnings; most others are errors. - The declared-tier ceiling. The gate only fails on errors at or below the tier you declared in
library.json(tier). Aconvergenterror on a plugin that declaresuniversaldoes not fail the gate - it shows up in the burndown to the next tier instead. See it as a to-do list:
node scripts/tier-report.mjs --jsonblocked.convergent and blocked.advanced each list the unmet reqId: <message> entries standing between this plugin and the next grade. The fix tables below are keyed to those same reqIds.
Re-run the gate after each fix; the error count and the blocked lists shrink.
Universal (Bronze) findings
Section titled “Universal (Bronze) findings”These gate any plugin that declares universal or higher.
U1 - library.json missing or not valid
Section titled “U1 - library.json missing or not valid”- Symptom:
library.json is missing...or...is not valid JSONor...missing required field "<key>". - Cause: the manifest that makes a directory a plugin is absent, malformed, or missing one of the five required fields:
name,version,description,standard,tier(Standard sec 5.1). A bare folder of skills with nolibrary.jsonis loose components, not a Bronze plugin. - Fix: scaffold one with
askit-init-plugin, or add the missing field by hand.versionmust be semver;tiermust beuniversal,convergent, oradvanced;standardis the Standard version you target (currently"0.11").
U2 - AGENTS.md missing
Section titled “U2 - AGENTS.md missing”- Symptom:
AGENTS.md is required at the repository root at every tier. - Cause: no root
AGENTS.md, the agent navigation entrypoint required at every tier (Standard sec 3.10). - Fix: generate one with
askit-build-agents-md. Keep its component counts in sync with the manifest - drift there is its own error class.
U3 - frontmatter invalid
Section titled “U3 - frontmatter invalid”- Symptom:
frontmatter does not parse...,missing required string "name", or aname/descriptionlength violation. - Cause: a
SKILL.mdhas malformed YAML, orname/descriptionis missing or out of bounds (name1-64 chars kebab-case;description1-1024 chars - Standard sec 3.1). - Fix: correct the YAML. If you are authoring the skill,
askit-build-skillwrites conformant frontmatter for you.
U4 - name does not match directory
Section titled “U4 - name does not match directory”- Symptom:
frontmatter name "<x>" must equal the directory name "<y>". - Cause: the skill’s frontmatter
namediffers from its parent directory name (Standard sec 3.1). - Fix: rename one to match the other. The directory name is usually the one to keep, since it carries the plugin
prefix.
U5 - weak description (warn)
Section titled “U5 - weak description (warn)”- Symptom:
description scores 0.NN (< 0.7).... - Cause: the description does not clearly state what the component does and when to use it, or it leans on anti-pattern verbs (“helps with”, “handles”), or it uses first person, angle brackets, or ALL-CAPS (Standard sec 8.1). This is a heuristic 0-1 score; below
0.7it warns, never errors - description quality is judgment, so it must not hard-gate. - Fix: rewrite to lead with an action verb (creates, validates, generates…), add an explicit trigger (“use when…”), and include concrete keywords a user would actually say.
askit-build-skillincludes a description pass. To see the score and rationale beside the gate, runaskit-evaluate.
U6 - reference link does not resolve
Section titled “U6 - reference link does not resolve”- Symptom:
reference link "<text>(<path>)" does not resolve. - Cause: a relative markdown link in a
SKILL.mdbody or areferences/*.mdfile points at a path that does not exist. Areferences/file sits one directory deeper thanSKILL.md, which is exactly where a copied../../prefix silently breaks (Standard sec 3.1). - Fix: correct the path (links resolve relative to the file they live in), or create the missing target. External
https:/mailto:/anchor links are not checked.
U7 - instruction budget (warn)
Section titled “U7 - instruction budget (warn)”- Symptom:
SKILL.md body is N lines (> ...); move deep content into references/. - Cause: the
SKILL.mdbody is long enough to spend context that progressive disclosure should defer (Standard sec 1, 3.1). - Fix: move deep procedural detail into
references/(one level deep) and link to it. The body should carry the instructions; the references carry the depth.
U8 - native-manifest drift (warn)
Section titled “U8 - native-manifest drift (warn)”- Symptom:
.claude-plugin/plugin.json <field> "<x>" differs from library.json "<y>".... - Cause: a generated native manifest (
.claude-plugin/plugin.jsonor.codex-plugin/plugin.json) has anameorversionthat no longer matcheslibrary.json, which is the single source of truth those files are generated from (Standard sec 5, G4). This usually means someone hand-edited a generated file, or bumpedlibrary.jsonwithout regenerating. - Fix: regenerate, never hand-edit:
node scripts/generators/gen-manifest.mjs . --write --target=allU9 - package.json version drift
Section titled “U9 - package.json version drift”- Symptom:
package.json version (<x>) must equal library.json version (<y>). - Cause: a
package.jsonwith aversionfield disagrees withlibrary.json, which is the version source of truth (Standard sec 5). This is conditional: nopackage.json, or noversionfield, means it does not apply. - Fix: set
package.jsonversionto matchlibrary.json. When you cut a release, bump inlibrary.jsonfirst (or useaskit-release, which keeps them aligned) and regenerate the native manifests (U8).
U11 - .mcp.json invalid
Section titled “U11 - .mcp.json invalid”- Symptom: an
mcp-validfinding against.mcp.json. - Cause: the portable MCP server definitions file is malformed or a server entry is not well-formed (Standard sec 3.9). Conditional: only fires when
.mcp.jsonis present. - Fix: correct the
{ "mcpServers": { ... } }shape, or regenerate the server entry withaskit-build-mcp. Never commit secrets - useenvindirection (Standard sec 9).
Silver (Convergent) findings
Section titled “Silver (Convergent) findings”These appear in blocked.convergent until you declare convergent, then they gate.
S1 - missing agent-targets
Section titled “S1 - missing agent-targets”- Symptom:
library.json is missing "agent-targets"or...must be a non-empty array. - Cause: a Convergent plugin must declare which agents it emits for (Standard sec 5.1, 2.2).
- Fix: add
"agent-targets": ["claude", "codex"](or just one). If you are unsure which to claim, see choose-agent-targets.
S2 - missing prefix
Section titled “S2 - missing prefix”- Symptom:
library.json is missing "prefix"or...must be lowercase kebab-case ending in "-". - Cause: generic component names collide across plugins on agents that do not namespace; the Standard requires a short unique prefix declared once in the manifest (Standard sec 8.2).
- Fix: add
"prefix": "<short>-"(this repo uses"askit-"). The same check also flags individual components whose names do not carry the prefix - rename them to match.
S3 - components index drift
Section titled “S3 - components index drift”- Symptom:
library.json components.skills declares "<x>" but it is not on disk(phantom entry), orskills/<x> exists on disk but is not declared(undeclared component). The same applies tosubagents,commands, andmcpServers. - Cause: the manifest’s
componentsindex no longer mirrors what is on disk (Standard sec 5.1, 10.3). An undeclared component and a dangling declaration both fail. - Fix: add or remove the entry so the index matches disk, each entry carrying
{ name, path, version, tier, status }. Regenerating the manifest keeps the index honest:
node scripts/generators/gen-manifest.mjs . --write --target=allS8 - components entry does not mirror frontmatter
Section titled “S8 - components entry does not mirror frontmatter”- Symptom:
library.json components.<type> entry "<x>" declares status/tier "<a>" but the component's frontmatter declares metadata.status/tier "<b>".... - Cause: S3 checks that entries exist; S8 checks that an existing entry’s
statusandtiermatch the component’s own frontmatter (Standard sec 5.1). A component markeddeprecatedin its frontmatter while the manifest entry still saysactiveis the exact drift that would let a deprecation slip past the G6 contract. - Fix: align the
library.jsonentry’sstatus/tierwith the component frontmatter (or regenerate the manifest). If you are deprecating, drive it throughaskit-deprecateso both sides move together.
S4 - chain contract orphan or phantom
Section titled “S4 - chain contract orphan or phantom”- Symptom:
"<caller>" declares (frontmatter chain) that it may invoke "<callee>" but ... does not permitit (orphan), orchain-permitted contract ... points at a missing component(phantom), orchaining is used ... but agents/_chain-permitted.yaml is missing. - Cause: chain contracts are a conditional MUST - required exactly when one component invokes another (Standard sec 3.6). An orphan is an invocation declared in a component’s frontmatter
chain:that the contract does not permit. A phantom is a contract entry naming a caller or callee that matches no on-disk component. - Fix: use
askit-build-chain-contractto author or repairagents/_chain-permitted.yaml. For an orphan, add the<caller>: [<callee>]edge. For a phantom, remove the stale entry or create the missing component. A plugin that does no inter-component invocation ships no contract at all - no empty governance files. See build-a-chain-contract.
S5 - workflow references a missing skill
Section titled “S5 - workflow references a missing skill”- Symptom:
workflow "<x>" references skill "<y>" which does not exist on disk. - Cause: a
_workflows/step names a skill that is not present (Standard sec 3.4). Conditional: only fires when workflows exist. - Fix: correct the step’s skill name, or create the skill.
askit-build-workflowvalidates step references as it writes.
S6 - native manifest missing for a declared target
Section titled “S6 - native manifest missing for a declared target”- Symptom: a
per-target-presencefinding that a declaredagent-targetsentry has no native manifest on disk. - Cause: you declared
claudeand/orcodexbut the matching.claude-plugin/plugin.json/.codex-plugin/plugin.jsonis absent (Standard sec 5.1, 10.1). - Fix: generate the missing manifest:
node scripts/generators/gen-manifest.mjs . --write --target=allS7 - command contract incomplete
Section titled “S7 - command contract incomplete”- Symptom:
commands/<x>.md is missing a non-empty "description", or...must declare "maps-to", ormaps-to "<y>" but no skill or workflow by that name exists. - Cause: a command must carry a description meeting the 8.1 bar and a
maps-toresolving to exactly one on-disk skill or workflow (Standard sec 3.2). Conditional: only fires when commands exist. - Fix: add the
descriptionand amaps-tonaming the backing skill or workflow.askit-build-commandwrites both and checks the target resolves. See build-a-command.
Gold (Advanced) findings
Section titled “Gold (Advanced) findings”These appear in blocked.advanced until you declare advanced, then they gate. The full per-rule table is in gold-checks.
G2 - no self-hosting CI
Section titled “G2 - no self-hosting CI”- Symptom:
no CI workflow under .github/workflows/, ora CI workflow is present but none runs the conformance gate. - Cause: Gold requires the plugin to ship CI that runs its own validators and passes (Standard sec 2.6 G2, sec 4). “Self-hosting” means the plugin proves itself with the same gate it ships.
- Fix: add a workflow under
.github/workflows/that runsnode scripts/check.mjs(directly or via an npm script that resolves to it), andnpm test. The CI config must only shell out to the portable scripts - it must contain no validation logic of its own (Standard sec 4.4), so any contributor reproduces a CI failure locally with the same command.
G3 - a chain or hook has no eval
Section titled “G3 - a chain or hook has no eval”- Symptom:
chain "<caller> -> <callee>" has no eval/regression case under evals/, orhook event "<x>" has no eval/regression case, orcovers chain "<...>" but agents/_chain-permitted.yaml does not permit that edge(a stale eval - the regression signal). - Cause: at Gold every permitted chain edge and every registered hook must carry at least one eval/regression case, executed in CI; and an eval covering an edge the contract no longer permits is the deterministic signal that a component or contract changed underneath it (Standard sec 2.6 G3, sec 8.3).
- Fix: add
evals/<name>.eval.jsondeclaring"covers": { "chain": ["<caller>", "<callee>"] }(or{ "hook": "<event>" }) for each uncovered edge; remove or update a stale eval whose covered edge is gone.templates/eval-set.jsonscaffolds the shape. See add-eval-coverage. G3 is presence-and-execution only; the multi-tier judging engine sits beside the gate, not inside it.
Other Gold findings, in brief
Section titled “Other Gold findings, in brief”- G1 - hook documentation: a hook in
hooks/hooks.jsonis missing atypeper action or amatcheron aPreToolUse/PostToolUseevent (Standard sec 2.6 G1, sec 3.5). Fix withaskit-build-hook, which writes documented hook entries. See build-a-hook. - G4 - INDEX drift:
INDEX.mdno longer matches whatgen-indexproduces (a hand-edited generated file). Regenerate:node scripts/generators/gen-index.mjs . --write- edit the source frontmatter orlibrary.json, neverINDEX.md. - G5 - RELEASE-NOTES missing: add a curated, user-facing
RELEASE-NOTES.md, distinct fromCHANGELOG.md(Standard sec 10.6).askit-releasecurates it. See cut-a-release. - G6 - deprecation policy: a component with
status: deprecatedmust also declaredeprecated-byandremove-in, and allstatusvalues must be valid (Standard sec 3.7, 7.5). Drive it throughaskit-deprecate. See deprecate-a-component.
General workflow
Section titled “General workflow”- Run
node scripts/check.mjs(ortier-report --jsonfor the burndown). - For each finding, find its
reqIdabove and apply the fix - usually anaskit-build-*skill or a generator underscripts/generators/. - Re-run the gate. When the error count at your declared tier is zero, the gate exits
0. - To climb a tier, clear its
blocked.<tier>list, then raisetierinlibrary.json. The Bronze-to-Silver how-to walks that move; the same pattern climbs to Gold.
If a finding cites a Standard sec you want to read in full, open STANDARD.md at that section - every message points at the rule it enforces.