bearings 0.3.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GEIRG7UT.js → chunk-5D5YO3E3.js} +145 -40
- package/dist/cli.js +60 -3
- package/dist/{update-XOUXGD2Z.js → update-QTWNGAGX.js} +212 -25
- package/package.json +1 -1
- package/templates/agents/commands/setup-repo.md +72 -21
- package/templates/agents/skills/checklist/SKILL.md +69 -0
- package/templates/agents/skills/checklist/previewer/index.html +38 -0
- package/templates/agents/skills/checklist/previewer/viewer.css +93 -0
- package/templates/agents/skills/checklist/previewer/viewer.js +340 -0
- package/templates/agents/skills/checklist/schema.reference.json +90 -0
- package/templates/agents/skills/checklist/scripts/build.mjs +98 -0
- package/templates/agents/skills/checklist/scripts/validate.mjs +175 -0
- package/templates/agents/skills/forge-a-skill/SKILL.md +162 -0
- package/templates/agents/skills/forge-a-skill/templates/guardrail.md +45 -0
- package/templates/agents/skills/forge-a-skill/templates/probe-set.json +45 -0
- package/templates/agents/skills/manual-testplan/SKILL.md +80 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const TOP_LEVEL_FIELDS = new Set(['title', 'summary', 'intro', 'callout', 'conventions', 'sections']);
|
|
7
|
+
const SECTION_FIELDS = new Set(['number', 'title', 'kind', 'intro', 'items']);
|
|
8
|
+
const ITEM_FIELDS = new Set([
|
|
9
|
+
'id',
|
|
10
|
+
'title',
|
|
11
|
+
'instruction',
|
|
12
|
+
'expectedResult',
|
|
13
|
+
'codeBlocks',
|
|
14
|
+
'links',
|
|
15
|
+
'optional',
|
|
16
|
+
'warning',
|
|
17
|
+
'failureGuidance',
|
|
18
|
+
'subItems',
|
|
19
|
+
]);
|
|
20
|
+
const SUB_ITEM_FIELDS = new Set([...ITEM_FIELDS].filter((field) => field !== 'subItems'));
|
|
21
|
+
|
|
22
|
+
function isObject(value) {
|
|
23
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function nonEmptyString(value) {
|
|
27
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function rejectUnknownFields(value, allowed, path, errors) {
|
|
31
|
+
for (const field of Object.keys(value)) {
|
|
32
|
+
if (!allowed.has(field)) errors.push(`${path}.${field} is not allowed`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function validateOptionalString(value, path, errors) {
|
|
37
|
+
if (value !== undefined && typeof value !== 'string') errors.push(`${path} must be a string`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function validateCodeBlocks(value, path, errors) {
|
|
41
|
+
if (value === undefined) return;
|
|
42
|
+
if (!Array.isArray(value)) {
|
|
43
|
+
errors.push(`${path} must be an array`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
value.forEach((block, index) => {
|
|
47
|
+
const blockPath = `${path}[${index}]`;
|
|
48
|
+
if (!isObject(block)) {
|
|
49
|
+
errors.push(`${blockPath} must be an object`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
rejectUnknownFields(block, new Set(['language', 'content']), blockPath, errors);
|
|
53
|
+
if (!nonEmptyString(block.language)) errors.push(`${blockPath}.language must be a non-empty string`);
|
|
54
|
+
if (typeof block.content !== 'string') errors.push(`${blockPath}.content must be a string`);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function validateLinks(value, path, errors) {
|
|
59
|
+
if (value === undefined) return;
|
|
60
|
+
if (!Array.isArray(value)) {
|
|
61
|
+
errors.push(`${path} must be an array`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
value.forEach((link, index) => {
|
|
65
|
+
const linkPath = `${path}[${index}]`;
|
|
66
|
+
if (!isObject(link)) {
|
|
67
|
+
errors.push(`${linkPath} must be an object`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
rejectUnknownFields(link, new Set(['label', 'url']), linkPath, errors);
|
|
71
|
+
for (const field of ['label', 'url']) {
|
|
72
|
+
if (!nonEmptyString(link[field])) errors.push(`${linkPath}.${field} must be a non-empty string`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function validateItem(item, path, ids, errors, subItem = false) {
|
|
78
|
+
if (!isObject(item)) {
|
|
79
|
+
errors.push(`${path} must be an object`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
rejectUnknownFields(item, subItem ? SUB_ITEM_FIELDS : ITEM_FIELDS, path, errors);
|
|
83
|
+
for (const field of ['id', 'title']) {
|
|
84
|
+
if (!nonEmptyString(item[field])) errors.push(`${path}.${field} must be a non-empty string`);
|
|
85
|
+
}
|
|
86
|
+
if (nonEmptyString(item.id)) {
|
|
87
|
+
if (ids.has(item.id)) errors.push(`${path}.id duplicates "${item.id}"`);
|
|
88
|
+
ids.add(item.id);
|
|
89
|
+
}
|
|
90
|
+
for (const field of ['instruction', 'expectedResult', 'warning', 'failureGuidance']) {
|
|
91
|
+
validateOptionalString(item[field], `${path}.${field}`, errors);
|
|
92
|
+
}
|
|
93
|
+
if (item.optional !== undefined && typeof item.optional !== 'boolean') {
|
|
94
|
+
errors.push(`${path}.optional must be a boolean`);
|
|
95
|
+
}
|
|
96
|
+
validateCodeBlocks(item.codeBlocks, `${path}.codeBlocks`, errors);
|
|
97
|
+
validateLinks(item.links, `${path}.links`, errors);
|
|
98
|
+
|
|
99
|
+
if (subItem || item.subItems === undefined) return;
|
|
100
|
+
if (!Array.isArray(item.subItems)) {
|
|
101
|
+
errors.push(`${path}.subItems must be an array`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
item.subItems.forEach((child, index) => validateItem(child, `${path}.subItems[${index}]`, ids, errors, true));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function validateChecklist(checklist) {
|
|
108
|
+
const errors = [];
|
|
109
|
+
const ids = new Set();
|
|
110
|
+
if (!isObject(checklist)) return ['$ must be an object'];
|
|
111
|
+
|
|
112
|
+
rejectUnknownFields(checklist, TOP_LEVEL_FIELDS, '$', errors);
|
|
113
|
+
for (const field of ['title', 'summary']) {
|
|
114
|
+
if (!nonEmptyString(checklist[field])) errors.push(`$.${field} must be a non-empty string`);
|
|
115
|
+
}
|
|
116
|
+
for (const field of ['intro', 'callout', 'conventions']) {
|
|
117
|
+
validateOptionalString(checklist[field], `$.${field}`, errors);
|
|
118
|
+
}
|
|
119
|
+
if (!Array.isArray(checklist.sections) || checklist.sections.length === 0) {
|
|
120
|
+
errors.push('$.sections must be a non-empty array');
|
|
121
|
+
return errors;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
checklist.sections.forEach((section, sectionIndex) => {
|
|
125
|
+
const sectionPath = `$.sections[${sectionIndex}]`;
|
|
126
|
+
if (!isObject(section)) {
|
|
127
|
+
errors.push(`${sectionPath} must be an object`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
rejectUnknownFields(section, SECTION_FIELDS, sectionPath, errors);
|
|
131
|
+
for (const field of ['number', 'title']) {
|
|
132
|
+
if (!nonEmptyString(section[field])) errors.push(`${sectionPath}.${field} must be a non-empty string`);
|
|
133
|
+
}
|
|
134
|
+
if (!['checklist', 'info'].includes(section.kind)) {
|
|
135
|
+
errors.push(`${sectionPath}.kind must be "checklist" or "info"`);
|
|
136
|
+
}
|
|
137
|
+
validateOptionalString(section.intro, `${sectionPath}.intro`, errors);
|
|
138
|
+
if (!Array.isArray(section.items) || section.items.length === 0) {
|
|
139
|
+
errors.push(`${sectionPath}.items must be a non-empty array`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
section.items.forEach((item, itemIndex) => validateItem(item, `${sectionPath}.items[${itemIndex}]`, ids, errors));
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return errors;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function loadAndValidateChecklist(path) {
|
|
149
|
+
let checklist;
|
|
150
|
+
try {
|
|
151
|
+
checklist = JSON.parse(await readFile(path, 'utf8'));
|
|
152
|
+
} catch (error) {
|
|
153
|
+
return { errors: [`Unable to read valid JSON: ${error.message}`] };
|
|
154
|
+
}
|
|
155
|
+
const errors = validateChecklist(checklist);
|
|
156
|
+
return errors.length === 0 ? { checklist, errors } : { errors };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function main() {
|
|
160
|
+
const path = process.argv[2];
|
|
161
|
+
if (!path || process.argv.length !== 3) {
|
|
162
|
+
console.error('Usage: node validate.mjs <checklist.json>');
|
|
163
|
+
process.exitCode = 1;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const { errors } = await loadAndValidateChecklist(path);
|
|
167
|
+
if (errors.length > 0) {
|
|
168
|
+
for (const error of errors) console.error(`ERROR ${error}`);
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
console.log('OK');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) await main();
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forge-a-skill
|
|
3
|
+
description: Forge one codebase rule into a guardrail skill. Use only when the developer invokes /forge-a-skill by name.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Forge a Skill
|
|
8
|
+
|
|
9
|
+
Forge exactly one agent-owned guardrail skill. Do not continue unless the
|
|
10
|
+
developer invoked `/forge-a-skill` by name.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
### Step 1: Guard and input
|
|
15
|
+
|
|
16
|
+
Confirm that the developer invoked `/forge-a-skill` by name. Take the rule from
|
|
17
|
+
the invocation arguments. If there is no rule argument, ask one question for
|
|
18
|
+
the rule. Stop if the skill was selected by the model instead of the developer.
|
|
19
|
+
|
|
20
|
+
### Step 2: Apply the one-job test
|
|
21
|
+
|
|
22
|
+
Ask yourself exactly one question: "Does this rule answer exactly one question
|
|
23
|
+
an agent asks itself?" Split a rule joined by "and", or a rule whose correct
|
|
24
|
+
tool depends on the request, into separate jobs. Forge only the first job and
|
|
25
|
+
save each remaining job for the report as follow-up `/forge-a-skill` runs.
|
|
26
|
+
|
|
27
|
+
### Step 3: Run the six-field interview
|
|
28
|
+
|
|
29
|
+
Read the repository guidance and its routed knowledge maps first. Then inspect
|
|
30
|
+
the relevant source, tests, configuration, and commands. Derive a candidate
|
|
31
|
+
name from the rule using the naming contract in Step 4, then derive:
|
|
32
|
+
|
|
33
|
+
- proposed anchors;
|
|
34
|
+
- one to three exemplars cited as `path#symbol`;
|
|
35
|
+
- a positive decision procedure;
|
|
36
|
+
- a repository violation check command, or one concrete manual check;
|
|
37
|
+
- current violations, including every finding's path and evidence; and
|
|
38
|
+
- whether a guardrail of that name already exists.
|
|
39
|
+
|
|
40
|
+
Do not treat a map statement as source evidence when a more direct file or
|
|
41
|
+
symbol is available. Complete the scan before the interview only when it has
|
|
42
|
+
one to three direct `path#symbol` exemplars. If none exists, stop and explain
|
|
43
|
+
that the rule cannot be forged from current repository evidence. If an
|
|
44
|
+
existing skill is a guardrail, this run is a **Re-forge**: use its current
|
|
45
|
+
content as the interview defaults and update it in place after approval. If the
|
|
46
|
+
existing canonical skill is not a guardrail, stop rather than replace it.
|
|
47
|
+
|
|
48
|
+
Present all six fields in one message. This is one fixed round; do not spread
|
|
49
|
+
the fields across multiple rounds. Present the one to three exemplars with the
|
|
50
|
+
six fields. Propose Anchors, Decision procedure, and Violation check command
|
|
51
|
+
from the scan. Ask the developer only for Question answered, Why, and
|
|
52
|
+
Exceptions; let them correct any proposal.
|
|
53
|
+
|
|
54
|
+
1. **Question answered**: the one question this rule answers.
|
|
55
|
+
2. **Why**: the system scale and use case that make the rule suitable.
|
|
56
|
+
3. **Anchors**: directories, libraries, layers, or verbs where the rule applies.
|
|
57
|
+
4. **Decision procedure**: positive steps an agent follows.
|
|
58
|
+
5. **Exceptions**: known cases where the rule does not apply.
|
|
59
|
+
6. **Violation check command**: a repository command that detects violations,
|
|
60
|
+
or a concrete manual check when no command exists.
|
|
61
|
+
|
|
62
|
+
### Step 4: Derive the skill contract
|
|
63
|
+
|
|
64
|
+
- Choose a lowercase, hyphenated, plain trigger-word-led name. It must match the
|
|
65
|
+
directory `.agents/skills/<name>/`.
|
|
66
|
+
- Write a description of at most 200 characters in exactly this form:
|
|
67
|
+
`<rule in one clause>. Use when planning, reviewing, or changing <anchors>.`
|
|
68
|
+
- Use the interview answers to fill
|
|
69
|
+
`.agents/skills/forge-a-skill/templates/guardrail.md`. Keep its eight sections
|
|
70
|
+
in order and keep the body at most 60 lines. Include one to three direct
|
|
71
|
+
`path#symbol` exemplars. Use `None confirmed` only for an exception or
|
|
72
|
+
reference that the available evidence does not show.
|
|
73
|
+
- Put the command and its success criterion in Verification. If there is no
|
|
74
|
+
command, put one concrete `Manual check:` line there.
|
|
75
|
+
|
|
76
|
+
### Step 5: Show the plan and get approval
|
|
77
|
+
|
|
78
|
+
Show the skill name, the description verbatim, anchors, exemplars, and
|
|
79
|
+
verification command or manual check. List every current violation and require
|
|
80
|
+
one choice for each finding before approval:
|
|
81
|
+
|
|
82
|
+
- **Grandfather**: add it to Known exceptions with its path.
|
|
83
|
+
- **Park**: delegate it to `defer-work`, which requires developer approval. This
|
|
84
|
+
skill does not park the work itself.
|
|
85
|
+
|
|
86
|
+
Count unique project skills and personal skills on the developer's machine;
|
|
87
|
+
do not count harness exposures or count an existing Re-forge twice. Sum their
|
|
88
|
+
description character lengths, including the new or updated guardrail. Use the
|
|
89
|
+
8,000-character budget and calculate
|
|
90
|
+
`headroom = 8,000 - description characters`. Show the calculated plan line with
|
|
91
|
+
all placeholders replaced:
|
|
92
|
+
|
|
93
|
+
`Skill listing: <project-count> project skills + <personal-count> personal skills; <total> description characters; 8,000-character budget; <headroom> headroom.`
|
|
94
|
+
|
|
95
|
+
If this rule is a consequential decision, offer to invoke
|
|
96
|
+
`recording-decisions`; that skill owns any ADR. If the developer accepts,
|
|
97
|
+
invoke `recording-decisions`, wait for its ADR path, and add that ADR path to
|
|
98
|
+
the planned References before asking for approval. End with one explicit
|
|
99
|
+
approval question. No guardrail file is written before the developer approves
|
|
100
|
+
the complete plan and every violation has a disposition.
|
|
101
|
+
|
|
102
|
+
### Step 6: Write the guardrail
|
|
103
|
+
|
|
104
|
+
After approval, invoke `defer-work` for each parked finding. Then confirm that
|
|
105
|
+
the name matches its directory, the description has the required form and is
|
|
106
|
+
at most 200 characters, the fixed sections remain in order, Exemplars contains
|
|
107
|
+
one to three `path#symbol` entries, and the body is at most 60 lines. Then
|
|
108
|
+
create a new guardrail, or update it in place for a Re-forge:
|
|
109
|
+
|
|
110
|
+
- Write `.agents/skills/<name>/SKILL.md` from the fixed guardrail template. Add
|
|
111
|
+
each grandfathered finding to Known exceptions with its path.
|
|
112
|
+
- Write `.agents/skills/<name>/evals/evals.json` from
|
|
113
|
+
`.agents/skills/forge-a-skill/templates/probe-set.json`. Replace every
|
|
114
|
+
placeholder with concrete repository language. Keep five should-trigger
|
|
115
|
+
prompts across planning, design, review, editing, and refactoring phrasings,
|
|
116
|
+
and three should-not-trigger prompts outside the anchors. Each
|
|
117
|
+
`expected_output` must state whether the guardrail loads.
|
|
118
|
+
|
|
119
|
+
Do not add the guardrail to `.agents/bearings.json`; forged skills are
|
|
120
|
+
agent-owned project files. Stop rather than replace an existing canonical
|
|
121
|
+
skill that is not a guardrail. Never edit source files or fix violations during
|
|
122
|
+
a forge.
|
|
123
|
+
|
|
124
|
+
### Step 7: Expose the guardrail
|
|
125
|
+
|
|
126
|
+
If `.agents/bearings.json` does not exist, write only the canonical skill
|
|
127
|
+
directory and state that no harness exposure was created. Otherwise, read
|
|
128
|
+
`harnesses` and `exposure` from the Manifest:
|
|
129
|
+
|
|
130
|
+
- For `symlink`, create `.<harness>/skills/<name>` as the relative symlink
|
|
131
|
+
`../../.agents/skills/<name>`.
|
|
132
|
+
- For `copy`, recursively copy the canonical skill directory to
|
|
133
|
+
`.<harness>/skills/<name>`.
|
|
134
|
+
|
|
135
|
+
Expose it to every configured harness. Do not change the Manifest or harness
|
|
136
|
+
settings, and do not replace an unrelated exposure collision.
|
|
137
|
+
|
|
138
|
+
### Step 8: Verify and report
|
|
139
|
+
|
|
140
|
+
When a Manifest exists, run `npx bearings verify` and fix only guardrail or
|
|
141
|
+
exposure errors from this run. Finish only when it reports zero failures.
|
|
142
|
+
Report the canonical path, exposure paths, a `git diff` pointer for review, the
|
|
143
|
+
fix list with every violation and its disposition, and all follow-up forges
|
|
144
|
+
from Step 2. When there is no Manifest, clearly state that verification and
|
|
145
|
+
exposure were not available.
|
|
146
|
+
|
|
147
|
+
Recalculate the Step 5 skill-listing math from the files now on disk and repeat
|
|
148
|
+
its exact `Skill listing:` line in the report.
|
|
149
|
+
|
|
150
|
+
If headroom is 1,600 characters or less, advise the developer that they can
|
|
151
|
+
raise `skillListingBudgetFraction`. Report only. Do not edit harness settings.
|
|
152
|
+
Tell the developer to use `skill-creator` description tuning when it is
|
|
153
|
+
installed. Otherwise, tell them to check all probes in a fresh session and
|
|
154
|
+
confirm that should-trigger prompts load the guardrail and should-not-trigger
|
|
155
|
+
prompts do not.
|
|
156
|
+
|
|
157
|
+
## Wall
|
|
158
|
+
|
|
159
|
+
This skill does not fix violations, record an ADR, park work, edit the Agent
|
|
160
|
+
Seed, edit knowledge maps, edit harness settings, or approve anything on the
|
|
161
|
+
developer's behalf. Delegate an approved ADR to `recording-decisions` and an
|
|
162
|
+
approved deferral to `defer-work`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: <skill-name>
|
|
3
|
+
description: <description>
|
|
4
|
+
metadata:
|
|
5
|
+
kind: guardrail
|
|
6
|
+
anchors:
|
|
7
|
+
- <anchor>
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# <Guardrail title>
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
<System scale and use case that make this rule suitable.>
|
|
15
|
+
|
|
16
|
+
## Applies when
|
|
17
|
+
|
|
18
|
+
<Directories, libraries, layers, or verbs governed by this rule.>
|
|
19
|
+
|
|
20
|
+
## Decision procedure
|
|
21
|
+
|
|
22
|
+
1. <Positive step.>
|
|
23
|
+
|
|
24
|
+
## Exemplars
|
|
25
|
+
|
|
26
|
+
- `<path>#<symbol>` - <Established shape to follow. Include one to three exemplar lines.>
|
|
27
|
+
|
|
28
|
+
## Known exceptions
|
|
29
|
+
|
|
30
|
+
- <Known exception, or None confirmed.>
|
|
31
|
+
- An agent may deviate only after asking the developer, then must add the approved exception here.
|
|
32
|
+
|
|
33
|
+
## Does not govern
|
|
34
|
+
|
|
35
|
+
<Nearest concern to which this rule must not be applied.>
|
|
36
|
+
|
|
37
|
+
## Verification
|
|
38
|
+
|
|
39
|
+
`<violation-check-command>`
|
|
40
|
+
|
|
41
|
+
Completion criterion: <Observable successful result.>
|
|
42
|
+
|
|
43
|
+
## References
|
|
44
|
+
|
|
45
|
+
- <ADR or documentation path, or None confirmed.>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "<skill-name>",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Plan a change that touches <anchor> and explain the approach before editing.",
|
|
7
|
+
"expected_output": "The <skill-name> guardrail loads before the plan is written."
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": 2,
|
|
11
|
+
"prompt": "Design a new <rule-subject> for <anchor>.",
|
|
12
|
+
"expected_output": "The <skill-name> guardrail loads while the design is prepared."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": 3,
|
|
16
|
+
"prompt": "Review the proposed work in <anchor> for compliance with repository patterns.",
|
|
17
|
+
"expected_output": "The <skill-name> guardrail loads for the review."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": 4,
|
|
21
|
+
"prompt": "Update <anchor> to support <rule-related-change>.",
|
|
22
|
+
"expected_output": "The <skill-name> guardrail loads before files are changed."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": 5,
|
|
26
|
+
"prompt": "Refactor the <rule-subject> implementation in <anchor>.",
|
|
27
|
+
"expected_output": "The <skill-name> guardrail loads for the edit."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": 6,
|
|
31
|
+
"prompt": "Plan an unrelated change in <outside-anchor>.",
|
|
32
|
+
"expected_output": "The <skill-name> guardrail does not load."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": 7,
|
|
36
|
+
"prompt": "Edit <outside-anchor> to update <unrelated-concern>.",
|
|
37
|
+
"expected_output": "The <skill-name> guardrail does not load."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": 8,
|
|
41
|
+
"prompt": "Explain <neighboring-concern> without changing repository files.",
|
|
42
|
+
"expected_output": "The <skill-name> guardrail does not load."
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: manual-testplan
|
|
3
|
+
description: Design a small human-run browser or curl test plan from product scope. Use when the developer asks for a manual test plan, acceptance test plan, smoke test, or feature test checklist.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Manual Test Plan
|
|
7
|
+
|
|
8
|
+
Select the smallest useful set of human-executed cases, then delegate its
|
|
9
|
+
checklist artifact to the `checklist` skill.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
1. Establish the test basis. Read the requested issue, specification,
|
|
14
|
+
acceptance criteria, changed behavior, and relevant known defects. Identify
|
|
15
|
+
the primary actor, intended outcome, supported configuration, and explicit
|
|
16
|
+
product risks. Ask a small number of blocking questions when these facts do
|
|
17
|
+
not establish what success means.
|
|
18
|
+
2. Map the basis to reachable public interfaces. Inspect repository maps,
|
|
19
|
+
runtime wiring, routes, UI flows, API contracts, authentication, feature
|
|
20
|
+
flags, test data, and supported setup, reset, and cleanup commands. Record
|
|
21
|
+
only browser and HTTP interfaces that a human can reach in the stated
|
|
22
|
+
environment.
|
|
23
|
+
3. Select cases in execution order:
|
|
24
|
+
- Start with the shortest principal happy path that proves the actor reaches
|
|
25
|
+
the final intended outcome with ordinary valid data.
|
|
26
|
+
- Add uncovered acceptance criteria.
|
|
27
|
+
- Add only the highest-value alternatives and failures, selected from
|
|
28
|
+
likelihood and impact, materially different input partitions, boundaries,
|
|
29
|
+
business rules, state transitions, and relevant defect history.
|
|
30
|
+
- Remove duplicate coverage and cosmetic data variations. Keep each case an
|
|
31
|
+
independent, repeatable workflow with one main reason to fail.
|
|
32
|
+
4. Define each case before delegation. Give it an outcome-focused title, the
|
|
33
|
+
criterion or risk it covers, its selection reason and priority,
|
|
34
|
+
configuration, known initial state, concrete non-secret data, ordered
|
|
35
|
+
actions and observable expectations, cleanup, and useful failure evidence.
|
|
36
|
+
5. Invoke the `checklist` skill with the selected cases and require the output
|
|
37
|
+
at `checklists/tests/<slug>.json`. The `checklist` skill owns the JSON
|
|
38
|
+
contract, identifiers, checklist structure, validation, library build,
|
|
39
|
+
preview opening, and execution state.
|
|
40
|
+
6. Review the resulting test content against the test basis. Every acceptance
|
|
41
|
+
criterion must be covered or named as an explicit gap, and every selected
|
|
42
|
+
risk must have a case whose oracle can detect that failure.
|
|
43
|
+
|
|
44
|
+
## Browser Cases
|
|
45
|
+
|
|
46
|
+
- State the tested build, browser, relevant viewport or device class, user
|
|
47
|
+
role, starting URL, and starting session state.
|
|
48
|
+
- Write actions in user and domain language while naming controls clearly
|
|
49
|
+
enough to find. Put an observable expectation after each important
|
|
50
|
+
validation point and verify the final visible or persisted outcome.
|
|
51
|
+
- Use supported fixtures, APIs, or seed commands for prerequisite data when
|
|
52
|
+
that keeps the browser workflow focused. Capture the current screen and exact
|
|
53
|
+
observed text first on failure.
|
|
54
|
+
|
|
55
|
+
## Curl Cases
|
|
56
|
+
|
|
57
|
+
- State the shell, base URL, authentication prerequisite, environment
|
|
58
|
+
variables, and data setup. Use secret placeholders such as `$TOKEN` through
|
|
59
|
+
the repository's established secret mechanism.
|
|
60
|
+
- Give a directly runnable `curl` command with the evidenced method, quoted
|
|
61
|
+
URL, headers, and body. State the exact expected HTTP status, relevant
|
|
62
|
+
headers, body fields, and externally observable side effects.
|
|
63
|
+
- Distinguish the HTTP result from curl's transfer exit status. State required
|
|
64
|
+
redirect and cookie behavior, preserve TLS verification unless the test
|
|
65
|
+
environment explicitly requires otherwise, and treat unexpected transport
|
|
66
|
+
failures as blocked environment failures.
|
|
67
|
+
|
|
68
|
+
## Evidence Guardrail
|
|
69
|
+
|
|
70
|
+
Requirements state intent; running code, configuration, contracts, tests, and
|
|
71
|
+
developer confirmation establish reachable behavior. Ask for missing critical
|
|
72
|
+
facts. Never invent commands, routes, URLs, credentials, selectors, status
|
|
73
|
+
codes, response fields, messages, seed data, or cleanup behavior.
|
|
74
|
+
|
|
75
|
+
## Completion
|
|
76
|
+
|
|
77
|
+
Finish only when the test basis and reachable interfaces are explicit, the
|
|
78
|
+
principal happy path proves the intended outcome, each additional case has a
|
|
79
|
+
traceable risk or coverage reason, every oracle is concrete and observable,
|
|
80
|
+
and the `checklist` skill completes one checklist under `checklists/tests/`.
|