genesis-compiler 1.10.19 → 1.10.20
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 +38 -4
- package/docs/prompt-integration.md +6 -0
- package/docs/stack-components.md +19 -3
- package/package.json +4 -1
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/prompts/data-pass.txt +21 -0
- package/prompts/identity-pass.txt +23 -0
- package/prompts/quality-pass.txt +21 -0
- package/skills/genesis-data-pass/SKILL.md +163 -0
- package/skills/genesis-data-pass/agents/openai.yaml +4 -0
- package/skills/genesis-deslop/SKILL.md +5 -0
- package/skills/genesis-identity-pass/SKILL.md +259 -0
- package/skills/genesis-identity-pass/agents/openai.yaml +4 -0
- package/skills/genesis-project/references/sanity-checks.md +6 -1
- package/skills/genesis-quality-pass/SKILL.md +166 -0
- package/skills/genesis-quality-pass/agents/openai.yaml +4 -0
- package/skills/genesis-ui-pass/SKILL.md +5 -0
- package/src/cli-commands.js +10 -1
- package/src/cli.js +21 -4
- package/src/index/agent-skills.js +6 -4
- package/src/index/assets.js +3 -2
- package/src/index/contracts.js +1 -0
- package/src/index/pass-record.js +61 -0
- package/src/index/passes.js +59 -0
- package/src/index/project-inspection.js +2 -1
- package/src/index/prompt.js +56 -11
- package/src/index/stack-piece.js +13 -12
- package/src/index/stack.js +2 -2
- package/src/index.js +11 -1
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genesis-identity-pass
|
|
3
|
+
description: Give software a visual identity of its own (one seed colour, artwork drawn in code for each kind of content, a logo, empty states, a loading screen and a sign-in page) through an explicitly requested identity pass over the whole app, a named section, or the agent's own changes. Use when asked for a visual identity, a look, artwork or a logo, or to make an app look designed rather than like a default template.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genesis identity pass
|
|
7
|
+
|
|
8
|
+
Give the software a look of its own, drawn in code, so it reads as designed
|
|
9
|
+
rather than as a default template. An identity pass is explicit: never run it
|
|
10
|
+
merely because implementation finished.
|
|
11
|
+
|
|
12
|
+
Resolve the invocation before running the first Genesis operation. Do not use a
|
|
13
|
+
Genesis operation or `genesis --version` as an availability probe.
|
|
14
|
+
|
|
15
|
+
1. Read the repository-root `package.json`. Treat Genesis as project-pinned only
|
|
16
|
+
when that manifest's `name` is `genesis-compiler`, or its `dependencies`,
|
|
17
|
+
`devDependencies`, or `optionalDependencies` contain the exact
|
|
18
|
+
`genesis-compiler` key.
|
|
19
|
+
2. For a project-pinned repository, invoke every Genesis CLI operation with
|
|
20
|
+
`npm exec --no -- genesis <arguments>`. This runs without fetching another
|
|
21
|
+
package. If the declared package is not installed, report that the project's
|
|
22
|
+
dependencies are not prepared; do not fall back to another Genesis version.
|
|
23
|
+
3. Otherwise, do not try `npm exec`. Run `command -v genesis` (or the current
|
|
24
|
+
shell's equivalent `PATH` lookup). When it resolves an executable, invoke
|
|
25
|
+
`genesis <arguments>` directly.
|
|
26
|
+
4. When neither source is available, stop and report that Genesis is
|
|
27
|
+
unavailable. Never install or update Genesis merely to satisfy a workflow
|
|
28
|
+
instruction.
|
|
29
|
+
|
|
30
|
+
Successful invocation resolution is routine. Do not narrate whether Genesis is
|
|
31
|
+
project-pinned or on `PATH`, and never describe direct `PATH` use as a fallback.
|
|
32
|
+
Mention how the invocation was selected only when resolution fails or the user
|
|
33
|
+
explicitly asks.
|
|
34
|
+
|
|
35
|
+
Follow the configured Collaboration approach for user-facing updates, including
|
|
36
|
+
its technical depth and response length. Report concrete progress,
|
|
37
|
+
findings, or blockers; do not announce that you are following guidance.
|
|
38
|
+
|
|
39
|
+
## Load the effective project instructions once
|
|
40
|
+
|
|
41
|
+
An identity pass request may arrive as a complete Genesis-generated prompt or
|
|
42
|
+
as a direct request such as `Give the app its visual identity`.
|
|
43
|
+
|
|
44
|
+
If the current task already contains `GENESIS CONTEXT` whose task is
|
|
45
|
+
`identity-pass`, continue with it directly. Do not generate another prompt.
|
|
46
|
+
|
|
47
|
+
Otherwise, before resolving scope, run the Genesis `prompt --task identity-pass`
|
|
48
|
+
operation once using the invocation rule above. For a bare request, pass no
|
|
49
|
+
request argument. When the user names a section, commits or your own changes,
|
|
50
|
+
pass that exact request as one safely quoted argument. Treat the printed prompt
|
|
51
|
+
as the instructions for this same turn; do not dispatch it to another agent and
|
|
52
|
+
do not generate it again. This step composes the selected Stack's identity pass
|
|
53
|
+
guidance and any project customization with the portable contract below.
|
|
54
|
+
|
|
55
|
+
## Resolve the scope
|
|
56
|
+
|
|
57
|
+
Inspect `git status --short` and the staged and unstaged diffs before editing.
|
|
58
|
+
A dirty worktree is allowed. Preserve the existing index and unrelated work; do
|
|
59
|
+
not stage, stash, commit, or discard changes as a prerequisite.
|
|
60
|
+
|
|
61
|
+
- **The whole app (default).** Every screen or view a person sees, the shell,
|
|
62
|
+
sign-in, the loading screen, the logo and the icons. An identity is
|
|
63
|
+
app-wide, so this is the scope when none is stated.
|
|
64
|
+
- **A section.** A named area (a module, a route subtree, a set of screens):
|
|
65
|
+
it receives the app's existing identity, such as art for a new kind of
|
|
66
|
+
content and its empty states.
|
|
67
|
+
- **The changes.** Your own changes for the current task, or explicit commits,
|
|
68
|
+
established and resolved as for Deslop: the screens they add or change
|
|
69
|
+
receive the existing identity.
|
|
70
|
+
|
|
71
|
+
A narrower scope in an app with no identity yet still needs the foundation
|
|
72
|
+
(the seed, the colour module and the logo, steps 1 and 2 below): build it, and
|
|
73
|
+
report that the rest of the app does not have the identity yet.
|
|
74
|
+
|
|
75
|
+
## Study the software first
|
|
76
|
+
|
|
77
|
+
Before drawing anything, run the software and look at its screens, and read the
|
|
78
|
+
Blueprint. Write a short look spec, a few lines kept for the report:
|
|
79
|
+
|
|
80
|
+
- what the software is for, who uses it, and the tone that suits it;
|
|
81
|
+
- its **content kinds**: the categories people browse, pick or make (recipes
|
|
82
|
+
by course, workouts by type, books by genre, levels by world). Take them
|
|
83
|
+
from the data the software already has; do not invent a taxonomy the
|
|
84
|
+
product lacks. Art that follows the categories helps people recognise an
|
|
85
|
+
item at a glance;
|
|
86
|
+
- the **style option** below that fits, with the reason, and the seed colour.
|
|
87
|
+
|
|
88
|
+
## Choose a style option
|
|
89
|
+
|
|
90
|
+
The look is a choice, not a fixed recipe. Pick the option that fits, or the one
|
|
91
|
+
the person or the project already uses:
|
|
92
|
+
|
|
93
|
+
- **Calm interface, energetic artwork.** The default for content apps, where
|
|
94
|
+
people browse, pick or make items. Interface surfaces stay quiet and the
|
|
95
|
+
generated artwork carries the colour and the energy, so the content stays at
|
|
96
|
+
the centre and the interface stays readable in both schemes.
|
|
97
|
+
- **Quiet tool.** For work tools, dashboards, administration and developer
|
|
98
|
+
tools, and command-line programs. The identity lives in the seed colour, the
|
|
99
|
+
logo, the type and the empty states, with little or no artwork in lists,
|
|
100
|
+
where density and quick scanning matter more.
|
|
101
|
+
- **The project's own brand.** When the project already has brand colours, a
|
|
102
|
+
logo or a style guide, follow them: the brand colour becomes the seed and its
|
|
103
|
+
other colours become named roles. Never redraw a brand's own logo.
|
|
104
|
+
|
|
105
|
+
Games and other expressive software usually have an art direction already. The
|
|
106
|
+
pass then brings the same discipline to it (one source for its colours, seeded
|
|
107
|
+
variation, contrast, reduced motion) instead of replacing it.
|
|
108
|
+
|
|
109
|
+
## Build the identity
|
|
110
|
+
|
|
111
|
+
Draw everything in code when possible: no stock photos, no downloaded images,
|
|
112
|
+
and no new dependency for drawing. Drawn art scales, follows the palette, costs
|
|
113
|
+
little, works offline and carries no licence risk. Artwork the person supplies,
|
|
114
|
+
and a brand's own files, are used as given. Keep the code small and direct, as
|
|
115
|
+
the engineering approach asks: one art component, one colour module, motifs as
|
|
116
|
+
data.
|
|
117
|
+
|
|
118
|
+
1. **One seed colour.** Generate the interface's colour schemes (light and
|
|
119
|
+
dark, where the platform has both) from one seed through the technology's
|
|
120
|
+
own theme mechanism, never by picking each colour by hand: one decision
|
|
121
|
+
keeps every role consistent, and both schemes follow when it changes. A
|
|
122
|
+
deep, slightly cool seed usually keeps its character in both schemes.
|
|
123
|
+
Colour roles the software needs of its own, such as one per content kind,
|
|
124
|
+
are named theme colours harmonised toward the seed, each with the roles for
|
|
125
|
+
writing on it and for a container, working in both schemes.
|
|
126
|
+
2. **Every non-interface colour in one place.** Artwork gradients, the logo,
|
|
127
|
+
the sign-in panel, share images and avatar colours are named constants in
|
|
128
|
+
one module, each with a short comment saying where it is used. Interface
|
|
129
|
+
code uses theme roles only, never a literal colour. A colour scattered
|
|
130
|
+
through screens cannot follow the brand and drifts; this is "Data: one
|
|
131
|
+
source for each fact" in
|
|
132
|
+
`.agents/skills/genesis-project/references/sanity-checks.md`.
|
|
133
|
+
3. **Artwork for each content kind.** One art component (a cover) draws an
|
|
134
|
+
item's art from its kind and a seed, the item's stable id or slug:
|
|
135
|
+
- per kind, a palette in the colour module: two gradient colours, an accent
|
|
136
|
+
and a light colour. Each kind has its own distinct gradient, and a brand
|
|
137
|
+
kind serves items without one;
|
|
138
|
+
- per kind, a **motif**: a few simple, bold geometric shapes that say what
|
|
139
|
+
the kind is (a bowl and rising steam for soups, a climbing line for
|
|
140
|
+
running, stacked spines for books, a leaf for plants). Describe each motif
|
|
141
|
+
as data (a shape name and its attributes) drawn by one renderer, so a new
|
|
142
|
+
kind is new data rather than new code;
|
|
143
|
+
- a **seeded random generator**, so the same item always draws the same art
|
|
144
|
+
and each item differs a little while staying recognisably its kind. For
|
|
145
|
+
example, mulberry32 over an FNV-1a hash of `kind:seed`:
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
function randomFor(kind, seed) {
|
|
149
|
+
let h = 2166136261;
|
|
150
|
+
for (const c of `${kind}:${seed}`) h = Math.imul(h ^ c.charCodeAt(0), 16777619);
|
|
151
|
+
let s = h >>> 0;
|
|
152
|
+
return () => {
|
|
153
|
+
s = (s + 0x6d2b79f5) >>> 0;
|
|
154
|
+
let n = Math.imul(s ^ (s >>> 15), 1 | s);
|
|
155
|
+
n = (n + Math.imul(n ^ (n >>> 7), 61 | n)) ^ n;
|
|
156
|
+
return ((n ^ (n >>> 14)) >>> 0) / 4294967296;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Each seed moves the motif's centre a little (right of centre leaves room
|
|
162
|
+
for text), tilts the gradient within about 25 degrees either way, and
|
|
163
|
+
scatters a few soft dots behind the motif (small, in the light colour, at
|
|
164
|
+
low opacity). Never seed from the clock or an unseeded random: the art
|
|
165
|
+
would change on every load;
|
|
166
|
+
- drawing: thick strokes with round caps, two or three opacity levels, and
|
|
167
|
+
the accent used once per motif as its focal point. A wide 2:1 drawing
|
|
168
|
+
cropped to fill its box serves a card, a strip and a thumbnail alike.
|
|
169
|
+
Gradients and other definitions get ids unique to their kind and seed, so
|
|
170
|
+
two covers on one page never share one. The art is decorative: hide it
|
|
171
|
+
from assistive technology and let the item's title carry the meaning.
|
|
172
|
+
4. **Where the identity appears**, where the software has these:
|
|
173
|
+
- **content cards** in lists and libraries: the art across the top, then the
|
|
174
|
+
title, the byline, a short description, chips (kind, level) and one meta
|
|
175
|
+
line (date, people). A "Featured" group can come before the rest;
|
|
176
|
+
- **a hero card and a profile header**: a strip of art with the avatar
|
|
177
|
+
overlapping its lower edge;
|
|
178
|
+
- **empty states**: a small cover with the state's icon on a disc in its
|
|
179
|
+
middle, a one-line title, a short hint and one action that gets the
|
|
180
|
+
person going. An empty screen is often a new person's first one;
|
|
181
|
+
- **the logo**: a rounded tile with the brand gradient and one bold symbolic
|
|
182
|
+
mark in two accent colours with a light core. The same drawing is the
|
|
183
|
+
favicon and the app icons. Draw it inline where possible rather than as a
|
|
184
|
+
cached image, so it follows the colour module;
|
|
185
|
+
- **the opening or loading screen**, shown before the software's code runs:
|
|
186
|
+
the logo, the name and a one-line tagline, with a way to reload if startup
|
|
187
|
+
fails. Its motion is gentle and stops when reduced motion is asked for;
|
|
188
|
+
- **sign-in**: on wide windows, a brand panel (a glow from the brand colour
|
|
189
|
+
into a dark ink, the logo, the name, the tagline and three short lines on
|
|
190
|
+
what the software does, with a large faint accent ring and a few soft light
|
|
191
|
+
bubbles); on phones, the logo and the name over a strip of art;
|
|
192
|
+
- a **command-line program** shows its name and tagline in help and version
|
|
193
|
+
output and maps its colours to the terminal's, with no colour when
|
|
194
|
+
`NO_COLOR` is set or the output is not a terminal; a **game** carries the
|
|
195
|
+
identity on its title and loading screens and its icons.
|
|
196
|
+
5. **Polish that keeps the identity calm.** Follow the selected Stack's UI pass
|
|
197
|
+
rules for layout; in addition:
|
|
198
|
+
- while loading, show skeletons with the shape of the real content rather
|
|
199
|
+
than a spinner, so nothing jumps when the data arrives;
|
|
200
|
+
- numbers that change use tabular figures (`font-variant-numeric:
|
|
201
|
+
tabular-nums` on the web), so they do not shift as they change;
|
|
202
|
+
- a new item entering a list may pop in briefly (from about 0.6 scale,
|
|
203
|
+
fading in over about 600 ms), with no motion when reduced motion is asked
|
|
204
|
+
for;
|
|
205
|
+
- phone navigation follows the platform's own pattern for its size, and a
|
|
206
|
+
navigation drawer with nothing in it is removed.
|
|
207
|
+
6. **Contrast.** Writing on any content or identity colour reaches at least
|
|
208
|
+
4.5:1 (WCAG AA for body text) in every scheme; aim for about 5.4:1 with white
|
|
209
|
+
writing on identity colours, since art and gradients vary beneath it.
|
|
210
|
+
Measure the ratios rather than judging by eye.
|
|
211
|
+
|
|
212
|
+
## Boundaries
|
|
213
|
+
|
|
214
|
+
- The pass changes how the software looks and adds only the few words an
|
|
215
|
+
identity needs (a tagline, the sign-in lines, empty-state hints). It does not
|
|
216
|
+
change what the software does: no feature, field, action, permission,
|
|
217
|
+
validation or data change. New words go through the project's translation
|
|
218
|
+
mechanism where it has one. A defect, missing behavior or test gap you notice
|
|
219
|
+
is a follow-up finding, left unchanged.
|
|
220
|
+
- The selected Stack's identity pass guidance says where each piece lives;
|
|
221
|
+
the identity never breaks a design rule the Stack marks as must-fix.
|
|
222
|
+
- **Fix at the owner.** When the framework itself blocks a result, report the
|
|
223
|
+
exact framework change instead of overriding it in the app's styles.
|
|
224
|
+
- You may add the art components, the colour module, the logo and icon files,
|
|
225
|
+
the loading screen and their styles, place the art in screens, and update
|
|
226
|
+
tests whose markup changed; every behavior assertion stays. Do not edit
|
|
227
|
+
`.genesis/`, Git metadata, dependency directories, generated build output,
|
|
228
|
+
retained migration history, or external resources.
|
|
229
|
+
|
|
230
|
+
## Prove it
|
|
231
|
+
|
|
232
|
+
- Take screenshots of the main list, a detail page, an empty state, sign-in
|
|
233
|
+
(wide and phone) and the profile, at phone and desktop widths (390 and 1280
|
|
234
|
+
pixels on the web), in light and dark, through the host's managed browser or
|
|
235
|
+
a temporary browser test. Look at every one. Keep them out of the
|
|
236
|
+
repository's tracked files, delete temporary test files, and close every
|
|
237
|
+
browser you start.
|
|
238
|
+
- Confirm that every content kind has its own art, that the same item draws the
|
|
239
|
+
same art on every load (render one seed twice, or reload and compare), and
|
|
240
|
+
that two items of one kind differ.
|
|
241
|
+
- Measure the contrast of writing on each identity colour in both schemes.
|
|
242
|
+
- Confirm that nothing shifts while loading: compare the skeleton and the
|
|
243
|
+
loaded frame, or read the platform's layout-shift measure.
|
|
244
|
+
- Run the checks the Stack guidance names and the focused tests of the
|
|
245
|
+
affected screens.
|
|
246
|
+
- Update the Blueprint with a short paragraph describing the look in plain
|
|
247
|
+
words: the style option, the seed's character, and the art for each kind of
|
|
248
|
+
content. It is product intent, so it names no files.
|
|
249
|
+
|
|
250
|
+
Leave the pass as ordinary uncommitted work for review and a later normal
|
|
251
|
+
commit. Never amend or rewrite selected commits. Summarize the resolved scope,
|
|
252
|
+
the look spec (style option, seed, content kinds and their motifs), what
|
|
253
|
+
changed, files changed, the checks, contrast figures and screenshots actually
|
|
254
|
+
taken (with their paths), and follow-up findings left unchanged.
|
|
255
|
+
|
|
256
|
+
Once the pass has finished, end with the prompt's `PASS RECORD` step: the
|
|
257
|
+
Genesis `passes done identity-pass` operation records it in `genesis/passes.json`, an
|
|
258
|
+
uncommitted change that lands in the pass's own commit. A pass that stopped
|
|
259
|
+
early, was abandoned or still has failing checks is not recorded.
|
|
@@ -284,7 +284,9 @@ across screens, navigation, layout at the standard widths, focus, the real
|
|
|
284
284
|
sign-in); a new browser check is an assertion in the existing test that already
|
|
285
285
|
reaches that screen, and a new browser test file is for a new flow. The app's
|
|
286
286
|
own delays (retry backoff, debounce, polling) run on a fake clock, never in
|
|
287
|
-
real time.
|
|
287
|
+
real time. A test's own time limit covers only its own work: what it needs
|
|
288
|
+
is loaded when its file loads, not inside the timed test, so a slow first load
|
|
289
|
+
on a busy machine cannot fail it.
|
|
288
290
|
|
|
289
291
|
**Check:** after every run, read the suite time, each phase's time
|
|
290
292
|
(preparation, import, sign-in, tests) and the slowest files. A wall time close
|
|
@@ -313,6 +315,9 @@ advance the clock instead, unless another test already proves that path.
|
|
|
313
315
|
existing browser test could carry the one layout assertion for nothing.
|
|
314
316
|
- A browser test waited out the app's two retries of a failed request in real
|
|
315
317
|
time, 3 s on every run.
|
|
318
|
+
- A test loaded its modules inside its 20 s limit, and on a busy machine
|
|
319
|
+
after a fresh install the loading alone used it up; loading them with the
|
|
320
|
+
file moved about 9 s out of the test, which then took under a second.
|
|
316
321
|
|
|
317
322
|
**Outer limit:** a suite running for hours (a small app's for an hour),
|
|
318
323
|
preparation in minutes, or a limit ten times the measured need. A new test
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genesis-quality-pass
|
|
3
|
+
description: Make software hold up in real use through an explicitly requested quality pass over the whole app, a named section, or the agent's own changes, covering loading, empty and error states, nothing jumping, edge cases, every refusal explained to the person, and accessibility basics, verified by actually using it. Use when asked for a quality pass, polish, robustness, or to check every state and edge case.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genesis quality pass
|
|
7
|
+
|
|
8
|
+
Make the software behave well in the situations people really meet, and prove
|
|
9
|
+
it by using it. A quality pass is explicit: never run it merely because
|
|
10
|
+
implementation finished.
|
|
11
|
+
|
|
12
|
+
Resolve the invocation before running the first Genesis operation. Do not use a
|
|
13
|
+
Genesis operation or `genesis --version` as an availability probe.
|
|
14
|
+
|
|
15
|
+
1. Read the repository-root `package.json`. Treat Genesis as project-pinned only
|
|
16
|
+
when that manifest's `name` is `genesis-compiler`, or its `dependencies`,
|
|
17
|
+
`devDependencies`, or `optionalDependencies` contain the exact
|
|
18
|
+
`genesis-compiler` key.
|
|
19
|
+
2. For a project-pinned repository, invoke every Genesis CLI operation with
|
|
20
|
+
`npm exec --no -- genesis <arguments>`. This runs without fetching another
|
|
21
|
+
package. If the declared package is not installed, report that the project's
|
|
22
|
+
dependencies are not prepared; do not fall back to another Genesis version.
|
|
23
|
+
3. Otherwise, do not try `npm exec`. Run `command -v genesis` (or the current
|
|
24
|
+
shell's equivalent `PATH` lookup). When it resolves an executable, invoke
|
|
25
|
+
`genesis <arguments>` directly.
|
|
26
|
+
4. When neither source is available, stop and report that Genesis is
|
|
27
|
+
unavailable. Never install or update Genesis merely to satisfy a workflow
|
|
28
|
+
instruction.
|
|
29
|
+
|
|
30
|
+
Successful invocation resolution is routine. Do not narrate whether Genesis is
|
|
31
|
+
project-pinned or on `PATH`, and never describe direct `PATH` use as a fallback.
|
|
32
|
+
Mention how the invocation was selected only when resolution fails or the user
|
|
33
|
+
explicitly asks.
|
|
34
|
+
|
|
35
|
+
Follow the configured Collaboration approach for user-facing updates, including
|
|
36
|
+
its technical depth and response length. Report concrete progress,
|
|
37
|
+
findings, or blockers; do not announce that you are following guidance.
|
|
38
|
+
|
|
39
|
+
## Load the effective project instructions once
|
|
40
|
+
|
|
41
|
+
A quality pass request may arrive as a complete Genesis-generated prompt or as
|
|
42
|
+
a direct request such as `Quality pass` or `Quality pass the Orders section`.
|
|
43
|
+
|
|
44
|
+
If the current task already contains `GENESIS CONTEXT` whose task is
|
|
45
|
+
`quality-pass`, continue with it directly. Do not generate another prompt.
|
|
46
|
+
|
|
47
|
+
Otherwise, before resolving scope, run the Genesis `prompt --task quality-pass`
|
|
48
|
+
operation once using the invocation rule above. For a bare `Quality pass`
|
|
49
|
+
request, pass no request argument. When the user names a section, commits or
|
|
50
|
+
your own changes, pass that exact request as one safely quoted argument. Treat
|
|
51
|
+
the printed prompt as the instructions for this same turn; do not dispatch it
|
|
52
|
+
to another agent and do not generate it again. This step composes the selected
|
|
53
|
+
Stack's quality pass guidance and any project customization with the portable
|
|
54
|
+
contract below.
|
|
55
|
+
|
|
56
|
+
## Resolve the scope
|
|
57
|
+
|
|
58
|
+
Inspect `git status --short` and the staged and unstaged diffs before editing.
|
|
59
|
+
A dirty worktree is allowed. Preserve the existing index and unrelated work; do
|
|
60
|
+
not stage, stash, commit, or discard changes as a prerequisite.
|
|
61
|
+
|
|
62
|
+
- **The whole app (default).** Every screen, command and flow a person uses.
|
|
63
|
+
- **A section.** A named area (a module, a route subtree, a set of screens or
|
|
64
|
+
commands): every screen and flow in it, touched or not.
|
|
65
|
+
- **The changes.** Your own changes for the current task, or explicit commits,
|
|
66
|
+
established and resolved as for Deslop: the screens and flows they create or
|
|
67
|
+
change.
|
|
68
|
+
|
|
69
|
+
If the scope is ambiguous, ask which section or changes.
|
|
70
|
+
|
|
71
|
+
## List the states before changing anything
|
|
72
|
+
|
|
73
|
+
For each screen, command or flow in scope, write down what it shows or does,
|
|
74
|
+
where its data comes from, and each state it can be in: loading, empty, partial,
|
|
75
|
+
full, failed, refused, slow or offline, and first use. Mark which states exist
|
|
76
|
+
and which are missing or wrong. A missing state stays invisible in a demonstration
|
|
77
|
+
with good data and is often the first thing a real person meets.
|
|
78
|
+
|
|
79
|
+
## Apply the quality contract
|
|
80
|
+
|
|
81
|
+
The sanity checks guide
|
|
82
|
+
(`.agents/skills/genesis-project/references/sanity-checks.md`) sections
|
|
83
|
+
"Screens in use", "The wait a person sees", "Inputs and access" and "Tests that
|
|
84
|
+
prove behavior" describe what good looks like. This pass works through the
|
|
85
|
+
whole scope with them and fixes what it finds:
|
|
86
|
+
|
|
87
|
+
- **Loading.** A wait shows a stable placeholder in the shape of what arrives,
|
|
88
|
+
never a blank screen, so nothing jumps when the data does. An action shows
|
|
89
|
+
that it is working and cannot be sent twice. Long work in a command-line
|
|
90
|
+
program reports progress.
|
|
91
|
+
- **Empty.** An empty view says what would be there and offers the next useful
|
|
92
|
+
action. A first-use empty state differs from "nothing matches this filter",
|
|
93
|
+
which offers clearing the filter.
|
|
94
|
+
- **Errors.** A failure says what happened, in the person's words, and what
|
|
95
|
+
they can do; it offers a retry where retrying can help, keeps what the person
|
|
96
|
+
typed, appears where the failure happened (beside the field, in the panel
|
|
97
|
+
that failed) and never covers the next action. A failure is never silent and
|
|
98
|
+
never a raw code or stack trace.
|
|
99
|
+
- **Nothing jumps.** Layout keeps its place through loading, arriving data,
|
|
100
|
+
feedback and errors, and feedback never covers the control the person reaches
|
|
101
|
+
for next.
|
|
102
|
+
- **Edge cases.** Try the ones that apply: very long and very short text,
|
|
103
|
+
missing optional values, zero, one and many items, large numbers, dates near
|
|
104
|
+
midnight and in another time zone, duplicates, a double click or double
|
|
105
|
+
submit, refresh or back in the middle of an action, two tabs, an expired
|
|
106
|
+
session, a slow or dropped connection. Fix what breaks, or report it.
|
|
107
|
+
- **Every refusal explained.** When the software refuses (invalid input, a
|
|
108
|
+
missing permission, a limit, a conflict, missing setup), the person sees what
|
|
109
|
+
was refused, why, and what they can do about it, in words they understand.
|
|
110
|
+
The server keeps the refusal's status, code and message to the client, and
|
|
111
|
+
the client shows that message rather than a generic failure. A refusal stays
|
|
112
|
+
a refusal: this pass explains it and never loosens it.
|
|
113
|
+
- **Accessibility basics.** Every control can be reached and used from the
|
|
114
|
+
keyboard in a sensible order, with visible focus; every field and icon-only
|
|
115
|
+
control has a name; status, selection and errors are never shown by colour
|
|
116
|
+
alone; contrast is at least WCAG AA in every scheme; text still works at 200%
|
|
117
|
+
zoom; motion stops when reduced motion is asked for; touch targets are about
|
|
118
|
+
48 pixels; meaningful images have text alternatives and decorative ones are
|
|
119
|
+
hidden. A command-line program uses meaningful exit codes, writes errors to
|
|
120
|
+
standard error, has `--help` and honours `NO_COLOR`; a game offers
|
|
121
|
+
remappable controls and subtitles for its speech where it has them.
|
|
122
|
+
|
|
123
|
+
## Use it
|
|
124
|
+
|
|
125
|
+
Verification is using the software as a person does, through its real
|
|
126
|
+
interface (a browser, a terminal, a device), not reading its code:
|
|
127
|
+
|
|
128
|
+
- use it as a new person (first run, no data) and as a returning one with
|
|
129
|
+
realistic data (hundreds of items, long names, a long history);
|
|
130
|
+
- walk each flow in scope to its end, then force each state: slow the network
|
|
131
|
+
or the server, go offline, make the server fail, empty the list, enter wrong
|
|
132
|
+
input, act without permission;
|
|
133
|
+
- go through each flow once with the keyboard only;
|
|
134
|
+
- take screenshots of each state you changed at phone and desktop widths (390
|
|
135
|
+
and 1280 pixels on the web), in light and dark, and look at every one. Keep
|
|
136
|
+
them out of the repository's tracked files, delete temporary test files, and
|
|
137
|
+
close every browser and process you start;
|
|
138
|
+
- lock in each fix with a test at the cheapest level that proves it, as the
|
|
139
|
+
sanity checks guide's "Tests: time" describes, and run the focused tests of
|
|
140
|
+
the affected areas and the checks the Stack guidance names.
|
|
141
|
+
|
|
142
|
+
## Boundaries
|
|
143
|
+
|
|
144
|
+
- The pass changes behavior only to handle a state or an edge case and to
|
|
145
|
+
explain a refusal. It adds no feature and changes no permission, product rule
|
|
146
|
+
or stored data; a larger gap is a follow-up finding, left unchanged.
|
|
147
|
+
- The selected Stack's quality pass guidance names where states, errors and
|
|
148
|
+
refusals live in its technology; follow it.
|
|
149
|
+
- **Fix at the owner.** When the framework itself blocks a result, report the
|
|
150
|
+
exact framework change instead of working around it in the app.
|
|
151
|
+
- You may edit source, styles, messages and tests in scope; every existing
|
|
152
|
+
behavior assertion stays. Do not edit `.genesis/`, Git metadata, dependency
|
|
153
|
+
directories, generated build output, retained migration history, or external
|
|
154
|
+
resources.
|
|
155
|
+
|
|
156
|
+
Leave the pass as ordinary uncommitted work for review and a later normal
|
|
157
|
+
commit. Never amend or rewrite selected commits. Summarize the resolved scope,
|
|
158
|
+
the states listed for each screen or flow with what was missing and what
|
|
159
|
+
changed, the edge cases tried and their results, the refusals reworded, the
|
|
160
|
+
accessibility checks, the screenshots and tests actually taken and run (with
|
|
161
|
+
their paths), files changed, and follow-up findings left unchanged.
|
|
162
|
+
|
|
163
|
+
Once the pass has finished, end with the prompt's `PASS RECORD` step: the
|
|
164
|
+
Genesis `passes done quality-pass` operation records it in `genesis/passes.json`, an
|
|
165
|
+
uncommitted change that lands in the pass's own commit. A pass that stopped
|
|
166
|
+
early, was abandoned or still has failing checks is not recorded.
|
|
@@ -109,3 +109,8 @@ commit. Never amend or rewrite the selected commits. Summarize the resolved
|
|
|
109
109
|
scope and any commit identities, what changed, files changed, the checks and
|
|
110
110
|
screenshots actually taken (with their paths), and follow-up findings left
|
|
111
111
|
unchanged.
|
|
112
|
+
|
|
113
|
+
Once the pass has finished, end with the prompt's `PASS RECORD` step: the
|
|
114
|
+
Genesis `passes done ui-pass` operation records it in `genesis/passes.json`, an
|
|
115
|
+
uncommitted change that lands in the pass's own commit. A pass that stopped
|
|
116
|
+
early, was abandoned or still has failing checks is not recorded.
|
package/src/cli-commands.js
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
inspectEnvironment,
|
|
15
15
|
inspectStackSection,
|
|
16
16
|
inspectSubsystems,
|
|
17
|
+
inspectPasses,
|
|
18
|
+
recordPassDone,
|
|
17
19
|
inspectProject,
|
|
18
20
|
inspectSkills,
|
|
19
21
|
installCodex,
|
|
@@ -70,6 +72,7 @@ async function execute({ command, operands, options }, { signal, hostContext = n
|
|
|
70
72
|
}
|
|
71
73
|
if (command === 'migrate') return migrate({ projectRoot, stackPackages });
|
|
72
74
|
if (command === 'skills') return syncSkills({ projectRoot, stackPackages });
|
|
75
|
+
if (command === 'passes') return { action: 'done', ...await recordPassDone({ projectRoot, pass: operands[1] }) };
|
|
73
76
|
if (command === 'adopt') {
|
|
74
77
|
return adoptProject({ projectRoot, request: operands.join(' '), stackPackages });
|
|
75
78
|
}
|
|
@@ -148,7 +151,13 @@ async function execute({ command, operands, options }, { signal, hostContext = n
|
|
|
148
151
|
}),
|
|
149
152
|
};
|
|
150
153
|
}
|
|
151
|
-
const inspections = {
|
|
154
|
+
const inspections = {
|
|
155
|
+
subsystems: inspectSubsystems,
|
|
156
|
+
environment: inspectEnvironment,
|
|
157
|
+
project: inspectProject,
|
|
158
|
+
skills: inspectSkills,
|
|
159
|
+
passes: inspectPasses,
|
|
160
|
+
};
|
|
152
161
|
return {
|
|
153
162
|
inspection: operands[0],
|
|
154
163
|
...await inspections[operands[0]]({ projectRoot, stackPackages }),
|
package/src/cli.js
CHANGED
|
@@ -26,6 +26,7 @@ const USAGE = `Usage:
|
|
|
26
26
|
genesis stack list
|
|
27
27
|
genesis stack add <piece...>
|
|
28
28
|
genesis skills sync
|
|
29
|
+
genesis passes done <pass>
|
|
29
30
|
genesis templates list
|
|
30
31
|
genesis templates apply <catalogue:technology/variant>
|
|
31
32
|
genesis context <path...>
|
|
@@ -38,9 +39,10 @@ const USAGE = `Usage:
|
|
|
38
39
|
genesis inspect environment
|
|
39
40
|
genesis inspect project
|
|
40
41
|
genesis inspect skills
|
|
42
|
+
genesis inspect passes
|
|
41
43
|
genesis inspect section <name>
|
|
42
44
|
genesis prompt [request...]
|
|
43
|
-
genesis prompt --task <start|adopt|work|deslop|ui-pass|program|blueprint|describe|review> [request...]
|
|
45
|
+
genesis prompt --task <start|adopt|work|deslop|ui-pass|identity-pass|quality-pass|data-pass|program|blueprint|describe|review> [request...]
|
|
44
46
|
genesis verify
|
|
45
47
|
genesis check
|
|
46
48
|
|
|
@@ -61,7 +63,7 @@ prompt to the agent you already use. Review all edits through the ordinary Git
|
|
|
61
63
|
diff, then run genesis verify for the Stack's concrete checks.
|
|
62
64
|
`;
|
|
63
65
|
|
|
64
|
-
const COMMANDS = new Set(['adopt', 'check', 'codex', 'collaboration', 'context', 'engineering', 'hook', 'index', 'init', 'inspect', 'migrate', 'parsers', 'prompt', 'skills', 'stack', 'templates', 'verify']);
|
|
66
|
+
const COMMANDS = new Set(['adopt', 'check', 'codex', 'collaboration', 'context', 'engineering', 'hook', 'index', 'init', 'inspect', 'migrate', 'parsers', 'passes', 'prompt', 'skills', 'stack', 'templates', 'verify']);
|
|
65
67
|
|
|
66
68
|
function parseCommand(argv) {
|
|
67
69
|
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h') || argv[0] === 'help') {
|
|
@@ -176,6 +178,10 @@ function parseCommand(argv) {
|
|
|
176
178
|
if (operands.length !== 1 || operands[0] !== 'sync') {
|
|
177
179
|
fail('CLI_SKILLS_ACTION_REQUIRED', 'Command skills requires exactly: sync.');
|
|
178
180
|
}
|
|
181
|
+
} else if (command === 'passes') {
|
|
182
|
+
if (operands.length !== 2 || operands[0] !== 'done') {
|
|
183
|
+
fail('CLI_PASSES_ACTION_REQUIRED', 'Command passes requires exactly: done <pass>.');
|
|
184
|
+
}
|
|
179
185
|
} else if (command === 'codex') {
|
|
180
186
|
if (operands.length !== 1 || operands[0] !== 'install') {
|
|
181
187
|
fail('CLI_CODEX_ACTION_REQUIRED', 'Command codex requires exactly: install.');
|
|
@@ -183,12 +189,12 @@ function parseCommand(argv) {
|
|
|
183
189
|
} else if (command === 'context' && operands.length === 0) {
|
|
184
190
|
fail('CONTEXT_PATH_REQUIRED', 'Command context requires at least one project path.');
|
|
185
191
|
} else if (command === 'inspect') {
|
|
186
|
-
const ordinaryInspection = operands.length === 1 && ['environment', 'project', 'skills', 'subsystems'].includes(operands[0]);
|
|
192
|
+
const ordinaryInspection = operands.length === 1 && ['environment', 'passes', 'project', 'skills', 'subsystems'].includes(operands[0]);
|
|
187
193
|
const sectionInspection = operands.length >= 2 && operands[0] === 'section';
|
|
188
194
|
if (!ordinaryInspection && !sectionInspection) {
|
|
189
195
|
fail(
|
|
190
196
|
'CLI_INSPECT_TARGET_REQUIRED',
|
|
191
|
-
'Command inspect requires project, environment, skills, subsystems, or section <name>.',
|
|
197
|
+
'Command inspect requires project, environment, skills, passes, subsystems, or section <name>.',
|
|
192
198
|
);
|
|
193
199
|
}
|
|
194
200
|
} else if (command === 'hook' && (operands.length !== 1 || !['discover', 'session', 'turn'].includes(operands[0]))) {
|
|
@@ -304,6 +310,17 @@ function writeResult(command, result) {
|
|
|
304
310
|
else line(process.stdout, `Parsers verified: ${result.languages.join(', ')}`);
|
|
305
311
|
return;
|
|
306
312
|
}
|
|
313
|
+
if (command === 'inspect' && result.inspection === 'passes') {
|
|
314
|
+
for (const pass of result.passes) {
|
|
315
|
+
line(process.stdout, `${pass.id}: ${pass.title} — ${pass.description}`);
|
|
316
|
+
line(process.stdout, ` recommended ${pass.recommend.hint}; Stack guidance: ${pass.stackGuidance ? 'yes' : 'no'}; last run: ${pass.lastRun ?? 'never'}`);
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (command === 'passes') {
|
|
321
|
+
line(process.stdout, `${result.pass}: recorded ${result.lastRun} in ${result.path}`);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
307
324
|
if (command === 'inspect' && result.inspection === 'skills') {
|
|
308
325
|
line(process.stdout, `Agent Skills: ${result.status}`);
|
|
309
326
|
for (const skill of result.skills) line(process.stdout, ` - ${skill.name}: ${skill.status}`);
|
|
@@ -17,6 +17,7 @@ import { parse as parseYaml } from 'yaml';
|
|
|
17
17
|
|
|
18
18
|
import { asDiagnostic, GenesisError } from './errors.js';
|
|
19
19
|
import { claudeSkillLinks } from './claude-hooks.js';
|
|
20
|
+
import { PASSES } from './passes.js';
|
|
20
21
|
import { sha256, stableJson, writeFileAtomic } from './utils.js';
|
|
21
22
|
|
|
22
23
|
const packageRoot = fileURLToPath(new URL('../../', import.meta.url));
|
|
@@ -34,12 +35,13 @@ const SKILL_FIELDS = new Set([
|
|
|
34
35
|
'allowed-tools',
|
|
35
36
|
]);
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
// Every project's Genesis workflow skills: the project and Program skills, and one for each pass.
|
|
39
|
+
export const CORE_SKILL_NAMES = Object.freeze([
|
|
38
40
|
'genesis-project',
|
|
39
41
|
'genesis-program',
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
...PASSES.map(({ task }) => `genesis-${task}`),
|
|
43
|
+
]);
|
|
44
|
+
const CORE_SKILLS = CORE_SKILL_NAMES.map((name) => ({
|
|
43
45
|
component: null,
|
|
44
46
|
package: null,
|
|
45
47
|
path: `skills/${name}`,
|
package/src/index/assets.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
|
|
3
|
+
import { PASSES } from './passes.js';
|
|
4
|
+
|
|
3
5
|
const root = new URL('../../', import.meta.url);
|
|
4
6
|
const assets = {
|
|
5
7
|
start: new URL('prompts/start.txt', root),
|
|
@@ -9,8 +11,7 @@ const assets = {
|
|
|
9
11
|
adopt: new URL('prompts/adopt.txt', root),
|
|
10
12
|
work: new URL('prompts/work.txt', root),
|
|
11
13
|
describe: new URL('prompts/describe.txt', root),
|
|
12
|
-
|
|
13
|
-
'ui-pass': new URL('prompts/ui-pass.txt', root),
|
|
14
|
+
...Object.fromEntries(PASSES.map(({ task }) => [task, new URL(`prompts/${task}.txt`, root)])),
|
|
14
15
|
program: new URL('prompts/program.txt', root),
|
|
15
16
|
blueprint: new URL('prompts/blueprint.txt', root),
|
|
16
17
|
review: new URL('prompts/review.txt', root),
|
package/src/index/contracts.js
CHANGED
|
@@ -2,6 +2,7 @@ export const GENESIS_CONTRACTS = Object.freeze({
|
|
|
2
2
|
subsystems: 'genesis.subsystems.v0',
|
|
3
3
|
projectInspection: 'genesis.project-inspection.v1',
|
|
4
4
|
promptTasks: 'genesis.prompt-tasks.v1',
|
|
5
|
+
passes: 'genesis.passes.v1',
|
|
5
6
|
templates: 'genesis.templates.v1',
|
|
6
7
|
templateApplication: 'genesis.template-application.v1',
|
|
7
8
|
collaboration: 'genesis.collaboration.v1',
|