genesis-compiler 1.10.14 → 1.10.16
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 +14 -12
- package/package.json +1 -1
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/profiles/engineering/baseline.md +13 -11
- package/prompts/review.txt +12 -1
- package/skills/genesis-project/SKILL.md +4 -1
- package/skills/genesis-project/references/sanity-checks.md +93 -13
- package/src/index/agent-skills.js +4 -1
package/README.md
CHANGED
|
@@ -367,7 +367,9 @@ The same baseline keeps what the software builds fast and correct as it
|
|
|
367
367
|
grows, through checks the agent makes and judges rather than numbers it must
|
|
368
368
|
hit. A request, job or test costs in proportion to the rows it handles, never
|
|
369
369
|
to stored history: the agent counts a list's, batch's or write's queries at a
|
|
370
|
-
few rows and at a realistic number and finds what grows with the rows.
|
|
370
|
+
few rows and at a realistic number and finds what grows with the rows. Each
|
|
371
|
+
read asks the store for exactly the rows the code uses, with filters, existence
|
|
372
|
+
checks and counts in the query and pickers searching on the server. Tests
|
|
371
373
|
take the time their work needs: the agent reads the suite's time and its
|
|
372
374
|
slowest files and fixes where the time goes, prepares test databases once per
|
|
373
375
|
run (usually from a stored snapshot checked by a digest, with the full
|
|
@@ -380,17 +382,17 @@ pre-existing, and a final run is one whole run of the pushed tree. Each declared
|
|
|
380
382
|
constraint and protection is tried with one input that breaks it, access comes
|
|
381
383
|
from the trusted context, and a change others depend on fails loudly where the
|
|
382
384
|
old shape is still used. A short list names what is wrong in any context, such
|
|
383
|
-
as a silently capped read, an edited migration that has
|
|
384
|
-
generated file, or tests against a real database. A time limit
|
|
385
|
-
a slow check is measured and its cause fixed, never hidden by a
|
|
386
|
-
retries or smaller data. Coarse outer limits, such as a list
|
|
387
|
-
queries or a suite running for hours, mark what is clearly
|
|
388
|
-
targets. The baseline is the short form: the
|
|
389
|
-
checks guide (`references/sanity-checks.md`)
|
|
390
|
-
outer limits and is read before the agent
|
|
391
|
-
Stack piece's "Sanity checks with <stack>"
|
|
392
|
-
for them, such as its query counter,
|
|
393
|
-
mode.
|
|
385
|
+
as a silently capped read, a read narrowed in code, an edited migration that has
|
|
386
|
+
run, an edited generated file, or tests against a real database. A time limit
|
|
387
|
+
catches a hang; a slow check is measured and its cause fixed, never hidden by a
|
|
388
|
+
longer limit, retries or smaller data. Coarse outer limits, such as a list
|
|
389
|
+
making hundreds of queries or a suite running for hours, mark what is clearly
|
|
390
|
+
broken; they are not targets. The baseline is the short form: the
|
|
391
|
+
genesis-project skill's sanity checks guide (`references/sanity-checks.md`)
|
|
392
|
+
gives each check's examples and outer limits and is read before the agent
|
|
393
|
+
reports such work done, and each Stack piece's "Sanity checks with <stack>"
|
|
394
|
+
guidance names the stack's own tools for them, such as its query counter,
|
|
395
|
+
parallel test runner and strict loading mode.
|
|
394
396
|
|
|
395
397
|
The installed, versioned profile descriptions live in
|
|
396
398
|
`profiles/engineering/*.md`. Straight Genesis users can inspect and select them
|
package/package.json
CHANGED
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
- Every implementation must be easy to reason about and be the smallest targeted change that fully satisfies the known requirements.
|
|
4
4
|
- Prefer direct control flow, existing ownership boundaries, and established project or technology seams.
|
|
5
|
-
- Do not overengineer or overcomplicate
|
|
5
|
+
- Do not overengineer or overcomplicate: add no speculative abstractions, layers, dependencies, infrastructure, compatibility paths, distributed patterns, cryptography, enterprise patterns or other advanced machinery unless an explicit requirement or concrete constraint needs it.
|
|
6
6
|
- If good software requires material complexity beyond these rules, stop before writing it. Explain the requirement, why the direct design is insufficient, and the smallest added complexity proposed, then ask the user to approve or clarify the tradeoff.
|
|
7
|
-
- A request, job or test costs what the rows it handles cost, never what stored history or the whole dataset costs; this is the direct design, not speculative scale work. Check it
|
|
8
|
-
-
|
|
7
|
+
- A request, job or test costs what the rows it handles cost, never what stored history or the whole dataset costs; this is the direct design, not speculative scale work. Check it: count a list's, batch's or write's queries or storage calls at a few rows and at a realistic number, and judge whether the count follows the pages read or grows with the rows. A count that grows usually means a read, lookup or access check runs per row, or an access check is sized by stored history; related rows come in batches, one query per related table, and every visibility check is bounded by the rows read. A list making hundreds of queries, or a save taking tens of seconds, is broken: find the cause first. Such limits mark what is clearly broken; they are not targets, and code is never bent to reach a number.
|
|
8
|
+
- A read asks the store for exactly the rows the code uses: filters, sorting, limits, existence checks and counts go in the query, and pickers and lookups search on the server.
|
|
9
|
+
- Give list, batch and write paths a test at realistic row counts and history, since a handful of rows hides per-row work; it compares counts at two sizes rather than holding a fixed ceiling tuned until it passes. Tests take the time their work needs, no more: read the suite's total time and slowest files, and find where a slow file's time goes (database preparation, replayed migrations, fixed sleeps, polling, server or build starts). Prepare databases and shared fixtures once per run, usually from a stored schema and seed snapshot checked by a digest of their sources rather than by replaying migrations, and keep the full-history migration proof as one separate check. Each test file owns its data, ports and files and can run beside any other, so identical runs agree; files run in parallel within the machine's test budget, and a suite whose wall time is close to the sum of its files' times ran them one at a time, so find why. A suite that runs for hours, or test preparation measured in minutes, is broken.
|
|
10
|
+
- A new test proves its behavior at the cheapest level; one that is mostly its own setup around one check is not acceptable.
|
|
9
11
|
- A refactor, consolidation or move keeps every behavior, or drops one only with the person's agreement. Before changing code, list what it does (its operations, inputs and their validation, permissions, states and edge cases) with the test covering each, adding one where none does; afterwards walk the list again, with the original tests passing and their assertions unchanged. A change that deletes tests or weakens their assertions is not a refactor.
|
|
10
|
-
- A failing test is a defect to explain, in
|
|
11
|
-
- Every constraint and protection the code declares is enforced: send one input that breaks each (a missing required field, a call past a rate limit, a caller without permission, another tenant's id) and see it refused. Authorization is decided before validation answers, from the trusted context
|
|
12
|
-
- A change
|
|
13
|
-
- Never, whatever the context: cap a read its callers treat as complete; drop a behavior, rule or access decision silently; declare a constraint or protection that nothing enforces; let a client's ids or a missing value decide access; store a missing value as a real one; run tests against a developer's or production database or configuration; edit a migration that has run anywhere; edit a generated file instead of its source; let the first visitor to a new deployment own it; run production with development settings; release a test's servers, processes or timers only where a timeout skips it. Each one silently loses data, protection or a whole run.
|
|
14
|
-
- During implementation, run the relevant checks
|
|
15
|
-
- Bound each long check by a time limit so
|
|
12
|
+
- A failing test is a defect to explain, in product or test, never noise or a "pre-existing" baseline: do not rerun it until it passes, skip it or loosen it to finish. A final run is one run of the whole suite on the tree that is pushed; reruns, chunks and partial runs are reported as partial. A skipped test records its reason and the run that covers it. A new test is seen to fail once, by breaking the behavior or reverting the fix.
|
|
13
|
+
- Every constraint and protection the code declares is enforced: send one input that breaks each (a missing required field, a call past a rate limit, a caller without permission, another tenant's id) and see it refused. Authorization is decided before validation answers, from the trusted context, not ids the client sends, and a missing value, scope or collaborator refuses instead of allowing.
|
|
14
|
+
- A change other code depends on (a name, a default, a contract) fails loudly, naming its fix, wherever the old shape remains, and every dependent project is booted and checked with it.
|
|
15
|
+
- Never, whatever the context: cap a read its callers treat as complete, or narrow a broad or capped read in code; drop a behavior, rule or access decision silently; declare a constraint or protection that nothing enforces; let a client's ids or a missing value decide access; store a missing value as a real one; run tests against a developer's or production database or configuration; edit a migration that has run anywhere; edit a generated file instead of its source; let the first visitor to a new deployment own it; run production with development settings; release a test's servers, processes or timers only where a timeout skips it; stop a process by name or pattern (`pkill`, `killall`, `kill $(pgrep ...)`) instead of the pid you started. Each one silently loses data, protection or a whole run.
|
|
16
|
+
- During implementation, run the relevant checks, batching cases that share setup. Follow the project's verification policy for broad or final checks; do not repeat them just because an item finishes or a session resumes. Preserve required coverage and isolation.
|
|
17
|
+
- Bound each long check by a time limit so a hang ends it; write its full output and exit status to a local file. Then read counts, timings and failure excerpts, expanding only when needed; never load full passing reports into context. Retain startup and cleanup failures; retry only after a change or new evidence justifies it.
|
|
16
18
|
- A time limit catches a hang; it does not fix slowness. When a check, test or request is slower than its work needs, measure where the time goes and fix the cause; never raise a time limit, add retries, repeat a call or shrink realistic data or coverage to make it pass.
|
|
17
|
-
- For browser verification, batch related actions
|
|
18
|
-
-
|
|
19
|
+
- For browser verification, batch related actions, return only the relevant values or page region, and take screenshots at visual checkpoints or failures, not after every action. Preserve required viewport, identity and security coverage; prefer existing automated cases for repeated checks.
|
|
20
|
+
- The sanity checks guide (`.agents/skills/genesis-project/references/sanity-checks.md`) gives each check's examples and outer limits: read the section that applies before reporting data access, tests, a refactor, a screen or a release done, and apply it with the tools your Stack pieces name.
|
package/prompts/review.txt
CHANGED
|
@@ -27,11 +27,22 @@ timing where one exists and the code path otherwise: a list or batch whose
|
|
|
27
27
|
query count grows with its rows, an access check whose cost grows with stored
|
|
28
28
|
history, a list, batch or write path never tested at realistic counts, test
|
|
29
29
|
preparation that replays the migration history, tests that share drifting data
|
|
30
|
-
or cannot run in parallel, and a time limit raised to absorb slowness.
|
|
30
|
+
or cannot run in parallel, and a time limit raised to absorb slowness. Search
|
|
31
|
+
for reads whose rows are then filtered, found, sliced or tested in code,
|
|
32
|
+
pickers and lookups included, and for capped reads (the latest N, a default
|
|
33
|
+
page) used as if complete: each belongs in the query unless the code shows the
|
|
34
|
+
store cannot express it, and a capped one also loses every match past the cap,
|
|
35
|
+
so report it as a defect, not only a cost. Report
|
|
31
36
|
behavior a refactor dropped: operations, validation, permissions or edge cases
|
|
32
37
|
the earlier code had and the current code lacks, and tests deleted or weakened
|
|
33
38
|
with it. Report declared constraints and protections that nothing enforces, and
|
|
34
39
|
access decided from ids the client sends rather than the trusted context.
|
|
40
|
+
Judge the structure, not only the change, since a change can look fine alone
|
|
41
|
+
in an application that lacks a layer: run the project's lint and checks and
|
|
42
|
+
read what they report; ask whether every table has one owner, whether every
|
|
43
|
+
query of a table goes through that owner, and whether an owner or repository
|
|
44
|
+
layer exists at all; and report work over a whole population (every user,
|
|
45
|
+
row or tenant) done inside a request rather than over the request's own rows.
|
|
35
46
|
Judge each against the matching section and outer limit of
|
|
36
47
|
`.agents/skills/genesis-project/references/sanity-checks.md`.
|
|
37
48
|
|
|
@@ -170,7 +170,10 @@ row counts and history that compares its query count at a few rows and at a
|
|
|
170
170
|
realistic number. Read the run's preparation, suite and slowest-file timings
|
|
171
171
|
with its counts; when one grows with the data, find the cause (a read per row,
|
|
172
172
|
an access check sized by stored history, test preparation that replays
|
|
173
|
-
migrations) before reporting completion.
|
|
173
|
+
migrations) before reporting completion. Search the changed reads, pickers and
|
|
174
|
+
lookups included, for rows filtered, found, sliced or tested in code and for a
|
|
175
|
+
capped read used as if complete; move each into the query, or state in the code
|
|
176
|
+
why the store cannot express it. After a refactor, walk the behavior
|
|
174
177
|
list made before it and report any item that no longer holds. Before reporting
|
|
175
178
|
data access, tests, a refactor, a screen or a release done, read the matching
|
|
176
179
|
section of [the sanity checks guide](references/sanity-checks.md) and apply its
|
|
@@ -21,6 +21,8 @@ reporting data access, tests, a refactor, a screen or a release done.
|
|
|
21
21
|
Each one silently loses data, protection or a whole run.
|
|
22
22
|
|
|
23
23
|
- Cap a read its callers treat as complete: they act on a silent first page.
|
|
24
|
+
- Narrow a broad or capped read in code: a broad one reads what it discards, a
|
|
25
|
+
capped one loses every match past the cap.
|
|
24
26
|
- Drop a behavior, rule or access decision silently in a restructure.
|
|
25
27
|
- Declare a constraint or protection that nothing enforces.
|
|
26
28
|
- Let a client's ids or a missing value decide access.
|
|
@@ -30,8 +32,34 @@ Each one silently loses data, protection or a whole run.
|
|
|
30
32
|
- Let the first visitor to a new deployment own it.
|
|
31
33
|
- Run production with development settings, fallbacks, hosts or secrets.
|
|
32
34
|
- Release a test's servers, processes or timers only where a timeout skips it.
|
|
35
|
+
- Stop a process by name or pattern (`pkill`, `killall`, `kill $(pgrep ...)`)
|
|
36
|
+
instead of the pid you started or the project's stop command: the match also
|
|
37
|
+
stops other projects' servers on the same machine.
|
|
33
38
|
- Edit a generated file instead of its source: the next generation erases it.
|
|
34
39
|
|
|
40
|
+
## Data: one owner per table
|
|
41
|
+
|
|
42
|
+
**Good:** every table has one owner, a repository or resource module, and every
|
|
43
|
+
query of the table goes through it, so the table's scoping, validation and
|
|
44
|
+
locking live in one place. A request works on the rows it concerns; work over a
|
|
45
|
+
whole population runs as a job in bounded chunks.
|
|
46
|
+
|
|
47
|
+
**Check:** judge the structure, not only a change. Run the project's lint and
|
|
48
|
+
checks and read what they report. For each table, name its owner and search for
|
|
49
|
+
queries that reach the table from anywhere else: routes, services, another
|
|
50
|
+
table's owner, raw SQL. Read each request path for work that covers every user,
|
|
51
|
+
row or tenant (a recount, a backfill, a sweep) instead of the request's own
|
|
52
|
+
rows. Each read and write path needs a test that seeds a second owner and sees
|
|
53
|
+
its rows stay unseen and unchanged, write hooks and side effects included.
|
|
54
|
+
|
|
55
|
+
**Examples:**
|
|
56
|
+
- An application had no repository layer: each route queried the tables it
|
|
57
|
+
needed with its own copy of the tenant filter, and every change looked fine
|
|
58
|
+
in a review of that change alone.
|
|
59
|
+
|
|
60
|
+
**Outer limit:** an application with no owner layer, a table written from
|
|
61
|
+
several places, or a request whose work grows with the whole population.
|
|
62
|
+
|
|
35
63
|
## Data: loading a dataset
|
|
36
64
|
|
|
37
65
|
**Good:** a list, page or report takes about as many queries for 10 rows as
|
|
@@ -65,18 +93,46 @@ Compare a response's size with what the screen shows of it.
|
|
|
65
93
|
a quiet database, runs the same access check more than a few times per
|
|
66
94
|
request, or returns megabytes for one screen is broken. Find the loop first.
|
|
67
95
|
|
|
96
|
+
## Data: each read asks for the rows it uses
|
|
97
|
+
|
|
98
|
+
**Good:** a read asks the data store for exactly the rows the code uses.
|
|
99
|
+
Filtering, sorting, limits, existence checks and counts go in the query. A
|
|
100
|
+
picker, lookup or autocomplete asks the server for the narrowed set, searching
|
|
101
|
+
on the server, instead of loading a list and filtering it in the browser.
|
|
102
|
+
|
|
103
|
+
**Check:** search for reads whose results are then filtered, found, sliced or
|
|
104
|
+
tested in code (`filter`, `find`, `some`, `slice`, a loop that skips rows, a
|
|
105
|
+
length taken to count rows or test for one), and for capped reads (the latest
|
|
106
|
+
N, a default page, a fixed limit) used as if complete. Move each into the
|
|
107
|
+
query, or the code states why the store cannot express it. A capped read
|
|
108
|
+
narrowed afterwards also loses every match past the cap, so it is a
|
|
109
|
+
correctness bug, not only a cost: seed more rows than the cap, with the oldest
|
|
110
|
+
one matching, and see it found.
|
|
111
|
+
|
|
112
|
+
**Examples:**
|
|
113
|
+
- Pickers loaded the latest 200 records of every kind and kept one kind in
|
|
114
|
+
code: slow, and a matching record older than the newest 200 never appeared.
|
|
115
|
+
|
|
116
|
+
**Outer limit:** a capped read narrowed in code is broken at any size.
|
|
117
|
+
|
|
68
118
|
## Data: saves, batches and background work
|
|
69
119
|
|
|
70
120
|
**Good:** a batch writes each table in a few statements inside the owner's
|
|
71
121
|
transaction, not one full create per row. Work nobody waits for runs as a
|
|
72
|
-
scheduled or queued job in bounded chunks
|
|
73
|
-
|
|
122
|
+
scheduled or queued job in bounded chunks: it loops over units of work (a
|
|
123
|
+
tenant, a user), one transaction each, never one around the whole run and
|
|
124
|
+
never one per row. A read request takes no lock and writes nothing. Every path
|
|
125
|
+
takes its locks in one order, parents before children, so two transactions
|
|
126
|
+
never wait on each other. Two writers on the same records never produce a
|
|
127
|
+
server error.
|
|
74
128
|
|
|
75
129
|
**Check:** count a batch's statements at 10 items and at 500. Look for due work
|
|
76
130
|
run inside whichever request comes first, and one long transaction around it.
|
|
77
131
|
Find any lock or write a read path takes for one-time setup: read first, lock
|
|
78
|
-
only on the rare unset path.
|
|
79
|
-
transaction must be safe to
|
|
132
|
+
only on the rare unset path. Compare the order in which each path locks rows.
|
|
133
|
+
Run two writers on the same records; a retried transaction must be safe to
|
|
134
|
+
repeat, so HTTP calls, email and uploads go before or after it, or into an
|
|
135
|
+
outbox row written inside it.
|
|
80
136
|
|
|
81
137
|
**Examples:**
|
|
82
138
|
- An import created each row through the full single-record create path, with
|
|
@@ -122,8 +178,8 @@ decision, or drops one only with the person's agreement.
|
|
|
122
178
|
|
|
123
179
|
**Check:** before changing code, list its operations, inputs and their
|
|
124
180
|
validation, permissions per role, states and edge cases, with the test covering
|
|
125
|
-
each
|
|
126
|
-
assertions unchanged. Compare per-file test counts before and after, and name
|
|
181
|
+
each; pin what a path answers with a test before moving it. Afterwards walk the
|
|
182
|
+
list again with the original tests passing and their assertions unchanged. Compare per-file test counts before and after, and name
|
|
127
183
|
each removal. Search for what a removed caller was the only caller of. After a
|
|
128
184
|
mechanical sweep, compare files changed with files expected and search for the
|
|
129
185
|
old form. A new mechanism replaces the one already doing the job.
|
|
@@ -161,26 +217,50 @@ look green, or dozens of skips nobody can place.
|
|
|
161
217
|
**Good:** tests take the time their work needs. Files run in parallel within
|
|
162
218
|
the machine's test budget. Databases and fixtures are prepared once per run
|
|
163
219
|
from a stored schema and seed, checked by a digest of their sources, and the
|
|
164
|
-
full migration history is replayed once, as its own check. Builds and server
|
|
220
|
+
full migration history is replayed once, as its own check. Builds and server
|
|
221
|
+
starts happen once per run. Each test proves its behavior at the cheapest
|
|
222
|
+
level that can: rules and calculations in a unit test; data, access and
|
|
223
|
+
refusals in a server or integration test; a component's content and states in
|
|
224
|
+
a component test. A browser test checks only what needs a real browser (a flow
|
|
225
|
+
across screens, navigation, layout at the standard widths, focus, the real
|
|
226
|
+
sign-in); a new browser check is an assertion in the existing test that already
|
|
227
|
+
reaches that screen, and a new browser test file is for a new flow. The app's
|
|
228
|
+
own delays (retry backoff, debounce, polling) run on a fake clock, never in
|
|
229
|
+
real time.
|
|
165
230
|
|
|
166
231
|
**Check:** after every run, read the suite time, each phase's time
|
|
167
232
|
(preparation, import, sign-in, tests) and the slowest files. A wall time close
|
|
168
233
|
to the sum of the files' times means they ran one at a time: find why. In a
|
|
169
234
|
slow file, find where the time goes: repeated preparation, replayed
|
|
170
|
-
migrations, fixed sleeps, polling, a process per test, repeated builds
|
|
171
|
-
sign-ins. Split test time into the app's request time and the
|
|
172
|
-
choosing a fix. Remove exact repeats across CI jobs. Each
|
|
173
|
-
condition it waits for; wait for that. Compare each raised
|
|
174
|
-
measured need, and check a limit exists. Assert counts,
|
|
235
|
+
migrations, fixed sleeps, polling, a process per test, repeated builds,
|
|
236
|
+
sign-ins or page loads. Split test time into the app's request time and the
|
|
237
|
+
harness's before choosing a fix. Remove exact repeats across CI jobs. Each
|
|
238
|
+
sleep names the condition it waits for; wait for that. Compare each raised
|
|
239
|
+
time limit with the measured need, and check a limit exists. Assert counts,
|
|
240
|
+
not tight times. Before adding a test, find the cheapest level that proves the
|
|
241
|
+
behavior and the existing test that already pays its setup; after adding it,
|
|
242
|
+
report its time, how much of that is setup, and the suite's time before and
|
|
243
|
+
after. A test that is mostly setup around one check is in the wrong place:
|
|
244
|
+
move the check, then see it fail once there. A test that changes its input to
|
|
245
|
+
skip a wait (another error, a shorter path) stops proving the skipped path:
|
|
246
|
+
advance the clock instead, unless another test already proves that path.
|
|
175
247
|
|
|
176
248
|
**Examples:**
|
|
177
249
|
- 359 tests ran one file at a time, 163 s in all, because the test command
|
|
178
250
|
forced a concurrency of one.
|
|
179
251
|
- Test databases were rebuilt by replaying every migration for each file.
|
|
180
252
|
- Time limits were raised until slow tests passed, and the slowness stayed.
|
|
253
|
+
- A new browser test file took 21 s for two cases checking what one card on a
|
|
254
|
+
page shows. A component test proves that in milliseconds, and the page's
|
|
255
|
+
existing browser test could carry the one layout assertion for nothing.
|
|
256
|
+
- A browser test waited out the app's two retries of a failed request in real
|
|
257
|
+
time, 3 s on every run.
|
|
181
258
|
|
|
182
259
|
**Outer limit:** a suite running for hours (a small app's for an hour),
|
|
183
|
-
preparation in minutes, or a limit ten times the measured need.
|
|
260
|
+
preparation in minutes, or a limit ten times the measured need. A new test
|
|
261
|
+
whose time is mostly its own setup, for a check that a cheaper level or an
|
|
262
|
+
existing test could make, is not acceptable: every run, by every person and
|
|
263
|
+
agent, pays for it for as long as it exists.
|
|
184
264
|
|
|
185
265
|
## Tests: each owns what it uses
|
|
186
266
|
|
|
@@ -305,7 +305,10 @@ async function resolveLocator(locator) {
|
|
|
305
305
|
: `genesis:${locator.path}`
|
|
306
306
|
);
|
|
307
307
|
const skill = await describeSkill(directory, source);
|
|
308
|
-
|
|
308
|
+
// A selected skill the installed package does not contain is missing from the project's dependencies, not malformed.
|
|
309
|
+
if (!skill) {
|
|
310
|
+
throw new GenesisError('AGENT_SKILL_UNAVAILABLE', `Selected Agent Skill is unavailable: ${directory}.`, { path: directory });
|
|
311
|
+
}
|
|
309
312
|
return { ...skill, component: locator.component };
|
|
310
313
|
}
|
|
311
314
|
|