@execuro-sw-ecosystem/sw-ecosystem-agentic-harness 0.1.6 → 0.1.8
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/CHANGELOG.md +87 -0
- package/CONTRIBUTING.md +13 -4
- package/README.md +67 -36
- package/SECURITY.md +1 -1
- package/bin/cli.mjs +21 -15
- package/lib/actions.mjs +1 -45
- package/lib/commands.mjs +111 -109
- package/lib/content.mjs +31 -1
- package/lib/guide.mjs +39 -38
- package/lib/hosts.mjs +44 -42
- package/lib/lock.mjs +51 -14
- package/lib/out.mjs +27 -6
- package/lib/prompt.mjs +18 -23
- package/lib/render.mjs +365 -0
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/skills/sw-design-requirements/SKILL.md +1 -1
- package/skills/sw-design-requirements/reference/editor-gate.md +1 -1
- package/skills/sw-design-requirements/reference/editor-mode.md +2 -2
- package/skills/sw-design-solution/SKILL.md +1 -1
- package/skills/sw-design-solution/reference/editor-mode.md +2 -2
- package/skills/sw-discover-tender/SKILL.md +2 -2
- package/skills/sw-discover-tender/reference/editor-session.md +3 -3
- package/skills/sw-discover-tender/reference/procedure.md +2 -2
- package/skills/sw-setup/SKILL.md +19 -17
- package/skills/sw-setup/reference/rows.md +120 -77
- package/lib/extra-components.mjs +0 -117
package/lib/render.mjs
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// The human view of a result body.
|
|
2
|
+
//
|
|
3
|
+
// Every command still builds exactly the same JSON object it always did — that
|
|
4
|
+
// object is the model. This module is the view: pure `body -> string`
|
|
5
|
+
// functions, no I/O, no process state, so the whole renderer is testable
|
|
6
|
+
// without a terminal and without running an install.
|
|
7
|
+
//
|
|
8
|
+
// Design rules, in the order they matter:
|
|
9
|
+
//
|
|
10
|
+
// 1. Nothing changed is ONE line. A file count is not news to a human, and
|
|
11
|
+
// "274 unchanged" reads like a failure to someone who typed `install`.
|
|
12
|
+
// 2. Something changed is reported per agent, in the user's vocabulary —
|
|
13
|
+
// skills and sub-agents by name, config files by path.
|
|
14
|
+
// 3. Conflicts, drift, manual steps and failures are never collapsed into a
|
|
15
|
+
// count: those are the only cases the user has to act on, so each one
|
|
16
|
+
// names its file and its remedy.
|
|
17
|
+
// 4. Never name an agent this project has not installed. A Claude Code user
|
|
18
|
+
// is not told about Codex, Cursor or Copilot.
|
|
19
|
+
//
|
|
20
|
+
// Zero dependencies: bare ANSI, and only when the caller says the stream is a
|
|
21
|
+
// terminal.
|
|
22
|
+
|
|
23
|
+
/** Human labels for the four supported coding agents. */
|
|
24
|
+
export const LABELS = {
|
|
25
|
+
'claude-code': 'Claude Code',
|
|
26
|
+
codex: 'Codex',
|
|
27
|
+
copilot: 'GitHub Copilot',
|
|
28
|
+
cursor: 'Cursor',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** What each agent needs before it reads the configuration we just wrote. */
|
|
32
|
+
export const RESTART = {
|
|
33
|
+
'claude-code': 'Restart Claude Code, or run `/mcp` in the running session',
|
|
34
|
+
codex: 'Restart `codex` — .codex/config.toml is read once at startup',
|
|
35
|
+
copilot: 'Reload the VS Code window (Developer: Reload Window) for .vscode/mcp.json',
|
|
36
|
+
cursor: 'Restart Cursor so it re-reads .cursor/mcp.json',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function label(id) {
|
|
40
|
+
return LABELS[id] ?? id;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ------------------------------------------------------------------ styling
|
|
44
|
+
|
|
45
|
+
const CODES = { bold: '1', dim: '2', red: '31', green: '32', yellow: '33' };
|
|
46
|
+
|
|
47
|
+
/** A theme whose functions are the identity when colour is off. */
|
|
48
|
+
function theme(color) {
|
|
49
|
+
const wrap = (code) => (color ? (s) => `\x1b[${code}m${s}\x1b[0m` : (s) => s);
|
|
50
|
+
const t = {};
|
|
51
|
+
for (const [name, code] of Object.entries(CODES)) t[name] = wrap(code);
|
|
52
|
+
return t;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// --------------------------------------------------------------- primitives
|
|
56
|
+
|
|
57
|
+
const MAX_NAMES = 6;
|
|
58
|
+
|
|
59
|
+
/** "a, b, c and 4 more" — a list a person reads, not a dump. */
|
|
60
|
+
function names(list) {
|
|
61
|
+
const max = MAX_NAMES;
|
|
62
|
+
const all = [...list];
|
|
63
|
+
if (all.length <= max) return all.join(', ');
|
|
64
|
+
return `${all.slice(0, max).join(', ')} and ${all.length - max} more`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function plural(n, one, many = `${one}s`) {
|
|
68
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* What a target is, in the words a user thinks in. A skill is one thing to
|
|
73
|
+
* them even though it is a directory of files; a config file is its path.
|
|
74
|
+
*/
|
|
75
|
+
export function classify(target) {
|
|
76
|
+
const skill = /(?:^|\/)skills\/([^/]+)\//.exec(target);
|
|
77
|
+
if (skill) return { kind: 'skill', name: skill[1] };
|
|
78
|
+
const agent = /(?:^|\/)agents\/([^/]+)$/.exec(target);
|
|
79
|
+
if (agent) return { kind: 'agent', name: agent[1].replace(/(\.agent)?\.(md|toml)$/, '') };
|
|
80
|
+
return { kind: 'file', name: target };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const VERBS = {
|
|
84
|
+
create: 'added', created: 'added',
|
|
85
|
+
update: 'updated', updated: 'updated',
|
|
86
|
+
removed: 'removed', reverted: 'reverted',
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const SHARED = '__shared__';
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Group the actions in `states` by agent, then by verb, then by what kind of
|
|
93
|
+
* thing they are. Returns `[{ id, buckets: Map<verb, {skills, agents, files}> }]`
|
|
94
|
+
* in the order the agents first appear.
|
|
95
|
+
*/
|
|
96
|
+
export function groupChanges(actions = [], states) {
|
|
97
|
+
const wanted = new Set(states);
|
|
98
|
+
const order = [];
|
|
99
|
+
const groups = new Map();
|
|
100
|
+
for (const action of actions) {
|
|
101
|
+
if (!wanted.has(action.state)) continue;
|
|
102
|
+
const id = !action.host || action.host === 'shared' ? SHARED : action.host;
|
|
103
|
+
if (!groups.has(id)) { groups.set(id, new Map()); order.push(id); }
|
|
104
|
+
const buckets = groups.get(id);
|
|
105
|
+
const verb = VERBS[action.state] ?? action.state;
|
|
106
|
+
if (!buckets.has(verb)) buckets.set(verb, { skill: new Set(), agent: new Set(), file: new Set() });
|
|
107
|
+
const bucket = buckets.get(verb);
|
|
108
|
+
const { kind, name } = classify(action.target);
|
|
109
|
+
// Several actions can target one config file (one per JSON pointer);
|
|
110
|
+
// the user changed one file, so it is named once.
|
|
111
|
+
bucket[kind].add(name);
|
|
112
|
+
(bucket.targets ??= []).push(action.target);
|
|
113
|
+
}
|
|
114
|
+
return order.map((id) => ({ id, buckets: groups.get(id) }));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function bucketLines(verb, bucket, { verbose }, t) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
if (verbose) {
|
|
120
|
+
for (const target of bucket.targets ?? []) lines.push(` ${t.dim(verb)} ${target}`);
|
|
121
|
+
return lines;
|
|
122
|
+
}
|
|
123
|
+
if (bucket.skill.size) lines.push(` ${verb} ${plural(bucket.skill.size, 'skill')}: ${names(bucket.skill)}`);
|
|
124
|
+
if (bucket.agent.size) lines.push(` ${verb} ${plural(bucket.agent.size, 'sub-agent')}: ${names(bucket.agent)}`);
|
|
125
|
+
if (bucket.file.size) lines.push(` ${verb} ${names(bucket.file)}`);
|
|
126
|
+
return lines;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function groupLines(groups, opts, t) {
|
|
130
|
+
const lines = [];
|
|
131
|
+
for (const { id, buckets } of groups) {
|
|
132
|
+
lines.push(` ${t.bold(id === SHARED ? 'Project files' : label(id))}`);
|
|
133
|
+
for (const [verb, bucket] of buckets) lines.push(...bucketLines(verb, bucket, opts, t));
|
|
134
|
+
}
|
|
135
|
+
return lines;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ------------------------------------------------------------------- issues
|
|
139
|
+
|
|
140
|
+
/** Everything the user has to act on, flattened into one shape. */
|
|
141
|
+
function issues(body) {
|
|
142
|
+
const found = [];
|
|
143
|
+
for (const a of body.actions ?? []) {
|
|
144
|
+
if (a.state === 'conflict' || a.state === 'drift' || a.state === 'failed') {
|
|
145
|
+
found.push({ kind: a.state, target: a.target, reason: a.reason, remedy: a.remedy });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const d of body.drift ?? []) {
|
|
149
|
+
found.push({ kind: d.state ?? 'drift', target: d.target, reason: d.reason, remedy: d.remedy });
|
|
150
|
+
}
|
|
151
|
+
for (const m of body.manual ?? []) {
|
|
152
|
+
found.push({ kind: 'manual', target: m.target ?? m.file, reason: m.reason, remedy: m.remedy });
|
|
153
|
+
}
|
|
154
|
+
for (const e of body.errors ?? []) {
|
|
155
|
+
found.push({ kind: 'failed', target: e.target ?? label(e.host), reason: e.error });
|
|
156
|
+
}
|
|
157
|
+
// The same file can reach us from both `actions` and `drift`; say it once.
|
|
158
|
+
const seen = new Set();
|
|
159
|
+
return found.filter((i) => {
|
|
160
|
+
const key = `${i.kind}:${i.target}`;
|
|
161
|
+
if (seen.has(key)) return false;
|
|
162
|
+
seen.add(key);
|
|
163
|
+
return true;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const ISSUE_TITLE = {
|
|
168
|
+
conflict: 'conflict', drift: 'edited since install',
|
|
169
|
+
manual: 'manual step', failed: 'failed',
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
function issueLines(list, t) {
|
|
173
|
+
if (!list.length) return [];
|
|
174
|
+
const paint = (kind) => (kind === 'drift' || kind === 'manual' ? t.yellow : t.red);
|
|
175
|
+
const lines = [` ${t.bold('Needs your attention')}`];
|
|
176
|
+
for (const i of list) {
|
|
177
|
+
lines.push(` ${paint(i.kind)(ISSUE_TITLE[i.kind] ?? i.kind)} ${i.target}`);
|
|
178
|
+
if (i.reason) lines.push(` ${i.reason}`);
|
|
179
|
+
if (i.remedy) lines.push(` ${t.dim('fix:')} ${i.remedy}`);
|
|
180
|
+
}
|
|
181
|
+
return lines;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ------------------------------------------------------------------ restart
|
|
185
|
+
|
|
186
|
+
function restartLines(body, changedIds, t) {
|
|
187
|
+
const ids = changedIds.length
|
|
188
|
+
? changedIds
|
|
189
|
+
: (body.agents ?? []).map((a) => a.id).filter((id) => RESTART[id]);
|
|
190
|
+
const uniq = [...new Set(ids)].filter((id) => RESTART[id]);
|
|
191
|
+
return uniq.map((id) => ` ${t.dim('→')} ${RESTART[id]}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ------------------------------------------------------------ apply/install
|
|
195
|
+
|
|
196
|
+
function renderApply(body, opts, t) {
|
|
197
|
+
const s = body.summary ?? {};
|
|
198
|
+
const changed = (s.created ?? 0) + (s.updated ?? 0);
|
|
199
|
+
const problems = issues(body);
|
|
200
|
+
const migrated = body.migrated ?? [];
|
|
201
|
+
|
|
202
|
+
if (changed === 0 && problems.length === 0 && migrated.length === 0) {
|
|
203
|
+
// ONE line. Nothing changed means nothing to restart and nothing to read.
|
|
204
|
+
return `${t.green('✓')} Shopware agentic harness: already up to date — nothing to change.\n`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const groups = groupChanges(body.actions, ['created', 'updated']);
|
|
208
|
+
const changedIds = groups.map((g) => g.id).filter((id) => id !== SHARED);
|
|
209
|
+
const verb = (s.updated ?? 0) === 0 ? 'Installed' : 'Updated';
|
|
210
|
+
const lines = [];
|
|
211
|
+
if (changed) lines.push(`${t.green('✓')} ${verb} the Shopware agentic harness.`);
|
|
212
|
+
else if (problems.length) lines.push(`${t.yellow('!')} Nothing was written — see below.`);
|
|
213
|
+
// Only tidy-up ran: the install itself was already current.
|
|
214
|
+
else lines.push(`${t.green('✓')} Shopware agentic harness: already up to date.`);
|
|
215
|
+
if (groups.length) {
|
|
216
|
+
lines.push('');
|
|
217
|
+
lines.push(...groupLines(groups, opts, t));
|
|
218
|
+
}
|
|
219
|
+
if (migrated.length) {
|
|
220
|
+
lines.push('');
|
|
221
|
+
for (const m of migrated) lines.push(` ${t.dim('·')} ${m.target}: ${m.detail}`);
|
|
222
|
+
}
|
|
223
|
+
if (problems.length) {
|
|
224
|
+
lines.push('');
|
|
225
|
+
lines.push(...issueLines(problems, t));
|
|
226
|
+
}
|
|
227
|
+
if (changed) {
|
|
228
|
+
lines.push('');
|
|
229
|
+
lines.push(...restartLines(body, changedIds, t));
|
|
230
|
+
}
|
|
231
|
+
return `${lines.join('\n')}\n`;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// -------------------------------------------------------------------- plan
|
|
235
|
+
|
|
236
|
+
function renderPlan(body, opts, t) {
|
|
237
|
+
const s = body.summary ?? {};
|
|
238
|
+
const changes = (s.create ?? 0) + (s.update ?? 0);
|
|
239
|
+
const problems = issues(body);
|
|
240
|
+
if (changes === 0 && problems.length === 0) {
|
|
241
|
+
return `${t.green('✓')} Nothing to do — every target is already up to date.\n`;
|
|
242
|
+
}
|
|
243
|
+
const lines = [];
|
|
244
|
+
// `plan` with nothing selected previews every supported agent. Say so, or
|
|
245
|
+
// the list silently names agents this project never installed.
|
|
246
|
+
if (/previews all four/i.test(body.next_step ?? '')) {
|
|
247
|
+
lines.push(t.dim('No agent selected and no recorded install — previewing every supported agent.'));
|
|
248
|
+
}
|
|
249
|
+
lines.push(`${plural(changes, 'change')} would be made. Nothing was written.`);
|
|
250
|
+
const groups = groupChanges(body.actions, ['create', 'update']);
|
|
251
|
+
if (groups.length) {
|
|
252
|
+
lines.push('');
|
|
253
|
+
lines.push(...groupLines(groups, opts, t));
|
|
254
|
+
}
|
|
255
|
+
if (problems.length) {
|
|
256
|
+
lines.push('');
|
|
257
|
+
lines.push(...issueLines(problems, t));
|
|
258
|
+
}
|
|
259
|
+
if (changes) {
|
|
260
|
+
lines.push('');
|
|
261
|
+
lines.push(` ${t.dim('→')} Run \`sw-ecosystem-agentic-harness apply --yes\` to perform them.`);
|
|
262
|
+
}
|
|
263
|
+
return `${lines.join('\n')}\n`;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ------------------------------------------------------------------ status
|
|
267
|
+
|
|
268
|
+
/** An agent is only ours to talk about once it has actually been installed. */
|
|
269
|
+
function installedAgents(body) {
|
|
270
|
+
return (body.agents ?? []).filter((a) => ['ok', 'drift', 'conflict'].includes(a.state));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function renderStatus(body, opts, t) {
|
|
274
|
+
const mine = installedAgents(body);
|
|
275
|
+
const problems = issues(body);
|
|
276
|
+
|
|
277
|
+
if (!mine.length) {
|
|
278
|
+
return `${t.yellow('!')} No coding agent is set up in this project yet.\n`
|
|
279
|
+
+ ` ${t.dim('→')} ${body.help?.[0] ?? 'sw-ecosystem-agentic-harness install'}\n`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const worst = ['conflict', 'drift'].find((state) => mine.some((a) => a.state === state));
|
|
283
|
+
const lines = [];
|
|
284
|
+
lines.push(worst
|
|
285
|
+
? `${t.yellow('!')} Shopware agentic harness ${body.installed_version ?? body.version} — ${plural(problems.length, 'item')} ${problems.length === 1 ? 'needs' : 'need'} attention.`
|
|
286
|
+
: `${t.green('✓')} Shopware agentic harness ${body.installed_version ?? body.version} — installed and up to date.`);
|
|
287
|
+
|
|
288
|
+
for (const a of mine) {
|
|
289
|
+
const counts = [];
|
|
290
|
+
if (a.installed?.skills) counts.push(plural(a.installed.skills, 'skill'));
|
|
291
|
+
if (a.installed?.agents) counts.push(plural(a.installed.agents, 'sub-agent'));
|
|
292
|
+
lines.push(` ${t.bold(label(a.id))}${counts.length ? `: ${counts.join(', ')}` : ''}`);
|
|
293
|
+
for (const note of a.notes ?? []) lines.push(` ${t.dim(note)}`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (problems.length) {
|
|
297
|
+
lines.push('');
|
|
298
|
+
lines.push(...issueLines(problems, t));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return `${lines.join('\n')}\n`;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// --------------------------------------------------------------- uninstall
|
|
305
|
+
|
|
306
|
+
function renderUninstall(body, opts, t) {
|
|
307
|
+
const s = body.summary ?? {};
|
|
308
|
+
const gone = (s.removed ?? 0) + (s.reverted ?? 0);
|
|
309
|
+
if (gone === 0 && !(body.kept ?? []).length) {
|
|
310
|
+
return `${t.green('✓')} Nothing to remove — this project has no recorded install.\n`;
|
|
311
|
+
}
|
|
312
|
+
const lines = [`${t.green('✓')} Removed the Shopware agentic harness — `
|
|
313
|
+
+ `${plural(s.removed ?? 0, 'file')} removed, ${plural(s.reverted ?? 0, 'config block')} reverted.`];
|
|
314
|
+
if ((body.kept ?? []).length) {
|
|
315
|
+
lines.push('');
|
|
316
|
+
lines.push(` ${t.bold('Kept, because you edited them')}`);
|
|
317
|
+
for (const k of body.kept) lines.push(` ${k.target}`);
|
|
318
|
+
}
|
|
319
|
+
lines.push('');
|
|
320
|
+
lines.push(` ${t.dim('→')} Restart your coding agent(s) so they drop the removed configuration.`);
|
|
321
|
+
return `${lines.join('\n')}\n`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ------------------------------------------------------------------ errors
|
|
325
|
+
|
|
326
|
+
function renderProblem(body, opts, t) {
|
|
327
|
+
const lines = [`${t.red('✗')} ${body.error}`];
|
|
328
|
+
for (const e of body.errors ?? []) {
|
|
329
|
+
lines.push(` ${e.target ?? label(e.host)} — ${e.error}`);
|
|
330
|
+
}
|
|
331
|
+
const problems = issues({ ...body, errors: [] });
|
|
332
|
+
if (problems.length) {
|
|
333
|
+
lines.push('');
|
|
334
|
+
lines.push(...issueLines(problems, t));
|
|
335
|
+
}
|
|
336
|
+
if (body.help?.length) {
|
|
337
|
+
lines.push('');
|
|
338
|
+
lines.push(` ${t.bold('Try')}`);
|
|
339
|
+
for (const h of body.help) lines.push(` ${h}`);
|
|
340
|
+
}
|
|
341
|
+
return `${lines.join('\n')}\n`;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ---------------------------------------------------------------- dispatch
|
|
345
|
+
|
|
346
|
+
const RENDERERS = {
|
|
347
|
+
install: renderApply,
|
|
348
|
+
apply: renderApply,
|
|
349
|
+
plan: renderPlan,
|
|
350
|
+
status: renderStatus,
|
|
351
|
+
uninstall: renderUninstall,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* `body` is the exact object `--json` prints. `opts.verbose` prints the
|
|
356
|
+
* per-file detail the JSON carries; `opts.color` enables ANSI.
|
|
357
|
+
*/
|
|
358
|
+
export function render(body, opts = {}) {
|
|
359
|
+
if (!body || typeof body !== 'object') return '';
|
|
360
|
+
const t = theme(opts.color === true);
|
|
361
|
+
if (body.ok === false) return renderProblem(body, opts, t);
|
|
362
|
+
const renderer = RENDERERS[body.command];
|
|
363
|
+
if (!renderer) return `${body.next_step ?? ''}\n`;
|
|
364
|
+
return renderer(body, opts, t);
|
|
365
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@execuro-sw-ecosystem/sw-ecosystem-agentic-harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Shopware 6 agentic harness: sw-* skills and sub-agents, plus an installer that writes them into Claude Code, Codex, GitHub Copilot and Cursor.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Execuro UG (haftungsbeschränkt)",
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "sw-ecosystem-agentic-harness",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"description": "Shopware 6 agentic harness: sw-* skills and sub-agents for requirements, specs, implementation, verification and documentation, with an installer CLI that writes them into Claude Code, Codex, GitHub Copilot and Cursor. The knowledge-base MCP and the editor tools are separate npm packages.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Execuro UG (haftungsbeschränkt)",
|
|
@@ -3,7 +3,7 @@ name: sw-design-requirements
|
|
|
3
3
|
description: Turn a briefing — chat text or a file, covering one or more features — into a lean, business-only PRD stored as specs/NNNN-slug.md. Runs an interactive clarification loop for the requirement gaps and inconsistencies that actually change the requirements, then scores a weighted confidence %. Use when asked to write, draft, refine, continue, or score a PRD / requirements doc / feature brief for this Shopware project. Never writes a tech spec or answers architecture questions — that's sw-design-solution.
|
|
4
4
|
when_to_use: Trigger phrases — "write a PRD", "draft requirements", "turn this brief into a PRD", "continue PRD 0003", "is this PRD ready for specification", "raise the confidence on this PRD", "requirements for <feature>".
|
|
5
5
|
argument-hint: '[file-path | briefing text | specs/NNNN-slug.md to continue] [--editor]'
|
|
6
|
-
allowed-tools: Read Write Edit Glob Grep AskUserQuestion Agent Skill Bash(ls *) Bash(mkdir -p specs) Bash(npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
6
|
+
allowed-tools: Read Write Edit Glob Grep AskUserQuestion Agent Skill Bash(ls *) Bash(mkdir -p specs) Bash(npx -y @execuro-sw-ecosystem/sw-specs-editor@latest *) mcp__ShopwareDevKnowledgeBase__list_docs mcp__ShopwareDevKnowledgeBase__grep_docs mcp__ShopwareDevKnowledgeBase__read_doc mcp__ShopwareDevKnowledgeBase__kb_status
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Runs before the `--editor` hand-off (step 0). The Specs Editor is an **optional** add-on: it is not part of this plugin, and a host that never installed it is a supported, normal setup. `sw-setup` offers to install it.
|
|
4
4
|
|
|
5
|
-
What is checked is the **skill**, `sw-specs-editor`, because that is what `sw-setup` installs and what the hand-off calls. The skill brings the CLI with it — it invokes `npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
5
|
+
What is checked is the **skill**, `sw-specs-editor`, because that is what `sw-setup` installs and what the hand-off calls. The skill brings the CLI with it — it invokes `npx -y @execuro-sw-ecosystem/sw-specs-editor@latest`, which fetches the package on first use.
|
|
6
6
|
|
|
7
7
|
Check: is the `sw-specs-editor` skill available in this session?
|
|
8
8
|
|
|
@@ -8,8 +8,8 @@ Invoked as `<path> --editor-session <url> --batch <batch.json>` — one note bat
|
|
|
8
8
|
- **Full pass on request only.** A review request ("check the whole PRD", "reconcile") runs the full flow: step 2, §11 gap review, missing options/marks/notes filled. Otherwise touched questions get options.
|
|
9
9
|
- **Scoped agent runs.** Spawn `sw-product-manager`/`sw-shopware-architect` only when a note touches feasibility, §10, or a §11 block changes (one brief per run); else edit, anchor, log alone.
|
|
10
10
|
- **Preserve on every write:** status tags on item ids (`- **FR-3** [done] …`, also `AC-n`/`BR-n`), the `Diagram:` line, the §11 question blocks and ticks. Rewrite in place; never regenerate.
|
|
11
|
-
- **Diagrams.** Domain diagram: `specs/NNNN-slug.domain.graph.json` (business concepts only). Write/update, run `npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
12
|
-
- **Progress.** Before each step, before/after each spawn: `npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
11
|
+
- **Diagrams.** Domain diagram: `specs/NNNN-slug.domain.graph.json` (business concepts only). Write/update, run `npx -y @execuro-sw-ecosystem/sw-specs-editor@latest diagram specs/NNNN-slug.domain.graph.json specs/NNNN-slug.domain.excalidraw`, ensure §4 carries `Diagram: specs/NNNN-slug.domain.excalidraw`; never write `.excalidraw` directly, first request only.
|
|
12
|
+
- **Progress.** Before each step, before/after each spawn: `npx -y @execuro-sw-ecosystem/sw-specs-editor@latest emit progress "<step>" --batch <id> --doc prd`.
|
|
13
13
|
- **Report:** changed blocks, answers (Q ids → anchor), top remaining gap or `none`, confidence %, status, `Agents: <list or none>`.
|
|
14
14
|
|
|
15
15
|
Graph shape (`bin/cli.mjs diagram` input): `{ "title", "direction": "LR", "groups": [{id,label}], "nodes": [{id,label,type: entity|actor|service|external|event|store, group?, note?}], "edges": [{from,to,label?}] }`.
|
|
@@ -3,7 +3,7 @@ name: sw-design-solution
|
|
|
3
3
|
description: Turn a PRD (specs/NNNN-slug.md) into a technical spec at specs/NNNN-slug-spec.md. Applies TDD — every acceptance criterion gets an implementation plan and e2e coverage, with Shopware toolchain (shopware-cli/PHPStan/ESLint/Stylelint) conventions baked into decisions up front. Runs a clarification loop for the gaps that change the implementation plan, and on the user's say-so extracts project-wide architecture/stack decisions into ADR files (specs/NNNN-slug-adr-<topic>.md) that gate readiness while proposed. Pre-checks vendor/ and the KB before it starts. Use when asked to write, draft, refine, or continue a tech spec / implementation plan. Never edits the source PRD or answers business/requirements questions — that's sw-design-requirements.
|
|
4
4
|
when_to_use: Trigger phrases — "write the tech spec for PRD 0007", "create an implementation plan for this PRD", "draft the spec", "continue spec 0007", "is this spec ready for implementation".
|
|
5
5
|
argument-hint: '[specs/NNNN-slug.md | specs/NNNN-slug-spec.md] [--editor]'
|
|
6
|
-
allowed-tools: Read Write Edit Glob Grep AskUserQuestion Agent Skill Bash(ls *) Bash(npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
6
|
+
allowed-tools: Read Write Edit Glob Grep AskUserQuestion Agent Skill Bash(ls *) Bash(npx -y @execuro-sw-ecosystem/sw-specs-editor@latest *) WebSearch WebFetch mcp__ShopwareDevKnowledgeBase__list_docs mcp__ShopwareDevKnowledgeBase__grep_docs mcp__ShopwareDevKnowledgeBase__read_doc mcp__ShopwareDevKnowledgeBase__kb_status
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# sw-design-solution
|
|
@@ -9,8 +9,8 @@ Same procedure/boundary/verification/ADR rules, plus:
|
|
|
9
9
|
- **Batch input.** Ticks first — a ticked question with no note is still an answer. `answer`/`[x]` tick → anchor, append Decision Log, delete block (`[adr]` sub-step 3, `[gate]` sub-step 5). `comment`/`free` → this run's briefing (block-bound `path`/`line`–`endLine`/`md`/`quote`/`hash`; verify `md` matches, fall back to `quote`; `selection` → rework only that text). `diagram` → update the graph file. *What*/*why* notes belong to the PRD. First write migrates a pre-template spec; blocks get missing options only when touched.
|
|
10
10
|
- **Scoped runs.** Re-spawn architect only for an overturned/new decision, QA only for a changed test plan, `sw-product-manager` only for feasibility — together still one message; else edit/verify/anchor/log alone, name agents.
|
|
11
11
|
- **Preserve:** status tags (`- **AC-2** [partly] (FR-3)`, `- **Decision:** [done] …`), `Diagram:` line, §6 blocks/ticks — rewrite in place, never regenerate.
|
|
12
|
-
- **Diagrams.** `specs/NNNN-slug-spec.architecture.graph.json`; run `npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
13
|
-
- **Progress.** `npx -y @execuro-sw-ecosystem/sw-specs-editor@
|
|
12
|
+
- **Diagrams.** `specs/NNNN-slug-spec.architecture.graph.json`; run `npx -y @execuro-sw-ecosystem/sw-specs-editor@latest diagram specs/NNNN-slug-spec.architecture.graph.json specs/NNNN-slug-spec.architecture.excalidraw`, keep §2's `Diagram:` line — never write it directly.
|
|
13
|
+
- **Progress.** `npx -y @execuro-sw-ecosystem/sw-specs-editor@latest emit --since <step-0.5 start> progress "<step>" --batch <id> --doc spec` before/after each step/spawn; `--since` prefixes `+m:ss`.
|
|
14
14
|
- **Report:** changed blocks; answers (Q ids → anchor); first unmet §7 criterion or `none`; status/confidence/`Open ADRs`; `Agents: <list or none>`; `Timing:`.
|
|
15
15
|
|
|
16
16
|
Graph shape: `{ title, direction: "LR", groups: [{id,label}], nodes: [{id,label,type: entity|actor|service|external|event|store,group?,note?}], edges: [{from,to,label?}] }`.
|
|
@@ -3,7 +3,7 @@ name: sw-discover-tender
|
|
|
3
3
|
description: Analyse a client tender (RFP, RFI or RFQ) for a Shopware 6 project into one markdown sidecar, <source basename>-analysis.md. Every requirement row gets a class against the installed Shopware version (stock / config / plugin / custom), a three-point person-day estimate, one line of mechanism and proposed scope-lock assumptions the partner accepts by ticking checkboxes — in the file or on the Tender Discovery Tool page (`--editor`); the next run reconciles the ticks, dissolves answered questions and re-estimates. At Ready to submit it exports one CSV per client table with compliance, comment and effort filled in the client's columns. Scope and PD only — never costs, prices, licence fees or budgets. Never designs the solution — that's sw-design-solution.
|
|
4
4
|
when_to_use: Trigger phrases — "scope this RFP", "analyse the tender", "answer the RFI", "discover RFP 0001", "continue RFP 0001", "reconcile RFP 0001", "export the response for RFP 0001", "is RFP 0001 ready to submit", "open RFP 0001 in the browser", "open the tender tool", "sw-discover-tender specs/rfp-0001-x-analysis.md --editor".
|
|
5
5
|
argument-hint: '[tender file or folder of exports (.xlsx|.md|.txt|.csv|.pdf) | specs/rfp-NNNN-slug-analysis.md to continue] [--editor] [--batch <n|all>] [--export]'
|
|
6
|
-
allowed-tools: Read Write Edit Glob Grep Agent AskUserQuestion Bash(ls *) Bash(mkdir -p specs) Bash(mkdir -p specs/.rfp *) Bash(shasum -a 256 *) Bash(npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
6
|
+
allowed-tools: Read Write Edit Glob Grep Agent AskUserQuestion Bash(ls *) Bash(mkdir -p specs) Bash(mkdir -p specs/.rfp *) Bash(shasum -a 256 *) Bash(npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest *) Bash(open *) Bash(xdg-open *) Bash(tail *) Bash(grep *) Bash(printf *) mcp__ShopwareDevKnowledgeBase__list_docs mcp__ShopwareDevKnowledgeBase__grep_docs mcp__ShopwareDevKnowledgeBase__read_doc mcp__ShopwareDevKnowledgeBase__kb_status
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# sw-discover-tender
|
|
@@ -24,7 +24,7 @@ One markdown sidecar per tender, `<source basename>-analysis.md`: class, three-p
|
|
|
24
24
|
| Argument | Behaviour |
|
|
25
25
|
| --- | --- |
|
|
26
26
|
| `.md` / `.txt` / `.csv` / `.pdf`, or a folder of such exports | New tender: extract, analyse, write `<basename>-analysis.md` next to the source |
|
|
27
|
-
| `.xlsx` | Import first, per `reference/procedure.md` step 1 ".xlsx import": `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
27
|
+
| `.xlsx` | Import first, per `reference/procedure.md` step 1 ".xlsx import": `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest import` proposes a mapping (install gate: `reference/editor-session.md` §0), confirmed via `--editor` or a one-line yes/no, before the normalised source and the analysis are set. A refusal (encrypted, `.xls`, `.xlsb`) is relayed verbatim and the run stops |
|
|
28
28
|
| `.docx` | Stop. One line: export every requirement table as CSV UTF-8 (or paste it as markdown tables, header row kept) and rerun with that file or folder |
|
|
29
29
|
| `*-analysis.md` | Continue: reconcile, advance, rewrite in place |
|
|
30
30
|
| `--export`, or "export the response for RFP NNNN" | Continue, then run step 9 if the gate holds |
|
|
@@ -5,7 +5,7 @@ The Tender Discovery Tool: a local live page for one analysis document. The skil
|
|
|
5
5
|
**The protocol is not in this file.** Run
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
8
|
+
npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest guide
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
and follow it: it is the single source for the xlsx import, start, the batch kinds, poll, emit, redelivery and close, and every command ends with a `next_step:` line. An installed copy of any of that goes stale against a newer CLI. This file adds only what `guide` cannot know — the install gate, the row-batch setting, which opening batch to post, the subagent brief, the follow-up queueing grammar and the close report.
|
|
@@ -58,7 +58,7 @@ Invoke it with the Skill tool: skill "sw-discover-tender", args "<analysis path>
|
|
|
58
58
|
Append the session's row-batch setting to the args when it is not the default: <--batch n | --batch all>.
|
|
59
59
|
If the Skill tool is not available to you, read the SKILL.md of the `sw-discover-tender` skill and follow it exactly, including its "Editor mode" section.
|
|
60
60
|
Rules: never ask the user a question with a structured question tool (Claude Code: `AskUserQuestion`; Codex: `request_user_input`); every gap becomes a §5 block with options; emit progress with
|
|
61
|
-
npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
61
|
+
npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest emit progress "<step>" --batch <id>
|
|
62
62
|
before each procedure step and before/after each agent wave; never change a [x] or [-] except by reconciling it; keep every [ ] line whose
|
|
63
63
|
Evidence / risk or Risk to says "partner"; frozen accepted/rejected lines stay byte-identical; never edit the client's file.
|
|
64
64
|
Context — last chat entries (newest last):
|
|
@@ -111,5 +111,5 @@ Invoked by the editor session (`reference/editor-session.md` in this skill's dir
|
|
|
111
111
|
- **Notes.** `comment` notes carry `block`, `blockKind`, `path` (section breadcrumb), `line`–`endLine`, `md` (the block's source line), `quote`, `hash` and sometimes `selection` (the exact text the user highlighted). Open the file at that range under that path, confirm the text matches `md`, fall back to searching for `quote` when lines shifted. By `blockKind`: `req` → the note questions the class, mechanism or estimate: re-spawn the architect for that row only and rewrite the `req` line; `assume` / `global` → rewrite the statement as a new `[ ]` line (a frozen line is never edited; a proposed line may be replaced in place), or adjust `PD saved` when the note is about the figure; `clarify` → the decision text; `question` → reword or re-option the block (keep its id); `section` / `paragraph` / `row` → that text. `free` notes and `chat` are the briefing for the run. No PD figure ever comes from the page: a note asking for a different number is an architect question, not a hand edit.
|
|
112
112
|
- **A note on a row still `queued` or `analysing`** is not an immediate re-spawn: carry it into that row's own estimate batch and answer it there.
|
|
113
113
|
- **Preserve on every write.** Frozen `accepted <date>` / `rejected <date>` lines byte-identical; every `[x]` / `[-]` untouched except by reconciling it; partner-proposed `[ ]` lines; `X-n` exclusions the page added; §1.1, §1.2, §8, §9 and the nine section headings; the frontmatter block. Rewrite lines in place, never regenerate from the template. Every write must leave the document parseable — the page re-renders on each one.
|
|
114
|
-
- **Progress.** `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
114
|
+
- **Progress.** `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest emit progress "<step>" --batch <id>` before each procedure step and before and after each spawn wave; the page shows it. Row status carries the rest: `queued` → `analysing` → `estimated`.
|
|
115
115
|
- **Report.** The 8-line report of step 8 with its `next:` line (plus the 3 export lines); the editor posts it to the page. Never paste the document into the report.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
`ls specs`. Keep `rfp-NNNN-` from the input name; else `NNNN` = highest existing + 1, zero-padded, slug = kebab-case `<client>-<project>`. An xlsx is imported and its mapping confirmed first (below). `shasum -a 256` every source file into frontmatter `source`; for an xlsx, the workbook, `import-map.json` and every CSV. Continue mode: keep path, number and slug; never renumber, never a second file for the same tender.
|
|
16
16
|
|
|
17
|
-
**.xlsx import.** Install gate first, per `reference/editor-session.md` §0: the `sw-tender-discovery-tool` skill must be installed; missing → stop, do not import. `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
17
|
+
**.xlsx import.** Install gate first, per `reference/editor-session.md` §0: the `sw-tender-discovery-tool` skill must be installed; missing → stop, do not import. `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest import --source <file>` reads the workbook (hidden and `_` sheets never leave it) and proposes a mapping — which tabs are requirement tables, where each header sits, what each column means, which tokens the dropdowns allow. **With `--editor`** the user confirms it on the steering screen. **Without it**, print the proposed table the command listed, ask the user in one line whether it is right, and on a yes run `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest import --source <file> --map --accept-proposed`; if a tab or a column is wrong, say so and rerun with `--editor`. Either way the confirmed `import-map.json` and the normalised `<source dir>/<basename>/<pos>-<sheet-slug>.csv` are then the source, and the analysis lands next to the workbook. A refusal (encrypted, `.xls`, `.xlsb`) is relayed verbatim and the run stops.
|
|
18
18
|
|
|
19
19
|
### 2. Reconcile — first step of every continue run, before any spawn
|
|
20
20
|
|
|
@@ -93,6 +93,6 @@ When the gate below holds, one more line: "Generate the response CSV?" Then end.
|
|
|
93
93
|
- **Assemble and check, delegated**: one `sw-tender-editor` per client table, all in one message, cap 10, brief `§ASSEMBLE`. Each concatenates its cluster CSVs behind the client's header row into `<source basename>-response-<n>-<table-slug>.csv` (`<n>` and slug from the Source map) and runs the file checks: row count and id sequence equal the source table; header equals the client's; every compliance value in the allowed list; every effort cell a number, or empty with the blocked comment; no `A-`, `CQ-`, `Q-`, `RC-`, `.a`, `.c`, `PD saved`, `EUR`, `€`; no proposed or rejected assumption text; constant column count. Any failure → the agent deletes the file and returns the failing check. The orchestrator never reads the CSVs.
|
|
94
94
|
- **Check the sums** itself, from the returned per-table effort sums: they must equal §2 per priority. Mismatch → delete the files, report the check.
|
|
95
95
|
- **Write back.** Frontmatter `export: {date, files, source_sha256, stale: false}`; one `C-n`: `Response exported: <files> files, <rows> rows, Must <n> PD`.
|
|
96
|
-
- **Workbook copy.** After every response CSV passes its checks, run `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@
|
|
96
|
+
- **Workbook copy.** After every response CSV passes its checks, run `npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest export --xlsx --source <file>`: it writes `<source basename>-response.xlsx`, a copy of the client's own workbook with compliance, comment and effort filled in from those CSVs, styles and dropdowns intact. The client's original is never written. Only for an xlsx tender with a confirmed mapping; a CSV/markdown tender stops at the CSVs.
|
|
97
97
|
- **Report** three lines: files with row counts · Must / Should / Could as exported · checks passed or the failing check.
|
|
98
98
|
- Same analysis and same source give byte-identical files.
|
package/skills/sw-setup/SKILL.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sw-setup
|
|
3
|
-
description: Print one environment-readiness table for the project's development/test setup — vendor/, Node, the editor CLIs, shopware-cli, the KB MCP, the acceptance-test project, Playwright browsers, its .env, per-plugin test scaffolding, the project wiki, `.gitignore` and whether the SW AH npm packages are current, plus the installer CLI's own configuration/drift status. Stops when every row is ticked. When rows are missing, asks one yes/no question and delegates the fix to the installer CLI. Use when asked to set up the project, check if the environment is ready, or bootstrap the tests. Never designs, implements or verifies a feature itself — that's sw-design-solution, sw-implement-feature and sw-verify-feature, which call this skill first. Never writes a
|
|
3
|
+
description: Print one environment-readiness table for the project's development/test setup — vendor/, Node, the editor CLIs, shopware-cli, the KB MCP, the acceptance-test project, Playwright browsers, its .env, per-plugin test scaffolding, the project wiki, `.gitignore` and whether the SW AH npm packages are current, plus the installer CLI's own configuration/drift status. Stops when every row is ticked. When rows are missing, asks one yes/no question and delegates the fix to the installer CLI. Use when asked to set up the project, check if the environment is ready, or bootstrap the tests. Never designs, implements or verifies a feature itself — that's sw-design-solution, sw-implement-feature and sw-verify-feature, which call this skill first. Never writes a coding agent's configuration file itself — that's the installer CLI.
|
|
4
4
|
when_to_use: Trigger phrases — "set up the project", "is the environment ready", "bootstrap the tests", "sw-setup".
|
|
5
|
-
allowed-tools: Read Glob Grep AskUserQuestion Skill Bash mcp__ShopwareDevKnowledgeBase__kb_status Bash(npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest *)
|
|
5
|
+
allowed-tools: Read Glob Grep AskUserQuestion Skill Bash mcp__ShopwareDevKnowledgeBase__kb_status Bash(npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest *) Bash(npx -y @execuro-sw-ecosystem/sw-specs-editor@latest *) Bash(npx -y @execuro-sw-ecosystem/sw-tender-discovery-tool@latest *)
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# sw-setup
|
|
@@ -40,25 +40,27 @@ table from this run's output — it does not re-run `sw-setup`'s checks.
|
|
|
40
40
|
Run:
|
|
41
41
|
|
|
42
42
|
```
|
|
43
|
-
npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest status
|
|
43
|
+
npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest status --json
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
`--json` is mandatory for every call this skill makes: without it the CLI
|
|
47
|
+
prints a human summary, not the object below. It prints one JSON object
|
|
48
|
+
(`ok`, `next_step`, `help`, and its own `agents[]`/`drift[]` configuration
|
|
49
|
+
state). Alongside it, run every
|
|
48
50
|
environment row's check from `reference/rows.md` in this skill's directory —
|
|
49
51
|
read-only, seconds each: file/directory existence, one version command, one
|
|
50
|
-
`kb_status` call,
|
|
51
|
-
|
|
52
|
+
`kb_status` call, one `npm view` registry lookup (Package updates row) — the
|
|
53
|
+
one part of step 1 that touches the network, so it is the slow part.
|
|
52
54
|
Never write, never install, never ask a question in this step.
|
|
53
55
|
|
|
54
56
|
Print one checkbox list, one line per row — the environment rows first, then
|
|
55
|
-
one line per configuration item the CLI's `
|
|
57
|
+
one line per configuration item the CLI's `agents[]`/`drift[]` reports:
|
|
56
58
|
|
|
57
59
|
```
|
|
58
60
|
- [x] vendor/ — shopware/core 6.7.13.0
|
|
59
61
|
- [ ] vendor/ — vendor/bin/phpunit missing (tree built --no-dev)
|
|
60
62
|
- [ ] Node — 18.x (need >= 20)
|
|
61
|
-
- [-] Visual editors (optional) — Specs Editor
|
|
63
|
+
- [-] Visual editors (optional) — Specs Editor installed, Tender tool declined
|
|
62
64
|
- [x] shopware-cli — 0.16.10
|
|
63
65
|
- [x] KB MCP — platform: implemented
|
|
64
66
|
- [ ] Acceptance-test project — tests/acceptance/ missing
|
|
@@ -66,7 +68,7 @@ one line per configuration item the CLI's `hosts[]`/`drift[]` reports:
|
|
|
66
68
|
- [ ] ATS env — tests/acceptance/.env missing
|
|
67
69
|
- [x] Plugin tests — AhCheckout: phpunit + jest ok
|
|
68
70
|
- [ ] Project wiki — docs/project-wiki/ missing
|
|
69
|
-
- [ ] Package updates — harness 0.1.0 → 0.1.3
|
|
71
|
+
- [ ] Package updates — harness 0.1.0 → 0.1.3
|
|
70
72
|
- [ ] Installer config — .mcp.json entry: drift (from CLI status)
|
|
71
73
|
```
|
|
72
74
|
|
|
@@ -88,7 +90,7 @@ For a missing/drifted configuration row, do not research or plan the fix
|
|
|
88
90
|
yourself — the CLI's `plan` command already has it:
|
|
89
91
|
|
|
90
92
|
```
|
|
91
|
-
npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest plan
|
|
93
|
+
npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest plan --json
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
List the concrete steps in plain words: environment-row fixes in order
|
|
@@ -104,7 +106,7 @@ if you have one (Claude Code: `AskUserQuestion`; Codex: `request_user_input`,
|
|
|
104
106
|
which is non-blocking outside Plan mode — so end the turn after asking).
|
|
105
107
|
Options:
|
|
106
108
|
- **Yes, run it** — run the environment-row fixes in order, then
|
|
107
|
-
`npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest apply --yes`
|
|
109
|
+
`npx -y @execuro-sw-ecosystem/sw-ecosystem-agentic-harness@latest apply --yes --json`
|
|
108
110
|
for the configuration changes, then re-run step 1 and print the final table.
|
|
109
111
|
- **No, stop** — stop; the table from step 1 is already on screen.
|
|
110
112
|
|
|
@@ -124,11 +126,11 @@ Options:
|
|
|
124
126
|
the corpus ships already built inside the
|
|
125
127
|
`@execuro-sw-ecosystem/sw-dev-knowledge-base-mcp` package. If `platform` is
|
|
126
128
|
not `implemented`, the fix is to check the registration (re-run the
|
|
127
|
-
installer CLI's `apply --yes`) or update that package — never build a
|
|
129
|
+
installer CLI's `apply --yes --json`) or update that package — never build a
|
|
128
130
|
corpus here. Neither is replicated in this skill.
|
|
129
|
-
- This skill never writes a
|
|
130
|
-
permission grants, `.gitignore` lines). Every such write goes
|
|
131
|
-
installer CLI's `apply --yes`,
|
|
131
|
+
- This skill never writes a coding agent's configuration file itself
|
|
132
|
+
(`.mcp.json`, permission grants, `.gitignore` lines). Every such write goes
|
|
133
|
+
through the installer CLI's `apply --yes --json`, after the user's yes.
|
|
132
134
|
|
|
133
135
|
### 5. Report
|
|
134
136
|
|
|
@@ -144,6 +146,6 @@ line:
|
|
|
144
146
|
|
|
145
147
|
`reference/rows.md` in this skill's directory — the twelve environment rows:
|
|
146
148
|
check command(s), what "ticked" means, the fix steps verbatim from the
|
|
147
|
-
guideline, and which skills the row blocks.
|
|
149
|
+
guideline, and which skills the row blocks. Agent configuration state (what
|
|
148
150
|
gets installed into `.mcp.json`, permissions, `.gitignore`) is not in this
|
|
149
151
|
file — it comes from the installer CLI's `status`/`plan`/`apply` output.
|