UNPKG

paqad-ai

Version:

Spec-driven development framework — AI agents that think before they type

75 lines (58 loc) • 5.14 kB
--- name: rule-script-generator description: 'Writes deterministic .mjs verification scripts with pass and fail fixtures for each deterministic or heuristic rule that has no enforcer, and registers a script only after it classifies its own fixtures correctly; a failing script goes to a Decision Pause. Use when the user asks to generate or regenerate rule scripts after analyze rules produced a reviewed map.' metadata: model_tier: reasoning cacheable: 'false' output_format: markdown paqad-meta: skill.meta.yaml --- ## What It Does For every rule in `rule-script-map.yml` whose `verifiability.kind ∈ {deterministic, heuristic}` and whose `enforced_by` is empty, authors one or more Node ESM scripts under `.paqad/scripts/rules/<mirror>/<rule-file>/NNN-name.mjs`, each with `__fixtures__/pass/` and `__fixtures__/fail/`. Each script: - Carries the `@paqad-rule-script` header (validated against the header schema). - Reads `{ projectRoot, files }` from stdin and writes the findings JSON contract to stdout. - Is validated against its own fixtures **before** registration. Pass fixtures must yield zero findings; fail fixtures at least one. A script that fails is rejected and surfaced, never registered. No `.sh` scripts are ever produced. See `references/script-authoring.md` for the full contract. ## Use This When - A user prompt matches the priority-225 router rules `generate rule scripts` or `regenerate scripts for rule RL-<id>`. - After `analyze rules` has produced a reviewed `rule-script-map.yml`. ## Inputs - `docs/instructions/rules/rule-script-map.yml` (read for rules + classifications; written only via the bundled `register-script.mjs` → `src/rule-scripts/apply.ts`). - The rule text for each target rule (to author the detection logic). - Existing in-scope source files, used for the over-flagging dry-run guard. ## Procedure 1. Load the map. Select target rules: `kind ∈ {deterministic, heuristic}` and `enforced_by == []`. If `only_rule_id` is set, restrict to it. 2. For each target rule, author `NNN-name.mjs` with the header + stdin/stdout contract (`references/script-authoring.md`), plus 2–4 synthetic 5–15 line fixtures under `__fixtures__/pass/` and `__fixtures__/fail/`. Fixtures are synthetic: never copied from the user's real code. When the script loops `for (const file of files)` and each file's findings depend only on that file's own content (no other file read, no state shared across files), add `// per_file: true` to the header so the pre-edit check can reuse its earlier results for files that did not change; leave it out otherwise. 3. Validate the script against its fixtures: ``` node scripts/validate-script.mjs <abs-script-path> ``` Exit 0 = accepted. Exit 1 = rejected: surface a Decision Pause packet ("script `NNN-name.mjs` failed its own fixtures, regenerate / edit / mark unverifiable?") and do **not** register. 4. Over-flag dry-run: run the accepted script across in-scope existing files. If the flag rate exceeds the per-kind threshold (`deterministic: 0.05`, `heuristic: 0.20`), surface a Decision Pause packet before registering. 5. Register the validated script onto its rule: ``` node scripts/register-script.mjs <project-root> <script-path-rel> <rule-id> <kind> <scope> ``` 6. At the end of the cycle, prune orphaned scripts (left by edited / downgraded / removed rules): ``` node scripts/prune.mjs <project-root> ``` Deletes any `.mjs` + `__fixtures__/` under `.paqad/scripts/rules/` not referenced by an active map rule. Archived rules' scripts survive one cycle, then this prunes them. 7. Present the `## Generation Summary`: scripts accepted, scripts rejected (with reasons), over-flag warnings, pruned files. Tell the user the next prompt (`feature-development` will now enforce them). ## Output Contract - Accepted scripts written under `.paqad/scripts/rules/...` with their `__fixtures__/`. - `rule-script-map.yml` updated via `src/rule-scripts/apply.ts` with each accepted script entry (`path`, `kind`, `runtime`, `scope`, `last_validated_at`, `fixtures_passed: true`). - A `## Generation Summary` markdown block listing accepted / rejected / over-flag, each rejection naming the exact regen prompt. ## Escalate / Stop Conditions - Never register a script that fails its fixtures or whose header is invalid: surface a Decision Pause packet instead. - Never author a `.sh` script; Node `.mjs` only. - Never copy fixtures from the user's real code: fixtures are synthetic. - Skip rules with non-empty `enforced_by` (already covered) and `unverifiable` rules. - All map writes go through `register-script.mjs` → `src/rule-scripts/apply.ts`. ## Resources - `references/script-authoring.md`: header + findings + fixtures contract. - `runtime/base/skills/rule-script-generator/agents/openai.yaml`: agent interface metadata. - `src/rule-scripts/fixture-runner.ts`: the fixture gate. - `src/rule-scripts/guard.ts`: the over-flagging guard. - `src/rule-scripts/prune.ts`: orphan-script pruning (end-of-cycle). - the Decision Pause Contract (in the framework bootstrap): packet semantics for rejected scripts.