genesis-compiler 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -15
- package/package.json +1 -1
- package/prompts/deslop.txt +10 -6
- package/skills/genesis-deslop/SKILL.md +41 -20
- package/skills/genesis-deslop/agents/openai.yaml +2 -2
- package/skills/genesis-project/SKILL.md +5 -2
- package/src/cli.js +25 -5
- package/src/index/agent-skills.js +54 -21
- package/src/index/check.js +2 -2
- package/src/index/collaboration.js +4 -0
- package/src/index/prompt.js +1 -1
- package/src/index/session-context.js +11 -3
- package/src/index.js +23 -0
package/README.md
CHANGED
|
@@ -213,8 +213,23 @@ skill.
|
|
|
213
213
|
|
|
214
214
|
`.agents/skills/.genesis-managed.json` records only copies Genesis owns.
|
|
215
215
|
Genesis never overwrites an unmanaged skill and preserves locally modified
|
|
216
|
-
managed skills.
|
|
217
|
-
|
|
216
|
+
managed skills. `genesis check` and `genesis inspect skills` distinguish outdated
|
|
217
|
+
managed copies from local customizations. After updating Genesis or a selected
|
|
218
|
+
skill package, run `genesis skills sync` to refresh only those skill directories
|
|
219
|
+
and their ownership manifest. Repeating it makes no changes. It does not install
|
|
220
|
+
packages, initialize project files, migrate contracts, rebuild indexes, or run
|
|
221
|
+
verification.
|
|
222
|
+
|
|
223
|
+
Projects that declare `genesis-compiler` use the skills from that installed
|
|
224
|
+
project dependency, including when a host embeds a different compiler. An
|
|
225
|
+
unprepared declared dependency is reported instead of substituting the host's
|
|
226
|
+
version. Other projects use the running compiler's packaged skills. Package
|
|
227
|
+
upgrades remain explicit dependency changes.
|
|
228
|
+
|
|
229
|
+
Inspection, context generation, and session hooks remain read-only and report
|
|
230
|
+
skill maintenance diagnostics. An assistant that already loaded old skills
|
|
231
|
+
needs its supported context refresh before using their replacement; changing
|
|
232
|
+
files alone does not refresh its existing context.
|
|
218
233
|
|
|
219
234
|
## Commands at a glance
|
|
220
235
|
|
|
@@ -228,9 +243,11 @@ or use `genesis stack add`, to synchronize selected skills.
|
|
|
228
243
|
| `genesis engineering set <profile>` | Records the selected engineering profile while preserving project-specific requirements. |
|
|
229
244
|
| `genesis stack list` | Lists technology components from the installed Stack catalog. |
|
|
230
245
|
| `genesis stack add <piece...>` | Resolves component dependencies/conflicts, records the selection, materializes missing project contracts, synchronizes declared skills, and prints the one-time preparation prompt. It does not install application packages or run an agent. |
|
|
246
|
+
| `genesis skills sync` | Refreshes selected, unmodified managed skills while preserving customized and unmanaged copies. |
|
|
231
247
|
| `genesis context <path...>` | Returns path-focused Program explanations, indexed functions, selected technology guidance, exact project contracts, and relevant skills. |
|
|
232
248
|
| `genesis index [function-or-path...]` | Regenerates the derived code indexes and optionally searches the existing function/method inventory. |
|
|
233
249
|
| `genesis inspect environment` | Reports declared resources, public defaults, missing input names, and environment-file paths without returning secret values. |
|
|
250
|
+
| `genesis inspect skills` | Reports selected skill freshness and ownership without changing files. |
|
|
234
251
|
| `genesis inspect section <name>` | Returns one exact consumer-owned Stack section without interpreting or executing it. |
|
|
235
252
|
| `genesis prompt [request...]` | Generates the ordinary implementation prompt. Use `--task` for opening, adoption, Deslop, explanation, review, and other explicit prompt tasks. |
|
|
236
253
|
| `genesis verify` | Executes only the ordered finite commands in `## Verification` and records exact evidence. |
|
|
@@ -281,6 +298,11 @@ genesis collaboration set direct balanced expert conclusions "Be candid."
|
|
|
281
298
|
Genesis owns the supported choices and their concise expansions. Authored
|
|
282
299
|
project requirements receive one fixed framing sentence and are otherwise
|
|
283
300
|
preserved. They are omitted when the source says `- Nothing.`.
|
|
301
|
+
The configured style applies to progress updates as well as final answers,
|
|
302
|
+
with technical depth and terminology matched to the selected experience level.
|
|
303
|
+
Updates should describe actual progress, findings, decisions, or blockers,
|
|
304
|
+
rather than announce compliance with guidance or reassure the user about
|
|
305
|
+
unrelated behavior staying unchanged.
|
|
284
306
|
|
|
285
307
|
Persistent hosts should install `projectSessionContext()` once when a provider
|
|
286
308
|
conversation is created or refreshed. They may then generate task prompts with
|
|
@@ -446,21 +468,25 @@ turn, and the project skill keeps intentional Blueprint and affected Program
|
|
|
446
468
|
changes aligned there.
|
|
447
469
|
|
|
448
470
|
Deslop runs only when explicitly requested. With no stated scope it reviews the
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
471
|
+
agent's own changes for the current task across preceding turns, committed or
|
|
472
|
+
uncommitted. An explicit commit, first-parent count, or range takes precedence
|
|
473
|
+
regardless of authorship. The agent establishes ownership from task and edit
|
|
474
|
+
history, preserves unrelated edits and existing staging, and asks for scope
|
|
475
|
+
when ownership is unclear. A dirty worktree is allowed, and cleanup remains
|
|
476
|
+
uncommitted for review. Genesis supplies the behavior-preserving boundary and
|
|
453
477
|
scope rules. Selected Stack components add technology-specific Deslop guidance
|
|
454
478
|
without weakening or broadening that contract.
|
|
455
479
|
|
|
456
|
-
### Deslop
|
|
480
|
+
### Deslop your changes or specified commits
|
|
457
481
|
|
|
458
482
|
Inside Codex, OpenCode, or another skill-aware coding agent, ask directly:
|
|
459
483
|
|
|
460
484
|
```text
|
|
461
485
|
Deslop
|
|
486
|
+
Deslop the last commit
|
|
462
487
|
Deslop the last 5 commits
|
|
463
488
|
Deslop commit a1b2c3d
|
|
489
|
+
Deslop a1b2c3d..d4e5f6a
|
|
464
490
|
```
|
|
465
491
|
|
|
466
492
|
The installed `genesis-deslop` skill generates the canonical project prompt
|
|
@@ -473,8 +499,10 @@ selection, generate the same complete prompt explicitly:
|
|
|
473
499
|
|
|
474
500
|
```bash
|
|
475
501
|
genesis prompt --task deslop
|
|
502
|
+
genesis prompt --task deslop "Deslop the last commit"
|
|
476
503
|
genesis prompt --task deslop "Deslop the last 5 commits"
|
|
477
504
|
genesis prompt --task deslop "Deslop commit a1b2c3d"
|
|
505
|
+
genesis prompt --task deslop "Deslop a1b2c3d..d4e5f6a"
|
|
478
506
|
```
|
|
479
507
|
|
|
480
508
|
Give the printed prompt to the coding agent that has access to the repository.
|
|
@@ -486,10 +514,12 @@ Stack component. Project additions or overrides from
|
|
|
486
514
|
The main `genesis/stack.md` records component selection and durable project
|
|
487
515
|
operations; it intentionally does not duplicate installed guidance bodies.
|
|
488
516
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
517
|
+
The whole dirty diff is not automatically the agent's work. Deslop preserves
|
|
518
|
+
the user's and other agents' changes, including edits in the same files. With
|
|
519
|
+
no changes of its own for the task, it reports that there is nothing to clean
|
|
520
|
+
up; it does not silently select the latest commit. Its result is a normal
|
|
521
|
+
uncommitted diff for review and a later commit. It never amends selected commits,
|
|
522
|
+
silently fixes newly discovered defects, or runs as an automatic completion phase.
|
|
493
523
|
|
|
494
524
|
Projects can customize a selected technology through its matching file, such
|
|
495
525
|
as `genesis/stack/jskit.md`:
|
|
@@ -563,7 +593,8 @@ genesis prompt # implementation work
|
|
|
563
593
|
genesis prompt --task start # open a new or existing project conversation
|
|
564
594
|
genesis prompt --task adopt # import an existing project's complete contract
|
|
565
595
|
genesis prompt "Add filtering by note title"
|
|
566
|
-
genesis prompt --task deslop # clean up the
|
|
596
|
+
genesis prompt --task deslop # clean up the agent's own task changes
|
|
597
|
+
genesis prompt --task deslop "Deslop the last commit"
|
|
567
598
|
genesis prompt --task deslop "Deslop the last 5 commits"
|
|
568
599
|
genesis prompt --task deslop "Deslop commit a1b2c3d"
|
|
569
600
|
genesis prompt --task program # refresh explanation
|
|
@@ -590,9 +621,10 @@ The eight task types are deliberately explicit:
|
|
|
590
621
|
- `work` implements the Blueprint and optional request using current code,
|
|
591
622
|
Program, the selected engineering approach, selected Stack context, and
|
|
592
623
|
progressively loaded Agent Skills.
|
|
593
|
-
- `deslop` requests behavior-preserving cleanup of
|
|
594
|
-
|
|
595
|
-
|
|
624
|
+
- `deslop` explicitly requests behavior-preserving cleanup of the agent's own
|
|
625
|
+
task changes, committed or uncommitted. An explicit commit, first-parent
|
|
626
|
+
count, or range takes precedence. It preserves unrelated work and existing
|
|
627
|
+
staging, permits a dirty worktree, and leaves its result uncommitted.
|
|
596
628
|
- `program` edits only `genesis/program/` to explain the code that exists, with
|
|
597
629
|
selected Stack guidance available for technology-specific correctness.
|
|
598
630
|
- `blueprint` edits only `genesis/blueprint.md` from explicit user intent. It
|
|
@@ -860,6 +892,7 @@ import {
|
|
|
860
892
|
inspectCollaboration,
|
|
861
893
|
inspectEngineering,
|
|
862
894
|
inspectEnvironment,
|
|
895
|
+
inspectSkills,
|
|
863
896
|
inspectStackSection,
|
|
864
897
|
installCodex,
|
|
865
898
|
listEngineeringProfiles,
|
|
@@ -869,6 +902,7 @@ import {
|
|
|
869
902
|
projectTurnContext,
|
|
870
903
|
setCollaboration,
|
|
871
904
|
setEngineeringProfile,
|
|
905
|
+
syncSkills,
|
|
872
906
|
verify,
|
|
873
907
|
withTrustedGitRepository,
|
|
874
908
|
} from 'genesis-compiler';
|
|
@@ -885,6 +919,12 @@ codebase. `installCodex()` installs the optional global discovery plugin.
|
|
|
885
919
|
project selection used by the CLI and hosts.
|
|
886
920
|
`inspectCollaboration()` and `setCollaboration()` expose the portable
|
|
887
921
|
communication declaration and Genesis-owned choice expansions.
|
|
922
|
+
`inspectSkills()` and `syncSkills()` expose the same inspection and narrow
|
|
923
|
+
synchronization used by the CLI. Both accept `projectRoot` and `stackPackages`.
|
|
924
|
+
Inspection returns aggregate status, per-skill status for valid installed copies,
|
|
925
|
+
and diagnostics for missing, invalid, outdated, customized, or unmanaged skills.
|
|
926
|
+
Synchronization returns changed paths, preservation diagnostics, and the resulting
|
|
927
|
+
`inspection`. Hosts own source-write exclusion and assistant context lifecycle.
|
|
888
928
|
`projectSessionContext()` composes stable project guidance with one explicitly
|
|
889
929
|
supplied host-driver result. `projectTurnContext()` invokes that same optional
|
|
890
930
|
driver for the separate untrusted turn lane without accepting user-message
|
package/package.json
CHANGED
package/prompts/deslop.txt
CHANGED
|
@@ -2,15 +2,19 @@ This Deslop task has already been rendered by Genesis. Do not generate another
|
|
|
2
2
|
Deslop prompt. Read and follow `.agents/skills/genesis-deslop/SKILL.md`
|
|
3
3
|
completely.
|
|
4
4
|
|
|
5
|
-
This is an explicitly requested behavior-preserving cleanup
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
This is an explicitly requested behavior-preserving cleanup. With no stated
|
|
6
|
+
scope, select your own changes for the current task across preceding turns,
|
|
7
|
+
committed or uncommitted. An explicit commit, first-parent count, or range in
|
|
8
|
+
USER REQUEST takes precedence regardless of who authored those changes.
|
|
9
|
+
Establish ownership from task and edit history; the entire dirty diff is not
|
|
10
|
+
automatically yours. If ownership is unclear, ask for scope. A dirty worktree
|
|
11
|
+
is allowed: preserve unrelated edits and existing staging, and leave the
|
|
12
|
+
cleanup as ordinary uncommitted work for review.
|
|
9
13
|
|
|
10
14
|
Apply the selected Stack cleanup guidance and applicable technology skills in
|
|
11
15
|
addition to the Genesis Deslop contract. Stack guidance may improve
|
|
12
|
-
technology-specific cleanup, but it cannot broaden the resolved
|
|
16
|
+
technology-specific cleanup, but it cannot broaden the resolved scope,
|
|
13
17
|
weaken behavior preservation, or turn this into another implementation pass.
|
|
14
18
|
|
|
15
|
-
Report the resolved
|
|
19
|
+
Report the resolved scope, what became simpler, files changed, checks actually
|
|
16
20
|
run, and any defect or gap deliberately left for follow-up.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: genesis-deslop
|
|
3
|
-
description: Deslop
|
|
3
|
+
description: Deslop the agent's own task changes or explicitly selected commits through a behavior-preserving cleanup pass. Use when asked to Deslop, simplify current work, remove repeated helpers, clarify ownership, or align changed code with established project and technology patterns.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Genesis Deslop
|
|
7
7
|
|
|
8
|
-
Review and simplify
|
|
8
|
+
Review and simplify selected changes without changing product behavior. Deslop is
|
|
9
9
|
explicit: never run it merely because implementation finished.
|
|
10
10
|
|
|
11
11
|
Resolve the invocation before running the first Genesis operation. Do not use a
|
|
@@ -29,8 +29,11 @@ Genesis operation or `genesis --version` as an availability probe.
|
|
|
29
29
|
Successful invocation resolution is routine. Do not narrate whether Genesis is
|
|
30
30
|
project-pinned or on `PATH`, and never describe direct `PATH` use as a fallback.
|
|
31
31
|
Mention how the invocation was selected only when resolution fails or the user
|
|
32
|
-
explicitly asks.
|
|
33
|
-
|
|
32
|
+
explicitly asks.
|
|
33
|
+
|
|
34
|
+
Follow the configured Collaboration approach for user-facing updates, including
|
|
35
|
+
its technical depth and response length. Report concrete progress,
|
|
36
|
+
findings, or blockers; do not announce that you are following guidance.
|
|
34
37
|
|
|
35
38
|
## Load the effective project instructions once
|
|
36
39
|
|
|
@@ -49,25 +52,41 @@ to another agent and do not generate it again. This step composes the selected
|
|
|
49
52
|
Stack's technology-specific Deslop guidance and any project customization with
|
|
50
53
|
the portable contract below.
|
|
51
54
|
|
|
52
|
-
## Resolve the
|
|
55
|
+
## Resolve the cleanup scope
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
Inspect `git status --short` and the staged and unstaged diffs before editing.
|
|
58
|
+
A dirty worktree is allowed; a prior commit is not required. Preserve the
|
|
59
|
+
existing index and unrelated work. Do not stage, stash, commit, or discard
|
|
60
|
+
changes as a prerequisite or as part of cleanup.
|
|
57
61
|
|
|
58
62
|
Resolve the user's scope as follows:
|
|
59
63
|
|
|
60
|
-
- With no stated scope,
|
|
64
|
+
- With no stated scope, select only your own changes for the current task,
|
|
65
|
+
including preceding turns. This can include staged and unstaged edits,
|
|
66
|
+
new untracked files, and already-committed task changes. Identify ownership
|
|
67
|
+
from task and edit history, then confirm those changes against the current
|
|
68
|
+
source and Git diffs. Neither the entire
|
|
69
|
+
dirty diff, the latest commit, nor a Git author identity proves ownership.
|
|
70
|
+
- Preserve changes made by the user or other agents, including edits in the
|
|
71
|
+
same files. If ownership cannot be established, ask which changes to deslop. If there
|
|
72
|
+
are no changes of your own for this task, report that there is nothing to
|
|
73
|
+
deslop; do not silently select the latest commit or somebody else's work.
|
|
74
|
+
- An explicit commit, first-parent count, or range takes precedence over the
|
|
75
|
+
default, regardless of who authored those changes.
|
|
76
|
+
- “The last commit” means `HEAD` against its first parent.
|
|
61
77
|
- “The last N commits” means the net surviving change from the first parent
|
|
62
78
|
before those N commits through `HEAD`.
|
|
63
79
|
- A named commit means that commit against its first parent.
|
|
64
80
|
- An explicit commit range means exactly that range.
|
|
65
81
|
- A root commit uses Git's root-diff form because it has no parent.
|
|
66
82
|
|
|
67
|
-
Inspect the resolved
|
|
68
|
-
|
|
69
|
-
affected Program and Stack context.
|
|
70
|
-
diff for the selected committed
|
|
83
|
+
Inspect the resolved changes and paths, plus commit identities when applicable.
|
|
84
|
+
Review their diff, current source, direct call sites, relevant tests, and the
|
|
85
|
+
affected Program and Stack context. For an explicit committed scope, do not
|
|
86
|
+
substitute the ordinary working-tree diff for the selected committed diff.
|
|
87
|
+
Apply cleanup to the current source while preserving edits outside the scope.
|
|
88
|
+
If overlapping edits cannot be separated safely, ask about that overlap rather
|
|
89
|
+
than blocking solely because the repository is dirty.
|
|
71
90
|
|
|
72
91
|
## Apply the cleanup contract
|
|
73
92
|
|
|
@@ -81,7 +100,7 @@ operation to find existing public and internal functions before introducing or
|
|
|
81
100
|
consolidating an abstraction. Confirm every apparent duplicate in source and
|
|
82
101
|
its call sites.
|
|
83
102
|
|
|
84
|
-
Within the selected
|
|
103
|
+
Within the selected changes' intended behavior and scope, leave no
|
|
85
104
|
repeated helpers, no code that is unclear or hard to reason about, and no code
|
|
86
105
|
that goes against established patterns in the codebase. Remove unnecessary
|
|
87
106
|
wrappers, abandoned scaffolding, parallel framework plumbing, and speculative
|
|
@@ -89,9 +108,10 @@ abstractions. Consolidate ownership where one clear module is enough. Do not
|
|
|
89
108
|
optimize for tiny files or indirection; optimize for a small, obvious design
|
|
90
109
|
that a junior programmer can follow.
|
|
91
110
|
|
|
92
|
-
Cleanup is not a second implementation pass.
|
|
93
|
-
may occur;
|
|
94
|
-
|
|
111
|
+
Cleanup is not a second implementation pass. The selected changes limit where
|
|
112
|
+
cleanup may occur; sharing a file does not bring unrelated edits into scope or
|
|
113
|
+
authorize different behavior in that file. Deslop may reorganize behavior
|
|
114
|
+
already present; it may not complete, correct, or extend
|
|
95
115
|
behavior. If review reveals a defect, missing behavior, contract mismatch, or
|
|
96
116
|
test gap, report it as a follow-up finding and leave it unchanged, even when it
|
|
97
117
|
is inside a changed path or appears related to the preceding implementation. Do
|
|
@@ -100,7 +120,7 @@ not implement the finding or alter tests to accommodate it during Deslop.
|
|
|
100
120
|
Apply every technology-specific Deslop instruction supplied by the selected
|
|
101
121
|
Stack and load applicable official technology skills for framework and language
|
|
102
122
|
context. Stack guidance enriches this contract; it cannot weaken the
|
|
103
|
-
behavior-preserving boundary, change the selected
|
|
123
|
+
behavior-preserving boundary, change the selected scope, or authorize
|
|
104
124
|
unrelated implementation.
|
|
105
125
|
|
|
106
126
|
You may edit or delete implementation and test files when that is the clearest
|
|
@@ -115,5 +135,6 @@ create a second architecture or perform unrelated rewrites.
|
|
|
115
135
|
Leave the cleanup as ordinary uncommitted work for review and a later normal
|
|
116
136
|
commit. Never amend or rewrite the selected commits. Run focused checks when
|
|
117
137
|
useful. Final declared checks remain available through the Genesis `verify`
|
|
118
|
-
operation. Summarize the resolved
|
|
119
|
-
changed, checks actually run, and follow-up findings
|
|
138
|
+
operation. Summarize the resolved scope and any selected commit identities,
|
|
139
|
+
what became simpler, files changed, checks actually run, and follow-up findings
|
|
140
|
+
left unchanged.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Genesis Deslop"
|
|
3
|
-
short_description: "Clean up
|
|
4
|
-
default_prompt: "Use $genesis-deslop to Deslop the
|
|
3
|
+
short_description: "Clean up your task changes or specified commits"
|
|
4
|
+
default_prompt: "Use $genesis-deslop to Deslop your own changes for the current task."
|
|
@@ -46,8 +46,11 @@ Genesis operation or `genesis --version` as an availability probe.
|
|
|
46
46
|
Successful invocation resolution is routine. Do not narrate whether Genesis is
|
|
47
47
|
project-pinned or on `PATH`, and never describe direct `PATH` use as a fallback.
|
|
48
48
|
Mention how the invocation was selected only when resolution fails or the user
|
|
49
|
-
explicitly asks.
|
|
50
|
-
|
|
49
|
+
explicitly asks.
|
|
50
|
+
|
|
51
|
+
Follow the configured Collaboration approach for user-facing updates, including
|
|
52
|
+
its technical depth and response length. Report concrete progress,
|
|
53
|
+
findings, or blockers; do not announce that you are following guidance.
|
|
51
54
|
|
|
52
55
|
## Resolve explicit technology choices
|
|
53
56
|
|
package/src/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
inspectEnvironment,
|
|
16
16
|
inspectStackSection,
|
|
17
17
|
inspectProject,
|
|
18
|
+
inspectSkills,
|
|
18
19
|
installCodex,
|
|
19
20
|
listEngineeringProfiles,
|
|
20
21
|
listStackPieces,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
migrate,
|
|
23
24
|
setCollaboration,
|
|
24
25
|
setEngineeringProfile,
|
|
26
|
+
syncSkills,
|
|
25
27
|
verify,
|
|
26
28
|
} from './index.js';
|
|
27
29
|
import {
|
|
@@ -54,6 +56,7 @@ const USAGE = `Usage:
|
|
|
54
56
|
genesis engineering set <profile>
|
|
55
57
|
genesis stack list
|
|
56
58
|
genesis stack add <piece...>
|
|
59
|
+
genesis skills sync
|
|
57
60
|
genesis templates list
|
|
58
61
|
genesis templates apply <catalogue:technology/variant>
|
|
59
62
|
genesis context <path...>
|
|
@@ -61,6 +64,7 @@ const USAGE = `Usage:
|
|
|
61
64
|
genesis migrate
|
|
62
65
|
genesis inspect environment
|
|
63
66
|
genesis inspect project
|
|
67
|
+
genesis inspect skills
|
|
64
68
|
genesis inspect section <name>
|
|
65
69
|
genesis prompt [request...]
|
|
66
70
|
genesis prompt --task <start|adopt|work|deslop|program|blueprint|describe|review> [request...]
|
|
@@ -80,7 +84,7 @@ prompt to the agent you already use. Review all edits through the ordinary Git
|
|
|
80
84
|
diff, then run genesis verify for the Stack's concrete checks.
|
|
81
85
|
`;
|
|
82
86
|
|
|
83
|
-
const COMMANDS = new Set(['adopt', 'check', 'codex', 'collaboration', 'context', 'engineering', 'hook', 'index', 'init', 'inspect', 'migrate', 'prompt', 'stack', 'templates', 'verify']);
|
|
87
|
+
const COMMANDS = new Set(['adopt', 'check', 'codex', 'collaboration', 'context', 'engineering', 'hook', 'index', 'init', 'inspect', 'migrate', 'prompt', 'skills', 'stack', 'templates', 'verify']);
|
|
84
88
|
|
|
85
89
|
function parseCommand(argv) {
|
|
86
90
|
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h') || argv[0] === 'help') {
|
|
@@ -167,6 +171,10 @@ function parseCommand(argv) {
|
|
|
167
171
|
if (action === 'set' && operands.length !== 2) {
|
|
168
172
|
fail('CLI_ENGINEERING_PROFILE_REQUIRED', 'Command engineering set requires exactly one profile.');
|
|
169
173
|
}
|
|
174
|
+
} else if (command === 'skills') {
|
|
175
|
+
if (operands.length !== 1 || operands[0] !== 'sync') {
|
|
176
|
+
fail('CLI_SKILLS_ACTION_REQUIRED', 'Command skills requires exactly: sync.');
|
|
177
|
+
}
|
|
170
178
|
} else if (command === 'codex') {
|
|
171
179
|
if (operands.length !== 1 || operands[0] !== 'install') {
|
|
172
180
|
fail('CLI_CODEX_ACTION_REQUIRED', 'Command codex requires exactly: install.');
|
|
@@ -174,12 +182,12 @@ function parseCommand(argv) {
|
|
|
174
182
|
} else if (command === 'context' && operands.length === 0) {
|
|
175
183
|
fail('CONTEXT_PATH_REQUIRED', 'Command context requires at least one project path.');
|
|
176
184
|
} else if (command === 'inspect') {
|
|
177
|
-
const ordinaryInspection = operands.length === 1 && ['environment', 'project'].includes(operands[0]);
|
|
185
|
+
const ordinaryInspection = operands.length === 1 && ['environment', 'project', 'skills'].includes(operands[0]);
|
|
178
186
|
const sectionInspection = operands.length >= 2 && operands[0] === 'section';
|
|
179
187
|
if (!ordinaryInspection && !sectionInspection) {
|
|
180
188
|
fail(
|
|
181
189
|
'CLI_INSPECT_TARGET_REQUIRED',
|
|
182
|
-
'Command inspect requires project, environment, or section <name>.',
|
|
190
|
+
'Command inspect requires project, environment, skills, or section <name>.',
|
|
183
191
|
);
|
|
184
192
|
}
|
|
185
193
|
} else if (command === 'hook' && (operands.length !== 1 || !['discover', 'session', 'turn'].includes(operands[0]))) {
|
|
@@ -278,6 +286,12 @@ function writeInspection(result) {
|
|
|
278
286
|
}
|
|
279
287
|
|
|
280
288
|
function writeResult(command, result) {
|
|
289
|
+
if (command === 'inspect' && result.inspection === 'skills') {
|
|
290
|
+
line(process.stdout, `Agent Skills: ${result.status}`);
|
|
291
|
+
for (const skill of result.skills) line(process.stdout, ` - ${skill.name}: ${skill.status}`);
|
|
292
|
+
for (const diagnostic of result.diagnostics) line(process.stdout, `${diagnostic.code}: ${diagnostic.message}`);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
281
295
|
if (command === 'templates') {
|
|
282
296
|
if (result.templates) for (const entry of result.templates) line(process.stdout, `${entry.id}: ${entry.name} — ${entry.description}`);
|
|
283
297
|
else {
|
|
@@ -419,6 +433,7 @@ async function execute({ command, operands, options }, { signal } = {}) {
|
|
|
419
433
|
return operands[0] === 'list' ? listTemplates(templateOptions) : applyTemplate({ ...templateOptions, templateId: operands[1] });
|
|
420
434
|
}
|
|
421
435
|
if (command === 'migrate') return migrate({ projectRoot, stackPackages });
|
|
436
|
+
if (command === 'skills') return syncSkills({ projectRoot, stackPackages });
|
|
422
437
|
if (command === 'adopt') {
|
|
423
438
|
return adoptProject({ projectRoot, request: operands.join(' '), stackPackages });
|
|
424
439
|
}
|
|
@@ -496,7 +511,7 @@ async function execute({ command, operands, options }, { signal } = {}) {
|
|
|
496
511
|
}),
|
|
497
512
|
};
|
|
498
513
|
}
|
|
499
|
-
const inspections = { environment: inspectEnvironment, project: inspectProject };
|
|
514
|
+
const inspections = { environment: inspectEnvironment, project: inspectProject, skills: inspectSkills };
|
|
500
515
|
return {
|
|
501
516
|
inspection: operands[0],
|
|
502
517
|
...await inspections[operands[0]]({ projectRoot, stackPackages }),
|
|
@@ -611,7 +626,12 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
611
626
|
formatDiagnostic,
|
|
612
627
|
);
|
|
613
628
|
if (options.json) line(process.stdout, JSON.stringify(result));
|
|
614
|
-
else
|
|
629
|
+
else {
|
|
630
|
+
writeResult(parsed.command, result);
|
|
631
|
+
for (const warning of result.warnings || []) {
|
|
632
|
+
if (warning.code !== formatDiagnostic?.code) line(process.stderr, `WARNING: ${warning.code}: ${warning.message}`);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
615
635
|
return ['blocked', 'failed', 'invalid'].includes(result?.status) ? 2 : 0;
|
|
616
636
|
} catch (error) {
|
|
617
637
|
const diagnostic = asDiagnostic(error);
|
|
@@ -242,12 +242,12 @@ async function describeSkill(directory, source) {
|
|
|
242
242
|
};
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
async function packageDirectory(packageName, resolveFrom = null) {
|
|
245
|
+
async function packageDirectory(packageName, resolveFrom = null, { projectOnly = false } = {}) {
|
|
246
246
|
const roots = [
|
|
247
247
|
...(resolveFrom
|
|
248
248
|
? createRequire(path.join(resolveFrom, 'package.json')).resolve.paths(packageName) || []
|
|
249
249
|
: []),
|
|
250
|
-
...(require.resolve.paths(packageName) || []),
|
|
250
|
+
...(projectOnly ? [] : require.resolve.paths(packageName) || []),
|
|
251
251
|
];
|
|
252
252
|
for (const modulesRoot of [...new Set(roots)]) {
|
|
253
253
|
const manifest = path.join(modulesRoot, packageName, 'package.json');
|
|
@@ -274,7 +274,7 @@ async function packageDirectory(packageName, resolveFrom = null) {
|
|
|
274
274
|
async function resolveLocator(locator) {
|
|
275
275
|
const root = locator.package
|
|
276
276
|
? await packageDirectory(locator.package, locator.resolveFrom)
|
|
277
|
-
: packageRoot;
|
|
277
|
+
: locator.root || packageRoot;
|
|
278
278
|
const directory = path.join(root, locator.path);
|
|
279
279
|
const source = locator.source || (
|
|
280
280
|
locator.package
|
|
@@ -287,9 +287,23 @@ async function resolveLocator(locator) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/** Resolves the three Genesis workflow skills plus authoritative selected Stack skills. */
|
|
290
|
-
export async function projectSkillPlan(stack) {
|
|
290
|
+
export async function projectSkillPlan(stack, { projectRoot } = {}) {
|
|
291
|
+
let coreRoot = packageRoot;
|
|
292
|
+
if (projectRoot) {
|
|
293
|
+
let manifest;
|
|
294
|
+
try { manifest = JSON.parse(await readFile(path.join(projectRoot, 'package.json'), 'utf8')); } catch (error) {
|
|
295
|
+
if (!['ENOENT', 'ENOTDIR'].includes(error?.code)) throw error;
|
|
296
|
+
}
|
|
297
|
+
if (manifest?.name === 'genesis-compiler') {
|
|
298
|
+
coreRoot = projectRoot;
|
|
299
|
+
} else if (['dependencies', 'devDependencies', 'optionalDependencies'].some((field) => (
|
|
300
|
+
Object.hasOwn(manifest?.[field] || {}, 'genesis-compiler')
|
|
301
|
+
))) {
|
|
302
|
+
coreRoot = await packageDirectory('genesis-compiler', projectRoot, { projectOnly: true });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
291
305
|
const locators = [
|
|
292
|
-
...CORE_SKILLS,
|
|
306
|
+
...CORE_SKILLS.map((skill) => ({ ...skill, root: coreRoot })),
|
|
293
307
|
...(stack?.components || []).flatMap((component) => (
|
|
294
308
|
component.skill ? [{ ...component.skill, component: component.id }] : []
|
|
295
309
|
)),
|
|
@@ -386,9 +400,19 @@ function targetFiles(skill) {
|
|
|
386
400
|
return skill.files.map(({ path: file }) => `${SKILLS_ROOT}/${skill.name}/${file}`);
|
|
387
401
|
}
|
|
388
402
|
|
|
403
|
+
function skillStatus(installed, managed, expected) {
|
|
404
|
+
if (!installed) return 'missing';
|
|
405
|
+
if (!managed) return 'unmanaged';
|
|
406
|
+
if (installed.hash !== managed.hash && installed.hash !== expected.hash) return 'customized';
|
|
407
|
+
if (installed.hash !== expected.hash || managed.hash !== expected.hash || managed.source !== expected.source) {
|
|
408
|
+
return 'outdated';
|
|
409
|
+
}
|
|
410
|
+
return 'current';
|
|
411
|
+
}
|
|
412
|
+
|
|
389
413
|
/** Installs only Genesis-owned or authoritative Stack-declared skills. */
|
|
390
414
|
export async function syncProjectSkills({ projectRoot, stack } = {}) {
|
|
391
|
-
const desired = await projectSkillPlan(stack);
|
|
415
|
+
const desired = await projectSkillPlan(stack, { projectRoot });
|
|
392
416
|
const desiredNames = new Set(desired.map(({ name }) => name));
|
|
393
417
|
const manifest = await readManifest(projectRoot);
|
|
394
418
|
const changedFiles = [];
|
|
@@ -400,13 +424,14 @@ export async function syncProjectSkills({ projectRoot, stack } = {}) {
|
|
|
400
424
|
const managed = Object.hasOwn(manifest.value.skills, skill.name)
|
|
401
425
|
? manifest.value.skills[skill.name]
|
|
402
426
|
: null;
|
|
403
|
-
|
|
427
|
+
const status = skillStatus(installed, managed, skill);
|
|
428
|
+
if (status === 'missing') {
|
|
404
429
|
await replaceSkill(skill.directory, target);
|
|
405
430
|
manifest.value.skills[skill.name] = { hash: skill.hash, source: skill.source };
|
|
406
431
|
changedFiles.push(...targetFiles(skill));
|
|
407
432
|
continue;
|
|
408
433
|
}
|
|
409
|
-
if (
|
|
434
|
+
if (status === 'unmanaged') {
|
|
410
435
|
diagnostics.push({
|
|
411
436
|
code: 'AGENT_SKILL_EXTERNAL',
|
|
412
437
|
message: `Preserved existing project Agent Skill ${skill.name}; Genesis does not own it.`,
|
|
@@ -414,11 +439,7 @@ export async function syncProjectSkills({ projectRoot, stack } = {}) {
|
|
|
414
439
|
});
|
|
415
440
|
continue;
|
|
416
441
|
}
|
|
417
|
-
if (
|
|
418
|
-
if (installed.hash === skill.hash) {
|
|
419
|
-
manifest.value.skills[skill.name] = { hash: skill.hash, source: skill.source };
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
442
|
+
if (status === 'customized') {
|
|
422
443
|
diagnostics.push({
|
|
423
444
|
code: 'AGENT_SKILL_CUSTOMIZED',
|
|
424
445
|
message: `Preserved locally modified Agent Skill ${skill.name}.`,
|
|
@@ -426,10 +447,12 @@ export async function syncProjectSkills({ projectRoot, stack } = {}) {
|
|
|
426
447
|
});
|
|
427
448
|
continue;
|
|
428
449
|
}
|
|
429
|
-
if (
|
|
430
|
-
|
|
450
|
+
if (status === 'outdated') {
|
|
451
|
+
if (installed.hash !== skill.hash) {
|
|
452
|
+
await replaceSkill(skill.directory, target);
|
|
453
|
+
changedFiles.push(...targetFiles(installed), ...targetFiles(skill));
|
|
454
|
+
}
|
|
431
455
|
manifest.value.skills[skill.name] = { hash: skill.hash, source: skill.source };
|
|
432
|
-
changedFiles.push(...new Set([...targetFiles(installed), ...targetFiles(skill)]));
|
|
433
456
|
}
|
|
434
457
|
}
|
|
435
458
|
|
|
@@ -469,13 +492,14 @@ export async function syncProjectSkills({ projectRoot, stack } = {}) {
|
|
|
469
492
|
|
|
470
493
|
/** Inspects the exact project copies without changing them. */
|
|
471
494
|
export async function inspectProjectSkills({ projectRoot, stack } = {}) {
|
|
472
|
-
const desired = await projectSkillPlan(stack);
|
|
495
|
+
const desired = await projectSkillPlan(stack, { projectRoot });
|
|
473
496
|
const manifest = await readManifest(projectRoot);
|
|
474
497
|
const diagnostics = [];
|
|
475
498
|
const skills = [];
|
|
476
499
|
let customized = false;
|
|
477
500
|
let invalid = false;
|
|
478
501
|
let missing = false;
|
|
502
|
+
let outdated = false;
|
|
479
503
|
for (const expected of desired) {
|
|
480
504
|
const target = path.join(projectRoot, SKILLS_ROOT, expected.name);
|
|
481
505
|
let installed;
|
|
@@ -488,7 +512,7 @@ export async function inspectProjectSkills({ projectRoot, stack } = {}) {
|
|
|
488
512
|
missing = true;
|
|
489
513
|
diagnostics.push({
|
|
490
514
|
code: 'AGENT_SKILL_MISSING',
|
|
491
|
-
message: `Project Agent Skill is missing: ${SKILLS_ROOT}/${expected.name}/SKILL.md.`,
|
|
515
|
+
message: `Project Agent Skill is missing: ${SKILLS_ROOT}/${expected.name}/SKILL.md. Run \`genesis skills sync\` to install selected skills.`,
|
|
492
516
|
details: { name: expected.name },
|
|
493
517
|
});
|
|
494
518
|
continue;
|
|
@@ -496,30 +520,39 @@ export async function inspectProjectSkills({ projectRoot, stack } = {}) {
|
|
|
496
520
|
const managed = Object.hasOwn(manifest.value.skills, expected.name)
|
|
497
521
|
? manifest.value.skills[expected.name]
|
|
498
522
|
: null;
|
|
499
|
-
|
|
523
|
+
const status = skillStatus(installed, managed, expected);
|
|
524
|
+
if (status === 'unmanaged') {
|
|
500
525
|
customized = true;
|
|
501
526
|
diagnostics.push({
|
|
502
527
|
code: 'AGENT_SKILL_EXTERNAL',
|
|
503
528
|
message: `Project Agent Skill ${expected.name} is externally managed; Genesis preserved it.`,
|
|
504
529
|
details: { name: expected.name, path: `${SKILLS_ROOT}/${expected.name}/SKILL.md` },
|
|
505
530
|
});
|
|
506
|
-
} else if (
|
|
531
|
+
} else if (status === 'customized') {
|
|
507
532
|
customized = true;
|
|
508
533
|
diagnostics.push({
|
|
509
534
|
code: 'AGENT_SKILL_CUSTOMIZED',
|
|
510
535
|
message: `Project Agent Skill ${expected.name} differs from its Genesis-managed source.`,
|
|
511
536
|
details: { name: expected.name, path: `${SKILLS_ROOT}/${expected.name}/SKILL.md` },
|
|
512
537
|
});
|
|
538
|
+
} else if (status === 'outdated') {
|
|
539
|
+
outdated = true;
|
|
540
|
+
diagnostics.push({
|
|
541
|
+
code: 'AGENT_SKILL_OUTDATED',
|
|
542
|
+
message: `Project Agent Skill ${expected.name} is outdated relative to the installed source. Run \`genesis skills sync\` to update unmodified managed skills.`,
|
|
543
|
+
details: { name: expected.name, path: `${SKILLS_ROOT}/${expected.name}/SKILL.md` },
|
|
544
|
+
});
|
|
513
545
|
}
|
|
514
546
|
skills.push({
|
|
515
547
|
name: installed.name,
|
|
516
548
|
description: installed.description,
|
|
517
549
|
path: `${SKILLS_ROOT}/${installed.name}/SKILL.md`,
|
|
518
550
|
component: expected.component,
|
|
551
|
+
status,
|
|
519
552
|
});
|
|
520
553
|
}
|
|
521
554
|
return {
|
|
522
|
-
status: invalid ? 'invalid' : missing ? 'missing' : customized ? 'customized' : 'current',
|
|
555
|
+
status: invalid ? 'invalid' : missing ? 'missing' : outdated ? 'outdated' : customized ? 'customized' : 'current',
|
|
523
556
|
diagnostics,
|
|
524
557
|
skills,
|
|
525
558
|
};
|
package/src/index/check.js
CHANGED
|
@@ -140,7 +140,7 @@ export async function checkProject({
|
|
|
140
140
|
if (program.status === 'missing') guidance.push('Generate an explanatory Program prompt with genesis prompt --task program.');
|
|
141
141
|
if (engineering.status === 'defaulted') guidance.push('Run genesis init or genesis engineering set focused.v1 to record the default engineering approach.');
|
|
142
142
|
if (program.status === 'invalid') guidance.push('Repair the Program with genesis prompt --task program.');
|
|
143
|
-
if (skills.status
|
|
143
|
+
if (['missing', 'outdated'].includes(skills.status)) guidance.push('Run genesis skills sync to refresh selected project Agent Skills.');
|
|
144
144
|
if (skills.status === 'invalid') guidance.push('Repair the reported Agent Skill or managed-skill manifest.');
|
|
145
145
|
if (missingResources.length > 0) {
|
|
146
146
|
guidance.push(`${missingResources.map(({ message }) => message).join(' ')} Prompt generation remains available.`);
|
|
@@ -152,7 +152,7 @@ export async function checkProject({
|
|
|
152
152
|
|
|
153
153
|
const needsAttention = program.status === 'missing'
|
|
154
154
|
|| engineering.status === 'defaulted'
|
|
155
|
-
|| skills.status
|
|
155
|
+
|| ['missing', 'outdated'].includes(skills.status)
|
|
156
156
|
|| missingResources.length > 0
|
|
157
157
|
|| extensionDiagnostics.length > 0
|
|
158
158
|
|| ['missing', 'stale', 'unconfigured'].includes(verification.status);
|
|
@@ -198,6 +198,10 @@ function collaborationCatalog() {
|
|
|
198
198
|
|
|
199
199
|
function collaborationGuidance(value) {
|
|
200
200
|
return [
|
|
201
|
+
'Apply the configured tone, response length, assumed experience, and explanation style to every user-facing message, including progress updates and final responses.',
|
|
202
|
+
'Match technical depth and terminology to the configured experience level. Report concrete changes, findings, decisions, or blockers at that level of detail.',
|
|
203
|
+
'Do not announce that you are following project, UI, Stack, or Agent Skill guidance, or add unsolicited assurances about unrelated behavior staying unchanged. Explain process or scope when the user asks or it matters to a decision or blocker, using the configured style.',
|
|
204
|
+
'',
|
|
201
205
|
'## Tone',
|
|
202
206
|
'',
|
|
203
207
|
DIMENSIONS.tone[value.tone].guidance,
|
package/src/index/prompt.js
CHANGED
|
@@ -27,7 +27,7 @@ const DEFAULT_REQUEST = {
|
|
|
27
27
|
start: 'Start a conversation about this project.',
|
|
28
28
|
adopt: 'Import the existing project into a truthful Genesis project contract.',
|
|
29
29
|
work: 'Implement the product intent expressed by the current Blueprint.',
|
|
30
|
-
deslop: 'Deslop the
|
|
30
|
+
deslop: 'Deslop your own changes for the current task.',
|
|
31
31
|
program: 'Refresh the complete useful Program for the code that exists now.',
|
|
32
32
|
describe: 'Create or refresh the complete Blueprint and useful Program for the codebase that exists now.',
|
|
33
33
|
review: 'Review the complete useful relationship between Blueprint, code, Program, and tests.',
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readCollaboration } from './collaboration.js';
|
|
2
|
+
import { inspectProjectSkills } from './agent-skills.js';
|
|
2
3
|
import { GENESIS_CONTRACTS } from './contracts.js';
|
|
3
4
|
import { readEngineering, readEngineeringBaseline } from './engineering.js';
|
|
4
|
-
import { GenesisError } from './errors.js';
|
|
5
|
+
import { asDiagnostic, GenesisError } from './errors.js';
|
|
5
6
|
import { gitContext } from './git.js';
|
|
6
7
|
import { inspectProject } from './project-inspection.js';
|
|
7
8
|
import { readStack } from './stack.js';
|
|
@@ -118,6 +119,11 @@ export async function projectSessionContext({
|
|
|
118
119
|
inspectProject({ projectRoot: root, stackPackages }),
|
|
119
120
|
]);
|
|
120
121
|
const availableComponents = await optionalStackComponentIds(root, stack, stackPackages);
|
|
122
|
+
const skills = stack && inspection.projectFormat.status === 'current'
|
|
123
|
+
? await inspectProjectSkills({ projectRoot: root, stack }).catch((error) => ({
|
|
124
|
+
diagnostics: [asDiagnostic(error)],
|
|
125
|
+
}))
|
|
126
|
+
: { diagnostics: [] };
|
|
121
127
|
const selected = stack?.components.map(({ id }) => id) || [];
|
|
122
128
|
const stackStatus = stack
|
|
123
129
|
? (selected.length > 0 ? selected.join(', ') : 'none')
|
|
@@ -140,11 +146,13 @@ export async function projectSessionContext({
|
|
|
140
146
|
'- 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.',
|
|
141
147
|
'- 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.',
|
|
142
148
|
'- Use the relevant project Agent Skills below `.agents/skills/`.',
|
|
149
|
+
...skills.diagnostics.map(({ message }) => `- Agent Skill maintenance: ${message}`),
|
|
150
|
+
...(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.'] : []),
|
|
143
151
|
'- 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.',
|
|
144
152
|
'- Program is fallible explanation; code, tests, and runtime behavior remain evidence.',
|
|
145
153
|
'- Keep Blueprint and affected Program explanations aligned with intentional observable product behavior in the same implementation turn. Private restructuring may need only source citations or no explanatory change.',
|
|
146
154
|
'- Before reporting completion, compare the requested observable behavior, required inputs and resources, declared project operations, and focused evidence with what actually exists. State anything not proven.',
|
|
147
|
-
'- Deslop only when explicitly requested.
|
|
155
|
+
'- Deslop only when explicitly requested. By default, clean up your own changes for the current task, committed or uncommitted; explicit commits or ranges take precedence. Preserve behavior, unrelated work, and existing staging; a dirty worktree is allowed. Selected Stack components may add technology-specific cleanup guidance.',
|
|
148
156
|
'- This guidance is loaded for a new session and refreshed after compaction. Continue the active request without restarting completed work.',
|
|
149
157
|
`Engineering profile: ${engineering.profile?.id || 'invalid; run the Genesis `check` operation'}.`,
|
|
150
158
|
`Selected Stack components: ${stackStatus}.`,
|
|
@@ -158,7 +166,7 @@ export async function projectSessionContext({
|
|
|
158
166
|
collaboration.guidance,
|
|
159
167
|
...(hostContext ? ['', 'HOST CONTEXT', '', hostContext] : []),
|
|
160
168
|
].join('\n');
|
|
161
|
-
return composedContext(GENESIS_CONTRACTS.sessionContext, output);
|
|
169
|
+
return { ...composedContext(GENESIS_CONTRACTS.sessionContext, output), warnings: skills.diagnostics };
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
export async function projectTurnContext({ hostDriver, hostDriverInput } = {}) {
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
|
|
3
3
|
import { checkProject } from './index/check.js';
|
|
4
|
+
import { inspectProjectSkills, syncProjectSkills } from './index/agent-skills.js';
|
|
5
|
+
import { gitContext } from './index/git.js';
|
|
6
|
+
import { inspectProjectFormatAtRoot, requireCurrentProjectFormat } from './index/project-format.js';
|
|
4
7
|
import { buildProjectIndex, GENESIS_DERIVED_ARTIFACTS } from './index/code-index.js';
|
|
5
8
|
import {
|
|
6
9
|
inspectProjectCollaboration,
|
|
@@ -200,3 +203,23 @@ export function verify(options) {
|
|
|
200
203
|
export function check(options) {
|
|
201
204
|
return checkProject(options);
|
|
202
205
|
}
|
|
206
|
+
|
|
207
|
+
async function projectSkillContext({ projectRoot = process.cwd(), stackPackages = [] } = {}) {
|
|
208
|
+
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
209
|
+
requireCurrentProjectFormat(await inspectProjectFormatAtRoot(root), { allowUninitialized: true });
|
|
210
|
+
return { projectRoot: root, stack: await readStack(root, { stackPackages }) };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export async function inspectSkills(options) {
|
|
214
|
+
return inspectProjectSkills(await projectSkillContext(options));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function syncSkills(options) {
|
|
218
|
+
const context = await projectSkillContext(options);
|
|
219
|
+
const result = await syncProjectSkills(context);
|
|
220
|
+
return {
|
|
221
|
+
...result,
|
|
222
|
+
inspection: await inspectProjectSkills(context),
|
|
223
|
+
guidance: 'Review changed skills in the ordinary Git diff. An assistant that already loaded them needs its supported context refresh before using the new guidance.',
|
|
224
|
+
};
|
|
225
|
+
}
|