Skip to content

Commit e74f98a

Browse files
FIX: Validation didn't flag missing context definition for variables.
1 parent fb95c3a commit e74f98a

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

SKILL.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
---
2+
name: promptopskit
3+
description: Guidance for creating and editing promptopskit prompt files, defaults, variables, and validation-safe templates.
4+
---
5+
16
# promptopskit — Prompt Engineering Skill
27

38
This project uses **promptopskit** to manage LLM prompts as code.
@@ -36,6 +41,13 @@ You are a helpful assistant.
3641
Hello {{ name }}, how can I help you?
3742
```
3843

44+
When creating a new prompt file with "just the necessary fields", include only
45+
the fields required by that specific file:
46+
- Always include `id` and `schema_version: 1`
47+
- Include `provider` and `model` only if they are not inherited from `defaults.md`
48+
- Include `context.inputs` whenever the body contains `{{ variable }}` placeholders
49+
- Omit `context` entirely only when the body has no placeholders
50+
3951
---
4052

4153
## Front matter reference
@@ -84,10 +96,31 @@ sections. Variables are replaced at render time.
8496

8597
Rules:
8698
- Declare all variables in `context.inputs` — validation warns on undeclared usage
99+
- Before finishing a new prompt file, scan the body for every `{{ variable }}` and
100+
ensure each exact variable name appears in `context.inputs`
87101
- Escape literal braces with `\{{` and `\}}`
88102
- In strict mode, missing variables throw an error
89103
- In permissive mode, unresolved placeholders are left intact
90104

105+
Example: this is the minimal valid shape for a prompt that references
106+
`{{ pull_request }}` even when provider/model are inherited from defaults:
107+
108+
```markdown
109+
---
110+
id: summarizePullRequest
111+
schema_version: 1
112+
context:
113+
inputs:
114+
- pull_request
115+
---
116+
117+
# Prompt template
118+
119+
Summarize the following pull request:
120+
121+
{{ pull_request }}
122+
```
123+
91124
---
92125

93126
## Includes (composition)
@@ -131,6 +164,9 @@ Supported default fields:
131164
This lets you configure app-wide settings like `provider` and `model`
132165
in a single root `defaults.md`, so individual prompts only declare what's unique to them.
133166

167+
Important: `defaults.md` does not declare or infer `context.inputs` for a prompt.
168+
If a prompt body uses placeholders, the prompt file itself must declare them.
169+
134170
Rules:
135171
- Nearest subfolder `defaults.md` overrides parent defaults
136172
- Prompt-local values always take precedence over defaults
@@ -316,7 +352,7 @@ Hello {{ name }}
316352

317353
1. **One prompt per file** — each `.md` file is a single prompt asset
318354
2. **Always set `id` and `schema_version: 1`** in front matter (or inherit `schema_version` from `defaults.md`)
319-
3. **Declare all variables** in `context.inputs` that appear in templates
355+
3. **Declare all variables** in `context.inputs` that appear in templates; do not leave placeholders undeclared just because other settings come from `defaults.md`
320356
4. **Use includes** for shared system instructions (tone, safety, formatting)
321357
5. **Keep prompt templates focused** — compose behavior via includes, not duplication
322358
6. **Use environment overrides** for dev/staging/prod model differences

src/validation/validate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export function validateAsset(
9595
}
9696

9797
for (const v of usedVars) {
98-
if (declaredInputs.size > 0 && !declaredInputs.has(v)) {
98+
if (!declaredInputs.has(v)) {
9999
warnings.push({
100100
code: 'POK011',
101101
message: `Variable "{{ ${v} }}" is used but not declared in context.inputs`,

tests/validation.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ describe('validateAsset', () => {
5555
expect(warning?.message).toContain('age');
5656
});
5757

58+
it('warns on variables used with no context.inputs declared', () => {
59+
const result = validateAsset({
60+
id: 'test',
61+
schema_version: 1,
62+
sections: { prompt_template: '{{ pull_request }}' },
63+
});
64+
const warning = result.warnings.find((w) => w.code === 'POK011');
65+
expect(warning).toBeDefined();
66+
expect(warning?.message).toContain('pull_request');
67+
});
68+
5869
it('warns on declared but unused variables', () => {
5970
const result = validateAsset({
6071
id: 'test',

0 commit comments

Comments
 (0)