orchestrix-skills 0.9.0 → 0.11.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 +37 -4
- package/adapters/claude/runtime.json +8 -1
- package/adapters/codex/AGENTS.md +3 -1
- package/adapters/codex/runtime.json +8 -1
- package/adapters/forge/github.json +20 -0
- package/adapters/forge/gitlab.json +20 -0
- package/bin/install.js +55 -1
- package/package.json +1 -1
- package/project-scaffold/core-config.yaml +14 -0
- package/project-scaffold/knowledge/taste/design-system.md +1 -0
- package/skills/README.md +9 -2
- package/skills/brainstorm/SKILL.md +3 -0
- package/skills/commit/SKILL.md +1 -0
- package/skills/deploy/SKILL.md +1 -0
- package/skills/design-architecture/SKILL.md +1 -0
- package/skills/design-directions/SKILL.md +104 -0
- package/skills/design-review/SKILL.md +6 -1
- package/skills/design-system/SKILL.md +102 -67
- package/skills/design-ui/SKILL.md +25 -13
- package/skills/draft-story/SKILL.md +12 -1
- package/skills/implement/SKILL.md +1 -0
- package/skills/investigate/SKILL.md +1 -0
- package/skills/map-codebase/SKILL.md +1 -0
- package/skills/orchestrate/SKILL.md +180 -15
- package/skills/pull-request/SKILL.md +157 -0
- package/skills/research/SKILL.md +1 -0
- package/skills/review-code/SKILL.md +1 -0
- package/skills/run-tests/SKILL.md +1 -0
- package/skills/smoke-test/SKILL.md +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orchestrix-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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
|
@@ -16,19 +16,43 @@ intent
|
|
|
16
16
|
└─ orchestrate (root: warm context, wires skills by output→input, enforces gates)
|
|
17
17
|
├─ brainstorm ──(needs facts?)─→ research
|
|
18
18
|
├─ (existing repo?) ──→ map-codebase (brownfield entry: evidence-based map → registry)
|
|
19
|
-
├─ (has UI?) ──→ design-system (once) → design-ui
|
|
19
|
+
├─ (has UI?) ──→ design-directions (human picks a rendered direction) → design-system (once) → design-ui
|
|
20
20
|
├─ (arch decision?) ──→ design-architecture
|
|
21
21
|
├─ draft-story → implement → run-tests → review-code → commit
|
|
22
22
|
│ ↑ verify ↑ design-review (UI only)
|
|
23
23
|
│ (objective) ↑ accept (batched)
|
|
24
24
|
├─ (verify failing, cause unknown?) ──→ investigate (root cause → rework)
|
|
25
25
|
├─ (runnable app?) ──→ smoke-test (drive real flows, evidence captured)
|
|
26
|
+
├─ (team mode?) ──→ pull-request after commit (PR on GitHub, MR on GitLab; CI red re-enters rework)
|
|
26
27
|
└─ (accepted + ship it?) ──→ deploy (inline gate, rollback-first)
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
Human gates are front-loaded (planning = direction) and at the end (acceptance);
|
|
30
31
|
the build loop runs lights-out, gated only by objective `verify`.
|
|
31
32
|
|
|
33
|
+
## Team mode
|
|
34
|
+
|
|
35
|
+
Uncomment the `collaboration:` block in `core-config.yaml` and the same loop
|
|
36
|
+
runs for a team. Planning happens once, on a planning branch, and reaches the
|
|
37
|
+
base branch through a PR. Each story is then one run on its own branch
|
|
38
|
+
(`story/<origin>/<slug>`) in its own workspace — a `git worktree` when several
|
|
39
|
+
sessions share a machine, a clone elsewhere — and ends with `pull-request`
|
|
40
|
+
instead of a local commit. Merging stays a reviewer's act in the forge.
|
|
41
|
+
|
|
42
|
+
There is no board file. A story's state is derived from git and the forge each
|
|
43
|
+
time it is needed: a remote branch means claimed, an open PR means in review, a
|
|
44
|
+
merged PR means done. Claiming is one push that the remote rejects if the
|
|
45
|
+
branch already exists, so two people cannot take the same story. The PR body
|
|
46
|
+
carries the run's evidence (acceptance criteria → code → test → verify log),
|
|
47
|
+
because `.orchestrate/` never leaves the machine that produced it.
|
|
48
|
+
|
|
49
|
+
GitHub and GitLab are supported through `adapters/forge/`; the exact CLI
|
|
50
|
+
commands are inlined in the `pull-request` skill and kept identical by test.
|
|
51
|
+
Team mode needs that forge's CLI (`gh` or `glab`) installed and logged in on
|
|
52
|
+
each machine. `install` and `doctor` check for it once the block is active;
|
|
53
|
+
without it a builder run still pushes its branch, then stops and asks a human
|
|
54
|
+
to open the PR — it never pretends the PR exists.
|
|
55
|
+
|
|
32
56
|
## Install
|
|
33
57
|
|
|
34
58
|
```bash
|
|
@@ -51,7 +75,7 @@ Re-running `install` refreshes the skills in place. It also writes a stamp at
|
|
|
51
75
|
`<skills-dir>/.orchestrix-skills.json`:
|
|
52
76
|
|
|
53
77
|
```json
|
|
54
|
-
{ "version": "0.
|
|
78
|
+
{ "version": "0.11.0", "ide": "claude", "skills": ["brainstorm", "commit", "…"] }
|
|
55
79
|
```
|
|
56
80
|
|
|
57
81
|
Two things read it. The installer prunes skills a previous version placed that
|
|
@@ -88,12 +112,21 @@ The root skill is where the interesting engineering lives. Beyond wiring:
|
|
|
88
112
|
even if it asked for a deferred one.
|
|
89
113
|
- **Two rules are hard-wired** because output→input matching structurally cannot
|
|
90
114
|
reach them: `smoke-test` is the acceptance floor for a runnable app the run
|
|
91
|
-
changed, and
|
|
115
|
+
changed, and visual work runs direction → system → screens, with the human
|
|
116
|
+
approving rendered artboards at each gate rather than token files.
|
|
117
|
+
- **Model tiers are declared, not guessed.** Each skill states
|
|
118
|
+
`requires.model: frontier | capable | cheap`; the adapter maps the tier to a
|
|
119
|
+
model, and the resolved model is recorded on every ledger step.
|
|
120
|
+
- **A team adds no shared state.** In team mode a run lives on a branch in
|
|
121
|
+
its own workspace, story state is derived from git and the forge, and an
|
|
122
|
+
epic is accepted on base with `smoke-test` — N green PRs do not prove the
|
|
123
|
+
composition.
|
|
92
124
|
|
|
93
125
|
## Runtime adapters
|
|
94
126
|
|
|
95
127
|
`skills/` is the runtime-neutral source of truth. `adapters/` describes how a
|
|
96
|
-
runtime maps generic capabilities to its tools
|
|
128
|
+
runtime maps generic capabilities to its tools, and how a forge (GitHub,
|
|
129
|
+
GitLab) maps the generic pull-request operations to its CLI. During a Codex install the CLI
|
|
97
130
|
removes Claude-only `allowed-tools`, preserves the contract, and adds Codex
|
|
98
131
|
runtime guidance. If the target has an unmanaged `AGENTS.md`, its content is left
|
|
99
132
|
untouched and the guidance is placed at `.codex/orchestrix/AGENTS.md` for manual
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
"filesystem.write": "Write, Edit",
|
|
9
9
|
"shell.execute": "Bash",
|
|
10
10
|
"web.read": "WebSearch, WebFetch",
|
|
11
|
-
"agent.spawn": "Task"
|
|
11
|
+
"agent.spawn": "Task",
|
|
12
|
+
"design.canvas": "the bundled design skill (Claude Design canvas) + Artifact publish",
|
|
13
|
+
"forge.pr": "Bash + the forge CLI (gh | glab) named by core-config collaboration.forge; op table in the pull-request skill"
|
|
14
|
+
},
|
|
15
|
+
"models": {
|
|
16
|
+
"frontier": "fable",
|
|
17
|
+
"capable": "opus",
|
|
18
|
+
"cheap": "haiku"
|
|
12
19
|
}
|
|
13
20
|
}
|
package/adapters/codex/AGENTS.md
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
- Use the skills installed under `.codex/skills/`; start end-to-end work with `orchestrate`.
|
|
5
5
|
- Treat each skill's `metadata.contract` as Orchestrix workflow data. Codex skill selection still depends on `name` and `description`.
|
|
6
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.
|
|
7
|
+
- Map capability names in `metadata.requires.capabilities` to the tools available in the current Codex session. `design.canvas` is not available: design skills write standalone HTML files, and you open them for the human at visual gates.
|
|
8
|
+
- Map `metadata.requires.model` tiers to models the session can select (`frontier` = the most capable available). When a step cannot switch models, record the session model in its ledger `step` event.
|
|
8
9
|
- 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
10
|
- Independently run every objective verification command. Never accept an agent's success report as proof.
|
|
10
11
|
- Keep runtime evidence at the fixed `.orchestrate/` path described by the `orchestrate` skill.
|
|
12
|
+
- When `core-config.yaml` has a `collaboration:` block, follow the `orchestrate` skill's Collaboration section: one story per branch per workspace (`git worktree add`, then `cd` into it — Codex has no worktree tool), builder runs end with `pull-request`, and forge operations come from that skill's op table.
|
|
11
13
|
<!-- orchestrix:end -->
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
"filesystem.write": "runtime patch/edit tools",
|
|
9
9
|
"shell.execute": "runtime shell tool",
|
|
10
10
|
"web.read": "runtime web tools when enabled",
|
|
11
|
-
"agent.spawn": "optional collaboration tools; otherwise sequential fallback"
|
|
11
|
+
"agent.spawn": "optional collaboration tools; otherwise sequential fallback",
|
|
12
|
+
"design.canvas": "not available; design skills write standalone HTML files",
|
|
13
|
+
"forge.pr": "runtime shell tool + the forge CLI (gh | glab) named by core-config collaboration.forge; op table in the pull-request skill"
|
|
14
|
+
},
|
|
15
|
+
"models": {
|
|
16
|
+
"frontier": "the most capable model the session can select; else the session model, recorded in the ledger",
|
|
17
|
+
"capable": "the session default model",
|
|
18
|
+
"cheap": "the smallest model the session can select; else the session model"
|
|
12
19
|
}
|
|
13
20
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github",
|
|
3
|
+
"term": "pull request",
|
|
4
|
+
"cli": "gh",
|
|
5
|
+
"ops": {
|
|
6
|
+
"auth": "gh auth status",
|
|
7
|
+
"pr_for_branch": "gh pr list --head {branch} --state all --json number,url,state,isDraft,headRefOid,mergedAt",
|
|
8
|
+
"pr_create_draft": "gh pr create --draft --base {base} --head {branch} --title {title} --body-file {body_file}",
|
|
9
|
+
"pr_view": "gh pr view {pr} --json number,url,state,isDraft,headRefOid,baseRefName",
|
|
10
|
+
"pr_update_body": "gh pr edit {pr} --body-file {body_file}",
|
|
11
|
+
"pr_ready": "gh pr ready {pr}",
|
|
12
|
+
"ci_status": "gh pr checks {pr}",
|
|
13
|
+
"ci_watch": "gh pr checks {pr} --watch --fail-fast"
|
|
14
|
+
},
|
|
15
|
+
"notes": {
|
|
16
|
+
"pr_for_branch": "An empty JSON array means no PR exists for the branch.",
|
|
17
|
+
"ci_status": "Exit code 0 = all checks passed, 8 = pending, 1 = at least one failed (gh 2.63).",
|
|
18
|
+
"protection": "Enforce on the base branch via rulesets: require a pull request, require status checks, require the branch to be up to date before merging."
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gitlab",
|
|
3
|
+
"term": "merge request",
|
|
4
|
+
"cli": "glab",
|
|
5
|
+
"ops": {
|
|
6
|
+
"auth": "glab auth status",
|
|
7
|
+
"pr_for_branch": "glab mr list --source-branch {branch} --all --output json",
|
|
8
|
+
"pr_create_draft": "glab mr create --draft --yes --source-branch {branch} --target-branch {base} --title {title} --description \"$(cat {body_file})\"",
|
|
9
|
+
"pr_view": "glab mr view {pr} --output json",
|
|
10
|
+
"pr_update_body": "glab mr update {pr} --description \"$(cat {body_file})\"",
|
|
11
|
+
"pr_ready": "glab mr update {pr} --ready",
|
|
12
|
+
"ci_status": "glab ci status --branch {branch} --compact",
|
|
13
|
+
"ci_watch": "glab ci status --branch {branch} --live"
|
|
14
|
+
},
|
|
15
|
+
"notes": {
|
|
16
|
+
"pr_for_branch": "An empty JSON array means no MR exists for the branch. The JSON carries state (opened | merged | closed), sha, and web_url.",
|
|
17
|
+
"ci_status": "Read the pipeline status word from the output (success | failed | running | pending); the exit code alone does not encode it in glab 1.50.",
|
|
18
|
+
"protection": "Enforce on the target branch: protected branch (no direct push), merge requests required, pipelines must succeed, and the merge method setting that requires the source to be up to date (fast-forward or semi-linear)."
|
|
19
|
+
}
|
|
20
|
+
}
|
package/bin/install.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copies skills into the runtime's skills dir + scaffolds knowledge/.
|
|
4
4
|
// No MCP, no license, no network calls. The hosted layer is a separate opt-in.
|
|
5
5
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
6
|
-
import { dirname, join } from "node:path";
|
|
6
|
+
import { delimiter, dirname, join } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
const PKG = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -45,6 +45,7 @@ What it does:
|
|
|
45
45
|
1. Copies the skills into your runtime's skills dir (default: .claude/skills/)
|
|
46
46
|
2. Scaffolds knowledge/ + core-config.yaml (never overwrites an existing brain)
|
|
47
47
|
3. Stamps <skills-dir>/.orchestrix-skills.json so upgrades and pruning are exact
|
|
48
|
+
4. Adds .orchestrate/ to .gitignore (once; ledger and verify logs are per-run state)
|
|
48
49
|
|
|
49
50
|
Hosted orchestration, knowledge hosting, and team features:
|
|
50
51
|
see https://orchestrix-mcp.youlidao.ai`);
|
|
@@ -115,6 +116,18 @@ function installSkills(dir, runtimeName, runtime) {
|
|
|
115
116
|
return { count: names.length, pruned };
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
// The ledger and verify logs are per-run, per-workspace state. Committed, they
|
|
120
|
+
// conflict on every PR in team mode, so the ignore line is written once and
|
|
121
|
+
// left alone if the project already has it.
|
|
122
|
+
function ignoreRuntimeDir(dir) {
|
|
123
|
+
const path = join(dir, ".gitignore");
|
|
124
|
+
const current = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
125
|
+
if (current.split("\n").some((line) => /^\.orchestrate\/?\s*$/.test(line))) return false;
|
|
126
|
+
const separator = current.length === 0 || current.endsWith("\n") ? "" : "\n";
|
|
127
|
+
writeFileSync(path, `${current}${separator}.orchestrate/\n`);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
118
131
|
function installRuntimeGuidance(dir, runtimeName) {
|
|
119
132
|
if (runtimeName !== "codex") return;
|
|
120
133
|
const source = join(PKG, "adapters", "codex", "AGENTS.md");
|
|
@@ -160,6 +173,37 @@ function nonemptyFile(path) {
|
|
|
160
173
|
return isFile(path) && readFileSync(path, "utf8").trim().length > 0;
|
|
161
174
|
}
|
|
162
175
|
|
|
176
|
+
// Team mode is opt-in: an uncommented `collaboration:` block in core-config.
|
|
177
|
+
// Returns the forge name it declares, or null when the block is absent.
|
|
178
|
+
function activeForge(configContent) {
|
|
179
|
+
const block = configContent.match(/^collaboration:\s*(?:#.*)?\n((?:[ \t]+.*\n?)*)/m);
|
|
180
|
+
if (!block) return null;
|
|
181
|
+
return block[1].match(/^[ \t]+forge:\s*([A-Za-z0-9_-]+)/m)?.[1] ?? "";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function forgeCli(forge) {
|
|
185
|
+
const path = join(PKG, "adapters", "forge", `${forge}.json`);
|
|
186
|
+
return isFile(path) ? JSON.parse(readFileSync(path, "utf8")).cli : null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function onPath(bin) {
|
|
190
|
+
const exts = process.platform === "win32" ? ["", ".exe", ".cmd"] : [""];
|
|
191
|
+
return (process.env.PATH ?? "").split(delimiter).some((dir) => dir && exts.some((ext) => isFile(join(dir, bin + ext))));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// The pull-request skill drives the forge through its CLI (gh | glab). Without
|
|
195
|
+
// it, builder runs stop at "push the branch, open the PR by hand" — better to
|
|
196
|
+
// hear that from install/doctor than mid-run.
|
|
197
|
+
function forgeCheck(configContent) {
|
|
198
|
+
const forge = activeForge(configContent);
|
|
199
|
+
if (forge === null) return null;
|
|
200
|
+
const cli = forgeCli(forge);
|
|
201
|
+
if (!cli) return { ok: false, detail: `collaboration.forge "${forge}" has no adapter (known: github, gitlab)` };
|
|
202
|
+
return onPath(cli)
|
|
203
|
+
? { ok: true, detail: `${cli} on PATH (collaboration.forge: ${forge})` }
|
|
204
|
+
: { ok: false, detail: `${cli} not on PATH — team mode needs it installed and logged in (collaboration.forge: ${forge})` };
|
|
205
|
+
}
|
|
206
|
+
|
|
163
207
|
function validSkill(path, runtimeName, expectedName) {
|
|
164
208
|
if (!nonemptyFile(path)) return false;
|
|
165
209
|
const content = readFileSync(path, "utf8");
|
|
@@ -203,6 +247,14 @@ function install() {
|
|
|
203
247
|
console.log("✓ core-config.yaml scaffolded");
|
|
204
248
|
}
|
|
205
249
|
|
|
250
|
+
// 4. Runtime dir — ledger + verify logs never belong in history.
|
|
251
|
+
if (ignoreRuntimeDir(dir)) console.log("✓ .orchestrate/ added to .gitignore");
|
|
252
|
+
else console.log("• .gitignore already ignores .orchestrate/");
|
|
253
|
+
|
|
254
|
+
// 5. Team mode, if the project turned it on: say now whether the forge CLI is there.
|
|
255
|
+
const forge = forgeCheck(nonemptyFile(cfgTarget) ? readFileSync(cfgTarget, "utf8") : "");
|
|
256
|
+
if (forge) console.log(`${forge.ok ? "✓" : "✗"} forge CLI: ${forge.detail}`);
|
|
257
|
+
|
|
206
258
|
if (ide === "cursor" || ide === "windsurf") {
|
|
207
259
|
console.log(`\nNote: ${ide} does not auto-load Anthropic skills yet — copied as reference rules.`);
|
|
208
260
|
}
|
|
@@ -234,6 +286,8 @@ function doctor() {
|
|
|
234
286
|
["core config valid", /(^|\n)knowledge:\s*(#.*)?\n/.test(configContent) && /(^|\n)work:\s*(#.*)?\n/.test(configContent), configPath],
|
|
235
287
|
["knowledge brain", isDirectory(join(dir, "knowledge")), join(dir, "knowledge")],
|
|
236
288
|
];
|
|
289
|
+
const forge = forgeCheck(configContent);
|
|
290
|
+
if (forge) checks.push(["forge CLI (team mode)", forge.ok, forge.detail]);
|
|
237
291
|
if (ide === "codex") {
|
|
238
292
|
const reference = join(dir, ".codex", "orchestrix", "AGENTS.md");
|
|
239
293
|
const rootInstructions = join(dir, "AGENTS.md");
|
package/package.json
CHANGED
|
@@ -18,6 +18,20 @@ work: # work products — skills WRITE these (outputs:), humans review at gates
|
|
|
18
18
|
# here for transparency only.
|
|
19
19
|
runtime: .orchestrate # ledger + verify logs (ephemeral, gitignored)
|
|
20
20
|
|
|
21
|
+
# Team mode (opt-in). Uncomment to make orchestrate run each story on its own
|
|
22
|
+
# branch in its own workspace and end builder runs with a PR/MR instead of a
|
|
23
|
+
# local commit. Absent = solo behaviour, unchanged. See the orchestrate skill,
|
|
24
|
+
# "Collaboration".
|
|
25
|
+
#
|
|
26
|
+
# collaboration:
|
|
27
|
+
# forge: github # github | gitlab
|
|
28
|
+
# base: main
|
|
29
|
+
# branch: story/{origin}/{slug}
|
|
30
|
+
# plan_branch: plan/{origin}
|
|
31
|
+
# workspace: worktree # worktree (same machine) | in-place (a clone elsewhere)
|
|
32
|
+
# pr:
|
|
33
|
+
# reviewers: []
|
|
34
|
+
|
|
21
35
|
# Org-level cascade (shared taste/standards across many products) is intentionally
|
|
22
36
|
# NOT enabled yet (YAGNI). When needed: add an `extends:` base that project paths
|
|
23
37
|
# override. The logical namespaces above do not change when cascade is added.
|
package/skills/README.md
CHANGED
|
@@ -18,6 +18,11 @@ Runtime-neutral capability requirements live under
|
|
|
18
18
|
Adapters map those names to runtime tools. Runtime-specific tool names are not
|
|
19
19
|
part of the orchestration contract.
|
|
20
20
|
|
|
21
|
+
`metadata.requires.model` declares the model tier a skill needs —
|
|
22
|
+
`frontier` (judgment: design, review, planning), `capable` (implementation),
|
|
23
|
+
or `cheap` (mechanical). Adapters map tiers to models under `models` in
|
|
24
|
+
`runtime.json`; the orchestrator states the resolved model on every dispatch.
|
|
25
|
+
|
|
21
26
|
### The contract (6 fields)
|
|
22
27
|
|
|
23
28
|
| Field | Meaning |
|
|
@@ -54,9 +59,9 @@ are different gates; never merge them.
|
|
|
54
59
|
intent
|
|
55
60
|
└─ orchestrate (root: warm context, wires skills by output→input, enforces gates)
|
|
56
61
|
├─ brainstorm ──(needs facts?)─→ research
|
|
57
|
-
├─ (has UI?) ──→ design-system (once) → design-ui
|
|
62
|
+
├─ (has UI?) ──→ design-directions (human picks a rendered direction) → design-system (once) → design-ui
|
|
58
63
|
├─ (arch decision?) ──→ design-architecture
|
|
59
|
-
└─ draft-story → implement → run-tests → review-code → commit
|
|
64
|
+
└─ draft-story → implement → run-tests → review-code → commit ──(team mode)─→ pull-request
|
|
60
65
|
↑ verify ↑ design-review (UI only)
|
|
61
66
|
(objective) ↑ accept (batched)
|
|
62
67
|
```
|
|
@@ -71,6 +76,7 @@ Human gates are front-loaded (planning = direction) and at the very end
|
|
|
71
76
|
| `orchestrate` | root | inline (delivery) |
|
|
72
77
|
| `brainstorm` | planning | inline (hard gate) |
|
|
73
78
|
| `research` | planning (optional) | never |
|
|
79
|
+
| `design-directions` | planning (UI, once) | inline |
|
|
74
80
|
| `design-system` | planning (UI, once) | inline |
|
|
75
81
|
| `design-ui` | planning (UI only) | inline |
|
|
76
82
|
| `design-architecture` | planning (when needed) | inline |
|
|
@@ -80,6 +86,7 @@ Human gates are front-loaded (planning = direction) and at the very end
|
|
|
80
86
|
| `review-code` | build | deferred |
|
|
81
87
|
| `design-review` | build (UI only) | deferred |
|
|
82
88
|
| `commit` | build | deferred |
|
|
89
|
+
| `pull-request` | build (team mode) | inline (first open) |
|
|
83
90
|
|
|
84
91
|
## Attribution
|
|
85
92
|
|
|
@@ -6,6 +6,7 @@ allowed-tools: [Read, Write, Grep, Glob]
|
|
|
6
6
|
metadata:
|
|
7
7
|
requires:
|
|
8
8
|
capabilities: [filesystem.read, filesystem.write]
|
|
9
|
+
model: frontier
|
|
9
10
|
contract:
|
|
10
11
|
inputs: [intent, project_context]
|
|
11
12
|
reads: [taste/*, architecture/*, registry/*]
|
|
@@ -75,6 +76,8 @@ origin: <stable short handle of this intent>
|
|
|
75
76
|
## Downstream — flags for the orchestrator:
|
|
76
77
|
|
|
77
78
|
- needs UI design? yes/no (→ design-ui)
|
|
79
|
+
- key screens (UI only): the 2–3 screens that carry the product, one line each
|
|
80
|
+
(→ design-directions renders these first)
|
|
78
81
|
- needs an architecture decision? yes/no (→ design-architecture)
|
|
79
82
|
- open question needing facts? yes/no (→ research)
|
|
80
83
|
|
package/skills/commit/SKILL.md
CHANGED
package/skills/deploy/SKILL.md
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-directions
|
|
3
|
+
description: Use when a product has a UI but no settled visual direction — renders 2–4 genuinely different low-fidelity directions of the key screens so the human picks one they can SEE, before any design system is written.
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: [Read, Write, Bash, Grep, Glob, Skill]
|
|
6
|
+
metadata:
|
|
7
|
+
requires:
|
|
8
|
+
capabilities: [filesystem.read, filesystem.write, shell.execute, "design.canvas?"]
|
|
9
|
+
model: frontier
|
|
10
|
+
contract:
|
|
11
|
+
inputs: [product_context, key_screens, "references?", "direction_feedback?"]
|
|
12
|
+
reads: [taste/brand, taste/design-system, registry/*]
|
|
13
|
+
outputs: [design_directions]
|
|
14
|
+
authority: "Write design assets under the specs namespace (default docs/specs/design/directions/). No source code, no production. Never publish or share externally — the orchestrator shows the artboards at the gate."
|
|
15
|
+
verify: "2–4 directions, each named by the axis it explores; every direction renders every key screen; every artboard passes the canvas check command (or is a standalone HTML file that opens from disk); directions.md gives every direction a motivation and a tradeoff."
|
|
16
|
+
accept:
|
|
17
|
+
when: "Always — the human picks a direction by looking at rendered screens, never by reading tokens."
|
|
18
|
+
timing: inline
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Design Directions
|
|
22
|
+
|
|
23
|
+
Settle the visual direction with the human, not for them. People react to a
|
|
24
|
+
rendered screen; they do not react to a typeface name or a hex value. So the
|
|
25
|
+
first thing a human sees of a new product's look is 2–4 low-fidelity screens
|
|
26
|
+
they can compare — and the direction they pick is what `design-system` then
|
|
27
|
+
codifies.
|
|
28
|
+
|
|
29
|
+
**Posture:** Senior product designer running a direction review. Breadth over
|
|
30
|
+
polish. Every option gets an honest case; a set where only your favorite is
|
|
31
|
+
argued for is a rigged vote.
|
|
32
|
+
|
|
33
|
+
## Precondition — skip when the direction is already settled
|
|
34
|
+
|
|
35
|
+
Do not explore what is already decided. Return `skipped` with a one-line
|
|
36
|
+
reason when either holds:
|
|
37
|
+
|
|
38
|
+
- `taste/design-system` is populated (a real system, not the unedited seed).
|
|
39
|
+
- `registry/*` shows an existing UI in the repo. Its look is the direction;
|
|
40
|
+
`design-system` extracts it from source.
|
|
41
|
+
|
|
42
|
+
## Inputs
|
|
43
|
+
|
|
44
|
+
- `product_context` — the approved spec from `brainstorm` (goal, requirement,
|
|
45
|
+
constraints).
|
|
46
|
+
- `key_screens` — the 2–3 screens that carry the product, from the spec's
|
|
47
|
+
`Downstream` section. If the spec lists none, derive them from the
|
|
48
|
+
requirement and name them at the top of `directions.md`. Never more than 3.
|
|
49
|
+
- `references?` — products, brands, or assets the human named.
|
|
50
|
+
- `direction_feedback?` — present on re-dispatch when the human rejected every
|
|
51
|
+
direction. Read it first; the new set must answer it.
|
|
52
|
+
|
|
53
|
+
## Process
|
|
54
|
+
|
|
55
|
+
1. **Read the signal.** `taste/brand`, references, and the product context.
|
|
56
|
+
What is the product for, and for whom? Which tone does the brief imply
|
|
57
|
+
(internal tool → utilitarian; consumer → expressive)?
|
|
58
|
+
2. **Name 2–4 directions, each on a named axis.** An axis is a real choice:
|
|
59
|
+
density (dense vs airy), type personality (editorial serif vs geometric
|
|
60
|
+
sans vs mono), color stance (one accent on neutral vs tonal), tone (quiet
|
|
61
|
+
vs bold). Two directions that differ only in shade are one direction —
|
|
62
|
+
replace one.
|
|
63
|
+
3. **Sketch every key screen in every direction, low-fi.** Structure,
|
|
64
|
+
hierarchy, a type pairing, one accent, real layout. Real copy where the
|
|
65
|
+
brief supplies it; a bracketed placeholder like `[price]` where it does
|
|
66
|
+
not. No filler sections, no emoji as icons, no fake device chrome. Low-fi
|
|
67
|
+
means decision fidelity, not deliverable fidelity — enough to choose, not
|
|
68
|
+
enough to ship.
|
|
69
|
+
4. **Author the artboards.**
|
|
70
|
+
- With `design.canvas`: one artboard per direction × screen, named
|
|
71
|
+
`<Direction>-<Screen>.dc.html`, plus a `canvas.json` that lays each
|
|
72
|
+
direction out as one row. `Main.dc.html` is the leading candidate's
|
|
73
|
+
first screen. Follow the runtime's design skill for the file format and
|
|
74
|
+
run its check command; its output is the verify evidence.
|
|
75
|
+
- Without it: one standalone `<Direction>-<Screen>.html` per artboard,
|
|
76
|
+
self-contained (inline CSS, no external assets except Google Fonts), and
|
|
77
|
+
an `index.html` that links every file under its direction name. Each
|
|
78
|
+
must open from disk.
|
|
79
|
+
5. **Write `directions.md`.** For each direction: name, the axis it explores,
|
|
80
|
+
the motivation (why it fits this product), and its main tradeoff (what it
|
|
81
|
+
costs). One paragraph each. End with the key screens list.
|
|
82
|
+
|
|
83
|
+
## Anti-slop
|
|
84
|
+
|
|
85
|
+
The canonical list lives in the `design-system` skill. A direction that lands
|
|
86
|
+
on one of those defaults is allowed only as a stated, justified choice — and
|
|
87
|
+
never as two of the 2–4.
|
|
88
|
+
|
|
89
|
+
## Output: `specs/design/directions/`
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
directions.md # name, axis, motivation, tradeoff per direction
|
|
93
|
+
canvas.json # with design.canvas only
|
|
94
|
+
<Direction>-<Screen>.dc.html # with design.canvas
|
|
95
|
+
<Direction>-<Screen>.html + index.html # without it
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Done
|
|
99
|
+
|
|
100
|
+
Write the files, run the check, then stop (`accept: inline`). The
|
|
101
|
+
orchestrator puts the rendered artboards in front of the human and records
|
|
102
|
+
their pick as `chosen_direction`. Never pick for them. If they reject every
|
|
103
|
+
direction, you are re-dispatched with `direction_feedback` — same skill, new
|
|
104
|
+
set.
|
|
@@ -6,8 +6,9 @@ allowed-tools: [Read, Bash, Grep, Glob]
|
|
|
6
6
|
metadata:
|
|
7
7
|
requires:
|
|
8
8
|
capabilities: [filesystem.read, shell.execute]
|
|
9
|
+
model: frontier
|
|
9
10
|
contract:
|
|
10
|
-
inputs: [built_ui, ui_spec, "screenshots?"]
|
|
11
|
+
inputs: [built_ui, ui_spec, "ui_artboards?", "screenshots?"]
|
|
11
12
|
reads: [taste/design-system, taste/brand]
|
|
12
13
|
outputs: [design_review_report]
|
|
13
14
|
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."
|
|
@@ -42,6 +43,10 @@ clean one.
|
|
|
42
43
|
- `built_ui` — the running app (a live URL, or a dev server this skill starts).
|
|
43
44
|
- `ui_spec` — `specs/<slug>-ui.md` it must satisfy, including its declared
|
|
44
45
|
**treatment** (`utility` / `product` / `editorial`).
|
|
46
|
+
- `ui_artboards?` — the artboards the human approved at the `design-ui` gate
|
|
47
|
+
(`specs/design/<slug>/`). They are the visual bar for Verdict 3: a built
|
|
48
|
+
screen that departs from its approved artboard in hierarchy, spacing, or
|
|
49
|
+
treatment is a finding, at the same severity as a deviation from the system.
|
|
45
50
|
- `screenshots?` — captures a prior `smoke-test` already took. Use them instead
|
|
46
51
|
of relaunching the app for the same screen.
|
|
47
52
|
- Read `taste/design-system` + `taste/brand` — the bar to calibrate against.
|