@zenera/cli 1.1.16 → 1.1.17
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 +20 -12
- package/dist/catalog.js +19 -20
- package/dist/commands/check.js +5 -1
- package/dist/commands/init.js +41 -6
- package/dist/commands/run.js +4 -0
- package/dist/engine.js +6 -0
- package/dist/env.d.ts +20 -0
- package/dist/env.js +65 -0
- package/dist/keys.d.ts +2 -0
- package/dist/keys.js +2 -0
- package/dist/sandbox.d.ts +9 -0
- package/dist/sandbox.js +23 -3
- package/dist/scaffold.d.ts +6 -0
- package/dist/scaffold.js +56 -15
- package/dist/validate.js +57 -15
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +256 -91
- package/templates/editor/.github/prompts/review-project.prompt.md +53 -14
- package/templates/editor/.github/prompts/sync-with-spec.prompt.md +208 -21
- package/templates/editor/.github/prompts/update-spec-from-feedback.prompt.md +142 -0
- package/templates/editor/.github/skills/zen-cli/references/check.md +6 -3
- package/templates/editor/.github/skills/zen-cli/references/frame.md +5 -3
- package/templates/editor/.github/skills/zen-cli/references/projects.md +19 -2
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +6 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +102 -30
- package/templates/editor/.github/skills/zen-memory/scripts/check-instructions.sh +115 -0
- package/templates/editor/.github/skills/zen-review/SKILL.md +123 -0
- package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +119 -0
- package/templates/editor/.github/skills/zen-review/scripts/review.sh +104 -0
- package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +197 -0
- package/templates/editor/.github/skills/zen-spec-sync/scripts/snapshot.sh +200 -0
- package/templates/editor/.vscode/settings.json +44 -4
- package/templates/parts/memory-terms.yaml.tmpl +16 -0
- package/templates/parts/memory.yaml.tmpl +12 -0
- package/templates/project/SPECIFICATION.md.tmpl +7 -0
- package/templates/project/agents/memory-instructions.md +278 -0
- package/templates/project/agents.yaml.tmpl +9 -0
- package/templates/project/env +22 -0
- /package/templates/project/{INSTRUCTIONS.md → agents/instructions.md} +0 -0
package/dist/validate.js
CHANGED
|
@@ -11,13 +11,43 @@ import { BuildError, ensurePodmanReady } from "./podman.js";
|
|
|
11
11
|
// Duplicated rather than exported, because a check that agreed with the loader
|
|
12
12
|
// by construction could not report that the two had diverged.
|
|
13
13
|
const CONFIG_NAMES = ['agents.yaml', 'agents.yml', 'agents/agents.yaml', 'agents/agents.yml'];
|
|
14
|
-
const
|
|
14
|
+
const AGENTS_DIR = 'agents';
|
|
15
|
+
const HOUSE_RULES = 'agents/instructions.md';
|
|
16
|
+
const INSTRUCTIONS_SUFFIX = '-instructions.md';
|
|
17
|
+
const LEGACY_HOUSE_RULES = 'INSTRUCTIONS.md';
|
|
15
18
|
const PROMPTS_DIR = 'agents/prompts';
|
|
16
19
|
const SKILLS_DIR = 'agents/skills';
|
|
17
20
|
const SKILL_FILE = 'SKILL.md';
|
|
18
21
|
const ASSETS_DIR = 'assets';
|
|
19
22
|
/** What `allow:` and `preload:` accept, so a skill outside it cannot be named. */
|
|
20
23
|
const REFERABLE = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/;
|
|
24
|
+
/**
|
|
25
|
+
* Mirrors `readHouseRules` in the loader, in the same order: the legacy file
|
|
26
|
+
* first, then `agents/instructions.md`, then every
|
|
27
|
+
* `agents/<topic>-instructions.md` by filename.
|
|
28
|
+
*/
|
|
29
|
+
function houseRules(root) {
|
|
30
|
+
const found = [];
|
|
31
|
+
const take = (rel) => {
|
|
32
|
+
if (existsSync(join(root, rel))) {
|
|
33
|
+
found.push(rel);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
take(LEGACY_HOUSE_RULES);
|
|
37
|
+
take(HOUSE_RULES);
|
|
38
|
+
const dir = join(root, AGENTS_DIR);
|
|
39
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) {
|
|
40
|
+
return found;
|
|
41
|
+
}
|
|
42
|
+
const topics = readdirSync(dir, { withFileTypes: true })
|
|
43
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(INSTRUCTIONS_SUFFIX))
|
|
44
|
+
.map((entry) => entry.name)
|
|
45
|
+
.sort((a, b) => a.localeCompare(b));
|
|
46
|
+
for (const name of topics) {
|
|
47
|
+
take(`${AGENTS_DIR}/${name}`);
|
|
48
|
+
}
|
|
49
|
+
return found;
|
|
50
|
+
}
|
|
21
51
|
export async function validateProject(opts) {
|
|
22
52
|
const root = resolve(opts.dir);
|
|
23
53
|
const findings = [];
|
|
@@ -140,23 +170,38 @@ export async function validateProject(opts) {
|
|
|
140
170
|
// -----------------------------------------------------------------------
|
|
141
171
|
// Files the config and the conventions name
|
|
142
172
|
// -----------------------------------------------------------------------
|
|
143
|
-
const
|
|
144
|
-
|
|
173
|
+
const rules = houseRules(root);
|
|
174
|
+
for (const rel of rules) {
|
|
175
|
+
record(rel, 'house rules — prepended to every agent prompt', 'file', false);
|
|
176
|
+
if (empty(join(root, rel))) {
|
|
177
|
+
add({
|
|
178
|
+
severity: 'warning',
|
|
179
|
+
code: 'house-rules.empty',
|
|
180
|
+
where: rel,
|
|
181
|
+
message: `${rel} is empty, so it contributes nothing but a prompt section`,
|
|
182
|
+
fix: 'write the rules that hold whichever agent is answering, or delete it',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (rules.length === 0) {
|
|
187
|
+
record(HOUSE_RULES, 'house rules — prepended to every agent prompt', 'file', false);
|
|
145
188
|
add({
|
|
146
189
|
severity: 'note',
|
|
147
190
|
code: 'house-rules.missing',
|
|
148
191
|
where: HOUSE_RULES,
|
|
149
|
-
message: 'no
|
|
192
|
+
message: 'no house rules, which is allowed: every agent then runs on its own role ' +
|
|
150
193
|
'prompt alone, with nothing shared between them',
|
|
151
194
|
});
|
|
152
195
|
}
|
|
153
|
-
|
|
196
|
+
if (rules.includes(LEGACY_HOUSE_RULES)) {
|
|
154
197
|
add({
|
|
155
198
|
severity: 'warning',
|
|
156
|
-
code: 'house-rules.
|
|
157
|
-
where:
|
|
158
|
-
message:
|
|
159
|
-
|
|
199
|
+
code: 'house-rules.legacy',
|
|
200
|
+
where: LEGACY_HOUSE_RULES,
|
|
201
|
+
message: `${LEGACY_HOUSE_RULES} is where the house rules used to live. It is still ` +
|
|
202
|
+
`read, and still first, but the layout now keeps them under ${AGENTS_DIR}/ ` +
|
|
203
|
+
'so a project can have more than one of them',
|
|
204
|
+
fix: `move it to ${HOUSE_RULES}, or fold it into the ${AGENTS_DIR}/*${INSTRUCTIONS_SUFFIX} files already there`,
|
|
160
205
|
});
|
|
161
206
|
}
|
|
162
207
|
// -----------------------------------------------------------------------
|
|
@@ -400,14 +445,11 @@ export function availableTools(root, config) {
|
|
|
400
445
|
}
|
|
401
446
|
function checkAgent(root, config, spec, entry, available, record, add) {
|
|
402
447
|
const where = `agents.${spec.name}`;
|
|
403
|
-
const instructions = [];
|
|
404
|
-
if (existsSync(join(root, HOUSE_RULES))) {
|
|
405
|
-
instructions.push(HOUSE_RULES);
|
|
406
|
-
}
|
|
448
|
+
const instructions = [...houseRules(root)];
|
|
407
449
|
// The role prompt: named by `system:`, or found by convention. A named one
|
|
408
450
|
// that is not there is an error — the loader says so too. An absent
|
|
409
451
|
// conventional one is not, because a project may keep everything it has to
|
|
410
|
-
// say in
|
|
452
|
+
// say in its house rules.
|
|
411
453
|
if (spec.system) {
|
|
412
454
|
const rel = normalise(root, spec.system);
|
|
413
455
|
const outside = rel === undefined;
|
|
@@ -457,7 +499,7 @@ function checkAgent(root, config, spec, entry, available, record, add) {
|
|
|
457
499
|
severity: 'warning',
|
|
458
500
|
code: 'agent.no-instructions',
|
|
459
501
|
where,
|
|
460
|
-
message: 'this agent has no prompt at all — no
|
|
502
|
+
message: 'this agent has no prompt at all — no house rules and no role file — so ' +
|
|
461
503
|
'it runs on the tool descriptions alone',
|
|
462
504
|
fix: `write ${join(PROMPTS_DIR, `${spec.name}.md`)}, or name one with \`system:\``,
|
|
463
505
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenera/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.17",
|
|
4
4
|
"description": "Command-line front end for @zenera/neo: agentic projects you can run, share and commit.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@inkjs/ui": "^2.0.0",
|
|
52
52
|
"ink": "^7.1.1",
|
|
53
53
|
"react": "^19.2.8",
|
|
54
|
-
"@zenera/neo": "^1.1.
|
|
54
|
+
"@zenera/neo": "^1.1.17",
|
|
55
55
|
"@anthropic-ai/sdk": "^0.120.0",
|
|
56
56
|
"@google/genai": "^2.18.0",
|
|
57
57
|
"@openrouter/sdk": "^1.2.80",
|