genesis-compiler 1.10.20 → 1.10.22

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.
Files changed (43) hide show
  1. package/README.md +74 -16
  2. package/docs/prompt-integration.md +19 -5
  3. package/docs/stack-components.md +22 -5
  4. package/package.json +11 -1
  5. package/plugins/genesis/.codex-plugin/plugin.json +1 -1
  6. package/prompts/deslop.txt +3 -0
  7. package/prompts/master-pass.txt +17 -0
  8. package/prompts/pass-deep.txt +77 -0
  9. package/prompts/pass-report.txt +15 -0
  10. package/prompts/review.txt +2 -1
  11. package/prompts/security-pass.txt +26 -0
  12. package/prompts/speed-pass.txt +28 -0
  13. package/prompts/ui-pass.txt +3 -1
  14. package/prompts/ux-pass.txt +25 -0
  15. package/skills/genesis-data-pass/SKILL.md +29 -4
  16. package/skills/genesis-deslop/SKILL.md +47 -6
  17. package/skills/genesis-identity-pass/SKILL.md +29 -4
  18. package/skills/genesis-master-pass/SKILL.md +132 -0
  19. package/skills/genesis-master-pass/agents/openai.yaml +4 -0
  20. package/skills/genesis-quality-pass/SKILL.md +30 -4
  21. package/skills/genesis-review/SKILL.md +120 -0
  22. package/skills/genesis-review/agents/openai.yaml +4 -0
  23. package/skills/genesis-security-pass/SKILL.md +297 -0
  24. package/skills/genesis-security-pass/agents/openai.yaml +4 -0
  25. package/skills/genesis-speed-pass/SKILL.md +351 -0
  26. package/skills/genesis-speed-pass/agents/openai.yaml +4 -0
  27. package/skills/genesis-ui-pass/SKILL.md +38 -7
  28. package/skills/genesis-ux-pass/SKILL.md +276 -0
  29. package/skills/genesis-ux-pass/agents/openai.yaml +4 -0
  30. package/src/cli-commands.js +3 -1
  31. package/src/cli.js +14 -4
  32. package/src/index/agent-skills.js +53 -29
  33. package/src/index/assets.js +4 -1
  34. package/src/index/code-index.js +2 -1
  35. package/src/index/contracts.js +2 -0
  36. package/src/index/master-pass.js +76 -0
  37. package/src/index/pass-record.js +124 -22
  38. package/src/index/pass-support.js +71 -0
  39. package/src/index/passes.js +92 -5
  40. package/src/index/project-files.js +2 -1
  41. package/src/index/prompt.js +306 -28
  42. package/src/index/source-size.js +62 -0
  43. package/src/index.js +6 -1
@@ -0,0 +1,297 @@
1
+ ---
2
+ name: genesis-security-pass
3
+ description: Close the ways software can be misused through an explicitly requested security pass over the whole app, a named section, or the agent's own changes, covering authorization on every route, action and job, sign-in and sessions, input handling, secrets, production settings, dependencies and outbound requests, each finding proved by sending the input that breaks it and seeing it refused once fixed. Use when asked for a security pass, hardening, a security review that fixes what it finds, or to check who can do what.
4
+ ---
5
+
6
+ # Genesis security pass
7
+
8
+ Make the software refuse what it should refuse, and prove each refusal by
9
+ trying to get past it. A security 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 security pass request may arrive as a complete Genesis-generated prompt or
42
+ as a direct request such as `Security pass` or `Security pass the billing
43
+ section`.
44
+
45
+ If the current task already contains `GENESIS CONTEXT` whose task is
46
+ `security-pass`, continue with it directly. Do not generate another prompt.
47
+
48
+ Otherwise, before resolving scope, run the Genesis `prompt --task security-pass`
49
+ operation once using the invocation rule above. For a bare `Security pass`
50
+ request, pass no request argument. When the user names a section, commits or
51
+ your own changes, pass that exact request as one safely quoted argument. Treat
52
+ the printed prompt as the instructions for this same turn; do not dispatch it
53
+ to another agent and do not generate it again. This step composes the selected
54
+ Stack's security pass guidance and any project customization with the portable
55
+ contract below.
56
+
57
+ When the user asks for a deep run of this pass, pass its Deep request,
58
+ `Security pass the whole app deeply.`, exactly;
59
+ Genesis then adds the run's `DEEP RUN` section.
60
+
61
+ ## Resolve the scope
62
+
63
+ Inspect `git status --short` and the staged and unstaged diffs before editing.
64
+ A dirty worktree is allowed. Preserve the existing index and unrelated work; do
65
+ not stage, stash, commit, or discard changes as a prerequisite.
66
+
67
+ When the prompt has a `PASS RUN` section, the request is one of the pass's own
68
+ runs (the whole app, the changes since its last completed run judged against
69
+ the whole app, or a deep run) or a run over the changes since a base commit the
70
+ request names, and its scope is the one that section states, whatever the
71
+ defaults below say. A deep run's prompt also has a `DEEP RUN`
72
+ section; follow it with "Deep run" below.
73
+
74
+ - **The whole app (default).** Every way in: each route, page, command,
75
+ action, message or socket handler, webhook, scheduled or background job,
76
+ file or document the software reads from outside, and every outbound call.
77
+ - **A section.** A named area (a module, a route subtree, a subsystem): every
78
+ way into it, touched or not.
79
+ - **The changes.** Your own changes for the current task, or explicit commits,
80
+ established and resolved as for Deslop: the ways in they create or change,
81
+ and the checks those depend on.
82
+
83
+ If the scope is ambiguous, ask which section or changes.
84
+
85
+ ## Map the ways in first
86
+
87
+ Read the engineering approach and these sections of the sanity checks guide
88
+ (`.agents/skills/genesis-project/references/sanity-checks.md`): "Never do
89
+ these", "Inputs and access", "Production settings" and "Tests that prove
90
+ behavior". They describe what good looks like; this pass applies them across
91
+ the whole scope and fixes what they find.
92
+
93
+ Then list, for the scope, each way in with who may use it (anyone, a signed-in
94
+ person, a role, a member of one tenant or workspace, the owner of a record, the
95
+ system itself), what it reads and changes, each input it takes and where that
96
+ input ends up (a query, a shell command, a template, a file path, a URL the
97
+ server fetches, a message sent to someone), and the secrets it uses. List too
98
+ the sign-in, sign-up, password reset, invitation and token flows, how sessions
99
+ are kept and ended, and how a new deployment gets its first administrator. A
100
+ hole is most often a way in that nobody listed, so the map comes first and
101
+ every later step works through it.
102
+
103
+ The areas below are advice with their reasons. Apply the ones that fit the
104
+ software: a game without accounts has no password reset, a command-line
105
+ program has no cookies, and a single-person tool may have no tenants. Say
106
+ which areas do not apply, and why.
107
+
108
+ ## Authorization
109
+
110
+ Every route, action and job refuses a caller without permission, because a
111
+ check that exists only in the interface is skipped by anyone who sends the
112
+ request directly.
113
+
114
+ - **Decide access first.** Check who the caller is and what they may do before
115
+ anything else, including before validation answers. A caller without
116
+ permission who sends a malformed request gets the refusal, not a list of
117
+ field errors, which would describe what the endpoint accepts.
118
+ - **Trust only the trusted context.** Who is acting, their role and their
119
+ tenant come from the signed-in session, a verified token or the job's own
120
+ identity, never from an id, role or tenant the client sends. A client-sent id
121
+ says which record is wanted; whether this caller may have it is decided on
122
+ the server every time.
123
+ - **Refuse other people's ids.** Another tenant's or another person's ids are
124
+ refused everywhere: reading, changing, deleting, listing, exporting, and
125
+ linking them to your own records. Where possible, scope the query itself by
126
+ the caller's tenant or ownership, so a forgotten check finds nothing rather
127
+ than someone else's data.
128
+ - **Fail closed.** A missing value, scope, role, tenant or collaborator (a
129
+ permission service, a policy, a configured list) refuses rather than allows.
130
+ "Nothing configured" must never mean "everyone allowed".
131
+ - **Background work too.** A job, queue consumer or scheduled task acting for a
132
+ person carries that person's access and is held to it when it runs. A
133
+ webhook verifies its signature, or another proof of its sender, before it
134
+ trusts its body.
135
+ - **Hidden is not protected.** A button that is not shown, an unlinked page or
136
+ a long URL still needs the server's check.
137
+
138
+ ## Authentication and sessions
139
+
140
+ - **Rate-limit what can be guessed or is costly.** Sign-in, sign-up, password
141
+ reset, verification and one-time codes, invitations, and anything that sends
142
+ email or messages or costs money, limited per account and per source address
143
+ where possible, so guessing and flooding are slow and visible. Behind a
144
+ proxy, make sure the limit counts each client, not the proxy.
145
+ - **Don't reveal who has an account.** Sign-in, sign-up and password reset
146
+ answer the same way whether or not the account exists ("If that address has
147
+ an account, we sent a link"), in about the same time.
148
+ - **Keep sessions safely.** Where sessions ride on cookies, make them
149
+ `HttpOnly`, `Secure` in production and `SameSite` where the app allows it,
150
+ and protect changing requests against cross-site request forgery. Issue a
151
+ new session at sign-in, end it at sign-out, and expire it. Tokens and reset
152
+ links are random, expire, work once where they should, and are compared in
153
+ constant time.
154
+ - **Store passwords for the purpose.** A slow, salted password hash made for
155
+ passwords; never a reversible form, and never in a log.
156
+
157
+ ## Input
158
+
159
+ - **Validate at the boundary.** Check each input where it enters (type, size,
160
+ range, allowed values) and refuse what does not fit rather than repairing it
161
+ quietly, so the code behind can rely on what it gets.
162
+ - **Nothing reaches an interpreter unescaped.** Parameterized queries, argument
163
+ lists instead of shell strings, the template engine's own escaping, and file
164
+ paths resolved and checked to stay inside the directory they belong to.
165
+ Markup a person writes is sanitized with an allow-list before anyone else
166
+ sees it. A value used as a regular expression is escaped or bounded.
167
+ - **Uploads.** Check the type from the content as well as the name, cap the
168
+ size before reading the whole body, store files under names the server
169
+ chooses, outside anything served or run as code, and serve them so a browser
170
+ downloads rather than runs them.
171
+ - **Cap the expensive.** Request bodies, page sizes, list lengths and costly
172
+ operations have limits, so one request cannot exhaust memory, the database
173
+ or a paid service.
174
+
175
+ ## Secrets
176
+
177
+ - **None in code, the repository, logs, errors or client bundles.** Search
178
+ source, configuration, fixtures, tests, the repository's history where
179
+ possible, log output, error responses and the built client for keys,
180
+ tokens, passwords and connection strings. Secrets come from the environment
181
+ or a secret store when the software runs; the client gets only values meant
182
+ to be public.
183
+ - **A committed secret is exposed.** Deleting it does not unexpose it: it must
184
+ be replaced at its issuer, which usually only the person can do. Report it;
185
+ never copy its value into the report, the chat or a test.
186
+ - **Logs leave secrets out.** Passwords, tokens, session ids and personal data
187
+ a log has no need for stay out of logs and error reports.
188
+
189
+ ## Production
190
+
191
+ - **Never development settings.** Production refuses to start without its
192
+ required settings rather than falling back to a development default: a fixed
193
+ secret, a debug mode, a local host, permissive cross-origin rules or a
194
+ development login. Debug pages, test accounts and sample data are off.
195
+ - **The first visitor cannot take it over.** A new deployment gets its first
196
+ administrator from a setup secret only its operator can read, an invitation
197
+ or the deployment's owner, never from whoever signs up first.
198
+ - **Errors don't leak.** A failure tells the person what happened in their
199
+ words and logs the details on the server; a response never carries a stack
200
+ trace, a query, a file path or internal versions.
201
+ - **Headers fit the software.** A content security policy, transport security,
202
+ no content-type sniffing and framing protection where it serves web pages,
203
+ and cross-origin access only for the origins that need it.
204
+
205
+ ## Dependencies and outbound calls
206
+
207
+ - **Known-vulnerable packages.** Run the ecosystem's dependency audit. Update a
208
+ vulnerable package to a fixed version, within its declared range where
209
+ possible, and report each one with no fix, saying whether the vulnerable part
210
+ is reachable.
211
+ - **Outbound requests a person can aim.** Each request whose address user input
212
+ chooses (a webhook URL, a link preview, an import from a URL, an image
213
+ fetch) is checked against server-side request forgery: an allow-list where
214
+ possible; otherwise refuse loopback, private, link-local and cloud metadata
215
+ addresses after resolving the name and again on every redirect, and cap its
216
+ time and size. A redirect whose target a person chooses is held to the
217
+ software's own origins.
218
+
219
+ ## Try each finding
220
+
221
+ Reading finds candidates; trying shows which are real. For each risk:
222
+
223
+ 1. Send the input that should break it, against a local or test copy the run
224
+ controls: a request without a session, as a caller without permission,
225
+ with another tenant's id, past the rate limit, with a crafted path, a shell
226
+ or query metacharacter, a script tag, a mistyped or oversized upload, a
227
+ private address as a URL.
228
+ 2. Record what happened. A finding is that request and the answer that should
229
+ have been a refusal.
230
+ 3. Fix it where the protection belongs (the shared policy, the query's scope,
231
+ the framework's own protection) rather than in one route, so the next way
232
+ in is protected too.
233
+ 4. Send the same input again and see it refused, with the status and message
234
+ the software uses for that refusal.
235
+ 5. Lock it in with a test that sends that input and expects the refusal. Watch
236
+ it fail once without the fix (undo the fix, run the test, restore it), so
237
+ the test is known to guard it.
238
+
239
+ Also try the protections that already exist: send one input each declared
240
+ protection should refuse and see it refused. A protection that is declared but
241
+ never enforced is a finding.
242
+
243
+ ## Boundaries
244
+
245
+ - **Never weaken a protection to make something pass.** Do not loosen a
246
+ permission, rate limit, validation, content security policy, sandbox or
247
+ header to make a test, build, deployment or feature work. When a protection
248
+ blocks something the person needs, explain the conflict and let them decide.
249
+ - The pass changes how the software checks, refuses, escapes, stores secrets
250
+ and runs in production. It adds no feature and does not change who the
251
+ product means to allow to do what; when that intent is unclear (may a member
252
+ see another member's records?), ask the person and keep the stricter
253
+ behavior meanwhile.
254
+ - Attacks are tried only against copies the run controls: local servers, test
255
+ databases and test accounts it creates. Never probe a production deployment,
256
+ a real person's account or another party's service, and never send real
257
+ email, messages or payments.
258
+ - **Report what it can't fix.** A secret to replace, a product decision, a
259
+ hosting setting, a vulnerable dependency with no fix: each is reported with
260
+ what it needs and who must act. When the framework itself blocks a fix,
261
+ report the exact framework change instead of working around it in the app
262
+ (**fix at the owner**).
263
+ - The selected Stack's security pass guidance names where its technology
264
+ decides access, scopes rows, limits requests, keeps sessions and secrets and
265
+ switches to production; follow it.
266
+ - You may edit source, configuration, messages and tests in scope; every
267
+ existing behavior assertion stays. Update dependencies through the package
268
+ manager. Do not edit `.genesis/`, Git metadata, dependency directories,
269
+ generated build output, retained migration history, or external resources.
270
+
271
+ Leave the pass as ordinary uncommitted work for review and a later normal
272
+ commit. Never amend or rewrite selected commits. Summarize the resolved scope,
273
+ the map of ways in, each finding with the input that broke it and the refusal
274
+ seen after the fix, the test guarding each fix and its failing run without the
275
+ fix, the protections tried that already held, the areas that do not apply and
276
+ why, the dependency audit, files changed, checks actually run, and everything
277
+ left unfixed with what it needs and who must act.
278
+
279
+ When the prompt ends with a `PASS RECORD` step, take it once the pass has
280
+ finished: the Genesis `passes done security-pass` operation records it in `genesis/passes.json`,
281
+ an uncommitted change that lands in the pass's own commit. Genesis adds that
282
+ step only to the pass's own runs, whose requests it writes itself, so a security pass
283
+ of a section, commits or your own changes is never recorded as the pass;
284
+ neither is a pass that stopped early, was abandoned or still has failing
285
+ checks.
286
+
287
+ ## Deep run
288
+
289
+ When the prompt has a `DEEP RUN` section, follow it: it says how the checklist,
290
+ evidence, chunks, commits and report work for every pass. This pass adds to the
291
+ checklist:
292
+
293
+ - every way in from the map (each route, page, command, action, handler,
294
+ webhook, job, file read from outside and outbound call), every sign-in,
295
+ session and token flow, and every secret;
296
+ - the cross-subsystem item: one resource guarded differently on different
297
+ ways in, and a protection applied on some ways in but not on others.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Genesis security pass"
3
+ short_description: "Make every way in refuse what it should, each fix proved by an attack"
4
+ default_prompt: "Use $genesis-security-pass to security pass the whole app."
@@ -0,0 +1,351 @@
1
+ ---
2
+ name: genesis-speed-pass
3
+ description: Make software and its tests take the time their work needs through an explicitly requested speed pass over the whole app, a named section, or the agent's own changes, covering test speed (the whole suite, its preparation and each file), client speed (first load, navigation, requests and the main thread) and server speed (latency at realistic sizes, startup, hot paths and work that runs without use), each wait measured before and after, its cause fixed, and nothing weakened to get there. Use when asked for a speed pass, when tests, pages, saves, commands or startup are slow, or to find where the time goes.
4
+ ---
5
+
6
+ # Genesis speed pass
7
+
8
+ Make the software, and the tests that prove it, take the time their work
9
+ needs, and prove each gain by measuring the same wait before and after. A
10
+ speed pass is explicit: never run it 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
+ A speed pass request may arrive as a complete Genesis-generated prompt or as a
42
+ direct request such as `Speed pass` or `Speed pass the Orders section`.
43
+
44
+ If the current task already contains `GENESIS CONTEXT` whose task is
45
+ `speed-pass`, continue with it directly. Do not generate another prompt.
46
+
47
+ Otherwise, before resolving scope, run the Genesis `prompt --task speed-pass`
48
+ operation once using the invocation rule above. For a bare `Speed 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 speed pass guidance and any project customization with the portable
54
+ contract below.
55
+
56
+ When the user asks for a deep run of this pass, pass its Deep request,
57
+ `Speed pass the whole app deeply.`, exactly;
58
+ Genesis then adds the run's `DEEP RUN` section.
59
+
60
+ ## Resolve the scope
61
+
62
+ Inspect `git status --short` and the staged and unstaged diffs before editing.
63
+ A dirty worktree is allowed. Preserve the existing index and unrelated work; do
64
+ not stage, stash, commit, or discard changes as a prerequisite.
65
+
66
+ When the prompt has a `PASS RUN` section, the request is one of the pass's own
67
+ runs (the whole app, the changes since its last completed run judged against
68
+ the whole app, or a deep run) or a run over the changes since a base commit the
69
+ request names, and its scope is the one that section states, whatever the
70
+ defaults below say. A deep run's prompt also has a `DEEP RUN`
71
+ section; follow it with "Deep run" below.
72
+
73
+ - **The whole app (default).** The test suite and its preparation, every
74
+ screen, view or command a person opens and the main actions in it, and
75
+ every route, job, loop or process the software runs.
76
+ - **A section.** A named area (a module, a route subtree, a set of screens or
77
+ commands, a test folder): its tests, its screens and its server paths,
78
+ touched or not.
79
+ - **The changes.** Your own changes for the current task, or explicit commits,
80
+ established and resolved as for Deslop: the tests, screens and paths they
81
+ create or change, and what they made slower.
82
+
83
+ If the scope is ambiguous, ask which section or changes.
84
+
85
+ ## Measure first
86
+
87
+ Read the engineering approach and these sections of the sanity checks guide
88
+ (`.agents/skills/genesis-project/references/sanity-checks.md`): "How to use
89
+ this guide", "Work that repeats or lingers", "The wait a person sees", "Tests:
90
+ time", "Tests: each owns what it uses", "Tests: nothing hangs or lingers",
91
+ "Screens in use" and "Data: loading a dataset". They describe what good looks
92
+ like; this pass measures the whole scope against them and fixes what they
93
+ find.
94
+
95
+ Then list, for the scope, where people and developers wait: the whole test
96
+ suite and each of its phases, the first screen and each navigation, the main
97
+ actions from click or key press to result, the main routes, commands and jobs,
98
+ startup, and any work that runs while nobody asks for anything. A guess about
99
+ where time goes is usually wrong, and a fix aimed at the wrong place costs
100
+ complexity for nothing, so measure each wait before changing anything:
101
+
102
+ - **Measure what people meet.** Use a realistic build (the production build,
103
+ not a development server), realistic data sizes (hundreds of rows in each
104
+ list, long histories, large files) and, where it matters, a cold start as
105
+ well as a warm one. A development server, an empty database or a warm cache
106
+ hides most of what a person waits for.
107
+ - **Record how each number was taken**: the machine and its load, the build,
108
+ the data size, cold or warm, so the measurement after can be taken the same
109
+ way. Take each one more than once, and compare like with like: the same
110
+ machine, load and data before and after.
111
+ - **Prefer counts where they answer the question.** Requests, queries, bytes,
112
+ processes, renders and preparations per run change less with the machine
113
+ than clock times do. Use a clock for what only a clock shows, and split each
114
+ time into its parts (waiting, network, database, computing, rendering)
115
+ before choosing a fix.
116
+
117
+ The areas below are advice with their reasons. Apply the ones that fit the
118
+ software: a library has no screens, a command-line program has no first page
119
+ load but has a start-up time, and a game measures frame times and level loads
120
+ more than requests. Say which areas do not apply, and why.
121
+
122
+ ## Test speed
123
+
124
+ Every person and agent pays for a slow suite on every run, and a slow suite
125
+ gets run less, so defects land later.
126
+
127
+ Measure:
128
+
129
+ - the whole suite's wall time, and each phase: preparation (databases,
130
+ fixtures, builds, servers), loading code, signing in, and the tests;
131
+ - each file's time, and the slowest files and tests;
132
+ - whether files ran together: a wall time close to the sum of the files' times
133
+ means they ran one after another. Find why: a forced concurrency of one,
134
+ files that collide on a shared resource, or files marked to run alone
135
+ without a reason;
136
+ - in each slow file, where its time goes: preparation repeated per file or
137
+ per test, a migration history replayed, fixed sleeps, polling, a server,
138
+ browser or build started per test, a sign-in per test, the software's own
139
+ retries and debounces waited out in real time, or a check made at an
140
+ expensive level (a browser) that a cheaper one (a unit or component test)
141
+ proves as well.
142
+
143
+ Fix the cause, when possible in the shared harness so every file gains:
144
+
145
+ - **Prepare once per run.** Build databases, fixtures, builds and servers once
146
+ per run, from a stored schema and seed checked by a digest of their sources,
147
+ and restore or reuse them from there; replay the full migration history
148
+ once, as its own check. Something every file only reads (a built app, a
149
+ generated project, a seeded snapshot) can be prepared once and shared
150
+ read-only, while a file that writes into it makes its own copy.
151
+ - **Run files in parallel within the machine's test budget.** Isolate what
152
+ files would share (ports the system picks, temporary directories, a database
153
+ or schema per file, their own caches) rather than running them one at a
154
+ time. A file that truly holds a resource of the whole machine runs alone and
155
+ says why. Stay within the budget: an overloaded machine makes every test
156
+ slower and some of them flaky.
157
+ - **Wait for events, not time.** Each sleep becomes a wait for the condition it
158
+ stood for. The software's own delays (retry backoff, debounce, polling) run
159
+ on a fake clock where the test runner allows it. A wait that often ends at
160
+ its cap is waiting for the wrong thing.
161
+ - **Prove each behavior at the cheapest level that can.** Move a check that
162
+ needs no real browser into a unit or component test, and add a new browser
163
+ assertion to the test that already reaches that screen rather than a new
164
+ file that signs in again.
165
+ - **Load what a test needs with its file**, not inside its timed body, so its
166
+ time limit covers only its own work.
167
+
168
+ Never raise a time limit, add retries, or shrink realistic data or coverage to
169
+ get faster: a raised limit hides the slowness, a retry hides a race, smaller
170
+ data hides work done per row, and a dropped test or assertion stops proving
171
+ behavior. A test that changes its input to skip a wait stops proving the
172
+ skipped path; advance a fake clock instead. A limit far above the measured
173
+ need is a finding too, since it lets the next slowdown pass unseen.
174
+
175
+ Prove it with the whole suite's wall time before and after, on the same
176
+ machine under the same load, with each phase and the slowest files, and the
177
+ same tests and assertions passing. A faster suite that proves less is not
178
+ faster.
179
+
180
+ ## Client speed
181
+
182
+ People wait for the first screen, for each navigation, for each action to show
183
+ its result, and for typing, scrolling or a frame that lags.
184
+
185
+ Measure on a production build, with a cold cache and a warm one, realistic
186
+ data and, where possible, the slower network and device the people who use it
187
+ have:
188
+
189
+ - what the first screen loads before it shows: scripts, styles, fonts and
190
+ images, their sizes compressed and not, the largest chunks and what pulls
191
+ each one in;
192
+ - the network waterfall: requests made one after another that could run
193
+ together, and requests that wait for code that could have started them
194
+ sooner;
195
+ - requests per screen and per action: the same request twice, a request per
196
+ item in a list, polling, and responses much larger than what the screen
197
+ shows;
198
+ - the main thread: long tasks, re-rendering on each keystroke or tick, work
199
+ for content nobody can see (a list rendering every row), and for a game or
200
+ animation, the time per frame, its worst frames and what each spends it on.
201
+
202
+ Fix the causes:
203
+
204
+ - **Load what the screen needs.** Split code a screen does not need into
205
+ chunks loaded with the screens that do, so a library one screen uses does
206
+ not load on every screen, and keep the first screen's code to what every
207
+ screen needs.
208
+ - **Batch requests, and drop duplicates.** Related records in one request
209
+ instead of one per item; one shared read for the same data, however many
210
+ components show it; independent requests started together.
211
+ - **Drop needless polling.** A poll stands in for an event: listen for the
212
+ event where the software has one (a push, a socket message, the action that
213
+ changed the data). A poll that has to stay runs only while its result is
214
+ visible, as rarely as its purpose allows.
215
+ - **Render what is visible.** Page or virtualize long lists, compute derived
216
+ values once per change rather than once per render, and move or split work
217
+ that blocks input.
218
+ - **Keep what does not change.** Content-hashed assets cached for long, images
219
+ at the size they are shown, and data kept while it is fresh, with a stated
220
+ rule for when it changes.
221
+
222
+ Prove it with the numbers before and after: what the first screen loads,
223
+ requests per screen and per action, and the main actions' time from click to
224
+ result, cold and warm.
225
+
226
+ ## Server speed
227
+
228
+ Measure, on test copies at realistic data sizes:
229
+
230
+ - latency of the main routes, commands and jobs, the first after a start and
231
+ later ones, each split into its parts: the database, outbound calls,
232
+ computing in the process, serializing the answer and waiting;
233
+ - startup, from launch to ready to serve, and what it spends that time on;
234
+ - the hot paths of the slow ones, with a profiler where the time is computing:
235
+ work repeated on every request whose answer does not change (reading
236
+ configuration or files, compiling templates or schemas, discovering
237
+ metadata, building clients or connections);
238
+ - outbound calls made one after another that could run together, or made once
239
+ per item;
240
+ - what runs while nobody asks for anything: the processes, servers, timers and
241
+ connections alive after the software has been idle a while, and the work
242
+ they do.
243
+
244
+ Fix the causes:
245
+
246
+ - **Do once what does not change.** Compute it at startup, or cache it with a
247
+ named owner and a stated rule for when it changes, instead of on every
248
+ request.
249
+ - **Nothing runs without real use.** Start a process, server or worker when its
250
+ first real use comes, give it an owner that stops it when it goes idle, and
251
+ keep answers rather than idle processes.
252
+ - **Run independent work together, within a bound.** Calls that do not depend
253
+ on each other run concurrently up to a limit, and a call per item becomes
254
+ one batch.
255
+ - **Work nobody waits for leaves the request.** A slow side effect (sending
256
+ email, building a report, syncing elsewhere) goes to a queue or a job, so the
257
+ request answers once its own work is done.
258
+ - **Start-up does only what serving needs.** Defer optional setup to its first
259
+ use, and keep maintenance out of the paths that serve people.
260
+ - **Answers hold what is used.** Page or stream large answers, and send what
261
+ the screen shows rather than whole records.
262
+
263
+ When the time is in the database, the data pass owns the cure: query counts
264
+ that grow with the rows read, reads narrowed in code instead of in the query,
265
+ and indexes for the filters the software really runs belong to the data pass
266
+ skill (`.agents/skills/genesis-data-pass/SKILL.md`). Apply its method to that
267
+ path, with its counts at a few rows and at a realistic size, or report the
268
+ path as a data pass finding when it lies beyond the scope. This pass does not
269
+ restate those rules; it measures the whole wait, end to end, and reports it
270
+ before and after.
271
+
272
+ ## Measure again, and keep it
273
+
274
+ For each wait:
275
+
276
+ 1. Take the measurement before, recorded as above.
277
+ 2. Fix the cause where it belongs (the shared test harness, the build's
278
+ configuration, the owner of the repeated work, the framework), not at one
279
+ call site, so the next test, screen or route is fast too.
280
+ 3. Take the same measurement after, the same way, and report both as absolute
281
+ numbers ("163 s to 41 s", "38 requests to 6"), never only as a ratio.
282
+ 4. Keep it where a count can guard it: a test that asserts the count (requests
283
+ per screen, queries per path, processes left after idle, preparations per
284
+ run, what the first screen's code imports), seen to fail once without the
285
+ fix. Assert counts rather than tight times, which change with the machine;
286
+ a time bound, where one is needed, is a generous outer limit set from the
287
+ measured need.
288
+ 5. Run the checks the Stack guidance names, and finish with one whole run of
289
+ the suite, timed.
290
+
291
+ ## Boundaries
292
+
293
+ - **Never weaken anything to get faster.** Do not raise a time limit, add a
294
+ retry, skip, shard away or delete a test, drop an assertion, shrink realistic
295
+ data, loosen a check or a protection, serve stale data where fresh data is
296
+ needed, or drop work the product needs. Each hides the cause instead of
297
+ removing it. When the speed someone wants needs a trade (staler data, a
298
+ smaller feature, less coverage), explain the trade and let the person
299
+ decide.
300
+ - The pass changes how the software and its tests spend time, never what they
301
+ do: no behavior, product rule or result changes. Every existing behavior
302
+ assertion stays, and a test moved to a cheaper level is named with where it
303
+ went.
304
+ - Measure on copies the run controls: test databases it creates and drops,
305
+ local builds and local servers. Never measure against a development or
306
+ production database, and never load a production deployment or another
307
+ party's service.
308
+ - Share the machine fairly: stay within its test budget, never fill a shared
309
+ machine with repeated full runs, and wait for long runs without polling.
310
+ - **Fix at the owner.** When the framework, the test runner or a library causes
311
+ the slowness, report the exact change it needs instead of working around it
312
+ in the app.
313
+ - **Report what it can't fix.** A slow outside service, a hosting limit or a
314
+ product decision is reported with its numbers, what it needs and who must
315
+ act.
316
+ - The selected Stack's speed pass guidance names its test runner and the
317
+ machine's test budget, how its build splits client code, its request
318
+ patterns and how to time its server; follow it.
319
+ - You may edit source, configuration, the test harness and tests in scope;
320
+ every existing behavior assertion stays. Do not edit `.genesis/`, Git
321
+ metadata, dependency directories, generated build output, retained
322
+ migration history, or external resources.
323
+
324
+ Leave the pass as ordinary uncommitted work for review and a later normal
325
+ commit. Never amend or rewrite selected commits. Summarize the resolved scope,
326
+ each wait with how it was measured and its numbers before and after, each
327
+ cause found and its fix, the whole suite's wall time before and after with its
328
+ phases and slowest files, the tests guarding each fix and their failing run
329
+ without it, the paths handed to the data pass, the areas that do not apply and
330
+ why, files changed, checks actually run, and everything left unfixed with what
331
+ it needs and who must act.
332
+
333
+ When the prompt ends with a `PASS RECORD` step, take it once the pass has
334
+ finished: the Genesis `passes done speed-pass` operation records it in `genesis/passes.json`,
335
+ an uncommitted change that lands in the pass's own commit. Genesis adds that
336
+ step only to the pass's own runs, whose requests it writes itself, so a speed
337
+ pass of a section, commits or your own changes is never recorded as the pass;
338
+ neither is a pass that stopped early, was abandoned or still has failing
339
+ checks.
340
+
341
+ ## Deep run
342
+
343
+ When the prompt has a `DEEP RUN` section, follow it: it says how the checklist,
344
+ evidence, chunks, commits and report work for every pass. This pass adds to the
345
+ checklist:
346
+
347
+ - every slow test file and phase of the suite, every screen's first load and
348
+ each navigation, every main request, command and job, startup, and work that
349
+ runs while nobody asks for anything, each measured before and after;
350
+ - the cross-subsystem item: the same work done in several places (repeated
351
+ setup, duplicate fetches, the same computation on several paths).
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Genesis speed pass"
3
+ short_description: "Make tests, screens and requests fast, each wait measured before and after"
4
+ default_prompt: "Use $genesis-speed-pass to speed pass the whole app."