plain-healthcheck
Original:🇺🇸 English
Translated
Verification gate for a ***plain project. Verifies that every `config.yaml` exists, points at scripts that actually live in `test_scripts/`, and that `codeplain <top_module>.plain --dry-run` passes for every top module in the project. Run this whenever anything in the project is finalized — including (but not limited to) the end of `forge-plain`, the end of `add-feature`, after `debug-specs`, after any single-skill edit that finalizes a concept, functional spec, requirement, template, or config — and any time the user asks "is the project ready to render?".
2installs
Sourcecodeplain-ai/plain-forge
Added on
NPX Install
npx skill4agent add codeplain-ai/plain-forge plain-healthcheckTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Plain Healthcheck
Always use the skill to retrieve the ***plain syntax rules — but only if you haven't done so yet.
load-plain-referenceWhen to run
Run this skill **whenever anything in the *plain project is finalized and the project is about to be left in a state the user (or another skill) might render from. That includes, but is not limited to:
- End of (Phase 4) — before presenting the render command.
forge-plain - End of (Phase 3 final review) — before declaring the feature done.
add-feature - End of — after applying a fix, before telling the user to re-render.
debug-specs - After finalizing any single edit that changes the renderable surface — e.g. after ,
add-concept,add-functional-spec,add-functional-specs,add-implementation-requirement,add-test-requirement,add-acceptance-test,add-template,add-resource,resolve-spec-conflict,break-down-func-spec,consolidate-concepts,refactor-module,create-import-module, or any of thecreate-requires-moduleskills.implement-*-testing-script - After hand-editing a file, a
.plain, or anything underconfig.yaml.test_scripts/ - On demand — whenever the user asks whether the project is in a renderable state.
The healthcheck is not a forge-plain-only step. Treat it as the default closing move for any workflow that finalizes something in the project.
Do not skip this skill because "the dry-run passed earlier" — s, scripts, and specs can all drift between runs. The healthcheck is cheap; rendering against stale specs is expensive.
config.yamlWorkflow
The skill is a detect → fix → re-run loop. It does not stop at the first failure; it surfaces everything wrong, fixes what it can, and only returns when either everything passes or a gap genuinely requires user input.
Step 1 — Inventory the project
- List every file in the repo root (and any subdirectories that contain
.plainfiles). Build the module graph from each file's YAML frontmatter (.plain,requires).import - Identify top modules — every module that is not -ed by any other module. A single-stack project has one top module; a multi-part project (e.g. backend + frontend) has one top module per part.
requires - List every in the repo (root and per-part directories such as
config.yaml,backend/).frontend/ - List every script under .
test_scripts/ - Pair each top module with the that governs it. The pairing rule is: the config file in the same directory as the top module wins; failing that, the repo-root
config.yaml. A multi-part project must have one config per part — record any top module that has no governing config as a failure.config.yaml
Print a one-line inventory summary so the rest of the run is easy to follow, e.g.
Top modules: backend/api.plain (config: backend/config.yaml), frontend/web.plain (config: frontend/config.yaml). Scripts in test_scripts/: 4.Step 2 — Validate every config.yaml
config.yamlFor each in the inventory, check all of the following. Collect every failure — do not stop at the first.
config.yaml- File parses. It is valid YAML.
- At minimum is present. Every project gets a unit-test runner.
unittests-script - For every script field that is present (,
unittests-script,conformance-tests-script):prepare-environment-script- The path is a string ending in (macOS/Linux) or
.sh(Windows). The extension must match the rest of the project — do not mix.ps1and.shin a single config..ps1 - The referenced file actually exists on disk under .
test_scripts/ - On Unix, the script has the executable bit set (). If not, that is a fixable failure.
-x
- The path is a string ending in
- No mixed stacks per config. Every script referenced from a single must target the same language/stack. For example,
config.yamlshould not referencebackend/config.yaml. If a config crosses stacks, that is a failure — the project should have been split into multiple configs per the rule inrun_unittests_js.sh.PLAIN_REFERENCE.md - No dangling fields. Any field whose target file does not exist is a failure.
*-script - implies
prepare-environment-script. Aconformance-tests-scriptonly makes sense in service of conformance tests — the environment is what those tests run against. If aprepare-environment-scriptdeclaresconfig.yamlbut does not declareprepare-environment-script, that is a failure. Surface it to the user and offer to either (a) invokeconformance-tests-scriptto add the missing script, or (b) remove theimplement-conformance-testing-scriptfield if it was added in error. Do not auto-pick.prepare-environment-script - No orphan scripts. Every script under should be referenced by some
test_scripts/. If a script is never referenced, surface it as a warning (not a hard failure — the user may be in the middle of authoring).config.yaml
For each failure, record the offending config path, the offending field, and the concrete problem (, , , etc.).
file missingnot executablemixed stackAuto-fixes you may apply
- Missing executable bit on a script that otherwise looks fine → .
chmod +x <path> - Stale path that points at a renamed script that clearly exists under a different name in → only if there is exactly one obvious candidate (same language tag, same script kind). When in doubt, leave it for the user.
test_scripts/
Anything else (missing script, mixed stacks, missing ) must be surfaced to the user — do not silently regenerate scripts here. Re-invoking , , or from inside the healthcheck is allowed only if the user explicitly approves it after being shown the gap.
config.yamlimplement-unit-testing-scriptimplement-conformance-testing-scriptimplement-prepare-environment-scriptStep 3 — Dry-run every top module
For each pair from Step 1, run a dry-run from the project root via the tool:
(top_module, config.yaml)terminalbash
codeplain <top_module>.plain --dry-runMatch the dry-run to how the user will actually render. Pass the flags the user would pass for the real render so what you validate is what they will run:
- — required whenever the governing config file is not the default
--config-name <name>, or when the project has multipleconfig.yamls and the dry-run is being launched from somewhere that isn't the part's directory.config.yamltakes a file name, not a path; if needed,--config-nameinto the part's directory before running so the rightcdis found.config.yaml - — only when templates live outside
--template-dir <path>andtemplate/is not already set in the relevant config.template_dir - — useful when an
--full-plain/importchain is suspect.requires - /
--verbose— strongly recommended on a failed dry-run; the extra log output usually pinpoints the offending-vfile and spec..plain
Treat the dry-run as a hard gate: the healthcheck only passes when every top module's dry-run exits successfully.
When a dry-run fails
Iterate until it passes:
- Read the error output. If the first run was not verbose, immediately re-run with . Identify the offending
--verbosefile, the line (if reported), and the kind of issue: missing concept, syntax error, cyclic definition, complexity violation (.plain), conflicting reqs, missing template, brokenFunctional spec too complex!/import, missing config field, etc.requires - Fix only the files (or the relevant
.plain/ template) using the appropriate edit skill —config.yaml,add-concept,add-functional-spec,add-functional-specs,add-implementation-requirement,resolve-spec-conflict,break-down-func-spec, or an inline edit. Never modify generated code underconsolidate-conceptsorplain_modules/.conformance_tests/ - If you are uncertain about ***plain syntax for the failing construct, re-load before fixing.
load-plain-reference - Re-run the same command with the same flags. Repeat until it exits successfully.
codeplain <top_module>.plain --dry-run …
If the failure is something the healthcheck cannot reasonably fix on its own (e.g. the user has to choose between two contradictory specs and neither side was pre-approved, or a missing concept whose semantics aren't clear), stop and surface it to the user with the offending snippet and a concrete question. Do not invent behavior.
Environment failures
If is not on PATH, or is not set:
codeplainCODEPLAIN_API_KEY- Do not pretend the dry-run passed.
- Tell the user exactly what's missing and how to fix it (install the CLI, export the env var) and stop the healthcheck with a clearly-marked environment failure. This is the only kind of failure that may legitimately remain unresolved at the end of the skill.
Step 4 — Report
Emit one of:
- — followed by a short summary of what was checked:
PASS,N config.yaml(s) validated,M top module(s) dry-run. The caller (K scripts referenced,forge-plain,add-feature) can then continue to its hand-off step.debug-specs - — followed by a numbered list of every unresolved problem. Each entry must include: the file (config /
FAIL/ script) it applies to, the concrete issue, and what the user needs to decide if the healthcheck couldn't resolve it..plain
The verdict goes on the first line so callers can pattern-match without parsing the whole report.
What this skill does NOT do
- It does not author new specs from scratch — use /
forge-plainfor that.add-feature - It does not run the real render — only .
--dry-run - It does not execute the testing scripts (,
run_unittests,run_conformance_tests). It only verifies that the scripts are wired up correctly viaprepare_environment. The user runs the scripts themselves.config.yaml - It does not silently regenerate config files or scripts. The most it does is and (with user approval) re-invoke the relevant
chmod +xskill.implement-*-testing-script
Validation Checklist
- Every module was inventoried and every top module was identified
.plain - Every top module is governed by exactly one
config.yaml - Every parses as YAML and has at least
config.yamlunittests-script - Every field points at a file that exists under
*-scripttest_scripts/ - No mixes stacks (e.g. Python + JS scripts in the same file)
config.yaml - No declares
config.yamlwithout also declaringprepare-environment-scriptconformance-tests-script - Every file is referenced by some
test_scripts/*(or surfaced as a warning)config.yaml - exits successfully for every top module, with the right
codeplain <top>.plain --dry-runfor multi-part projects--config-name - Verdict (/
PASS) is on the first line, with a numbered list of remaining problems if it failedFAIL