@lemoncode/lemony 0.5.1 → 0.6.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/README.md +17 -16
- package/catalog/VERSION +1 -1
- package/catalog/agents/implementer.md +36 -1
- package/catalog/agents/orchestrator.md +206 -83
- package/catalog/agents/reviewer.md +8 -3
- package/catalog/agents/spinoff.md +3 -2
- package/catalog/agents/ui-design.md +3 -1
- package/catalog/agents/ui-designer.md +6 -3
- package/catalog/commands/pause.md +50 -5
- package/catalog/commands/resume.md +13 -2
- package/catalog/commands/spinoff.md +5 -3
- package/catalog/commands/sync-design-tokens.md +3 -1
- package/catalog/harness.config.schema.json +4 -0
- package/catalog/hooks/init.sh +60 -9
- package/catalog/hooks/lib/live-branch.sh +37 -0
- package/catalog/hooks/lib/merge-pr.sh +14 -4
- package/catalog/hooks/session-close.sh +26 -7
- package/catalog/schemas/tier2-events-history.md +33 -2
- package/catalog/schemas/tier2-events.md +30 -22
- package/catalog/skills/build-ui/SKILL.md +5 -2
- package/catalog/skills/design-tool-sync/SKILL.md +15 -7
- package/catalog/skills/grill-ui/SKILL.md +4 -1
- package/catalog/skills/grill-ui/ui-handoff-format.md +2 -1
- package/catalog/skills/mutation-testing/SKILL.md +22 -8
- package/catalog/skills/prd-to-spec/SKILL.md +27 -5
- package/catalog/skills/review-pr/SKILL.md +7 -1
- package/catalog/skills/review-pr/reference.md +3 -2
- package/catalog/templates/claude-code/agents.md.tpl +2 -1
- package/catalog/templates/claude-code/harness.config.yml.tpl +8 -2
- package/dist/cli.mjs +1694 -513
- package/package.json +11 -10
|
@@ -20,6 +20,11 @@ ahead. That asymmetry shapes everything here:
|
|
|
20
20
|
- **drift** is one-directional and deterministic: "has the JSON changed since the last
|
|
21
21
|
export?" — a pure-JSON check that needs no tool connection.
|
|
22
22
|
|
|
23
|
+
**Which file.** `docs/design-tokens.json` is the default path. When `harness.config.yml` sets
|
|
24
|
+
`design_tokens.file`, the path it names (relative to the repository root) is the token file:
|
|
25
|
+
read the binding from it and expect the CLI's import and export to act on it, wherever this
|
|
26
|
+
skill says `docs/design-tokens.json`. Never create a second file at the default.
|
|
27
|
+
|
|
23
28
|
You are invoked two ways: by `/sync-design-tokens` (the human's explicit handle, argument
|
|
24
29
|
`import` or `export`), and at DEFINE when the drift check shows an export is pending and the
|
|
25
30
|
current user has the tool connected.
|
|
@@ -80,10 +85,11 @@ variables and the DTCG JSON:
|
|
|
80
85
|
|
|
81
86
|
The CLI maps this to the 3-tier DTCG model: `ref` → an alias `{path}`, `modes` →
|
|
82
87
|
`$extensions["com.lemony.modes"]`, and the tier follows the path. A name without a tier
|
|
83
|
-
lands on the one tier `docs/design-tokens.json` already has it in; otherwise a
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
lands on the one tier `docs/design-tokens.json` already has it in; otherwise a variable that
|
|
89
|
+
is literal in every mode defaults to `primitive`, and one that is an alias in its base value
|
|
90
|
+
or any mode to `semantic` (a primitive is literal in every mode). A bare `ref` — or a bare
|
|
91
|
+
`{alias}` mode value — resolves to the tiered path its target lands at in the same neutral
|
|
92
|
+
file, or to the one tier the token file has it in.
|
|
87
93
|
|
|
88
94
|
## import — tool → JSON
|
|
89
95
|
|
|
@@ -109,9 +115,11 @@ one tier the token file has it in.
|
|
|
109
115
|
`primitive` target is neither in the file nor in the slice: add the target to the same
|
|
110
116
|
`--only`, or fix the file first. When the neutral file does not carry the target at
|
|
111
117
|
all, the refusal says so: create it in the tool first, or leave out what references
|
|
112
|
-
it.
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
it. A fault no slice fixes, such as a `primitive` that aliases, is named the same way:
|
|
119
|
+
fix that variable in the tool, or leave it out. An `--only` path no variable lands at
|
|
120
|
+
is refused rather than skipped. A refusal prints the preview again, so the slice can be
|
|
121
|
+
re-curated from the paths it lists. Then run `lemony design-tokens validate` to confirm
|
|
122
|
+
the result is well-formed.
|
|
115
123
|
|
|
116
124
|
## export — JSON → tool
|
|
117
125
|
|
|
@@ -75,7 +75,10 @@ the design direction it settles can inform the spec. Before the first question:
|
|
|
75
75
|
[Persisting personas](#persisting-personas-when-absent)) — an opt-in offer on your human-facing
|
|
76
76
|
surface, never an unasked write.
|
|
77
77
|
- **Consume `docs/design-tokens.json` if it exists** — the single source of truth for tokens. The
|
|
78
|
-
handoff §11 points at it; you never inline token values.
|
|
78
|
+
handoff §11 points at it; you never inline token values. That is the default path: when
|
|
79
|
+
`harness.config.yml` sets `design_tokens.file`, the path it names (relative to the repository
|
|
80
|
+
root) is the token file — read, scaffold, bind and point at that path wherever this skill says
|
|
81
|
+
`docs/design-tokens.json`, and never create a second file at the default.
|
|
79
82
|
- **Read `docs/architecture.md` if it exists** — orient against the system's shape so design
|
|
80
83
|
proposals don't contradict existing surfaces. Absent is fine; never push the user to create it.
|
|
81
84
|
|
|
@@ -84,7 +84,8 @@ Every section is **N/A-able** per task: mark a section N/A rather than padding i
|
|
|
84
84
|
|
|
85
85
|
## 11. Token reference
|
|
86
86
|
|
|
87
|
-
Reference `docs/design-tokens.json
|
|
87
|
+
Reference the token file — `docs/design-tokens.json`, or the path `design_tokens.file` names in
|
|
88
|
+
`harness.config.yml` — the single, client-owned source of truth, a 3-tier
|
|
88
89
|
W3C-DTCG model (`primitive` → `semantic` → `component`). **Never inline token values here; point at
|
|
89
90
|
the file.** If the project has no token file yet, the interview offers to scaffold one (derived from
|
|
90
91
|
the answers) or to connect a design tool; if the human declines both, say so and capture it as an
|
|
@@ -71,19 +71,33 @@ Without a script, each probe is yours to run. The mechanics:
|
|
|
71
71
|
as accounted-for, is the ledger contract's rule, not this skill's — the floor asks
|
|
72
72
|
for accounting, never exhaustion. One or two well-aimed probes per logic-bearing
|
|
73
73
|
file usually answer the question.
|
|
74
|
-
- **The round trip is one composite command
|
|
75
|
-
mutation, run the focused test, and restore —
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
- **The round trip is one composite command whose revert is a trap, installed before
|
|
75
|
+
the mutation.** Apply the mutation, run the focused test, and restore — in one
|
|
76
|
+
shell invocation, never separate edit / test / revert calls, and never a revert
|
|
77
|
+
that a red test or an interrupt can skip. The session can be stopped at any instant
|
|
78
|
+
(Esc stops the running command with SIGTERM), and a mutant left behind reads as
|
|
79
|
+
real work to whoever resumes. The `EXIT` trap restores on every way out — green,
|
|
80
|
+
red, or interrupted:
|
|
78
81
|
|
|
79
82
|
```bash
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
( trap 'mv -f src/queue.ts.bak src/queue.ts 2>/dev/null' EXIT; \
|
|
84
|
+
trap 'kill $! 2>/dev/null; exit 130' INT TERM HUP; \
|
|
85
|
+
sed -i.bak '128s/>=/>/' src/queue.ts; \
|
|
86
|
+
npx vitest run src/queue.spec.ts & wait $! )
|
|
83
87
|
```
|
|
84
88
|
|
|
85
89
|
(Line-addressed on purpose — one targeted mutant per trip keeps the kill
|
|
86
|
-
attributable; the `.bak` the in-place edit leaves is the revert.
|
|
90
|
+
attributable; the `.bak` the in-place edit leaves is the revert. The subshell
|
|
91
|
+
scopes the traps to the probe; the `INT TERM HUP` trap stops the runner and turns
|
|
92
|
+
the signal into an ordinary exit so the `EXIT` trap runs. The test runs in the
|
|
93
|
+
background under `wait` because a shell runs no trap while a foreground child is
|
|
94
|
+
still running, and Claude Code follows Esc's SIGTERM with a SIGKILL within a
|
|
95
|
+
second or two: `wait` returns on the signal, so the restore lands first. The
|
|
96
|
+
`kill $!` matters for a Ctrl-C too — a background job in a non-interactive shell
|
|
97
|
+
ignores SIGINT. Only a `SIGKILL` before the trap runs or a machine crash can
|
|
98
|
+
still strand a mutant — `git status` after the
|
|
99
|
+
trip shows the tree exactly as you found it, and a leftover `.bak` is the sign
|
|
100
|
+
one was stranded.)
|
|
87
101
|
|
|
88
102
|
A **killed** mutant (the focused test went red) is the good outcome; a **survivor**
|
|
89
103
|
(still green on broken code) is the finding. Batching buys trips, never
|
|
@@ -209,7 +209,11 @@ close, is always read as the declaration: it is reported if it does not end the
|
|
|
209
209
|
even when a list ends a later line. Keep every other `(R<n>)` mention in detail prose
|
|
210
210
|
**mid-line**. When two lists end continuation lines the validator cannot tell which is
|
|
211
211
|
the declaration and reports the task; on a task that declares no list, the one
|
|
212
|
-
line-ending mention is read as its declaration, and a mid-line one is reported.
|
|
212
|
+
line-ending mention is read as its declaration, and a mid-line one is reported. An
|
|
213
|
+
aside that must open a parenthesis with a requirement id opens it with `per` —
|
|
214
|
+
`(per R42, …)` — because a bare `(R42…` falls under the rules above exactly like a
|
|
215
|
+
declaration, and can be elected over the real list, sometimes silently. A `per` aside
|
|
216
|
+
is never read, so it never stands in for the list: the task still declares its own.
|
|
213
217
|
|
|
214
218
|
The review evidence ledger's validator enumerates each group's review slice from these
|
|
215
219
|
refs; a task it cannot read is reported as `malformed-task-refs` — a spec defect that
|
|
@@ -220,14 +224,32 @@ when the task reaches green, with the task's commit. Write every task `- [ ]`; t
|
|
|
220
224
|
validator reports a task still `[ ]` in a group the loop has passed
|
|
221
225
|
(`unticked-completed-task`), so the file tracks the progress its shape promises.
|
|
222
226
|
|
|
227
|
+
**Line shapes — read by the same script.** A task line is `- [ ]` or `- [x]` and a bare
|
|
228
|
+
`T<n>` id, at the task list's own indentation; a group header is exactly `## Group <n>`,
|
|
229
|
+
numbered from 1, with `Group` in English even when the spec is written in another
|
|
230
|
+
language. A line that looks like one but is not — an in-progress `[-]`, a suffixed
|
|
231
|
+
`T12b` or `T1.1`, a numbered `1. [ ]` item, a `- T6` with no box, a task inside a `>`
|
|
232
|
+
quote, a `T<n>` sub-item indented under another task, `### Group 3`, `## Group 0`, a
|
|
233
|
+
digit-less `## Group P`, a translated `## Grupo 2 — … _(…)_` — is reported
|
|
234
|
+
(`malformed-task-line`, `malformed-group-header`), never skipped; a note bullet about a
|
|
235
|
+
task opens with
|
|
236
|
+
something other than its `T<n>`. Every `T<n>` is used once in the file
|
|
237
|
+
(`duplicate-task-id` otherwise). Detail prose may run to several paragraphs: a blank
|
|
238
|
+
line inside a task is fine while the next line stays indented at least to the task's
|
|
239
|
+
text (two spaces under `- [ ]`); less, and it is no longer the task's. Code fences and
|
|
240
|
+
`>` quotes are never read as tasks, but a task or header shape inside one is reported
|
|
241
|
+
too — a quoted sample looks exactly like a task under a fence left open — so quote
|
|
242
|
+
samples without a `T<n>` id or a group header.
|
|
243
|
+
|
|
223
244
|
Rules: order so the first task is a tracer bullet; never "write all tests" then
|
|
224
245
|
"write all code"; keep each task small enough to verify on its own. Grouping never
|
|
225
246
|
changes task granularity — checkboxes stay atomic and TDD runs per task; only review
|
|
226
247
|
and checkpoint frequency follow the groups (all-at-once mode ignores the headers).
|
|
227
|
-
Tasks added mid-implementation (from a discovery)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
248
|
+
Tasks added mid-implementation (from a discovery) take the **next free `T<n>`** (never
|
|
249
|
+
a suffixed `T12b`) and default to **their own group** — they are risk by definition,
|
|
250
|
+
and grouping rule 5 applies to them unchanged — but they are added **after** the spec
|
|
251
|
+
gate, and no later gate presents a group header, so their tags get no human reading at
|
|
252
|
+
all. Tag them for the record; do not rely on anyone
|
|
231
253
|
catching a wrong one.
|
|
232
254
|
|
|
233
255
|
### 5. Self-check before handing off
|
|
@@ -37,7 +37,7 @@ Read the repo's `CLAUDE.md` (and `CONTEXT.md` if present). Summarize in ≤ 50 l
|
|
|
37
37
|
code-style rules, comment conventions, naming, architecture constraints. This is what
|
|
38
38
|
the analysis judges "against project convention" by.
|
|
39
39
|
|
|
40
|
-
### 2. Analyze (single sub-agent, the review lenses as a checklist)
|
|
40
|
+
### 2. Analyze (one pass — a single sub-agent, or inline — the review lenses as a checklist)
|
|
41
41
|
|
|
42
42
|
Spawn **one** `Explore` sub-agent with the full diff, the changed-files list, and the
|
|
43
43
|
project context. Its prompt walks the five review lenses as a checklist — **not** five
|
|
@@ -58,6 +58,12 @@ The agent returns a strict JSON array of findings (see [reference.md](reference.
|
|
|
58
58
|
the exact prompt and schema). It returns `[]` when the diff is clean — it must **not**
|
|
59
59
|
manufacture findings to seem thorough.
|
|
60
60
|
|
|
61
|
+
**A Reviewer, or no `Agent` tool?** A Reviewer never spawns, whatever its tools (the
|
|
62
|
+
opening rule of the Reviewer contract, `.claude/agents/reviewer.md`), and an agent at
|
|
63
|
+
Claude Code's nesting depth limit has no `Agent` tool unless it is a fork. Then walk
|
|
64
|
+
the five lenses yourself, in this context, with the same prompt as your checklist, and
|
|
65
|
+
produce the same JSON array; the rest of the flow is unchanged.
|
|
66
|
+
|
|
61
67
|
### 3. Dry-run
|
|
62
68
|
|
|
63
69
|
Print the findings as a numbered table (don't post anything yet):
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Analysis agent prompt
|
|
4
4
|
|
|
5
|
-
Pass this to the single `Explore` sub-agent
|
|
6
|
-
|
|
5
|
+
Pass this to the single `Explore` sub-agent — or, as a Reviewer or with no `Agent`
|
|
6
|
+
tool (SKILL.md §2), walk it yourself. The five lenses are a **checklist one agent
|
|
7
|
+
walks**, not a fan-out.
|
|
7
8
|
|
|
8
9
|
```
|
|
9
10
|
You are reviewing a GitHub PR diff. Find real issues worth posting as inline review
|
|
@@ -105,7 +105,8 @@ A task deserves the harness if it is **specifiable**, **verifiable**, or
|
|
|
105
105
|
checks precondition (`.claude/hooks/lib/merge-pr.sh --approve-issue <issue>`)
|
|
106
106
|
and never lands on red, absent, or still-pending checks without asking — nor
|
|
107
107
|
content that no longer matches what the Reviewer's APPROVE reviewed (the
|
|
108
|
-
stale-approve guard; a clean update-branch
|
|
108
|
+
stale-approve guard; a clean update-branch or a task-state write under
|
|
109
|
+
`.claude/state` stays valid, any other content change
|
|
109
110
|
routes back to re-review). The task stays at `in-review`
|
|
110
111
|
until merged.
|
|
111
112
|
10. **Closeout** — `task-closeout`: confirm the merge via `gh`, run the three Architect
|
|
@@ -83,7 +83,7 @@ rollback:
|
|
|
83
83
|
# - test
|
|
84
84
|
# - build
|
|
85
85
|
|
|
86
|
-
# Design tokens (`design-tokens
|
|
86
|
+
# Design tokens (the `design-tokens` verbs, and the token lines of `doctor` / `status`).
|
|
87
87
|
# `scan_extensions`: the anti-hardcode scan inspects a built-in set of UI/style
|
|
88
88
|
# extensions (.css/.scss/.ts/.tsx/.vue/.svelte/.astro/.js/.mdx/.html/…). Add extra
|
|
89
89
|
# suffixes here for a stack the built-ins don't cover — additive, never a replacement.
|
|
@@ -92,10 +92,16 @@ rollback:
|
|
|
92
92
|
# (through `sh -c`, in the repo root) — your design system's own verifier for the rules
|
|
93
93
|
# only it can know (palette under colour-vision-deficiency simulation, property grammar,
|
|
94
94
|
# CSS scans). Its output is forwarded; a non-zero exit fails the gate. It runs on every
|
|
95
|
-
# path: with no
|
|
95
|
+
# path: with no token file only the WCAG pair check is skipped, and a file
|
|
96
96
|
# that cannot be read or parsed is reported alongside it — never the verifier you
|
|
97
97
|
# declared. Default none.
|
|
98
|
+
# `file`: where the token file lives, relative to the repository root — for a DTCG
|
|
99
|
+
# file kept (or generated) somewhere other than docs/design-tokens.json. Every
|
|
100
|
+
# design-tokens verb, `doctor` and `status` read it from here. An absolute path, a `\`
|
|
101
|
+
# separator, a path that leads out of the repository or names its root, or one ending
|
|
102
|
+
# in `/` or `/.` is a config error. Default docs/design-tokens.json.
|
|
98
103
|
# design_tokens:
|
|
99
104
|
# scan_extensions:
|
|
100
105
|
# - .foo
|
|
101
106
|
# verify: pnpm exec my-design-system verify
|
|
107
|
+
# file: design/tokens.json
|