orchestrix-skills 0.7.0 → 0.9.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.
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "orchestrix-skills",
3
- "version": "0.7.0",
3
+ "version": "0.9.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",
7
7
  "license": "MIT",
8
- "keywords": ["orchestrix", "skills", "ai-development", "orchestration"],
8
+ "keywords": [
9
+ "orchestrix",
10
+ "skills",
11
+ "ai-development",
12
+ "orchestration"
13
+ ],
9
14
  "skills": "./skills"
10
15
  }
package/README.md CHANGED
@@ -6,8 +6,8 @@ contract-bearing skills from intent to commit — with independent verification
6
6
  that never trusts the model's self-report.
7
7
 
8
8
  Open source (MIT). The skills run in any runtime that loads Anthropic skills
9
- (Claude Code, Claude apps, Agent SDK). The hosted orchestrator, knowledge
10
- hosting, and team features are the premium layer — see below.
9
+ (Claude Code, Claude apps, Agent SDK). You run them in your own runtime with your
10
+ own API key: no server, no license, no telemetry.
11
11
 
12
12
  ## The graph
13
13
 
@@ -29,42 +29,85 @@ intent
29
29
  Human gates are front-loaded (planning = direction) and at the end (acceptance);
30
30
  the build loop runs lights-out, gated only by objective `verify`.
31
31
 
32
- ## Install (free, no license)
32
+ ## Install
33
33
 
34
34
  ```bash
35
- npx orchestrix-skills install # default: Claude Code (.claude/skills/)
35
+ npx orchestrix-skills install # default: Claude Code (.claude/skills/)
36
36
  npx orchestrix-skills install --ide codex # Codex (.codex/skills/ + AGENTS.md)
37
37
  npx orchestrix-skills install --ide cursor
38
38
  npx orchestrix-skills doctor --ide codex # validate an installation
39
39
  ```
40
40
 
41
41
  This copies the skills into your runtime's skills dir and scaffolds `knowledge/`
42
- + `core-config.yaml` (it never overwrites an existing `knowledge/` — that's your
43
- brain). Then use the `orchestrate` skill. You run it in your own runtime with
44
- your own API key. No server, no license.
42
+ + `core-config.yaml` (it never overwrites an existing `knowledge/` — that is your
43
+ brain). Then use the `orchestrate` skill.
45
44
 
46
- For Claude Code you can also install via the plugin marketplace:
45
+ For Claude Code you can also install from the plugin marketplace:
47
46
  `/plugin install orchestrix-skills`.
48
47
 
48
+ ### Upgrading, and how hosts automate it
49
+
50
+ Re-running `install` refreshes the skills in place. It also writes a stamp at
51
+ `<skills-dir>/.orchestrix-skills.json`:
52
+
53
+ ```json
54
+ { "version": "0.8.0", "ide": "claude", "skills": ["brainstorm", "commit", "…"] }
55
+ ```
56
+
57
+ Two things read it. The installer prunes skills a previous version placed that
58
+ the package no longer ships — and only those names, so a skill you or your
59
+ platform installed alongside them is never touched. And a host that provisions
60
+ projects can compare `version` against the npm dist-tag to decide whether to
61
+ reinstall, instead of maintaining its own version constant that silently drifts.
62
+
63
+ The stamp is written last: a run that dies mid-copy leaves the older stamp
64
+ behind, so the next run still sees a mismatch and reinstalls rather than
65
+ declaring itself current.
66
+
67
+ ## What `orchestrate` guarantees
68
+
69
+ The root skill is where the interesting engineering lives. Beyond wiring:
70
+
71
+ - **Verification is executable.** Each step's `verify` must be proven by a real
72
+ command the orchestrator runs itself, with the command, exit code, and output
73
+ tail captured to `.orchestrate/verify/step-<n>-attempt-<k>.log`. A subagent's
74
+ own success report is not evidence.
75
+ - **State lives outside the context window.** Every run appends to
76
+ `.orchestrate/ledger.jsonl` (`run_start` / `plan` / `step` / `gate` /
77
+ `run_end`). The ledger is the run's durable memory, not the conversation.
78
+ - **Cold re-entry is deterministic.** After compaction, an interruption, or a
79
+ wake-up, the orchestrator replays the ledger instead of trusting recall. A
80
+ step left dangling at `dispatched` is trusted in neither direction: its verify
81
+ command is re-run to decide whether it completed.
82
+ - **Rework is bounded.** A failed verify re-dispatches the same skill with the
83
+ failure as input — capped at 3 attempts, and a failure whose cause is not
84
+ understood goes to `investigate` first, so the retry aims at a mechanism
85
+ rather than re-rolling the dice.
86
+ - **Accept gates are enforced by authority, not by declaration.** A skill that
87
+ spends, sends, deploys, deletes, or signs is escalated to an inline human gate
88
+ even if it asked for a deferred one.
89
+ - **Two rules are hard-wired** because output→input matching structurally cannot
90
+ reach them: `smoke-test` is the acceptance floor for a runnable app the run
91
+ changed, and `design-system` precedes `design-ui`.
92
+
49
93
  ## Runtime adapters
50
94
 
51
95
  `skills/` is the runtime-neutral source of truth. `adapters/` describes how a
52
96
  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
97
+ removes Claude-only `allowed-tools`, preserves the contract, and adds Codex
98
+ runtime guidance. If the target has an unmanaged `AGENTS.md`, its content is left
99
+ untouched and the guidance is placed at `.codex/orchestrix/AGENTS.md` for manual
100
+ merging. Installer-created guidance uses a marked block, so later installs
101
+ refresh that block while preserving surrounding user instructions.
102
+
103
+ `doctor` validates every installed skill's required frontmatter, the Codex
61
104
  transformation, configuration shape, knowledge directory, and active root
62
105
  guidance. A reference file that has not been merged into an existing root
63
106
  `AGENTS.md` is reported as unhealthy rather than silently treated as active.
64
107
 
65
108
  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.
109
+ runs leaf skills sequentially. Cursor and Windsurf remain reference-rule installs
110
+ until those runtimes provide native compatible skill execution.
68
111
 
69
112
  ## How it works
70
113
 
@@ -75,19 +118,15 @@ installs until those runtimes provide native compatible skill execution.
75
118
  verify. See `skills/README.md`.
76
119
  - **Two zones in your project:** `knowledge/` (the brain skills read — AI-primary,
77
120
  structured, with provenance) and `docs/` + `src/` (work products and the
78
- deliverable). `core-config.yaml` maps logical namespaces to physical paths.
79
-
80
- ## Premium (hosted)
81
-
82
- The skills are free and open. The hosted layer is where the work runs for you:
83
- the orchestrator-as-a-service, knowledge hosting + metabolism, team sync, and the
84
- transparent AI software company ("建造中心"). See
85
- [orchestrix-mcp.youlidao.ai](https://orchestrix-mcp.youlidao.ai).
121
+ deliverable). `core-config.yaml` maps logical namespaces to physical paths, so
122
+ a project keeps its brain wherever it already lives.
86
123
 
87
- ## Design
124
+ ## Hosted
88
125
 
89
- Full design rationale: `Skill 编排器与最小契约设计` (the capability-first model,
90
- the 6-field contract, lights-out accept gates, the knowledge KB, distribution).
126
+ A hosted layer orchestrator-as-a-service, knowledge hosting, and team features
127
+ is available separately at
128
+ [orchestrix-mcp.youlidao.ai](https://orchestrix-mcp.youlidao.ai). Nothing in this
129
+ package requires it or talks to it.
91
130
 
92
131
  ## Attribution
93
132
 
package/bin/install.js CHANGED
@@ -1,14 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  // orchestrix-skills installer — zero dependencies.
3
- // Free path: copy skills into the runtime's skills dir + scaffold knowledge/.
4
- // No MCP, no license. Premium (hosted orchestrator / KB / 建造中心) is a separate opt-in.
5
- import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
3
+ // Copies skills into the runtime's skills dir + scaffolds knowledge/.
4
+ // No MCP, no license, no network calls. The hosted layer is a separate opt-in.
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
10
  const MANAGED_START = "<!-- orchestrix:start -->";
11
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";
12
17
 
13
18
  // Where each runtime auto-loads skills from (relative to the target project).
14
19
  function adapter(name) {
@@ -36,11 +41,12 @@ Usage:
36
41
  npx orchestrix-skills install [--ide claude|codex|cursor|windsurf] [--dir <project>]
37
42
  npx orchestrix-skills doctor [--ide claude|codex|cursor|windsurf] [--dir <project>]
38
43
 
39
- What it does (free, no license):
44
+ What it does:
40
45
  1. Copies the skills into your runtime's skills dir (default: .claude/skills/)
41
46
  2. Scaffolds knowledge/ + core-config.yaml (never overwrites an existing brain)
47
+ 3. Stamps <skills-dir>/.orchestrix-skills.json so upgrades and pruning are exact
42
48
 
43
- Premium (hosted orchestrator, KB hosting, teams, 建造中心):
49
+ Hosted orchestration, knowledge hosting, and team features:
44
50
  see https://orchestrix-mcp.youlidao.ai`);
45
51
  }
46
52
 
@@ -54,9 +60,22 @@ function transformSkill(source, runtime) {
54
60
  );
55
61
  }
56
62
 
63
+ function packageVersion() {
64
+ return JSON.parse(readFileSync(join(PKG, "package.json"), "utf8")).version;
65
+ }
66
+
67
+ function readStamp(target) {
68
+ try {
69
+ return JSON.parse(readFileSync(join(target, STAMP), "utf8"));
70
+ } catch {
71
+ return null; // absent, or written by a version that predates stamping
72
+ }
73
+ }
74
+
57
75
  function installSkills(dir, runtimeName, runtime) {
58
76
  const target = join(dir, runtime.skillsDir);
59
77
  mkdirSync(target, { recursive: true });
78
+ const previous = readStamp(target);
60
79
  const entries = readdirSync(join(PKG, "skills"), { withFileTypes: true });
61
80
  for (const entry of entries) {
62
81
  const source = join(PKG, "skills", entry.name);
@@ -74,7 +93,26 @@ function installSkills(dir, runtimeName, runtime) {
74
93
  }
75
94
  }
76
95
  }
77
- return entries.filter((entry) => entry.isDirectory()).length;
96
+
97
+ const names = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
98
+ // Retire skills a PREVIOUS install of this package placed that it no longer
99
+ // ships. Only names recorded in our own stamp are candidates, so a skill the
100
+ // project or its host installed alongside ours is never touched.
101
+ let pruned = 0;
102
+ for (const name of previous?.skills ?? []) {
103
+ if (names.includes(name)) continue;
104
+ const stale = join(target, name);
105
+ if (!isDirectory(stale)) continue;
106
+ rmSync(stale, { recursive: true, force: true });
107
+ pruned += 1;
108
+ }
109
+ // Stamp LAST: a crash mid-copy leaves the older stamp in place, so the next
110
+ // run still sees a mismatch and reinstalls rather than declaring itself current.
111
+ writeFileSync(
112
+ join(target, STAMP),
113
+ `${JSON.stringify({ version: packageVersion(), ide: runtimeName, skills: names }, null, 2)}\n`,
114
+ );
115
+ return { count: names.length, pruned };
78
116
  }
79
117
 
80
118
  function installRuntimeGuidance(dir, runtimeName) {
@@ -142,8 +180,9 @@ function install() {
142
180
  }
143
181
 
144
182
  // 1. Skills (capabilities) — always refreshed.
145
- const count = installSkills(dir, ide, runtime);
146
- console.log(`✓ ${count} skills → ${runtime.skillsDir}/`);
183
+ const { count, pruned } = installSkills(dir, ide, runtime);
184
+ console.log(`✓ ${count} skills → ${runtime.skillsDir}/ (v${packageVersion()})`);
185
+ if (pruned > 0) console.log(`✓ ${pruned} retired skill(s) removed`);
147
186
  installRuntimeGuidance(dir, ide);
148
187
 
149
188
  // 2. Knowledge (the brain) — scaffold only if absent; never clobber the user's brain.
@@ -167,7 +206,7 @@ function install() {
167
206
  if (ide === "cursor" || ide === "windsurf") {
168
207
  console.log(`\nNote: ${ide} does not auto-load Anthropic skills yet — copied as reference rules.`);
169
208
  }
170
- console.log(`\nDone. Start with the "orchestrate" skill. Premium hosting: https://orchestrix-mcp.youlidao.ai`);
209
+ console.log(`\nDone. Start with the "orchestrate" skill.`);
171
210
  }
172
211
 
173
212
  function doctor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrix-skills",
3
- "version": "0.7.0",
3
+ "version": "0.9.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": {
@@ -4,8 +4,6 @@ What the framework installs into a **target project** (the thing being built)
4
4
  not the framework's own content. Skills (capabilities) arrive separately via MCP
5
5
  or `.orchestrix/`; this scaffold is the project's durable knowledge + config.
6
6
 
7
- Maps to the design doc `cc-plans/Skill编排器与最小契约设计-v0.1.md` §10.
8
-
9
7
  ```
10
8
  <project>/
11
9
  ├── knowledge/ # the brain — what skills READ (reads:). AI-primary, human-audited.
package/skills/README.md CHANGED
@@ -4,8 +4,6 @@ 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
5
5
  matching one skill's `outputs` to another's `inputs`.
6
6
 
7
- Design source of truth: `cc-plans/Skill编排器与最小契约设计-v0.1.md`.
8
-
9
7
  ## Format
10
8
 
11
9
  Every skill is a standard [Anthropic Agent Skill](https://agentskills.io/specification)
@@ -37,22 +37,28 @@ Record verified work as one conventional commit.
37
37
  secrets, no `.env*`.
38
38
  4. Commit with the message format below.
39
39
 
40
- ## Message format (required)
40
+ ## Message format
41
41
 
42
- A conventional-commit subject, then the mandatory footer, exactly:
42
+ A conventional-commit subject, optional body, and whatever trailer this project
43
+ requires:
43
44
 
44
45
  ```
45
46
  <type>(<scope>): <summary>
46
47
 
47
48
  <optional body>
48
49
 
49
- 🤖 Generated with [Orchestrix](https://orchestrix-mcp.youlidao.ai)
50
+ <project-required trailer, if any>
50
51
  ```
51
52
 
52
53
  - `<type>`: feat | fix | refactor | docs | test | chore | …
53
- - **The footer line is mandatory and exact.** A commit hook rejects commits
54
- without it.
55
- - **Never** add `Co-Authored-By` or a "Claude Code" footer.
54
+ - **The project decides the trailer, and it is binding.** Look for a required
55
+ commit trailer in `CLAUDE.md` / `AGENTS.md` / contributing docs / a commit
56
+ hook, and reproduce it EXACTLY a hook that enforces one will reject the
57
+ commit otherwise, and a near-miss costs a rewrite. If the project defines
58
+ none, write no trailer.
59
+ - **Never invent a trailer**, and never add `Co-Authored-By` or a tool-attribution
60
+ footer the project did not ask for. Whose name ends up in a project's history
61
+ is the project's call, not this skill's.
56
62
 
57
63
  ## Done
58
64
 
@@ -4,7 +4,7 @@ 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: 5
7
+ version: 6
8
8
  requires:
9
9
  capabilities: [filesystem.read, filesystem.write, shell.execute, "agent.spawn?"]
10
10
  contract:
@@ -36,9 +36,10 @@ no step above intent.
36
36
  1. **Bind intent.** Read the human's goal and constraints. This is the only
37
37
  place intent enters. Then run the first-run preflight (below) before any
38
38
  wiring.
39
- 2. **Select.** Read the skill registry. Pick skills by their `description`
40
- (when-to-use). Load a skill's full `contract` only when it is a candidate —
41
- never load every contract at once.
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.
42
43
  3. **Wire (emergent, not hardcoded).** Build the path by matching one skill's
43
44
  `outputs` to the next skill's `inputs`. Skills do not know each other; only
44
45
  you do. Do not assume a fixed pipeline — wire what this intent needs.
@@ -68,8 +69,12 @@ no step above intent.
68
69
  6. **Accept (gate).** Apply the rule below. Then continue — do not pause to ask
69
70
  "should I keep going?" mid-run.
70
71
  7. **Repeat** 3–6 until the intent is fulfilled.
71
- 8. **Final acceptance.** Present the batched deferred accepts and a final review
72
- to the human, once. Apply corrections (see Metabolism), then deliver.
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.
73
78
 
74
79
  ## Namespace resolution (`core-config.yaml`)
75
80
 
@@ -114,6 +119,27 @@ resolved paths):
114
119
 
115
120
  Both checks are per-run and idempotent: a populated brain makes them no-ops.
116
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
+
117
143
  ## Accept gate
118
144
 
119
145
  | Skill's `accept.timing` | Skill's `authority` | Action |
@@ -141,8 +167,9 @@ aimed at a symptom re-rolls the dice.
141
167
  STOP the run — do not burn a 4th attempt. Write a `gate` event to the ledger
142
168
  (`{"e":"gate","kind":"rework_exhausted","question":"step <n> (<skill>) failed 3
143
169
  attempts: <one-line why>"}`), summarize the three failures for the human, and
144
- report AWAIT. A step that cannot pass its own verify after three tries needs a
145
- human decision (wrong approach, wrong spec, or wrong verify), not more tokens.
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.
146
173
 
147
174
  ## Metabolism — governed writeback
148
175
 
@@ -181,13 +208,18 @@ platform renders it as live progress). It is append-only JSONL: one JSON event
181
208
  per line, appended with `Bash` (`echo '<json>' >> .orchestrate/ledger.jsonl`).
182
209
  Never rewrite or delete lines. Timestamps: `date -u +%FT%TZ`.
183
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
+
184
216
  Events and when to write them:
185
217
 
186
218
  | Event | When | Shape |
187
219
  | ----- | ---- | ----- |
188
220
  | `run_start` | right after binding intent | `{"e":"run_start","run":"r-<yyyymmdd>-<slug>","intent":"...","ts":"..."}` |
189
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 |
190
- | `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) |
191
223
  | `gate` | when stopping at a human gate | `{"e":"gate","run":"...","kind":"inline_accept","question":"...","ts":"..."}` |
192
224
  | `run_end` | at delivery or abandonment | `{"e":"run_end","run":"...","result":"delivered\|paused\|abandoned","ts":"..."}` |
193
225
 
@@ -196,6 +228,24 @@ step is required and should be the step's verify log path
196
228
  (`.orchestrate/verify/step-<n>-attempt-<k>.log`); a `done` with no evidence is
197
229
  a false claim.
198
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
+
199
249
  ## Context discipline (stay lean)
200
250
 
201
251
  - **Files, not paste.** Move artifacts between steps as files. Never paste a
@@ -211,6 +261,8 @@ a false claim.
211
261
  - Hardcoding a fixed skill order instead of wiring outputs→inputs
212
262
  - Pasting a step's full output into your context instead of handing a file
213
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
214
266
  - Dispatching a step without first writing its `dispatched` ledger line
215
267
  - Ending a run without a `run_end` ledger line
216
268
  - Marking a step done on the subagent's say-so, without your own verify command
@@ -219,4 +271,7 @@ a false claim.
219
271
  - Appending to `taste/*` without reading it first (duplicate/contradiction risk)
220
272
  - Dispatching a design/build skill in an existing codebase while `registry/*`
221
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
222
277
  - Marking the run complete without every step's `verify` evidence