orchestrix-skills 0.6.0 → 0.8.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/.claude-plugin/plugin.json +1 -1
- package/README.md +22 -0
- package/adapters/claude/runtime.json +13 -0
- package/adapters/codex/AGENTS.md +11 -0
- package/adapters/codex/runtime.json +13 -0
- package/bin/install.js +191 -14
- package/package.json +5 -1
- package/project-scaffold/knowledge/taste/design-system.md +17 -4
- package/skills/README.md +17 -1
- package/skills/brainstorm/SKILL.md +2 -0
- package/skills/commit/SKILL.md +2 -0
- package/skills/deploy/SKILL.md +2 -0
- package/skills/design-architecture/SKILL.md +3 -1
- package/skills/design-review/SKILL.md +165 -19
- package/skills/design-system/SKILL.md +59 -12
- package/skills/design-ui/SKILL.md +97 -14
- package/skills/draft-story/SKILL.md +3 -1
- package/skills/implement/SKILL.md +3 -1
- package/skills/investigate/SKILL.md +3 -1
- package/skills/map-codebase/SKILL.md +4 -2
- package/skills/orchestrate/SKILL.md +74 -17
- package/skills/research/SKILL.md +3 -1
- package/skills/review-code/SKILL.md +2 -0
- package/skills/run-tests/SKILL.md +3 -1
- package/skills/smoke-test/SKILL.md +3 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orchestrix-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Capability-first AI development skill graph (Anthropic-native): plan → build with a warm-context orchestrator, contract-wired skills, and independent verification.",
|
|
5
5
|
"author": "Orchestrix",
|
|
6
6
|
"homepage": "https://orchestrix-mcp.youlidao.ai",
|
package/README.md
CHANGED
|
@@ -33,7 +33,9 @@ the build loop runs lights-out, gated only by objective `verify`.
|
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
npx orchestrix-skills install # default: Claude Code (.claude/skills/)
|
|
36
|
+
npx orchestrix-skills install --ide codex # Codex (.codex/skills/ + AGENTS.md)
|
|
36
37
|
npx orchestrix-skills install --ide cursor
|
|
38
|
+
npx orchestrix-skills doctor --ide codex # validate an installation
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
This copies the skills into your runtime's skills dir and scaffolds `knowledge/`
|
|
@@ -44,6 +46,26 @@ your own API key. No server, no license.
|
|
|
44
46
|
For Claude Code you can also install via the plugin marketplace:
|
|
45
47
|
`/plugin install orchestrix-skills`.
|
|
46
48
|
|
|
49
|
+
## Runtime adapters
|
|
50
|
+
|
|
51
|
+
`skills/` is the runtime-neutral source of truth. `adapters/` describes how a
|
|
52
|
+
runtime maps generic capabilities to its tools. During a Codex install the CLI
|
|
53
|
+
removes Claude-only `allowed-tools`, preserves the Orchestrix contract, and adds
|
|
54
|
+
Codex runtime guidance. If the target has an unmanaged `AGENTS.md`, its content
|
|
55
|
+
is left untouched and the guidance is placed at `.codex/orchestrix/AGENTS.md`
|
|
56
|
+
for manual merging. Installer-created guidance uses a marked Orchestrix block,
|
|
57
|
+
so later installs refresh that block while preserving surrounding user
|
|
58
|
+
instructions.
|
|
59
|
+
|
|
60
|
+
`doctor` validates every installed Skill's required frontmatter, Codex
|
|
61
|
+
transformation, configuration shape, knowledge directory, and active root
|
|
62
|
+
guidance. A reference file that has not been merged into an existing root
|
|
63
|
+
`AGENTS.md` is reported as unhealthy rather than silently treated as active.
|
|
64
|
+
|
|
65
|
+
Codex uses isolated agents when the active session exposes them and otherwise
|
|
66
|
+
runs leaf skills sequentially. Cursor and Windsurf remain reference-rule
|
|
67
|
+
installs until those runtimes provide native compatible skill execution.
|
|
68
|
+
|
|
47
69
|
## How it works
|
|
48
70
|
|
|
49
71
|
- **Every skill is a standard [Anthropic Agent Skill](https://agentskills.io/specification)**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "claude",
|
|
3
|
+
"skillsDir": ".claude/skills",
|
|
4
|
+
"projectInstructions": "CLAUDE.md",
|
|
5
|
+
"nativeSkills": true,
|
|
6
|
+
"capabilities": {
|
|
7
|
+
"filesystem.read": "Read, Grep, Glob",
|
|
8
|
+
"filesystem.write": "Write, Edit",
|
|
9
|
+
"shell.execute": "Bash",
|
|
10
|
+
"web.read": "WebSearch, WebFetch",
|
|
11
|
+
"agent.spawn": "Task"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!-- orchestrix:start -->
|
|
2
|
+
# Orchestrix runtime guidance
|
|
3
|
+
|
|
4
|
+
- Use the skills installed under `.codex/skills/`; start end-to-end work with `orchestrate`.
|
|
5
|
+
- Treat each skill's `metadata.contract` as Orchestrix workflow data. Codex skill selection still depends on `name` and `description`.
|
|
6
|
+
- Resolve logical knowledge and work namespaces through `core-config.yaml`.
|
|
7
|
+
- Map capability names in `metadata.requires.capabilities` to the tools available in the current Codex session.
|
|
8
|
+
- When isolated agents are available, dispatch independent leaf skills concurrently and await them. Otherwise execute leaf skills sequentially in the current context, reading only their declared inputs before each step.
|
|
9
|
+
- Independently run every objective verification command. Never accept an agent's success report as proof.
|
|
10
|
+
- Keep runtime evidence at the fixed `.orchestrate/` path described by the `orchestrate` skill.
|
|
11
|
+
<!-- orchestrix:end -->
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "codex",
|
|
3
|
+
"skillsDir": ".codex/skills",
|
|
4
|
+
"projectInstructions": "AGENTS.md",
|
|
5
|
+
"nativeSkills": true,
|
|
6
|
+
"capabilities": {
|
|
7
|
+
"filesystem.read": "runtime file tools or shell",
|
|
8
|
+
"filesystem.write": "runtime patch/edit tools",
|
|
9
|
+
"shell.execute": "runtime shell tool",
|
|
10
|
+
"web.read": "runtime web tools when enabled",
|
|
11
|
+
"agent.spawn": "optional collaboration tools; otherwise sequential fallback"
|
|
12
|
+
}
|
|
13
|
+
}
|
package/bin/install.js
CHANGED
|
@@ -2,20 +2,31 @@
|
|
|
2
2
|
// orchestrix-skills installer — zero dependencies.
|
|
3
3
|
// Free path: copy skills into the runtime's skills dir + scaffold knowledge/.
|
|
4
4
|
// No MCP, no license. Premium (hosted orchestrator / KB / 建造中心) is a separate opt-in.
|
|
5
|
-
import { cpSync, existsSync, mkdirSync, readdirSync } from "node:fs";
|
|
5
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
const PKG = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
+
const MANAGED_START = "<!-- orchestrix:start -->";
|
|
11
|
+
const MANAGED_END = "<!-- orchestrix:end -->";
|
|
12
|
+
// Written into the skills dir after every successful install. Two consumers:
|
|
13
|
+
// this installer (prunes skills it placed that the package no longer ships) and
|
|
14
|
+
// hosts that auto-upgrade projects (compare `version` against the npm dist-tag
|
|
15
|
+
// to decide whether to reinstall — no second version constant to maintain).
|
|
16
|
+
const STAMP = ".orchestrix-skills.json";
|
|
10
17
|
|
|
11
18
|
// Where each runtime auto-loads skills from (relative to the target project).
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
function adapter(name) {
|
|
20
|
+
return JSON.parse(readFileSync(join(PKG, "adapters", name, "runtime.json"), "utf8"));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const RUNTIMES = {
|
|
24
|
+
claude: adapter("claude"),
|
|
25
|
+
codex: adapter("codex"),
|
|
15
26
|
// Cursor / Windsurf don't auto-load Anthropic skills; they read rule files.
|
|
16
27
|
// For those, skills are copied as reference rules (best-effort) until native support lands.
|
|
17
|
-
cursor: ".cursor/rules/orchestrix",
|
|
18
|
-
windsurf: ".windsurf/rules/orchestrix",
|
|
28
|
+
cursor: { skillsDir: ".cursor/rules/orchestrix", nativeSkills: false },
|
|
29
|
+
windsurf: { skillsDir: ".windsurf/rules/orchestrix", nativeSkills: false },
|
|
19
30
|
};
|
|
20
31
|
|
|
21
32
|
function arg(name, fallback) {
|
|
@@ -28,6 +39,7 @@ function help() {
|
|
|
28
39
|
|
|
29
40
|
Usage:
|
|
30
41
|
npx orchestrix-skills install [--ide claude|codex|cursor|windsurf] [--dir <project>]
|
|
42
|
+
npx orchestrix-skills doctor [--ide claude|codex|cursor|windsurf] [--dir <project>]
|
|
31
43
|
|
|
32
44
|
What it does (free, no license):
|
|
33
45
|
1. Copies the skills into your runtime's skills dir (default: .claude/skills/)
|
|
@@ -37,21 +49,140 @@ Premium (hosted orchestrator, KB hosting, teams, 建造中心):
|
|
|
37
49
|
see https://orchestrix-mcp.youlidao.ai`);
|
|
38
50
|
}
|
|
39
51
|
|
|
52
|
+
function transformSkill(source, runtime) {
|
|
53
|
+
if (runtime !== "codex") return source;
|
|
54
|
+
return source
|
|
55
|
+
.replace(/^allowed-tools:.*\n/m, "")
|
|
56
|
+
.replace(
|
|
57
|
+
/^(---\n\n# )/m,
|
|
58
|
+
"---\n\n<!-- Codex adapter: tool access is governed by the active session. Map metadata.requires capabilities to available tools. -->\n\n# ",
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function packageVersion() {
|
|
63
|
+
return JSON.parse(readFileSync(join(PKG, "package.json"), "utf8")).version;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function readStamp(target) {
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(readFileSync(join(target, STAMP), "utf8"));
|
|
69
|
+
} catch {
|
|
70
|
+
return null; // absent, or written by a version that predates stamping
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function installSkills(dir, runtimeName, runtime) {
|
|
75
|
+
const target = join(dir, runtime.skillsDir);
|
|
76
|
+
mkdirSync(target, { recursive: true });
|
|
77
|
+
const previous = readStamp(target);
|
|
78
|
+
const entries = readdirSync(join(PKG, "skills"), { withFileTypes: true });
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
const source = join(PKG, "skills", entry.name);
|
|
81
|
+
const destination = join(target, entry.name);
|
|
82
|
+
if (!entry.isDirectory()) {
|
|
83
|
+
cpSync(source, destination);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
mkdirSync(destination, { recursive: true });
|
|
87
|
+
for (const file of readdirSync(source, { withFileTypes: true })) {
|
|
88
|
+
if (file.isFile() && file.name === "SKILL.md") {
|
|
89
|
+
writeFileSync(join(destination, file.name), transformSkill(readFileSync(join(source, file.name), "utf8"), runtimeName));
|
|
90
|
+
} else {
|
|
91
|
+
cpSync(join(source, file.name), join(destination, file.name), { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const names = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
97
|
+
// Retire skills a PREVIOUS install of this package placed that it no longer
|
|
98
|
+
// ships. Only names recorded in our own stamp are candidates, so a skill the
|
|
99
|
+
// project or its host installed alongside ours is never touched.
|
|
100
|
+
let pruned = 0;
|
|
101
|
+
for (const name of previous?.skills ?? []) {
|
|
102
|
+
if (names.includes(name)) continue;
|
|
103
|
+
const stale = join(target, name);
|
|
104
|
+
if (!isDirectory(stale)) continue;
|
|
105
|
+
rmSync(stale, { recursive: true, force: true });
|
|
106
|
+
pruned += 1;
|
|
107
|
+
}
|
|
108
|
+
// Stamp LAST: a crash mid-copy leaves the older stamp in place, so the next
|
|
109
|
+
// run still sees a mismatch and reinstalls rather than declaring itself current.
|
|
110
|
+
writeFileSync(
|
|
111
|
+
join(target, STAMP),
|
|
112
|
+
`${JSON.stringify({ version: packageVersion(), ide: runtimeName, skills: names }, null, 2)}\n`,
|
|
113
|
+
);
|
|
114
|
+
return { count: names.length, pruned };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function installRuntimeGuidance(dir, runtimeName) {
|
|
118
|
+
if (runtimeName !== "codex") return;
|
|
119
|
+
const source = join(PKG, "adapters", "codex", "AGENTS.md");
|
|
120
|
+
const rootInstructions = join(dir, "AGENTS.md");
|
|
121
|
+
const referenceTarget = join(dir, ".codex", "orchestrix", "AGENTS.md");
|
|
122
|
+
mkdirSync(dirname(referenceTarget), { recursive: true });
|
|
123
|
+
cpSync(source, referenceTarget);
|
|
124
|
+
const guidance = readFileSync(source, "utf8");
|
|
125
|
+
if (!existsSync(rootInstructions)) {
|
|
126
|
+
writeFileSync(rootInstructions, guidance);
|
|
127
|
+
console.log("✓ AGENTS.md created with Codex runtime guidance");
|
|
128
|
+
} else {
|
|
129
|
+
const current = readFileSync(rootInstructions, "utf8");
|
|
130
|
+
const start = current.indexOf(MANAGED_START);
|
|
131
|
+
const end = current.indexOf(MANAGED_END);
|
|
132
|
+
if (start !== -1 && end > start) {
|
|
133
|
+
const updated = `${current.slice(0, start)}${guidance.trimEnd()}${current.slice(end + MANAGED_END.length)}`;
|
|
134
|
+
writeFileSync(rootInstructions, updated);
|
|
135
|
+
console.log("✓ Orchestrix block refreshed in AGENTS.md");
|
|
136
|
+
} else {
|
|
137
|
+
console.log("• AGENTS.md exists — left untouched; merge .codex/orchestrix/AGENTS.md to activate guidance");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function isFile(path) {
|
|
143
|
+
try {
|
|
144
|
+
return statSync(path).isFile();
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function isDirectory(path) {
|
|
151
|
+
try {
|
|
152
|
+
return statSync(path).isDirectory();
|
|
153
|
+
} catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function nonemptyFile(path) {
|
|
159
|
+
return isFile(path) && readFileSync(path, "utf8").trim().length > 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function validSkill(path, runtimeName, expectedName) {
|
|
163
|
+
if (!nonemptyFile(path)) return false;
|
|
164
|
+
const content = readFileSync(path, "utf8");
|
|
165
|
+
const frontmatter = content.match(/^---\n([\s\S]*?)\n---/);
|
|
166
|
+
if (!frontmatter) return false;
|
|
167
|
+
if (!new RegExp(`^name:\\s*${expectedName}\\s*$`, "m").test(frontmatter[1])) return false;
|
|
168
|
+
if (!/^description:\s*\S.+$/m.test(frontmatter[1])) return false;
|
|
169
|
+
return runtimeName !== "codex" || !/^allowed-tools:/m.test(frontmatter[1]);
|
|
170
|
+
}
|
|
171
|
+
|
|
40
172
|
function install() {
|
|
41
173
|
const ide = arg("ide", "claude");
|
|
42
174
|
const dir = arg("dir", process.cwd());
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
45
|
-
console.error(`Unknown --ide "${ide}". Options: ${Object.keys(
|
|
175
|
+
const runtime = RUNTIMES[ide];
|
|
176
|
+
if (!runtime) {
|
|
177
|
+
console.error(`Unknown --ide "${ide}". Options: ${Object.keys(RUNTIMES).join(", ")}`);
|
|
46
178
|
process.exit(1);
|
|
47
179
|
}
|
|
48
180
|
|
|
49
181
|
// 1. Skills (capabilities) — always refreshed.
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
console.log(`✓ ${count} skills → ${rel}/`);
|
|
182
|
+
const { count, pruned } = installSkills(dir, ide, runtime);
|
|
183
|
+
console.log(`✓ ${count} skills → ${runtime.skillsDir}/ (v${packageVersion()})`);
|
|
184
|
+
if (pruned > 0) console.log(`✓ ${pruned} retired skill(s) removed`);
|
|
185
|
+
installRuntimeGuidance(dir, ide);
|
|
55
186
|
|
|
56
187
|
// 2. Knowledge (the brain) — scaffold only if absent; never clobber the user's brain.
|
|
57
188
|
const knowledgeTarget = join(dir, "knowledge");
|
|
@@ -77,6 +208,52 @@ function install() {
|
|
|
77
208
|
console.log(`\nDone. Start with the "orchestrate" skill. Premium hosting: https://orchestrix-mcp.youlidao.ai`);
|
|
78
209
|
}
|
|
79
210
|
|
|
211
|
+
function doctor() {
|
|
212
|
+
const ide = arg("ide", "claude");
|
|
213
|
+
const dir = arg("dir", process.cwd());
|
|
214
|
+
const runtime = RUNTIMES[ide];
|
|
215
|
+
if (!runtime) {
|
|
216
|
+
console.error(`Unknown --ide "${ide}". Options: ${Object.keys(RUNTIMES).join(", ")}`);
|
|
217
|
+
process.exitCode = 1;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const skillsTarget = join(dir, runtime.skillsDir);
|
|
221
|
+
const expectedSkills = readdirSync(join(PKG, "skills"), { withFileTypes: true })
|
|
222
|
+
.filter((entry) => entry.isDirectory())
|
|
223
|
+
.map((entry) => entry.name);
|
|
224
|
+
const configPath = join(dir, "core-config.yaml");
|
|
225
|
+
const configContent = nonemptyFile(configPath) ? readFileSync(configPath, "utf8") : "";
|
|
226
|
+
const checks = [
|
|
227
|
+
["skills directory", isDirectory(skillsTarget), skillsTarget],
|
|
228
|
+
[
|
|
229
|
+
`all ${expectedSkills.length} skills valid`,
|
|
230
|
+
expectedSkills.every((name) => validSkill(join(skillsTarget, name, "SKILL.md"), ide, name)),
|
|
231
|
+
skillsTarget,
|
|
232
|
+
],
|
|
233
|
+
["core config valid", /(^|\n)knowledge:\s*(#.*)?\n/.test(configContent) && /(^|\n)work:\s*(#.*)?\n/.test(configContent), configPath],
|
|
234
|
+
["knowledge brain", isDirectory(join(dir, "knowledge")), join(dir, "knowledge")],
|
|
235
|
+
];
|
|
236
|
+
if (ide === "codex") {
|
|
237
|
+
const reference = join(dir, ".codex", "orchestrix", "AGENTS.md");
|
|
238
|
+
const rootInstructions = join(dir, "AGENTS.md");
|
|
239
|
+
const referenceContent = nonemptyFile(reference) ? readFileSync(reference, "utf8") : "";
|
|
240
|
+
const rootContent = nonemptyFile(rootInstructions) ? readFileSync(rootInstructions, "utf8") : "";
|
|
241
|
+
checks.push(["Codex guidance reference", referenceContent.includes(MANAGED_START) && referenceContent.includes(MANAGED_END), reference]);
|
|
242
|
+
checks.push(["root AGENTS guidance active", rootContent.includes(MANAGED_START) && rootContent.includes(MANAGED_END), rootInstructions]);
|
|
243
|
+
}
|
|
244
|
+
let healthy = true;
|
|
245
|
+
for (const [label, ok, path] of checks) {
|
|
246
|
+
healthy &&= ok;
|
|
247
|
+
console.log(`${ok ? "✓" : "✗"} ${label}: ${path}`);
|
|
248
|
+
}
|
|
249
|
+
if (healthy) console.log(`\nHealthy: ${ide} installation is complete.`);
|
|
250
|
+
else {
|
|
251
|
+
console.error(`\nUnhealthy: run "orchestrix-skills install --ide ${ide} --dir ${dir}".`);
|
|
252
|
+
process.exitCode = 1;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
80
256
|
const cmd = process.argv[2];
|
|
81
257
|
if (cmd === "install") install();
|
|
258
|
+
else if (cmd === "doctor") doctor();
|
|
82
259
|
else help();
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orchestrix-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Capability-first AI development skill graph — Anthropic-native skills that run in any agent runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"orchestrix-skills": "bin/install.js"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"skills",
|
|
11
14
|
"project-scaffold",
|
|
15
|
+
"adapters",
|
|
12
16
|
"bin",
|
|
13
17
|
".claude-plugin"
|
|
14
18
|
],
|
|
@@ -13,13 +13,23 @@ typography:
|
|
|
13
13
|
typeface: "" # named (not Inter/Roboto unless deliberate + justified)
|
|
14
14
|
scale: [] # real sizes/weights, e.g. [12/400, 14/400, 16/500, 24/600, 40/700]
|
|
15
15
|
line_height: ""
|
|
16
|
-
|
|
16
|
+
measure: "" # target line length for running text, e.g. 65ch
|
|
17
|
+
color: # roles, not framework swatches. THIS BLOCK IS THE LIGHT PALETTE.
|
|
17
18
|
bg: ""
|
|
18
19
|
surface: ""
|
|
19
20
|
text: ""
|
|
20
|
-
accent: ""
|
|
21
|
-
states: { success: "", warning: "", error: "" }
|
|
22
|
-
contrast_floor: "" # e.g. WCAG AA 4.5:1 body text
|
|
21
|
+
accent: "" # the one brand hue. Never used to signal state.
|
|
22
|
+
states: { success: "", warning: "", error: "" } # semantic; must read as distinct from accent
|
|
23
|
+
contrast_floor: "" # e.g. WCAG AA — 4.5:1 body text, 3:1 UI + graphics
|
|
24
|
+
theme:
|
|
25
|
+
modes: "" # light | dark | both. "both" = both are designed and reviewed, not inverted.
|
|
26
|
+
selection: "" # how a mode is chosen: OS preference | explicit user toggle | both
|
|
27
|
+
dark: # required when modes includes dark. Same roles, re-picked — never a naive inversion.
|
|
28
|
+
bg: ""
|
|
29
|
+
surface: ""
|
|
30
|
+
text: ""
|
|
31
|
+
accent: "" # must still meet contrast_floor on the dark ground
|
|
32
|
+
states: { success: "", warning: "", error: "" }
|
|
23
33
|
space:
|
|
24
34
|
scale: [] # e.g. [4, 8, 12, 16, 24, 32, 48, 64]
|
|
25
35
|
density: "" # tight | airy, tied to the product
|
|
@@ -27,6 +37,9 @@ motion:
|
|
|
27
37
|
timing: "" # e.g. 150ms enter / 100ms exit
|
|
28
38
|
easing: ""
|
|
29
39
|
use_where: "" # and where motion is deliberately absent
|
|
40
|
+
reduced_motion: "" # what prefers-reduced-motion removes, and what must still work without it
|
|
41
|
+
focus:
|
|
42
|
+
visible_style: "" # the keyboard focus indicator every interactive element carries
|
|
30
43
|
|
|
31
44
|
provenance: { source: design-system, added: "", approved_by: "" }
|
|
32
45
|
```
|
package/skills/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Skills
|
|
1
|
+
# Skills
|
|
2
2
|
|
|
3
3
|
Capability-oriented skills, not role-oriented agents. Each skill is a single
|
|
4
4
|
capability with a clear contract. The `orchestrate` skill wires them together by
|
|
@@ -14,6 +14,12 @@ SDK runtime reads `name` + `description` + `allowed-tools` and ignores
|
|
|
14
14
|
`metadata.contract`, so each skill runs anywhere. Our orchestrator additionally
|
|
15
15
|
reads `metadata.contract` to wire, gate, and verify.
|
|
16
16
|
|
|
17
|
+
Runtime-neutral capability requirements live under
|
|
18
|
+
`metadata.requires.capabilities` using names such as `filesystem.read`,
|
|
19
|
+
`filesystem.write`, `shell.execute`, `web.read`, and optional `agent.spawn?`.
|
|
20
|
+
Adapters map those names to runtime tools. Runtime-specific tool names are not
|
|
21
|
+
part of the orchestration contract.
|
|
22
|
+
|
|
17
23
|
### The contract (6 fields)
|
|
18
24
|
|
|
19
25
|
| Field | Meaning |
|
|
@@ -25,6 +31,16 @@ reads `metadata.contract` to wire, gate, and verify.
|
|
|
25
31
|
| `verify` | Objective, automated success check. Never skipped. |
|
|
26
32
|
| `accept` | Subjective human sign-off: `{ when, timing }`. |
|
|
27
33
|
|
|
34
|
+
**Optional entries** in `inputs` / `reads` / `updates` carry a trailing `?` and
|
|
35
|
+
**must be quoted** — `"qa_feedback?"`, not `qa_feedback?`. A bare `?` inside a
|
|
36
|
+
YAML flow sequence is not valid YAML; permissive loaders accept it, strict ones
|
|
37
|
+
reject the whole file.
|
|
38
|
+
|
|
39
|
+
**Names are semantic, not literal.** `inputs` name the role a skill needs
|
|
40
|
+
(`story`, `diff`, `spec`); `outputs` name the artifact produced
|
|
41
|
+
(`stories/<slug>.md`, `code_diff`). The orchestrator matches them by meaning —
|
|
42
|
+
do not expect string equality when reading the graph.
|
|
43
|
+
|
|
28
44
|
`accept.timing`:
|
|
29
45
|
|
|
30
46
|
- `deferred` (default) — batch the human check at the end (lights-out middle).
|
|
@@ -4,6 +4,8 @@ description: Use before any build, when an idea or intent must become an agreed,
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [intent, project_context]
|
|
9
11
|
reads: [taste/*, architecture/*, registry/*]
|
package/skills/commit/SKILL.md
CHANGED
|
@@ -4,6 +4,8 @@ description: Use when verified work is ready to be recorded in version control.
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [verified_changes, message_intent]
|
|
9
11
|
reads: []
|
package/skills/deploy/SKILL.md
CHANGED
|
@@ -4,6 +4,8 @@ description: Use when an ACCEPTED deliverable must be shipped to a live environm
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [accepted_deliverable, target]
|
|
9
11
|
reads: [registry/deploy]
|
|
@@ -4,11 +4,13 @@ description: Use when a feature needs a new or changed architectural decision
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [requirement, system_context]
|
|
9
11
|
reads: [architecture/*, registry/api, registry/db]
|
|
10
12
|
outputs: [specs/<slug>-arch.md]
|
|
11
|
-
updates: [architecture/decisions, registry/api
|
|
13
|
+
updates: [architecture/decisions, "registry/api?", "registry/db?"]
|
|
12
14
|
authority: "Write to the specs namespace (default docs/specs/) and update the architecture KB / registry. No source code, no production."
|
|
13
15
|
verify: "States the alternatives and the rationale; consistent with existing decisions (or explicitly supersedes one); no placeholder."
|
|
14
16
|
accept:
|
|
@@ -4,12 +4,14 @@ description: Use after a UI feature is built and running, before merging, to rev
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [built_ui, ui_spec]
|
|
10
|
+
inputs: [built_ui, ui_spec, "screenshots?"]
|
|
9
11
|
reads: [taste/design-system, taste/brand]
|
|
10
12
|
outputs: [design_review_report]
|
|
11
|
-
authority: "Read-only on code
|
|
12
|
-
verify: "
|
|
13
|
+
authority: "Read-only on code. Start and stop the app locally to render it, and drive it via browser automation or HTTP. No edits, no commits, no deploy, no external spend."
|
|
14
|
+
verify: "Every verdict rests on a rendered artifact, not on source; each objective check reports pass, fail, or untested-with-reason — never a pass without its evidence; contains all three verdicts (spec compliance, rendering + accessibility, visual quality); any process this skill started was cleaned up."
|
|
13
15
|
accept:
|
|
14
16
|
when: "never — findings route back to implement; the human reviews at the end batch."
|
|
15
17
|
timing: deferred
|
|
@@ -18,45 +20,153 @@ metadata:
|
|
|
18
20
|
# Design Review
|
|
19
21
|
|
|
20
22
|
Review a built UI with a senior designer's eye. The visual counterpart of
|
|
21
|
-
`review-code`:
|
|
22
|
-
world-class.
|
|
23
|
+
`review-code`: three verdicts, in order — does it match the spec, does it
|
|
24
|
+
actually render correctly, and is it world-class.
|
|
23
25
|
|
|
24
26
|
**Core principle:** You cannot review design from source. Render it and look at
|
|
25
27
|
the pixels. A claim about how it looks, without a screenshot, is a guess — the
|
|
26
28
|
visual equivalent of claiming tests pass without running them.
|
|
27
29
|
|
|
30
|
+
## The Iron Law
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
UNRENDERED IS NOT PASSED. Every check ends in exactly one of:
|
|
34
|
+
pass (with evidence) | fail (with evidence) | untested (with the reason)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
A review run without a browser is a partial review, and says so. It is never a
|
|
38
|
+
clean one.
|
|
39
|
+
|
|
28
40
|
## Inputs
|
|
29
41
|
|
|
30
|
-
- `built_ui` — the running app (
|
|
31
|
-
- `ui_spec` — `specs/<slug>-ui.md` it must satisfy
|
|
42
|
+
- `built_ui` — the running app (a live URL, or a dev server this skill starts).
|
|
43
|
+
- `ui_spec` — `specs/<slug>-ui.md` it must satisfy, including its declared
|
|
44
|
+
**treatment** (`utility` / `product` / `editorial`).
|
|
45
|
+
- `screenshots?` — captures a prior `smoke-test` already took. Use them instead
|
|
46
|
+
of relaunching the app for the same screen.
|
|
32
47
|
- Read `taste/design-system` + `taste/brand` — the bar to calibrate against.
|
|
33
48
|
Deviations from the system are higher severity, not lower.
|
|
34
49
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
50
|
+
## How to render (do this before any verdict)
|
|
51
|
+
|
|
52
|
+
Prefer what already exists: if `screenshots` covers a screen, do not relaunch
|
|
53
|
+
the app for it. When you must launch it yourself, follow the same protocol
|
|
54
|
+
`smoke-test` uses — it is the same hazard.
|
|
55
|
+
|
|
56
|
+
1. **Discover how to run it.** `registry/app` first; else the project's manifest
|
|
57
|
+
(`package.json` scripts, `Makefile`, `README`). Genuinely unguessable → every
|
|
58
|
+
render-dependent check is `untested: cannot launch`. Do not invent a server.
|
|
59
|
+
2. **Launch in the background, capture logs** to
|
|
60
|
+
`.orchestrate/verify/design-review-server.log`. Record the PID. Pick a free
|
|
61
|
+
port if configurable, to avoid colliding with anything already running.
|
|
62
|
+
3. **Wait for readiness, bounded** — poll the health endpoint / port / ready
|
|
63
|
+
line for up to ~60s. Not ready → the checks are `failed: app did not start`,
|
|
64
|
+
attach the server log, skip to cleanup.
|
|
65
|
+
4. **Render** every screen and state in the spec (loading, empty, error too), in
|
|
66
|
+
every mode under the system's `theme.modes`, with the best driver available:
|
|
67
|
+
- **Browser automation** (a Playwright/Chrome MCP tool, if available in this
|
|
68
|
+
session) — the only driver that can reach computed style, keyboard focus,
|
|
69
|
+
a media-query override, or a viewport change.
|
|
70
|
+
- **Handed-in screenshots** — enough for layout, hierarchy, contrast, and the
|
|
71
|
+
greyscale check; not enough for focus, computed font, or media queries.
|
|
72
|
+
- **No driver at all** — state it once, mark the dependent checks `untested`,
|
|
73
|
+
and still deliver Verdict 1 and every judgment call the spec supports.
|
|
74
|
+
5. **Capture evidence per screen** to
|
|
75
|
+
`.orchestrate/verify/design-review-<screen>-<mode>.png` (or `.log`).
|
|
76
|
+
6. **ALWAYS clean up** — kill only the processes you started, and remove temp
|
|
77
|
+
state you created. Cleanup runs even when checks fail.
|
|
78
|
+
|
|
79
|
+
Record which modes you actually rendered. An unrendered mode is `untested`,
|
|
80
|
+
never a passing one.
|
|
81
|
+
|
|
82
|
+
## When the design system predates these fields
|
|
83
|
+
|
|
84
|
+
A `taste/design-system` written before `theme`, `focus.visible_style`, and
|
|
85
|
+
`motion.reduced_motion` existed will not carry them — and an upgrade never
|
|
86
|
+
rewrites an existing brain, so this is the normal case for any project older
|
|
87
|
+
than those fields. **A missing field is unspecified, not satisfied:**
|
|
88
|
+
|
|
89
|
+
| Missing | Assume | Consequence |
|
|
90
|
+
| ----------------------- | ------------------------------------- | ------------------------------------------------------------------------------- |
|
|
91
|
+
| `theme` / `theme.modes` | light-only | Render light. Do not fail a dark mode that was never designed. |
|
|
92
|
+
| `color.contrast_floor` | WCAG AA — 4.5:1 text, 3:1 UI/graphics | Still measure. Label the floor `assumed` in the report. |
|
|
93
|
+
| `focus.visible_style` | any clearly visible indicator | Check 3 still runs; only the specific style is unspecified. |
|
|
94
|
+
| `motion.reduced_motion` | all non-essential animation stops | Check 5 still runs. |
|
|
95
|
+
|
|
96
|
+
Every assumption goes in the report's `assumptions` list, so the human sees
|
|
97
|
+
which bar was applied. Raise the gap **once** as a `Minor` finding so the system
|
|
98
|
+
gets backfilled — never once per screen.
|
|
39
99
|
|
|
40
100
|
## Verdict 1 — Spec compliance
|
|
41
101
|
|
|
42
102
|
For each screen/flow/state in `ui_spec`: present and correct, missing, or wrong.
|
|
43
103
|
Missing a screen or a non-happy state → spec verdict FAIL.
|
|
44
104
|
|
|
45
|
-
## Verdict 2 —
|
|
105
|
+
## Verdict 2 — Rendering & accessibility (objective)
|
|
106
|
+
|
|
107
|
+
These are measurements, not opinions. Measure them; do not eyeball them. Each
|
|
108
|
+
check reports `pass`, `fail`, or `untested` with its reason — **a check you
|
|
109
|
+
could not run is never a pass.** The `needs` tag names what the check requires;
|
|
110
|
+
without it, the check is `untested`. Any failure here is at least **Important**;
|
|
111
|
+
anything that makes content unreadable or a control unreachable is **Critical**.
|
|
112
|
+
|
|
113
|
+
1. **Themes** *(needs: a render per declared mode)*. Render each screen in every
|
|
114
|
+
declared mode. Also render the *un-stamped* default state — where no explicit
|
|
115
|
+
theme is selected and only the OS preference applies — because a color
|
|
116
|
+
defined solely inside a `[data-theme]` or media block never applies there,
|
|
117
|
+
and the page renders one theme's text on the other theme's ground. Any text,
|
|
118
|
+
icon, border, or focus ring that vanishes or loses contrast in one mode is a
|
|
119
|
+
defect in that mode.
|
|
120
|
+
2. **Contrast** *(needs: a screenshot or computed style)*. Compute the ratios
|
|
121
|
+
against `contrast_floor` for body text and for UI/graphic elements, in every
|
|
122
|
+
rendered mode. Report the number, not an impression.
|
|
123
|
+
3. **Keyboard focus** *(needs: browser)*. Tab through every screen. Every
|
|
124
|
+
interactive element has a visible focus indicator, focus order follows visual
|
|
125
|
+
order, and no element traps focus. An invisible focus ring is Critical.
|
|
126
|
+
4. **Overflow** *(needs: browser — viewport resize)*. At the narrowest supported
|
|
127
|
+
width, the page body must not scroll horizontally. Wide content — tables,
|
|
128
|
+
code, charts, diagrams — scrolls inside its own container. Check for
|
|
129
|
+
overlapping or clipped elements at each tested width.
|
|
130
|
+
5. **Reduced motion** *(needs: browser — media override)*. Render with
|
|
131
|
+
`prefers-reduced-motion: reduce`. Animation is removed or reduced, and
|
|
132
|
+
nothing becomes unusable or permanently invisible — scroll-reveal content
|
|
133
|
+
that never reveals is Critical.
|
|
134
|
+
6. **Fonts actually loaded** *(needs: browser — computed style)*. Confirm the
|
|
135
|
+
system's named typeface is the one rendering, not a silent fallback to a
|
|
136
|
+
system face. Compare computed `font-family` against what actually painted.
|
|
137
|
+
7. **Spacing integrity** *(needs: a screenshot + the spacing scale)*. Gaps
|
|
138
|
+
between sibling groups match the scale — no collapsed or doubled margins, no
|
|
139
|
+
ad-hoc values off the scale.
|
|
140
|
+
8. **State without color** *(needs: a screenshot)*. Convert it to greyscale. If
|
|
141
|
+
success, warning, and error can no longer be told apart, state is encoded in
|
|
142
|
+
color alone — a defect, not a style.
|
|
143
|
+
|
|
144
|
+
## Verdict 3 — Visual quality (judgment)
|
|
46
145
|
|
|
47
146
|
Against the design system and world-class craft:
|
|
48
147
|
|
|
148
|
+
- **Treatment match.** Compare against the treatment the spec declared. Flag
|
|
149
|
+
both directions: a `product` screen built with no hierarchy or presence, and a
|
|
150
|
+
`utility` screen wearing a hero, decorative motion, or ornament it did not
|
|
151
|
+
earn. **Over-design is a finding, at the same severity as under-design.**
|
|
49
152
|
- **Hierarchy** obvious in one glance? **Spacing** on the system's scale?
|
|
50
153
|
- **Consistency** with the system's type/color/tokens? Drift = defect.
|
|
51
154
|
- Is the **memorable-thing** actually visible here?
|
|
52
155
|
- **Non-happy states** real, not stubs (loading/empty/error)?
|
|
156
|
+
- **Copy** — do labels, confirmations, empty states, and errors match the spec
|
|
157
|
+
and `taste/brand`? A control whose label and confirmation use different verbs,
|
|
158
|
+
an error that only apologizes, or shipped placeholder text are all findings.
|
|
53
159
|
- **Interaction quality** — jank, slow transitions, layout shift?
|
|
54
160
|
|
|
55
161
|
### Anti-slop check
|
|
56
162
|
|
|
57
|
-
Flag any AI-default tell
|
|
58
|
-
|
|
59
|
-
|
|
163
|
+
Flag any AI-default tell. The canonical list lives in the `design-system` skill;
|
|
164
|
+
short form: warm cream + serif + terracotta · near-black with one acid-green or
|
|
165
|
+
vermilion pop · purple-to-blue gradient hero · default framework swatches ·
|
|
166
|
+
Inter / Roboto / Space Grotesk where the system says otherwise · three-column
|
|
167
|
+
rounded-card grids · accent rail on a rounded card · `rounded-lg` and drop
|
|
168
|
+
shadows on everything · emoji as icons · everything centered · `01 / 02 / 03`
|
|
169
|
+
numbering on content that is not a sequence.
|
|
60
170
|
|
|
61
171
|
Rate each finding **Critical** (must fix) · **Important** (fix before merge) ·
|
|
62
172
|
**Minor** (note it).
|
|
@@ -64,20 +174,56 @@ Rate each finding **Critical** (must fix) · **Important** (fix before merge) ·
|
|
|
64
174
|
## Output: `design_review_report`
|
|
65
175
|
|
|
66
176
|
```yaml
|
|
177
|
+
coverage: partial # full | partial — partial whenever any check is untested
|
|
178
|
+
driver: browser # browser | screenshots | none
|
|
179
|
+
themes_rendered: [light] # modes actually rendered; [] if none
|
|
180
|
+
assumptions: ["contrast_floor absent from taste/design-system — applied WCAG AA 4.5:1"]
|
|
67
181
|
spec_compliance: pass # pass | fail
|
|
182
|
+
rendering_a11y: # one verdict per check: pass | fail | untested (+ reason)
|
|
183
|
+
themes: pass
|
|
184
|
+
contrast: fail
|
|
185
|
+
focus: untested — no browser driver in this session
|
|
186
|
+
overflow: untested — no browser driver in this session
|
|
187
|
+
reduced_motion: untested — no browser driver in this session
|
|
188
|
+
fonts: untested — no browser driver in this session
|
|
189
|
+
spacing: pass
|
|
190
|
+
state_without_color: pass
|
|
68
191
|
missing: [<screen/state not built>]
|
|
69
192
|
findings:
|
|
70
|
-
- {
|
|
193
|
+
- {
|
|
194
|
+
severity: Important,
|
|
195
|
+
kind: rendering, # spec | rendering | a11y | visual | treatment | copy | anti-slop
|
|
196
|
+
screen: settings,
|
|
197
|
+
mode: dark,
|
|
198
|
+
issue: "...",
|
|
199
|
+
evidence: "measured 3.1:1 against a 4.5:1 floor",
|
|
200
|
+
fix: "...",
|
|
201
|
+
shot: ".orchestrate/verify/design-review-settings-dark.png",
|
|
202
|
+
}
|
|
71
203
|
verdict: changes_requested # approved | changes_requested
|
|
204
|
+
cleanup: "started pid 48213, killed" # or "nothing started"
|
|
72
205
|
```
|
|
73
206
|
|
|
74
207
|
## Rules
|
|
75
208
|
|
|
76
|
-
- **Evidence-based.** Every finding names the screen and, where
|
|
77
|
-
screenshot.
|
|
209
|
+
- **Evidence-based.** Every finding names the screen and, where applicable, the
|
|
210
|
+
theme mode and a screenshot. Objective findings carry the measurement. No
|
|
211
|
+
"looks off" without showing it.
|
|
212
|
+
- **`untested` never rounds up.** Do not infer a check from the CSS, from a
|
|
213
|
+
neighbouring screen, or from what the framework "usually" does. If `coverage`
|
|
214
|
+
is `partial`, say which checks are missing in one line — an `approved` verdict
|
|
215
|
+
must never imply coverage it does not have.
|
|
78
216
|
- **Don't pre-judge.** Surface deviations; don't excuse one because the spec or a
|
|
79
217
|
deadline pushed it.
|
|
80
218
|
- **Findings route back, not to the human.** Critical/Important go to `implement`
|
|
81
219
|
(re-run with this report as `qa_feedback`). The human sees the result at the
|
|
82
220
|
end-of-run acceptance.
|
|
83
|
-
- If it's clean and on-
|
|
221
|
+
- If it's clean, on-system, and on-treatment, say so plainly and approve.
|
|
222
|
+
|
|
223
|
+
## Red flags — stop
|
|
224
|
+
|
|
225
|
+
- Reporting `pass` on a check you could not run
|
|
226
|
+
- A measurement (contrast, computed font) stated without the number
|
|
227
|
+
- Leaving a dev server you started still running after the report
|
|
228
|
+
- Failing a dark mode the design system never declared
|
|
229
|
+
- Raising the same missing-KB-field finding once per screen
|
|
@@ -4,12 +4,14 @@ description: Use when a project has no design direction yet, or must (re)establi
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, WebSearch, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write, web.read]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [product_context, references?]
|
|
10
|
+
inputs: [product_context, "references?"]
|
|
9
11
|
reads: [taste/brand, taste/design-system]
|
|
10
12
|
outputs: [taste/design-system, taste/brand]
|
|
11
13
|
authority: "Author the durable design KB (taste/design-system, taste/brand). High-authority, audited (knowledge write). No source code, no production."
|
|
12
|
-
verify: "Specific, not generic: a named typeface, real type/space scales, named reference products, one memorable-thing. Covers type + color + space + motion. No AI-default tells (see anti-slop)."
|
|
14
|
+
verify: "Specific, not generic: a named typeface, real type/space scales, named reference products, one memorable-thing. Covers type + color + theme + space + motion + focus. Every mode listed under theme.modes has a full palette. No AI-default tells (see anti-slop)."
|
|
13
15
|
accept:
|
|
14
16
|
when: "Always — the aesthetic direction is foundational and brand-defining."
|
|
15
17
|
timing: inline
|
|
@@ -47,27 +49,72 @@ point of view BEFORE specifying anything:
|
|
|
47
49
|
## Specify the system (specifics, not adjectives)
|
|
48
50
|
|
|
49
51
|
- **Typography** — a named typeface (not Inter/Roboto unless deliberate and
|
|
50
|
-
justified), a type scale with real sizes/weights, line-height rules
|
|
52
|
+
justified), a type scale with real sizes/weights, line-height rules, and the
|
|
53
|
+
target measure for running text (~65 characters).
|
|
51
54
|
- **Color** — a real palette with roles (bg, surface, text, accent, states), not
|
|
52
|
-
default framework swatches; state the contrast floor.
|
|
55
|
+
default framework swatches; state the contrast floor as a number.
|
|
56
|
+
**Accent and semantic color are two different systems.** The accent is the one
|
|
57
|
+
brand hue; success/warning/error carry meaning. If the accent doubles as
|
|
58
|
+
"success", state cannot be read at a glance — pick again.
|
|
59
|
+
- **Theme** — decide `light | dark | both`, and how a mode is selected (OS
|
|
60
|
+
preference, an explicit user toggle, or both). If dark is in scope, specify a
|
|
61
|
+
**second full palette, role for role**. A dark palette is re-picked, not
|
|
62
|
+
inverted: an accent that holds 4.5:1 on white usually fails on near-black.
|
|
63
|
+
Deciding light-only is allowed — but it must be written down as a decision, so
|
|
64
|
+
`design-review` knows there is nothing else to check.
|
|
53
65
|
- **Space** — a spacing scale; density posture (tight/airy) tied to the product.
|
|
54
66
|
- **Layout** — grid and composition principles; how hierarchy is created.
|
|
55
|
-
- **Motion** — timing, easing,
|
|
67
|
+
- **Motion** — timing, easing, where motion is used (and where it is not), and
|
|
68
|
+
what `prefers-reduced-motion` removes while keeping the UI usable.
|
|
69
|
+
- **Focus** — the keyboard focus indicator every interactive element carries. An
|
|
70
|
+
invisible focus ring is a broken system, not a style choice.
|
|
56
71
|
|
|
57
|
-
## Anti-slop (
|
|
72
|
+
## Anti-slop (the canonical list — `design-ui` and `design-review` check it too)
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
AI-generated design converges on a small set of looks. These are not banned —
|
|
75
|
+
they are **disqualified as defaults**. Picking one is allowed only as a stated,
|
|
76
|
+
justified decision, never as where you landed without choosing.
|
|
77
|
+
|
|
78
|
+
**Palettes** — warm cream ground (`#F4F1EA` and neighbors) with a serif display
|
|
79
|
+
and a terracotta accent · near-black with one acid-green or vermilion pop ·
|
|
80
|
+
purple-to-blue gradient hero on white · default framework swatches
|
|
81
|
+
(`blue-500`, `slate-800`, …).
|
|
82
|
+
|
|
83
|
+
**Type** — Inter, Roboto, or Space Grotesk as the "safe" face · a display face
|
|
84
|
+
used at body sizes so its personality never shows.
|
|
85
|
+
|
|
86
|
+
**Layout** — three-column rounded-card feature grids · an accent bar/rail down
|
|
87
|
+
the side of a rounded card · `rounded-lg` on everything · drop shadow on
|
|
88
|
+
everything · everything centered · broadsheet hairline rules over dense columns.
|
|
89
|
+
|
|
90
|
+
**Ornament** — emoji as product icons or section markers · `01 / 02 / 03`
|
|
91
|
+
numbering on content that is not actually a sequence · gradients or
|
|
92
|
+
glassmorphism with no reason.
|
|
93
|
+
|
|
94
|
+
Structural devices must encode something true. Number a set of steps only when
|
|
95
|
+
order is information the reader needs; otherwise the numbers are decoration
|
|
96
|
+
pretending to be structure.
|
|
64
97
|
|
|
65
98
|
## Output: the durable KB (structured, with provenance)
|
|
66
99
|
|
|
67
100
|
Write `taste/design-system` and `taste/brand` as structured entries (per the
|
|
68
101
|
knowledge format: terse, chunked, each with `source`/`added`/`approved_by`).
|
|
69
102
|
Record the memorable-thing, the references, the one distinctive rule, and each
|
|
70
|
-
specified token/scale.
|
|
103
|
+
specified token/scale. Leave no field of the seed blank: `theme`,
|
|
104
|
+
`motion.reduced_motion`, and `focus.visible_style` are decisions, and a blank
|
|
105
|
+
one reads to `design-review` as unspecified rather than as "not needed". This is
|
|
106
|
+
the source `design-ui` reads.
|
|
107
|
+
|
|
108
|
+
**Backfilling an older system.** An upgrade refreshes skills but never rewrites
|
|
109
|
+
an existing `knowledge/` — that brain belongs to the project. So a system
|
|
110
|
+
authored before `theme`, `focus.visible_style`, `motion.reduced_motion`, and
|
|
111
|
+
`typography.measure` existed will simply be missing them, and `design-review`
|
|
112
|
+
will report every dependent check against an assumed bar. When you re-run on
|
|
113
|
+
such a project, add those fields rather than re-authoring the whole system:
|
|
114
|
+
keep every existing value untouched, fill only the gaps, and give the new
|
|
115
|
+
entries their own `added` date and approver. Adding a dark palette to a
|
|
116
|
+
light-only product is a real design decision — put it through the same accept
|
|
117
|
+
gate as the rest, don't infer it.
|
|
71
118
|
|
|
72
119
|
## Self-critique before done
|
|
73
120
|
|
|
@@ -4,13 +4,15 @@ description: Use when a feature has a user interface, to design its screens and
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [requirement, ui_context]
|
|
9
11
|
reads: [taste/design-system, taste/brand]
|
|
10
12
|
outputs: [specs/<slug>-ui.md]
|
|
11
|
-
updates: [taste/design-system
|
|
13
|
+
updates: ["taste/design-system?", "taste/brand?"]
|
|
12
14
|
authority: "Write to the specs namespace (default docs/specs/) and design assets. No source code, no production."
|
|
13
|
-
verify: "Every screen and flow maps to a requirement; expresses the design system (not generic defaults);
|
|
15
|
+
verify: "Every screen and flow maps to a requirement; a treatment is declared and held to; expresses the design system (not generic defaults); copy and non-happy states are specified for every screen; the design plan passed its critique before the spec was written."
|
|
14
16
|
accept:
|
|
15
17
|
when: "Visual direction — the look is foundational; everything downstream builds on it."
|
|
16
18
|
timing: inline
|
|
@@ -34,33 +36,107 @@ aesthetic — that is exactly how product consistency dies.
|
|
|
34
36
|
Carry the system's **memorable-thing** and **distinctive rule** through every
|
|
35
37
|
screen. If this feature can't express them, say so.
|
|
36
38
|
|
|
39
|
+
## Treatment — declare one before designing
|
|
40
|
+
|
|
41
|
+
Craft is constant. Visual ambition is not. **Over-design is a defect, not
|
|
42
|
+
enthusiasm**: a settings page with a full-bleed hero is as wrong as a landing
|
|
43
|
+
page without one. Pick exactly one treatment for this feature, write it at the
|
|
44
|
+
top of the spec, and hold every screen to it. `design-review` checks the built
|
|
45
|
+
UI against the treatment you declared, so declaring `utility` and shipping
|
|
46
|
+
ornament is a finding.
|
|
47
|
+
|
|
48
|
+
| Treatment | Use for | Budget |
|
|
49
|
+
| ----------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| `utility` | internal tools, admin, settings, dense data screens | Information design only. Real hierarchy, spacing on the scale, system palette. No hero, no decorative motion, no ornament. |
|
|
51
|
+
| `product` | the core user-facing surfaces — **the default** | Full system expression. The memorable-thing is present but quiet. Motion is functional: state changes, transitions, feedback. |
|
|
52
|
+
| `editorial` | marketing, landing, launch, first-run onboarding | Opinionated composition. One deliberate aesthetic risk, spent in one place; everything around it stays quiet. |
|
|
53
|
+
|
|
54
|
+
When the requirement doesn't say, use `product`. Escalating to `editorial` is a
|
|
55
|
+
choice you must justify in one sentence in the spec.
|
|
56
|
+
|
|
37
57
|
## Process
|
|
38
58
|
|
|
39
|
-
1. **Map screens to requirements.** Every screen
|
|
59
|
+
1. **Map screens to requirements.** Every screen and state must trace to a
|
|
40
60
|
requirement. Cut the rest (YAGNI).
|
|
41
|
-
2. **
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
2. **Write the design plan, then attack it — before specifying anything.**
|
|
62
|
+
Three to five lines: the treatment, the system tokens this feature leans on,
|
|
63
|
+
the layout concept, and where the memorable-thing shows up. Then read it back
|
|
64
|
+
and ask: *would this same plan work, unchanged, for any other feature in any
|
|
65
|
+
other product?* Whatever survives that substitution is generic — revise it,
|
|
66
|
+
and record in the spec what you changed and why. Catching this in the plan is
|
|
67
|
+
far cheaper than catching it in a finished spec.
|
|
68
|
+
3. **Apply the system, don't restate it.** Use its typeface, scale, palette,
|
|
69
|
+
spacing, motion. Reuse existing components and tokens before proposing new
|
|
70
|
+
ones.
|
|
71
|
+
4. **Specify each screen:** purpose, layout and hierarchy, the system tokens
|
|
44
72
|
used, and the non-happy states — loading, empty, error. These are where UIs
|
|
45
73
|
actually fail.
|
|
46
|
-
|
|
47
|
-
|
|
74
|
+
5. **Specify the copy** for every screen — see below. A screen whose labels are
|
|
75
|
+
unwritten is not specified.
|
|
76
|
+
6. **Cover every theme the system declares.** If `theme.modes` is `both`, each
|
|
77
|
+
screen's spec names the tokens it uses, not literal colors, and calls out any
|
|
78
|
+
place the two palettes need different treatment (elevation, dividers, images
|
|
79
|
+
on a dark ground). If the system is light-only, say so once and move on.
|
|
80
|
+
7. **Show, don't just tell.** When a layout choice is clearer shown than
|
|
81
|
+
described, produce a mockup or wireframe, not prose.
|
|
82
|
+
|
|
83
|
+
## Copy is design material
|
|
84
|
+
|
|
85
|
+
Words are part of the design, not filler dropped in later. Read `taste/brand`
|
|
86
|
+
for voice, then write the actual strings:
|
|
87
|
+
|
|
88
|
+
- **Name things the way the user names them**, not the way the system is built.
|
|
89
|
+
A person manages *notifications*, not *webhook config*.
|
|
90
|
+
- **A control says exactly what happens.** Button `Publish` → toast `Published`.
|
|
91
|
+
Label and confirmation must use the same verb.
|
|
92
|
+
- **Errors state what went wrong and what to do next.** No apologies, no
|
|
93
|
+
"something went wrong", no error code alone.
|
|
94
|
+
- **Empty states say what goes here and how to get the first one**, not "No
|
|
95
|
+
data".
|
|
96
|
+
- Active voice. Specific beats clever. Never ship lorem ipsum or placeholder
|
|
97
|
+
text into a spec — write the real string or mark it `TODO: copy`.
|
|
98
|
+
|
|
99
|
+
## When the surface is operated, not read
|
|
100
|
+
|
|
101
|
+
A dashboard, console, or tool is scanned and acted on, not read top to bottom.
|
|
102
|
+
For those screens the craft shifts from typography to information design:
|
|
103
|
+
|
|
104
|
+
- Summary before detail. What needs attention resolves in one glance.
|
|
105
|
+
- **Encode state in form, not only in number** — a pill, a chip, a severity
|
|
106
|
+
stripe. Color alone is not an encoding; it fails for color-blind users and in
|
|
107
|
+
a screenshot.
|
|
108
|
+
- **Semantic color (success / warning / error) is separate from the accent hue**
|
|
109
|
+
and never counts as your accent.
|
|
110
|
+
- Charts and sparklines get the same care as type: a considered fill, a faint
|
|
111
|
+
grid, an emphasized endpoint. Numbers in columns get tabular figures.
|
|
112
|
+
- What is interactive must look interactive.
|
|
48
113
|
|
|
49
114
|
## Anti-slop (forbidden defaults)
|
|
50
115
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
116
|
+
The canonical list lives in the `design-system` skill; `design-review` checks
|
|
117
|
+
the same one. Short form — none of these may be where you landed without
|
|
118
|
+
choosing: warm cream + serif + terracotta · near-black with one acid-green or
|
|
119
|
+
vermilion pop · purple-to-blue gradient hero · default framework swatches ·
|
|
120
|
+
Inter / Roboto / Space Grotesk as the safe face · three-column rounded-card
|
|
121
|
+
grids · accent rail on a rounded card · `rounded-lg` and drop shadows on
|
|
122
|
+
everything · emoji as icons · everything centered · `01 / 02 / 03` numbering on
|
|
123
|
+
content that is not a sequence.
|
|
124
|
+
|
|
125
|
+
A default is only allowed as a deliberate, justified choice — and any deviation
|
|
126
|
+
from `taste/design-system` needs the same justification.
|
|
55
127
|
|
|
56
128
|
## Designer's-eye self-critique (mandatory gate before done)
|
|
57
129
|
|
|
58
|
-
|
|
130
|
+
The plan critique in step 2 catches generic direction. This catches generic
|
|
131
|
+
execution. Look at the result and ask:
|
|
59
132
|
|
|
60
133
|
- Does this look like it could ship from {the named references}, or like a
|
|
61
134
|
generic AI UI? If the latter, fix it.
|
|
62
135
|
- Is hierarchy obvious in one glance? Is spacing on the scale? Is the
|
|
63
136
|
memorable-thing visible here?
|
|
137
|
+
- **Does the ambition match the declared treatment** — nothing under-designed,
|
|
138
|
+
and nothing decorated past its budget?
|
|
139
|
+
- Every screen: loading, empty, error specified? Copy written, not placeholder?
|
|
64
140
|
- Did any anti-slop tell sneak in?
|
|
65
141
|
|
|
66
142
|
Fix until it passes. This is the visual equivalent of `run-tests` — don't claim
|
|
@@ -71,13 +147,20 @@ done without running it.
|
|
|
71
147
|
```markdown
|
|
72
148
|
# <Feature> — UI Spec
|
|
73
149
|
|
|
150
|
+
## Treatment — utility | product | editorial, and why (one sentence).
|
|
151
|
+
|
|
152
|
+
## Design plan — the plan from step 2, plus what the critique changed and why.
|
|
153
|
+
|
|
74
154
|
## Screens — each: purpose, the requirement it serves, layout + hierarchy.
|
|
75
155
|
|
|
76
156
|
## Flows — how the user moves between screens.
|
|
77
157
|
|
|
78
158
|
## States — loading / empty / error for each screen.
|
|
79
159
|
|
|
80
|
-
##
|
|
160
|
+
## Copy — the real strings per screen: labels, confirmations, empties, errors.
|
|
161
|
+
|
|
162
|
+
## System use — tokens/components used; theme coverage; how the
|
|
163
|
+
memorable-thing shows up here.
|
|
81
164
|
|
|
82
165
|
## New patterns — anything the system lacked, with rationale (candidate for KB).
|
|
83
166
|
```
|
|
@@ -4,9 +4,11 @@ description: Use when a feature request or requirement must become an implementa
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [requirement, context]
|
|
9
|
-
reads: [taste/coding-standards, registry/api, registry/db, front-end-spec?]
|
|
11
|
+
reads: [taste/coding-standards, registry/api, registry/db, "front-end-spec?"]
|
|
10
12
|
outputs: [stories/<slug>.md]
|
|
11
13
|
authority: "Write one flat story file in the stories namespace (physical path from core-config.yaml; default docs/stories/). No folders. No source code. No production. No spend."
|
|
12
14
|
verify: "Every requirement maps to at least one acceptance criterion; constraints are copied verbatim; no placeholders (no TBD/TODO/'handle edge cases')."
|
|
@@ -4,8 +4,10 @@ description: Use when implementing a feature or bugfix from a spec with acceptan
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Edit, Bash]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [story, acceptance_criteria, scope, qa_feedback?]
|
|
10
|
+
inputs: [story, acceptance_criteria, scope, "qa_feedback?"]
|
|
9
11
|
reads: [taste/coding-standards, registry/api, registry/db]
|
|
10
12
|
outputs: [code_diff, ac_traceability, test_files]
|
|
11
13
|
authority: "Write src/ and tests/. No production, no deploy, no network spend."
|
|
@@ -4,8 +4,10 @@ description: Use when something is broken and the CAUSE is unknown — a repeate
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [symptom, context
|
|
10
|
+
inputs: [symptom, "context?", "prior_attempts?"]
|
|
9
11
|
reads: [registry/architecture, taste/coding-standards]
|
|
10
12
|
outputs: [root_cause_report]
|
|
11
13
|
authority: "Read code and run diagnostics/reproductions. Temporary instrumentation is allowed but MUST be reverted before finishing. No fixes — the fix belongs to a re-dispatched implement."
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
name: map-codebase
|
|
3
3
|
description: Use when entering an EXISTING codebase (brownfield) before designing or changing anything — build an evidence-based map of its architecture, conventions, and hazards.
|
|
4
4
|
license: MIT
|
|
5
|
-
allowed-tools: [Read, Bash, Grep, Glob]
|
|
5
|
+
allowed-tools: [Read, Write, Bash, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [repo_path, focus?]
|
|
10
|
+
inputs: [repo_path, "focus?"]
|
|
9
11
|
reads: []
|
|
10
12
|
outputs: [codebase_map, registry_updates]
|
|
11
13
|
authority: "Read-only on source; non-mutating commands only (ls, grep, git log, test discovery). Writes go ONLY to the registry/* namespace (physical path from core-config.yaml; default knowledge/registry/)."
|
|
@@ -4,9 +4,11 @@ description: Use when a goal must be delivered end-to-end by composing skills, w
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Task]
|
|
6
6
|
metadata:
|
|
7
|
-
version:
|
|
7
|
+
version: 6
|
|
8
|
+
requires:
|
|
9
|
+
capabilities: [filesystem.read, filesystem.write, shell.execute, "agent.spawn?"]
|
|
8
10
|
contract:
|
|
9
|
-
inputs: [intent, constraints?]
|
|
11
|
+
inputs: [intent, "constraints?"]
|
|
10
12
|
reads: [core-config, skill-registry, taste/*]
|
|
11
13
|
outputs: [accepted_deliverable, run_ledger]
|
|
12
14
|
authority: "Dispatch leaf skills, each within its own authority. Do not directly touch source, production, or spend — leaf skills do that, gated. Enforce every accept gate."
|
|
@@ -34,21 +36,22 @@ no step above intent.
|
|
|
34
36
|
1. **Bind intent.** Read the human's goal and constraints. This is the only
|
|
35
37
|
place intent enters. Then run the first-run preflight (below) before any
|
|
36
38
|
wiring.
|
|
37
|
-
2. **Select.** Read the skill registry
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
2. **Select.** Read the skill registry (the `description:` line of every
|
|
40
|
+
SKILL.md in the runtime's skills directory). Pick skills by that
|
|
41
|
+
when-to-use description. Load a skill's full `contract` only when it is a
|
|
42
|
+
candidate — never load every contract at once.
|
|
40
43
|
3. **Wire (emergent, not hardcoded).** Build the path by matching one skill's
|
|
41
44
|
`outputs` to the next skill's `inputs`. Skills do not know each other; only
|
|
42
45
|
you do. Do not assume a fixed pipeline — wire what this intent needs.
|
|
43
46
|
4. **Dispatch.** Hand the skill exactly the `inputs` it declares, as files —
|
|
44
47
|
resolving each logical namespace it reads/writes to a physical path via
|
|
45
|
-
`core-config.yaml` (see Namespace resolution).
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
`core-config.yaml` (see Namespace resolution). If the runtime supports isolated
|
|
49
|
+
agents, run each leaf as a fresh dispatch and choose the cheapest capable model.
|
|
50
|
+
Dispatch independent steps concurrently and await them in the same turn; keep
|
|
51
|
+
dependent steps sequential. Never fire-and-forget a background agent. If the
|
|
52
|
+
runtime has no isolated-agent capability, execute leaves sequentially in the
|
|
53
|
+
current context, reloading only the declared inputs before each step. Isolation
|
|
54
|
+
is preferred; it is not required for correctness.
|
|
52
55
|
5. **Verify (gate) — executable, not prose.** Prove the skill's `verify` with a
|
|
53
56
|
REAL command you run yourself via Bash, and capture the proof:
|
|
54
57
|
|
|
@@ -66,8 +69,12 @@ no step above intent.
|
|
|
66
69
|
6. **Accept (gate).** Apply the rule below. Then continue — do not pause to ask
|
|
67
70
|
"should I keep going?" mid-run.
|
|
68
71
|
7. **Repeat** 3–6 until the intent is fulfilled.
|
|
69
|
-
8. **Final acceptance.**
|
|
70
|
-
|
|
72
|
+
8. **Final acceptance.** FIRST re-read the intent from the `run_start` ledger
|
|
73
|
+
line and check the assembled result against IT — every step passing its own
|
|
74
|
+
verify does not prove the composition serves the intent (steps can each be
|
|
75
|
+
right while the whole drifts). Then present the batched deferred accepts and
|
|
76
|
+
a final review to the human, once. Apply corrections (see Metabolism), then
|
|
77
|
+
deliver.
|
|
71
78
|
|
|
72
79
|
## Namespace resolution (`core-config.yaml`)
|
|
73
80
|
|
|
@@ -112,6 +119,27 @@ resolved paths):
|
|
|
112
119
|
|
|
113
120
|
Both checks are per-run and idempotent: a populated brain makes them no-ops.
|
|
114
121
|
|
|
122
|
+
## Hard wiring rules (what emergence cannot reach)
|
|
123
|
+
|
|
124
|
+
Output→input matching wires most of the graph. Two skills it structurally
|
|
125
|
+
CANNOT reach — wire these by rule, not by match:
|
|
126
|
+
|
|
127
|
+
1. **`smoke-test` is the acceptance floor for runnable apps.** Nothing in the
|
|
128
|
+
graph outputs its `flows` or `run_instructions`, so no output→input match
|
|
129
|
+
will ever select it. If the deliverable is a runnable app or service and
|
|
130
|
+
this run changed it, wire `smoke-test` before final acceptance and derive
|
|
131
|
+
its inputs yourself: `flows` from the story's acceptance criteria (or from
|
|
132
|
+
the intent, when there is no story), `run_instructions` from `registry/app`
|
|
133
|
+
(or the project's own manifest). `run-tests` proves functions; `smoke-test`
|
|
134
|
+
proves the product — green unit tests are not this evidence. A `failed` or
|
|
135
|
+
`untested` verdict is a real result: carry it into final acceptance
|
|
136
|
+
verbatim, never round it up to passed.
|
|
137
|
+
2. **`design-system` comes before `design-ui`.** `design-ui` READS
|
|
138
|
+
`taste/design-system` — it never produces it. If UI work is wired and the
|
|
139
|
+
resolved `taste/design-system` namespace is empty, wire `design-system`
|
|
140
|
+
first; otherwise `design-ui` dresses a project that has a brand in generic
|
|
141
|
+
defaults.
|
|
142
|
+
|
|
115
143
|
## Accept gate
|
|
116
144
|
|
|
117
145
|
| Skill's `accept.timing` | Skill's `authority` | Action |
|
|
@@ -139,8 +167,9 @@ aimed at a symptom re-rolls the dice.
|
|
|
139
167
|
STOP the run — do not burn a 4th attempt. Write a `gate` event to the ledger
|
|
140
168
|
(`{"e":"gate","kind":"rework_exhausted","question":"step <n> (<skill>) failed 3
|
|
141
169
|
attempts: <one-line why>"}`), summarize the three failures for the human, and
|
|
142
|
-
|
|
143
|
-
human
|
|
170
|
+
stop for their decision. A step that cannot pass its own verify after three
|
|
171
|
+
tries needs a human (wrong approach, wrong spec, or wrong verify), not more
|
|
172
|
+
tokens.
|
|
144
173
|
|
|
145
174
|
## Metabolism — governed writeback
|
|
146
175
|
|
|
@@ -179,13 +208,18 @@ platform renders it as live progress). It is append-only JSONL: one JSON event
|
|
|
179
208
|
per line, appended with `Bash` (`echo '<json>' >> .orchestrate/ledger.jsonl`).
|
|
180
209
|
Never rewrite or delete lines. Timestamps: `date -u +%FT%TZ`.
|
|
181
210
|
|
|
211
|
+
**Quoting hazard:** the single-quoted `echo` breaks on `'` inside the JSON —
|
|
212
|
+
and a mangled line corrupts the run's only durable memory. Keep every free-text
|
|
213
|
+
field (`intent`, `question`, `title`) to one line with no single quotes:
|
|
214
|
+
rephrase (`don't` → `do not`) before writing, never fight the shell escaping.
|
|
215
|
+
|
|
182
216
|
Events and when to write them:
|
|
183
217
|
|
|
184
218
|
| Event | When | Shape |
|
|
185
219
|
| ----- | ---- | ----- |
|
|
186
220
|
| `run_start` | right after binding intent | `{"e":"run_start","run":"r-<yyyymmdd>-<slug>","intent":"...","ts":"..."}` |
|
|
187
221
|
| `plan` | after wiring the graph, and EVERY time the graph changes | `{"e":"plan","run":"...","steps":[{"n":1,"skill":"research","title":"..."}, …]}` — full current plan; latest `plan` line wins; steps may be added, never removed |
|
|
188
|
-
| `step` | immediately BEFORE each dispatch, and again after its verify | `{"e":"step","run":"...","n":3,"skill":"implement","status":"dispatched\|done\|failed","attempt":1,"evidence":"<file or one-line result>","ts":"..."}` — rework = same `n`, next `attempt` |
|
|
222
|
+
| `step` | immediately BEFORE each dispatch, and again after its verify | `{"e":"step","run":"...","n":3,"skill":"implement","status":"dispatched\|done\|failed\|skipped","attempt":1,"evidence":"<file or one-line result>","ts":"..."}` — rework = same `n`, next `attempt`; a step a replan made obsolete gets `skipped` with the reason in `evidence` (plan lines are never removed, so this is how an obsolete step closes) |
|
|
189
223
|
| `gate` | when stopping at a human gate | `{"e":"gate","run":"...","kind":"inline_accept","question":"...","ts":"..."}` |
|
|
190
224
|
| `run_end` | at delivery or abandonment | `{"e":"run_end","run":"...","result":"delivered\|paused\|abandoned","ts":"..."}` |
|
|
191
225
|
|
|
@@ -194,6 +228,24 @@ step is required and should be the step's verify log path
|
|
|
194
228
|
(`.orchestrate/verify/step-<n>-attempt-<k>.log`); a `done` with no evidence is
|
|
195
229
|
a false claim.
|
|
196
230
|
|
|
231
|
+
## Resume — cold re-entry (deterministic, not from memory)
|
|
232
|
+
|
|
233
|
+
Whenever you enter with an existing ledger — after compaction, an interrupted
|
|
234
|
+
session, or a wake-up — do NOT continue from what you remember. Replay:
|
|
235
|
+
|
|
236
|
+
1. Read `.orchestrate/ledger.jsonl`. The active run is the last `run_start`
|
|
237
|
+
with no matching `run_end`. Its `intent` line — not your recollection — is
|
|
238
|
+
what you are delivering. No active run → this is a fresh start.
|
|
239
|
+
2. Rebuild state from events alone: the latest `plan` wins; `done` and
|
|
240
|
+
`skipped` steps are closed; prior `attempt` values count toward each step's
|
|
241
|
+
cap of 3.
|
|
242
|
+
3. **A dangling `dispatched`** (no `done`/`failed`/`skipped` after it) means
|
|
243
|
+
that attempt was cut off mid-flight. Trust it in NEITHER direction: run that
|
|
244
|
+
step's verify command now. Pass → append its `done` with the evidence.
|
|
245
|
+
Fail → re-dispatch as the next attempt.
|
|
246
|
+
4. Continue the loop from the first open step. If the run was stopped at a
|
|
247
|
+
`gate`, re-ask that gate's question — never assume it was answered.
|
|
248
|
+
|
|
197
249
|
## Context discipline (stay lean)
|
|
198
250
|
|
|
199
251
|
- **Files, not paste.** Move artifacts between steps as files. Never paste a
|
|
@@ -209,6 +261,8 @@ a false claim.
|
|
|
209
261
|
- Hardcoding a fixed skill order instead of wiring outputs→inputs
|
|
210
262
|
- Pasting a step's full output into your context instead of handing a file
|
|
211
263
|
- Re-dispatching a step the ledger already marks done
|
|
264
|
+
- Resuming from memory instead of replaying the ledger — or trusting a
|
|
265
|
+
dangling `dispatched` in either direction without running its verify
|
|
212
266
|
- Dispatching a step without first writing its `dispatched` ledger line
|
|
213
267
|
- Ending a run without a `run_end` ledger line
|
|
214
268
|
- Marking a step done on the subagent's say-so, without your own verify command
|
|
@@ -217,4 +271,7 @@ a false claim.
|
|
|
217
271
|
- Appending to `taste/*` without reading it first (duplicate/contradiction risk)
|
|
218
272
|
- Dispatching a design/build skill in an existing codebase while `registry/*`
|
|
219
273
|
is empty (first-run preflight skipped)
|
|
274
|
+
- Delivering a runnable app this run changed with no `smoke-test` verdicts
|
|
275
|
+
(unit tests are not that evidence)
|
|
276
|
+
- Dispatching `design-ui` while the resolved `taste/design-system` is empty
|
|
220
277
|
- Marking the run complete without every step's `verify` evidence
|
package/skills/research/SKILL.md
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
name: research
|
|
3
3
|
description: Use when a planning or design decision needs external facts — market, competitor, feasibility, or a library/tech choice — before committing.
|
|
4
4
|
license: MIT
|
|
5
|
-
allowed-tools: [Read, WebSearch, WebFetch]
|
|
5
|
+
allowed-tools: [Read, Write, WebSearch, WebFetch]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write, web.read]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [question, scope]
|
|
9
11
|
reads: []
|
|
@@ -4,6 +4,8 @@ description: Use after implementing a task or feature and before merging, to che
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
10
|
inputs: [diff, spec]
|
|
9
11
|
reads: [taste/coding-standards]
|
|
@@ -4,8 +4,10 @@ description: Use before claiming any work is complete, fixed, or passing, and be
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [target, expected_outcome?]
|
|
10
|
+
inputs: [target, "expected_outcome?"]
|
|
9
11
|
reads: []
|
|
10
12
|
outputs: [verification_report]
|
|
11
13
|
authority: "Run test, lint, and build commands. Read-only on source. No edits, no production."
|
|
@@ -4,8 +4,10 @@ description: Use when the deliverable is a runnable app or service and its real
|
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: [Read, Bash, Grep, Glob]
|
|
6
6
|
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, shell.execute]
|
|
7
9
|
contract:
|
|
8
|
-
inputs: [run_instructions, flows, qa_feedback?]
|
|
10
|
+
inputs: [run_instructions, flows, "qa_feedback?"]
|
|
9
11
|
reads: [registry/app]
|
|
10
12
|
outputs: [smoke_report, verify_evidence]
|
|
11
13
|
authority: "Start and stop the app locally; drive it via browser automation, HTTP, or CLI. Read-only on source. No deploy, no external spend, no mutations outside the app's own local state."
|