genesis-compiler 1.10.13 → 1.10.15
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 +18 -13
- package/package.json +1 -1
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/profiles/engineering/baseline.md +11 -9
- package/prompts/review.txt +12 -1
- package/skills/genesis-project/SKILL.md +4 -1
- package/skills/genesis-project/references/sanity-checks.md +90 -13
- package/src/index/agent-skills.js +10 -1
- package/src/index/session-context.js +30 -8
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
|
|
@@ -1078,7 +1080,10 @@ and diagnostics for missing, invalid, outdated, customized, or unmanaged skills.
|
|
|
1078
1080
|
Synchronization returns changed paths, preservation diagnostics, and the resulting
|
|
1079
1081
|
`inspection`. Hosts own source-write exclusion and assistant context lifecycle.
|
|
1080
1082
|
`projectSessionContext()` composes stable project guidance with one explicitly
|
|
1081
|
-
supplied host-driver result.
|
|
1083
|
+
supplied host-driver result. A project file Genesis cannot read does not stop
|
|
1084
|
+
it: the context names the file, the line and the text Genesis found there, so
|
|
1085
|
+
the agent can repair it. That includes an Agent Skill source and an agent
|
|
1086
|
+
integration file such as `.claude/settings.json`. `projectTurnContext()` invokes that same optional
|
|
1082
1087
|
driver for the separate untrusted turn lane without accepting user-message
|
|
1083
1088
|
text.
|
|
1084
1089
|
`getContext()` resolves source paths to the Program modules that cite 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 a concrete constraint makes it necessary.
|
|
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 being 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 its 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 two identical runs give the same result; 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 the product or in the 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
|
|
12
|
+
- A failing test is a defect to explain, in the product or in the 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.
|
|
11
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 rather than ids the client sends, and a missing value, scope or collaborator refuses instead of allowing.
|
|
12
14
|
- A change that other code depends on (a name, a default, a contract) fails loudly, naming its fix, wherever the old shape is still used, and every dependent project is booted and checked with it.
|
|
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
|
|
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. 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 complete output to a local file and keep its exit status. Then read counts, timings and failure excerpts first, expanding only when needed; never load full passing reports into agent 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
|
+
- Genesis's 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.
|
|
@@ -32,6 +34,29 @@ Each one silently loses data, protection or a whole run.
|
|
|
32
34
|
- Release a test's servers, processes or timers only where a timeout skips it.
|
|
33
35
|
- Edit a generated file instead of its source: the next generation erases it.
|
|
34
36
|
|
|
37
|
+
## Data: one owner per table
|
|
38
|
+
|
|
39
|
+
**Good:** every table has one owner, a repository or resource module, and every
|
|
40
|
+
query of the table goes through it, so the table's scoping, validation and
|
|
41
|
+
locking live in one place. A request works on the rows it concerns; work over a
|
|
42
|
+
whole population runs as a job in bounded chunks.
|
|
43
|
+
|
|
44
|
+
**Check:** judge the structure, not only a change. Run the project's lint and
|
|
45
|
+
checks and read what they report. For each table, name its owner and search for
|
|
46
|
+
queries that reach the table from anywhere else: routes, services, another
|
|
47
|
+
table's owner, raw SQL. Read each request path for work that covers every user,
|
|
48
|
+
row or tenant (a recount, a backfill, a sweep) instead of the request's own
|
|
49
|
+
rows. Each read and write path needs a test that seeds a second owner and sees
|
|
50
|
+
its rows stay unseen and unchanged, write hooks and side effects included.
|
|
51
|
+
|
|
52
|
+
**Examples:**
|
|
53
|
+
- An application had no repository layer: each route queried the tables it
|
|
54
|
+
needed with its own copy of the tenant filter, and every change looked fine
|
|
55
|
+
in a review of that change alone.
|
|
56
|
+
|
|
57
|
+
**Outer limit:** an application with no owner layer, a table written from
|
|
58
|
+
several places, or a request whose work grows with the whole population.
|
|
59
|
+
|
|
35
60
|
## Data: loading a dataset
|
|
36
61
|
|
|
37
62
|
**Good:** a list, page or report takes about as many queries for 10 rows as
|
|
@@ -65,18 +90,46 @@ Compare a response's size with what the screen shows of it.
|
|
|
65
90
|
a quiet database, runs the same access check more than a few times per
|
|
66
91
|
request, or returns megabytes for one screen is broken. Find the loop first.
|
|
67
92
|
|
|
93
|
+
## Data: each read asks for the rows it uses
|
|
94
|
+
|
|
95
|
+
**Good:** a read asks the data store for exactly the rows the code uses.
|
|
96
|
+
Filtering, sorting, limits, existence checks and counts go in the query. A
|
|
97
|
+
picker, lookup or autocomplete asks the server for the narrowed set, searching
|
|
98
|
+
on the server, instead of loading a list and filtering it in the browser.
|
|
99
|
+
|
|
100
|
+
**Check:** search for reads whose results are then filtered, found, sliced or
|
|
101
|
+
tested in code (`filter`, `find`, `some`, `slice`, a loop that skips rows, a
|
|
102
|
+
length taken to count rows or test for one), and for capped reads (the latest
|
|
103
|
+
N, a default page, a fixed limit) used as if complete. Move each into the
|
|
104
|
+
query, or the code states why the store cannot express it. A capped read
|
|
105
|
+
narrowed afterwards also loses every match past the cap, so it is a
|
|
106
|
+
correctness bug, not only a cost: seed more rows than the cap, with the oldest
|
|
107
|
+
one matching, and see it found.
|
|
108
|
+
|
|
109
|
+
**Examples:**
|
|
110
|
+
- Pickers loaded the latest 200 records of every kind and kept one kind in
|
|
111
|
+
code: slow, and a matching record older than the newest 200 never appeared.
|
|
112
|
+
|
|
113
|
+
**Outer limit:** a capped read narrowed in code is broken at any size.
|
|
114
|
+
|
|
68
115
|
## Data: saves, batches and background work
|
|
69
116
|
|
|
70
117
|
**Good:** a batch writes each table in a few statements inside the owner's
|
|
71
118
|
transaction, not one full create per row. Work nobody waits for runs as a
|
|
72
|
-
scheduled or queued job in bounded chunks
|
|
73
|
-
|
|
119
|
+
scheduled or queued job in bounded chunks: it loops over units of work (a
|
|
120
|
+
tenant, a user), one transaction each, never one around the whole run and
|
|
121
|
+
never one per row. A read request takes no lock and writes nothing. Every path
|
|
122
|
+
takes its locks in one order, parents before children, so two transactions
|
|
123
|
+
never wait on each other. Two writers on the same records never produce a
|
|
124
|
+
server error.
|
|
74
125
|
|
|
75
126
|
**Check:** count a batch's statements at 10 items and at 500. Look for due work
|
|
76
127
|
run inside whichever request comes first, and one long transaction around it.
|
|
77
128
|
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
|
|
129
|
+
only on the rare unset path. Compare the order in which each path locks rows.
|
|
130
|
+
Run two writers on the same records; a retried transaction must be safe to
|
|
131
|
+
repeat, so HTTP calls, email and uploads go before or after it, or into an
|
|
132
|
+
outbox row written inside it.
|
|
80
133
|
|
|
81
134
|
**Examples:**
|
|
82
135
|
- An import created each row through the full single-record create path, with
|
|
@@ -122,8 +175,8 @@ decision, or drops one only with the person's agreement.
|
|
|
122
175
|
|
|
123
176
|
**Check:** before changing code, list its operations, inputs and their
|
|
124
177
|
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
|
|
178
|
+
each; pin what a path answers with a test before moving it. Afterwards walk the
|
|
179
|
+
list again with the original tests passing and their assertions unchanged. Compare per-file test counts before and after, and name
|
|
127
180
|
each removal. Search for what a removed caller was the only caller of. After a
|
|
128
181
|
mechanical sweep, compare files changed with files expected and search for the
|
|
129
182
|
old form. A new mechanism replaces the one already doing the job.
|
|
@@ -161,26 +214,50 @@ look green, or dozens of skips nobody can place.
|
|
|
161
214
|
**Good:** tests take the time their work needs. Files run in parallel within
|
|
162
215
|
the machine's test budget. Databases and fixtures are prepared once per run
|
|
163
216
|
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
|
|
217
|
+
full migration history is replayed once, as its own check. Builds and server
|
|
218
|
+
starts happen once per run. Each test proves its behavior at the cheapest
|
|
219
|
+
level that can: rules and calculations in a unit test; data, access and
|
|
220
|
+
refusals in a server or integration test; a component's content and states in
|
|
221
|
+
a component test. A browser test checks only what needs a real browser (a flow
|
|
222
|
+
across screens, navigation, layout at the standard widths, focus, the real
|
|
223
|
+
sign-in); a new browser check is an assertion in the existing test that already
|
|
224
|
+
reaches that screen, and a new browser test file is for a new flow. The app's
|
|
225
|
+
own delays (retry backoff, debounce, polling) run on a fake clock, never in
|
|
226
|
+
real time.
|
|
165
227
|
|
|
166
228
|
**Check:** after every run, read the suite time, each phase's time
|
|
167
229
|
(preparation, import, sign-in, tests) and the slowest files. A wall time close
|
|
168
230
|
to the sum of the files' times means they ran one at a time: find why. In a
|
|
169
231
|
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,
|
|
232
|
+
migrations, fixed sleeps, polling, a process per test, repeated builds,
|
|
233
|
+
sign-ins or page loads. Split test time into the app's request time and the
|
|
234
|
+
harness's before choosing a fix. Remove exact repeats across CI jobs. Each
|
|
235
|
+
sleep names the condition it waits for; wait for that. Compare each raised
|
|
236
|
+
time limit with the measured need, and check a limit exists. Assert counts,
|
|
237
|
+
not tight times. Before adding a test, find the cheapest level that proves the
|
|
238
|
+
behavior and the existing test that already pays its setup; after adding it,
|
|
239
|
+
report its time, how much of that is setup, and the suite's time before and
|
|
240
|
+
after. A test that is mostly setup around one check is in the wrong place:
|
|
241
|
+
move the check, then see it fail once there. A test that changes its input to
|
|
242
|
+
skip a wait (another error, a shorter path) stops proving the skipped path:
|
|
243
|
+
advance the clock instead, unless another test already proves that path.
|
|
175
244
|
|
|
176
245
|
**Examples:**
|
|
177
246
|
- 359 tests ran one file at a time, 163 s in all, because the test command
|
|
178
247
|
forced a concurrency of one.
|
|
179
248
|
- Test databases were rebuilt by replaying every migration for each file.
|
|
180
249
|
- Time limits were raised until slow tests passed, and the slowness stayed.
|
|
250
|
+
- A new browser test file took 21 s for two cases checking what one card on a
|
|
251
|
+
page shows. A component test proves that in milliseconds, and the page's
|
|
252
|
+
existing browser test could carry the one layout assertion for nothing.
|
|
253
|
+
- A browser test waited out the app's two retries of a failed request in real
|
|
254
|
+
time, 3 s on every run.
|
|
181
255
|
|
|
182
256
|
**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.
|
|
257
|
+
preparation in minutes, or a limit ten times the measured need. A new test
|
|
258
|
+
whose time is mostly its own setup, for a check that a cheaper level or an
|
|
259
|
+
existing test could make, is not acceptable: every run, by every person and
|
|
260
|
+
agent, pays for it for as long as it exists.
|
|
184
261
|
|
|
185
262
|
## Tests: each owns what it uses
|
|
186
263
|
|
|
@@ -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
|
|
|
@@ -315,6 +318,12 @@ export async function projectSkillPlan(stack, { projectRoot } = {}) {
|
|
|
315
318
|
if (projectRoot) {
|
|
316
319
|
let manifest;
|
|
317
320
|
try { manifest = JSON.parse(await readFile(path.join(projectRoot, 'package.json'), 'utf8')); } catch (error) {
|
|
321
|
+
// The manifest says whether the project declares its own genesis-compiler skills.
|
|
322
|
+
if (error instanceof SyntaxError) {
|
|
323
|
+
throw new GenesisError('AGENT_SKILL_SOURCE_INVALID',
|
|
324
|
+
`package.json is not valid JSON, so the project's genesis-compiler skills cannot be located: ${error.message}.`,
|
|
325
|
+
{ path: 'package.json' });
|
|
326
|
+
}
|
|
318
327
|
if (!['ENOENT', 'ENOTDIR'].includes(error?.code)) throw error;
|
|
319
328
|
}
|
|
320
329
|
if (manifest?.name === 'genesis-compiler') {
|
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { readCollaboration } from './collaboration.js';
|
|
2
|
+
import { inspectAgentIntegrations } from './agent-integrations.js';
|
|
2
3
|
import { inspectProjectSkills, renderAgentSkillCatalog } from './agent-skills.js';
|
|
3
4
|
import { GENESIS_CONTRACTS } from './contracts.js';
|
|
4
5
|
import { readEngineering, readEngineeringBaseline } from './engineering.js';
|
|
5
6
|
import { asDiagnostic } from './errors.js';
|
|
6
7
|
import { gitContext } from './git.js';
|
|
8
|
+
import { STACK_PATH } from './paths.js';
|
|
7
9
|
import { inspectProjectAtRoot } from './project-inspection.js';
|
|
8
10
|
import { readStack } from './stack.js';
|
|
9
11
|
import { listStackCatalogPieces } from './stack-catalog.js';
|
|
10
12
|
import { composedContext, hostContextContribution } from './host-context.js';
|
|
11
13
|
|
|
14
|
+
/**
|
|
15
|
+
* A diagnostic as the agent needs it to repair the file: the file, the line and the text found there,
|
|
16
|
+
* when Genesis knows them. Stack section parsers number lines within their section.
|
|
17
|
+
*/
|
|
18
|
+
function diagnosticText({ message, details }) {
|
|
19
|
+
const file = typeof details?.path === 'string' ? details.path : '';
|
|
20
|
+
const line = Number.isSafeInteger(details?.line)
|
|
21
|
+
? ` (line ${details.line}${file === STACK_PATH ? ' of its section' : ''})`
|
|
22
|
+
: '';
|
|
23
|
+
const where = file && (line || !message.includes(file)) ? `${file}${line}: ` : '';
|
|
24
|
+
const found = typeof details?.observed === 'string' ? ` Found: ${JSON.stringify(details.observed)}.` : '';
|
|
25
|
+
return `${where}${message}${found}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
async function optionalStack(projectRoot, stackPackages) {
|
|
13
29
|
try { return await readStack(projectRoot, { stackPackages }); } catch { return null; }
|
|
14
30
|
}
|
|
@@ -68,11 +84,16 @@ export async function projectSessionContext({
|
|
|
68
84
|
inspectProjectAtRoot(root, { stackPackages, count: false }),
|
|
69
85
|
]);
|
|
70
86
|
const availableComponents = await optionalStackComponentIds(root, stack, stackPackages);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}))
|
|
75
|
-
|
|
87
|
+
const current = inspection.projectFormat.status === 'current';
|
|
88
|
+
const [skills, integrations] = await Promise.all([
|
|
89
|
+
stack && current
|
|
90
|
+
? inspectProjectSkills({ projectRoot: root, stack }).catch((error) => ({
|
|
91
|
+
diagnostics: [asDiagnostic(error)],
|
|
92
|
+
}))
|
|
93
|
+
: { diagnostics: [] },
|
|
94
|
+
// Only an integration file Genesis cannot read is reported; a missing or outdated one is synchronization work.
|
|
95
|
+
current ? inspectAgentIntegrations({ projectRoot: root }).then(() => [], (error) => [asDiagnostic(error)]) : [],
|
|
96
|
+
]);
|
|
76
97
|
const selected = stack?.components.map(({ id }) => id) || [];
|
|
77
98
|
const stackStatus = stack
|
|
78
99
|
? (selected.length > 0 ? selected.join(', ') : 'none')
|
|
@@ -85,7 +106,7 @@ export async function projectSessionContext({
|
|
|
85
106
|
] : inspection.state === 'adoption' ? [
|
|
86
107
|
'- Existing project content needs description and configuration. Ask what this project does and what the user wants to run, using answers already supplied. Inspect its implementation to work backwards into Blueprint, Stack and Program. Do not offer seeds or replace existing source/history. Run `genesis adopt` and follow its prompt; initialized Genesis files already express the user’s decision to use Genesis.',
|
|
87
108
|
] : inspection.state === 'attention' ? [
|
|
88
|
-
`- Genesis needs attention: ${inspection.diagnostics.map(
|
|
109
|
+
`- Genesis needs attention: ${inspection.diagnostics.map(diagnosticText).join(' ')} Next action: ${inspection.nextAction}. Preserve source and explain the specific issue before the relevant migration or repair. Do not offer seeds.`,
|
|
89
110
|
] : []),
|
|
90
111
|
'- Opening or resuming a session only reads project metadata and content paths. Do not run verification, tests, builds, dependency installation, or database preparation just because a session started. Run relevant checks when the requested work calls for them.',
|
|
91
112
|
'- Read `genesis/blueprint.md`, `genesis/collaboration.md`, `genesis/engineering.md`, and `genesis/stack.md` for product intent, collaboration approach, engineering approach, and selected technology.',
|
|
@@ -95,8 +116,9 @@ export async function projectSessionContext({
|
|
|
95
116
|
'- When the user names an unselected technology that exactly matches this catalog, run `genesis stack list`, ask whether to add and prepare it, and wait for confirmation. If confirmed, run `genesis stack add <piece...>` and follow its returned preparation prompt in the same task; then use `genesis context` and any installed technology skill. Never infer dependency commands from a component id. If declined or unmatched, continue through authoritative technology documentation without inventing a component.',
|
|
96
117
|
'- Project-owned operation sections in `genesis/stack.md` are the durable application contract. Make the implementation satisfy them or update a complete section to match evidenced reality; Genesis executes only Verification.',
|
|
97
118
|
'- Use the relevant project Agent Skills below `.agents/skills/`.',
|
|
98
|
-
...skills.diagnostics.map((
|
|
119
|
+
...skills.diagnostics.map((diagnostic) => `- Agent Skill maintenance: ${diagnosticText(diagnostic)}`),
|
|
99
120
|
...(skills.diagnostics.length > 0 ? ['- Skill inspection is read-only. Synchronization is an explicit source change; follow the current task authorization and host write boundary before running it.'] : []),
|
|
121
|
+
...integrations.map((diagnostic) => `- Agent integration maintenance: ${diagnosticText(diagnostic)}`),
|
|
100
122
|
'- After locating source, run `genesis context <path...>`; before adding a helper or public operation, run `genesis index <name-or-path...>` and reuse an existing owner.',
|
|
101
123
|
'- If genesis/subsystems.md is missing or empty in an existing explained application, author it from source, schema and existing Program before implementation. This is ordinary explanatory adoption, not a startup blocker; do not run tests or application commands merely to create the map.',
|
|
102
124
|
'- Read genesis/subsystems.md for declared subsystem responsibilities, Program membership, and data ownership/use. Maintain it in the same implementation turn when those facts change; reuse existing boundaries, verify source/schema, and require one Source Directory per subsystem and assign each Program module once; Program folder names do not assign ownership.',
|
|
@@ -118,7 +140,7 @@ export async function projectSessionContext({
|
|
|
118
140
|
...(skills.skills?.length ? ['', 'PROJECT AGENT SKILLS', '', renderAgentSkillCatalog(skills.skills)] : []),
|
|
119
141
|
...(hostContext ? ['', 'HOST CONTEXT', '', hostContext] : []),
|
|
120
142
|
].join('\n');
|
|
121
|
-
return { ...composedContext(GENESIS_CONTRACTS.sessionContext, output), warnings: skills.diagnostics };
|
|
143
|
+
return { ...composedContext(GENESIS_CONTRACTS.sessionContext, output), warnings: [...skills.diagnostics, ...integrations] };
|
|
122
144
|
}
|
|
123
145
|
|
|
124
146
|
export { projectTurnContext } from './host-context.js';
|