mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-07-15 19:06:18 +08:00
a517ecee07
scripts/skill-conformance.test.ts auto-discovers each .claude/skills/*/SKILL.md with nc: fences (15 today) and asserts, per skill: lint clean (errors and warn-lints); per branch-scenario from a colocated apply-fixtures.json, a full applySkill run with stubbed exec/execStream/resolveRemote goes green — nothing deferred, nothing degraded to agent, every var bound; every when: guard value is exercised by some scenario (coverage read from ApplyResult.vars, with documented exclusions); static effect ordering (mutations before build, build before test, restart only after both); and a run-health sabotage probe — a failing fetch/check/external run must gate every later restart/step/wire. Fixture values satisfy the skills' real validate: regexes, so a fixture can't paper over a broken prompt. Skills with prompts but no fixture fail with an actionable message; prompt-less skills get a default empty scenario. scripts/skill-inputs.ts adds the inputsFromEnv helper from the seam spec §6 (NC_INPUT_<VAR>, collision error); its test round-trips env-supplied inputs through a real skill apply. Runs in the existing CI vitest step — no workflow change needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
33 lines
1.5 KiB
TypeScript
33 lines
1.5 KiB
TypeScript
// inputsFromEnv — the pipeline consumer's input path (docs/skill-engine-seam.md §6).
|
|
//
|
|
// A CI/pipeline caller supplies prompt answers as environment variables using
|
|
// the `NC_INPUT_<VAR>` convention (prompt var uppercased). This helper parses
|
|
// the skill's prompt vars via parseDirectives and returns the `inputs` record
|
|
// applySkill consumes. It is a helper, not an engine feature — the engine never
|
|
// reads process.env for inputs; `inputs` stays the only env-agnostic seam.
|
|
//
|
|
// Var names are case-sensitive in the grammar, so uppercasing can collide
|
|
// (`bot_token` vs `Bot_Token` both map to NC_INPUT_BOT_TOKEN); a collision is
|
|
// an error, never a silent last-writer-wins.
|
|
|
|
import { parseDirectives, promptVar } from './skill-directives.js';
|
|
|
|
export function inputsFromEnv(md: string, env: Record<string, string | undefined> = process.env): Record<string, string> {
|
|
const inputs: Record<string, string> = {};
|
|
const byKey = new Map<string, string>(); // NC_INPUT_<VAR> → the prompt var that claimed it
|
|
for (const d of parseDirectives(md)) {
|
|
if (d.kind !== 'prompt') continue;
|
|
const v = promptVar(d);
|
|
if (!v) continue;
|
|
const key = `NC_INPUT_${v.toUpperCase()}`;
|
|
const prior = byKey.get(key);
|
|
if (prior !== undefined && prior !== v) {
|
|
throw new Error(`inputsFromEnv: prompt vars "${prior}" and "${v}" both map to ${key} — rename one (var names must be case-insensitively unique)`);
|
|
}
|
|
byKey.set(key, v);
|
|
const val = env[key];
|
|
if (val !== undefined) inputs[v] = val;
|
|
}
|
|
return inputs;
|
|
}
|