agentic-workflow-manager 2.0.0 → 2.0.1
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/dist/src/commands/doctor.js +7 -7
- package/dist/src/commands/init.js +10 -10
- package/dist/src/commands/registry/index.js +2 -2
- package/dist/src/commands/sensors/index.js +2 -2
- package/dist/src/commands/sensors/status.js +3 -3
- package/dist/src/core/context/provider.js +2 -2
- package/dist/src/core/diagnostics/checks.js +18 -18
- package/dist/src/core/init/steps.js +7 -7
- package/dist/src/core/update-check.js +5 -5
- package/dist/src/index.js +6 -6
- package/dist/tests/commands/doctor.test.js +8 -8
- package/dist/tests/commands/init.test.js +5 -5
- package/dist/tests/commands/sensors/status.test.js +2 -2
- package/dist/tests/core/diagnostics/checks.test.js +1 -1
- package/package.json +1 -1
|
@@ -30,24 +30,24 @@ function line(r) {
|
|
|
30
30
|
}
|
|
31
31
|
function renderReport(report) {
|
|
32
32
|
const lines = [];
|
|
33
|
-
lines.push(picocolors_1.default.bold('AWM ·
|
|
33
|
+
lines.push(picocolors_1.default.bold('AWM · harness status'));
|
|
34
34
|
lines.push('');
|
|
35
|
-
lines.push('
|
|
35
|
+
lines.push('Machine (global)');
|
|
36
36
|
for (const r of report.results.filter((x) => x.level === 'machine'))
|
|
37
37
|
lines.push(line(r));
|
|
38
38
|
lines.push('');
|
|
39
39
|
if (report.hasProject) {
|
|
40
|
-
lines.push(`
|
|
40
|
+
lines.push(`Project: ${report.projectName ?? ''}`.trimEnd());
|
|
41
41
|
for (const r of report.results.filter((x) => x.level === 'project'))
|
|
42
42
|
lines.push(line(r));
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
|
-
lines.push(picocolors_1.default.dim('(
|
|
45
|
+
lines.push(picocolors_1.default.dim('(no project in cwd)'));
|
|
46
46
|
}
|
|
47
47
|
lines.push('');
|
|
48
48
|
const actions = report.results.filter((r) => r.remedy.kind !== 'none').length;
|
|
49
|
-
const
|
|
50
|
-
lines.push(`
|
|
49
|
+
const status = report.overall === 'healthy' ? picocolors_1.default.green('healthy') : picocolors_1.default.red('degraded');
|
|
50
|
+
lines.push(`status: ${status} · ${actions} suggested actions`);
|
|
51
51
|
return lines.join('\n');
|
|
52
52
|
}
|
|
53
53
|
function runDoctor(opts = {}) {
|
|
@@ -56,7 +56,7 @@ function runDoctor(opts = {}) {
|
|
|
56
56
|
report = (0, checks_1.runChecks)((0, context_1.gatherContext)({ cwd: opts.cwd }));
|
|
57
57
|
}
|
|
58
58
|
catch (err) {
|
|
59
|
-
process.stderr.write(`awm doctor: error
|
|
59
|
+
process.stderr.write(`awm doctor: internal error: ${err.message}\n`);
|
|
60
60
|
return 2;
|
|
61
61
|
}
|
|
62
62
|
if (opts.json) {
|
|
@@ -65,26 +65,26 @@ function renderInitOutcome(o) {
|
|
|
65
65
|
const lines = [];
|
|
66
66
|
lines.push(picocolors_1.default.bold('AWM · init'));
|
|
67
67
|
lines.push('');
|
|
68
|
-
// ---
|
|
69
|
-
lines.push(picocolors_1.default.bold('
|
|
68
|
+
// --- Initial state ---
|
|
69
|
+
lines.push(picocolors_1.default.bold('Initial state'));
|
|
70
70
|
lines.push((0, doctor_1.renderReport)(o.before));
|
|
71
71
|
lines.push('');
|
|
72
|
-
// ---
|
|
73
|
-
lines.push(picocolors_1.default.bold('
|
|
72
|
+
// --- Actions ---
|
|
73
|
+
lines.push(picocolors_1.default.bold('Actions'));
|
|
74
74
|
for (const s of o.steps) {
|
|
75
75
|
const det = s.detail ? picocolors_1.default.dim(` ${s.detail}`) : '';
|
|
76
76
|
const err = s.error ? picocolors_1.default.red(` [${s.error}]`) : '';
|
|
77
77
|
lines.push(` ${stepGlyph(s.action)} ${s.id}${det}${err}`);
|
|
78
78
|
}
|
|
79
79
|
lines.push('');
|
|
80
|
-
// ---
|
|
81
|
-
lines.push(picocolors_1.default.bold('
|
|
80
|
+
// --- Final state ---
|
|
81
|
+
lines.push(picocolors_1.default.bold('Final state'));
|
|
82
82
|
lines.push((0, doctor_1.renderReport)(o.after));
|
|
83
83
|
lines.push('');
|
|
84
84
|
// --- Summary ---
|
|
85
85
|
const pendingCount = o.pending;
|
|
86
|
-
const
|
|
87
|
-
lines.push(`
|
|
86
|
+
const status = o.after.overall === 'healthy' ? picocolors_1.default.green('healthy') : picocolors_1.default.red('degraded');
|
|
87
|
+
lines.push(`status: ${status} · ${pendingCount} steps require an agent (skills above)`);
|
|
88
88
|
return lines.join('\n');
|
|
89
89
|
}
|
|
90
90
|
async function runInit(opts = {}) {
|
|
@@ -121,7 +121,7 @@ async function runInit(opts = {}) {
|
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
catch (err) {
|
|
124
|
-
process.stderr.write(`awm init: error
|
|
124
|
+
process.stderr.write(`awm init: internal error: ${err.message}\n`);
|
|
125
125
|
return 2;
|
|
126
126
|
}
|
|
127
127
|
if (opts.json) {
|
|
@@ -149,7 +149,7 @@ function makeConfirmExtensions(yes) {
|
|
|
149
149
|
return [];
|
|
150
150
|
const { multiselect, isCancel } = await Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
151
151
|
const choice = await multiselect({
|
|
152
|
-
message: `
|
|
152
|
+
message: `Extensions detected (${signals.join(', ')}) — activate?`,
|
|
153
153
|
options: proposed.map((p) => ({ value: p, label: p })),
|
|
154
154
|
initialValues: proposed,
|
|
155
155
|
required: false,
|
|
@@ -124,8 +124,8 @@ function registerRegistryCommand(program) {
|
|
|
124
124
|
console.log(`${picocolors_1.default.cyan(r.name)} ${r.remote} ${picocolors_1.default.dim(counts)}`);
|
|
125
125
|
for (const o of (0, status_1.overrideStatus)(r.contentRoot, earlier)) {
|
|
126
126
|
console.log(o.active
|
|
127
|
-
? picocolors_1.default.yellow(` ↑ override
|
|
128
|
-
: picocolors_1.default.dim(` ∅ override
|
|
127
|
+
? picocolors_1.default.yellow(` ↑ override active: ${o.name}`)
|
|
128
|
+
: picocolors_1.default.dim(` ∅ override with no effect: ${o.name}`));
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
catch (e) {
|
|
@@ -58,8 +58,8 @@ function registerSensorsCommand(program) {
|
|
|
58
58
|
const writeDir = manifestDir ?? process.cwd();
|
|
59
59
|
(0, baseline_1.writeBaseline)(writeDir, baseline);
|
|
60
60
|
const total = Object.values(baseline).reduce((n, fps) => n + fps.length, 0);
|
|
61
|
-
prompts_1.log.success(`Baseline
|
|
62
|
-
prompts_1.log.info('
|
|
61
|
+
prompts_1.log.success(`Baseline saved: ${total} findings accepted in .awm/sensors.baseline.json`);
|
|
62
|
+
prompts_1.log.info('Sensors now fail only on new findings. Re-run `awm sensors baseline` after reducing debt.');
|
|
63
63
|
});
|
|
64
64
|
sensors
|
|
65
65
|
.command('status')
|
|
@@ -20,7 +20,7 @@ function configCheck(parts, cwd) {
|
|
|
20
20
|
const i = parts.indexOf('--config');
|
|
21
21
|
const cfg = i !== -1 ? parts[i + 1] : undefined;
|
|
22
22
|
if (cfg && !fs_1.default.existsSync(path_1.default.join(cwd, cfg))) {
|
|
23
|
-
return { ok: false, detail: `config
|
|
23
|
+
return { ok: false, detail: `missing config: ${cfg}` };
|
|
24
24
|
}
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
@@ -38,12 +38,12 @@ function checkCmd(cmd, cwd) {
|
|
|
38
38
|
if (bin === 'npx') {
|
|
39
39
|
const tool = npxTool(parts);
|
|
40
40
|
if (!tool)
|
|
41
|
-
return { ok: false, detail: 'npx
|
|
41
|
+
return { ok: false, detail: 'npx without a tool specified' };
|
|
42
42
|
const localBin = path_1.default.join(cwd, 'node_modules', '.bin', tool);
|
|
43
43
|
if (!fs_1.default.existsSync(localBin)) {
|
|
44
44
|
return {
|
|
45
45
|
ok: false,
|
|
46
|
-
detail: `${tool}
|
|
46
|
+
detail: `${tool} not installed locally (npx would download a remote package) — add it to devDependencies`,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
return configCheck(parts, cwd) ?? { ok: true, detail: `${tool} (node_modules/.bin)` };
|
|
@@ -22,8 +22,8 @@ function buildContext(input) {
|
|
|
22
22
|
throw new Error(`using-awm skill not found at ${skillPath}. Run 'awm update' first.`);
|
|
23
23
|
}
|
|
24
24
|
const skill = fs_1.default.readFileSync(skillPath, 'utf-8');
|
|
25
|
-
const exts = input.profileExtensions.length ? input.profileExtensions.join(', ') : '
|
|
26
|
-
const header = `<!-- AWM context (generated) -->\n# AWM\n\
|
|
25
|
+
const exts = input.profileExtensions.length ? input.profileExtensions.join(', ') : 'none';
|
|
26
|
+
const header = `<!-- AWM context (generated) -->\n# AWM\n\nActive extensions: ${exts}\n\n`;
|
|
27
27
|
const markdown = header + skill;
|
|
28
28
|
return { markdown, sourceVersion: parseVersion(skill), contentHash: sha256(markdown) };
|
|
29
29
|
}
|
|
@@ -21,7 +21,7 @@ function machineChecks(m) {
|
|
|
21
21
|
}
|
|
22
22
|
else if (m.registryCache.gitState === 'behind') {
|
|
23
23
|
out.push({ id: 'machine.cli', level: 'machine', label: 'CLI', status: 'warn',
|
|
24
|
-
detail: 'cache
|
|
24
|
+
detail: 'cache out of date', remedy: cmd('awm update') });
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
27
|
// dirty | unknown | undefined → advisory, sin acción
|
|
@@ -34,7 +34,7 @@ function machineChecks(m) {
|
|
|
34
34
|
}
|
|
35
35
|
else if (m.hook.present) {
|
|
36
36
|
out.push({ id: 'machine.hook', level: 'machine', label: 'hook SessionStart', status: 'warn',
|
|
37
|
-
detail: 'scripts
|
|
37
|
+
detail: 'incomplete scripts', remedy: cmd('awm init') });
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
40
|
out.push({ id: 'machine.hook', level: 'machine', label: 'hook SessionStart', status: 'missing',
|
|
@@ -46,7 +46,7 @@ function machineChecks(m) {
|
|
|
46
46
|
}
|
|
47
47
|
else if (m.devCore.present) {
|
|
48
48
|
out.push({ id: 'machine.devCore', level: 'machine', label: 'dev-core (baseline)', status: 'warn',
|
|
49
|
-
detail: `${m.devCore.brokenLinks.length} symlinks
|
|
49
|
+
detail: `${m.devCore.brokenLinks.length} broken symlinks`, remedy: cmd('awm init') });
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
52
|
out.push({ id: 'machine.devCore', level: 'machine', label: 'dev-core (baseline)', status: 'missing',
|
|
@@ -55,11 +55,11 @@ function machineChecks(m) {
|
|
|
55
55
|
// machine.globalSkills — integridad de symlinks en ~/.claude/skills (fuera del baseline)
|
|
56
56
|
const brokenGlobal = m.globalSkills.repairable.length + m.globalSkills.dead.length;
|
|
57
57
|
if (brokenGlobal === 0) {
|
|
58
|
-
out.push({ id: 'machine.globalSkills', level: 'machine', label: 'skills
|
|
58
|
+
out.push({ id: 'machine.globalSkills', level: 'machine', label: 'global skills', status: 'ok', remedy: none });
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
|
-
out.push({ id: 'machine.globalSkills', level: 'machine', label: 'skills
|
|
62
|
-
detail: `${brokenGlobal}
|
|
61
|
+
out.push({ id: 'machine.globalSkills', level: 'machine', label: 'global skills', status: 'warn',
|
|
62
|
+
detail: `${brokenGlobal} broken links`, remedy: cmd('awm init') });
|
|
63
63
|
}
|
|
64
64
|
// machine.ambient.<b> — una fila por bundle deseado
|
|
65
65
|
for (const b of m.ambient.wanted) {
|
|
@@ -70,15 +70,15 @@ function machineChecks(m) {
|
|
|
70
70
|
// machine.context.<agent> — una fila por agente con contexto AWM gestionado
|
|
71
71
|
for (const c of m.contextInjection) {
|
|
72
72
|
if (c.state === 'injected') {
|
|
73
|
-
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `
|
|
73
|
+
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `AWM context (${c.agent})`,
|
|
74
74
|
status: 'ok', remedy: none });
|
|
75
75
|
}
|
|
76
76
|
else if (c.state === 'stale') {
|
|
77
|
-
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `
|
|
78
|
-
status: 'warn', detail: '
|
|
77
|
+
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `AWM context (${c.agent})`,
|
|
78
|
+
status: 'warn', detail: 'context out of date', remedy: cmd('awm init') });
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `
|
|
81
|
+
out.push({ id: `machine.context.${c.agent}`, level: 'machine', label: `AWM context (${c.agent})`,
|
|
82
82
|
status: 'missing', remedy: cmd('awm init') });
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -88,7 +88,7 @@ function projectChecks(p) {
|
|
|
88
88
|
const out = [];
|
|
89
89
|
// project.profile
|
|
90
90
|
if (p.profile.present) {
|
|
91
|
-
const exts = p.profile.extensions.length ? p.profile.extensions.join(', ') : '
|
|
91
|
+
const exts = p.profile.extensions.length ? p.profile.extensions.join(', ') : 'no extensions';
|
|
92
92
|
out.push({ id: 'project.profile', level: 'project', label: `.awm/profile.json (${exts})`,
|
|
93
93
|
status: 'ok', remedy: none });
|
|
94
94
|
}
|
|
@@ -99,21 +99,21 @@ function projectChecks(p) {
|
|
|
99
99
|
// project.activation
|
|
100
100
|
const missingLinks = p.activeBundles.expected.filter((s) => !p.activeBundles.linked.includes(s));
|
|
101
101
|
if (p.activeBundles.broken.length === 0 && missingLinks.length === 0) {
|
|
102
|
-
out.push({ id: 'project.activation', level: 'project', label: 'bundles
|
|
102
|
+
out.push({ id: 'project.activation', level: 'project', label: 'active bundles', status: 'ok', remedy: none });
|
|
103
103
|
}
|
|
104
104
|
else {
|
|
105
|
-
out.push({ id: 'project.activation', level: 'project', label: 'bundles
|
|
106
|
-
detail: `${missingLinks.length}
|
|
105
|
+
out.push({ id: 'project.activation', level: 'project', label: 'active bundles', status: 'missing',
|
|
106
|
+
detail: `${missingLinks.length} missing, ${p.activeBundles.broken.length} broken`, remedy: cmd('awm sync') });
|
|
107
107
|
}
|
|
108
108
|
// project.sensors
|
|
109
109
|
out.push(p.sensors.present
|
|
110
|
-
? { id: 'project.sensors', level: 'project', label: '
|
|
111
|
-
: { id: 'project.sensors', level: 'project', label: '
|
|
110
|
+
? { id: 'project.sensors', level: 'project', label: 'sensors', status: 'ok', remedy: none }
|
|
111
|
+
: { id: 'project.sensors', level: 'project', label: 'sensors not initialized', status: 'missing',
|
|
112
112
|
remedy: cmd('awm sensors init') });
|
|
113
113
|
// project.constitution (missing degrada; remedio agente)
|
|
114
114
|
out.push(p.constitution.present
|
|
115
115
|
? { id: 'project.constitution', level: 'project', label: 'CONSTITUTION.md', status: 'ok', remedy: none }
|
|
116
|
-
: { id: 'project.constitution', level: 'project', label: 'CONSTITUTION.md
|
|
116
|
+
: { id: 'project.constitution', level: 'project', label: 'CONSTITUTION.md missing', status: 'missing',
|
|
117
117
|
remedy: skillRemedy('project-constitution') });
|
|
118
118
|
// project.context (advisory; no degrada)
|
|
119
119
|
if (p.context.present) {
|
|
@@ -121,7 +121,7 @@ function projectChecks(p) {
|
|
|
121
121
|
status: 'ok', remedy: none });
|
|
122
122
|
}
|
|
123
123
|
else {
|
|
124
|
-
out.push({ id: 'project.context', level: 'project', label: '
|
|
124
|
+
out.push({ id: 'project.context', level: 'project', label: 'agent context (CLAUDE.md/AGENTS.md) missing', status: 'warn',
|
|
125
125
|
remedy: skillRemedy('project-context-init') });
|
|
126
126
|
}
|
|
127
127
|
return out;
|
|
@@ -170,10 +170,10 @@ async function stepProfile(d) {
|
|
|
170
170
|
const alreadyPresent = proj.profile.extensions;
|
|
171
171
|
const newProposed = proposed.filter((p) => !alreadyPresent.includes(p));
|
|
172
172
|
if (newProposed.length === 0)
|
|
173
|
-
return bootstrapOrSkip(d, proj, '
|
|
173
|
+
return bootstrapOrSkip(d, proj, 'no new extensions');
|
|
174
174
|
const confirmed = await d.confirmExtensions(newProposed, signals);
|
|
175
175
|
if (confirmed.length === 0)
|
|
176
|
-
return bootstrapOrSkip(d, proj, '
|
|
176
|
+
return bootstrapOrSkip(d, proj, 'no extensions confirmed');
|
|
177
177
|
for (const name of confirmed) {
|
|
178
178
|
d.actions.addExtension(proj.root, name);
|
|
179
179
|
}
|
|
@@ -188,7 +188,7 @@ async function stepProfile(d) {
|
|
|
188
188
|
function bootstrapOrSkip(d, proj, skipDetail) {
|
|
189
189
|
if (!proj.profile.present) {
|
|
190
190
|
d.actions.ensureProfile(proj.root);
|
|
191
|
-
return ok('project.profile', 'project', 'applied', '
|
|
191
|
+
return ok('project.profile', 'project', 'applied', 'profile initialized (no extensions)');
|
|
192
192
|
}
|
|
193
193
|
return ok('project.profile', 'project', 'skipped', skipDetail);
|
|
194
194
|
}
|
|
@@ -239,10 +239,10 @@ function stepConstitutionInjection(d) {
|
|
|
239
239
|
return ok('project.constitutionInjection', 'project', 'skipped', 'no project');
|
|
240
240
|
const inj = (0, providers_1.getInjection)(d.agent);
|
|
241
241
|
if (!inj || inj.type !== 'config-instructions') {
|
|
242
|
-
return ok('project.constitutionInjection', 'project', 'skipped', '
|
|
242
|
+
return ok('project.constitutionInjection', 'project', 'skipped', 'covered by hook');
|
|
243
243
|
}
|
|
244
244
|
if (!proj.constitution.present) {
|
|
245
|
-
return ok('project.constitutionInjection', 'project', 'skipped', '
|
|
245
|
+
return ok('project.constitutionInjection', 'project', 'skipped', 'no CONSTITUTION.md');
|
|
246
246
|
}
|
|
247
247
|
const res = d.actions.injectProjectConstitution({ projectRoot: proj.root, agent: d.agent });
|
|
248
248
|
if (res === 'injected')
|
|
@@ -262,9 +262,9 @@ function stepContext(d) {
|
|
|
262
262
|
function stepContextInjection(d) {
|
|
263
263
|
const inj = (0, providers_1.getInjection)(d.agent);
|
|
264
264
|
if (!inj)
|
|
265
|
-
return ok('machine.contextInjection', 'machine', 'skipped', '
|
|
265
|
+
return ok('machine.contextInjection', 'machine', 'skipped', 'no injection mechanism');
|
|
266
266
|
if (inj.type === 'cc-settings-merge')
|
|
267
|
-
return ok('machine.contextInjection', 'machine', 'skipped', '
|
|
267
|
+
return ok('machine.contextInjection', 'machine', 'skipped', 'covered by hook');
|
|
268
268
|
const op = {
|
|
269
269
|
agent: d.agent,
|
|
270
270
|
scope: 'global',
|
|
@@ -72,7 +72,7 @@ function maybeNotifyUpdate(opts) {
|
|
|
72
72
|
const spawnWorker = opts?.spawnWorker ?? spawnRefreshWorker;
|
|
73
73
|
const cache = readUpdateCache();
|
|
74
74
|
if (cache?.latest && (0, versioning_1.compareSemver)(cache.latest, (0, cli_version_1.cliVersion)()) > 0) {
|
|
75
|
-
console.log(picocolors_1.default.dim(`\n⬆ awm v${cache.latest}
|
|
75
|
+
console.log(picocolors_1.default.dim(`\n⬆ awm v${cache.latest} available → npm i -g ${cli_version_1.CLI_PACKAGE_NAME}`));
|
|
76
76
|
}
|
|
77
77
|
if (!cache || now - cache.lastCheck > TTL_MS)
|
|
78
78
|
spawnWorker();
|
|
@@ -90,17 +90,17 @@ async function offerSelfUpdate(deps = {}) {
|
|
|
90
90
|
const r = await (0, prompts_1.confirm)({ message });
|
|
91
91
|
return !(0, prompts_1.isCancel)(r) && r === true;
|
|
92
92
|
});
|
|
93
|
-
const yes = await confirmImpl(
|
|
93
|
+
const yes = await confirmImpl(`Update awm v${current} → v${latest} now?`);
|
|
94
94
|
if (!yes) {
|
|
95
|
-
console.log(picocolors_1.default.dim(`
|
|
95
|
+
console.log(picocolors_1.default.dim(` To update later: npm i -g ${cli_version_1.CLI_PACKAGE_NAME}`));
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
const runner = deps.runner ?? ((cmd, args) => (0, child_process_1.spawnSync)(cmd, args, { stdio: 'inherit', shell: true }));
|
|
99
99
|
const r = runner('npm', ['i', '-g', `${cli_version_1.CLI_PACKAGE_NAME}@latest`]);
|
|
100
100
|
if (r.status === 0) {
|
|
101
|
-
console.log(picocolors_1.default.green(` ✓ CLI
|
|
101
|
+
console.log(picocolors_1.default.green(` ✓ CLI updated to v${latest} (takes effect from the next command)`));
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
|
-
console.warn(picocolors_1.default.yellow(` ⚠
|
|
104
|
+
console.warn(picocolors_1.default.yellow(` ⚠ Automatic update failed — run: npm i -g ${cli_version_1.CLI_PACKAGE_NAME}`));
|
|
105
105
|
}
|
|
106
106
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -321,7 +321,7 @@ program.command('update')
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
for (const f of (0, registries_1.verifyMinCliVersions)()) {
|
|
324
|
-
console.warn(picocolors_1.default.yellow(` ⚠
|
|
324
|
+
console.warn(picocolors_1.default.yellow(` ⚠ Registry ${f.name} requires CLI ≥ ${f.min} (you have ${(0, cli_version_1.cliVersion)()}) — run: npm i -g agentic-workflow-manager`));
|
|
325
325
|
}
|
|
326
326
|
try {
|
|
327
327
|
const regen = (0, regenerate_1.regenerateGlobalContext)();
|
|
@@ -351,7 +351,7 @@ program.command('update')
|
|
|
351
351
|
}
|
|
352
352
|
catch { /* no aborta */ }
|
|
353
353
|
await (0, update_check_1.offerSelfUpdate)(); // capa 2 — Task 13
|
|
354
|
-
(0, prompts_1.outro)('✅ Registries, skills
|
|
354
|
+
(0, prompts_1.outro)('✅ Registries, skills and hooks updated.');
|
|
355
355
|
});
|
|
356
356
|
program.command('sync')
|
|
357
357
|
.description('Rebuild local skill symlinks from .awm/profile.json (e.g. after cloning on a new machine)')
|
|
@@ -385,8 +385,8 @@ program.command('sync')
|
|
|
385
385
|
const cliFailures = (0, registries_1.verifyMinCliVersions)();
|
|
386
386
|
if (cliFailures.length > 0) {
|
|
387
387
|
for (const f of cliFailures) {
|
|
388
|
-
console.error(picocolors_1.default.red(`
|
|
389
|
-
console.error(picocolors_1.default.red('
|
|
388
|
+
console.error(picocolors_1.default.red(`Registry ${f.name} requires CLI ≥ ${f.min} (you have ${(0, cli_version_1.cliVersion)()}).`));
|
|
389
|
+
console.error(picocolors_1.default.red(' Run: npm i -g agentic-workflow-manager'));
|
|
390
390
|
}
|
|
391
391
|
process.exit(1);
|
|
392
392
|
}
|
|
@@ -408,8 +408,8 @@ program.command('sync')
|
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
410
|
else {
|
|
411
|
-
console.error(picocolors_1.default.red(`
|
|
412
|
-
console.error(picocolors_1.default.red(`
|
|
411
|
+
console.error(picocolors_1.default.red(`This machine has ${f.name} @ ${f.actual ? `v${f.actual}` : 'HEAD (no tag)'} but the project requires v${f.required}.`));
|
|
412
|
+
console.error(picocolors_1.default.red(` Run: awm pin ${f.name} ${f.required} && awm update`));
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
process.exit(1);
|
|
@@ -22,27 +22,27 @@ function report(partial = {}) {
|
|
|
22
22
|
describe('renderReport', () => {
|
|
23
23
|
it('renders the machine block with glyphs and remedies', () => {
|
|
24
24
|
const out = (0, doctor_1.renderReport)(report());
|
|
25
|
-
expect(out).toContain('AWM ·
|
|
26
|
-
expect(out).toContain('
|
|
25
|
+
expect(out).toContain('AWM · harness status');
|
|
26
|
+
expect(out).toContain('Machine (global)');
|
|
27
27
|
expect(out).toContain('✔ CLI v1.0.0');
|
|
28
28
|
expect(out).toContain('✖ hook SessionStart');
|
|
29
29
|
expect(out).toContain('→ awm init');
|
|
30
|
-
expect(out).toContain('
|
|
30
|
+
expect(out).toContain('status: degraded · 1 suggested actions');
|
|
31
31
|
});
|
|
32
32
|
it('omits the project block and shows a hint when hasProject is false', () => {
|
|
33
33
|
const out = (0, doctor_1.renderReport)(report());
|
|
34
|
-
expect(out).toContain('(
|
|
34
|
+
expect(out).toContain('(no project in cwd)');
|
|
35
35
|
expect(out).not.toContain('Proyecto:');
|
|
36
36
|
});
|
|
37
37
|
it('renders the detail field in parentheses when present', () => {
|
|
38
38
|
const out = (0, doctor_1.renderReport)(report({
|
|
39
39
|
results: [
|
|
40
40
|
{ id: 'machine.cli', level: 'machine', label: 'CLI v1.2.0', status: 'warn',
|
|
41
|
-
detail: 'cache
|
|
41
|
+
detail: 'cache out of date', remedy: { kind: 'command', value: 'awm update' } },
|
|
42
42
|
],
|
|
43
43
|
}));
|
|
44
44
|
expect(out).toContain('CLI v1.2.0');
|
|
45
|
-
expect(out).toContain('(cache
|
|
45
|
+
expect(out).toContain('(cache out of date)');
|
|
46
46
|
expect(out).toContain('→ awm update');
|
|
47
47
|
});
|
|
48
48
|
it('renders the project block titled with projectName', () => {
|
|
@@ -50,11 +50,11 @@ describe('renderReport', () => {
|
|
|
50
50
|
hasProject: true,
|
|
51
51
|
projectName: 'belanz',
|
|
52
52
|
results: [
|
|
53
|
-
{ id: 'project.constitution', level: 'project', label: 'CONSTITUTION.md
|
|
53
|
+
{ id: 'project.constitution', level: 'project', label: 'CONSTITUTION.md missing',
|
|
54
54
|
status: 'missing', remedy: { kind: 'skill', value: 'project-constitution' } },
|
|
55
55
|
],
|
|
56
56
|
}));
|
|
57
|
-
expect(out).toContain('
|
|
57
|
+
expect(out).toContain('Project: belanz');
|
|
58
58
|
expect(out).toContain('→ skill: project-constitution');
|
|
59
59
|
});
|
|
60
60
|
});
|
|
@@ -35,13 +35,13 @@ describe('renderInitOutcome', () => {
|
|
|
35
35
|
};
|
|
36
36
|
const out = (0, init_1.renderInitOutcome)(outcome);
|
|
37
37
|
expect(out).toContain('AWM · init');
|
|
38
|
-
expect(out).toContain('
|
|
39
|
-
expect(out).toContain('
|
|
38
|
+
expect(out).toContain('Initial state');
|
|
39
|
+
expect(out).toContain('Actions');
|
|
40
40
|
expect(out).toContain('machine.cache');
|
|
41
41
|
expect(out).toContain('skill: project-constitution');
|
|
42
|
-
expect(out).toContain('
|
|
43
|
-
expect(out).toContain('AWM ·
|
|
44
|
-
expect(out).toContain('1
|
|
42
|
+
expect(out).toContain('Final state');
|
|
43
|
+
expect(out).toContain('AWM · harness status'); // viene de renderReport
|
|
44
|
+
expect(out).toContain('1 steps require an agent');
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
describe('runInit', () => {
|
|
@@ -50,7 +50,7 @@ describe('computeSensorStatus', () => {
|
|
|
50
50
|
const result = (0, status_1.computeSensorStatus)(tmpDir);
|
|
51
51
|
expect(result.overall).toBe('DEGRADED');
|
|
52
52
|
expect(result.checks.depcheck.ok).toBe(false);
|
|
53
|
-
expect(result.checks.depcheck.detail).toMatch(/
|
|
53
|
+
expect(result.checks.depcheck.detail).toMatch(/not installed locally/i);
|
|
54
54
|
});
|
|
55
55
|
it('marks a sensor DEGRADED when its --config file is missing', () => {
|
|
56
56
|
installLocalBin('eslint');
|
|
@@ -61,7 +61,7 @@ describe('computeSensorStatus', () => {
|
|
|
61
61
|
}));
|
|
62
62
|
const result = (0, status_1.computeSensorStatus)(tmpDir);
|
|
63
63
|
expect(result.checks.lint.ok).toBe(false);
|
|
64
|
-
expect(result.checks.lint.detail).toMatch(/config
|
|
64
|
+
expect(result.checks.lint.detail).toMatch(/missing config/i);
|
|
65
65
|
});
|
|
66
66
|
it('is HEALTHY when the npx tool is installed and the --config file exists', () => {
|
|
67
67
|
installLocalBin('eslint');
|
|
@@ -138,7 +138,7 @@ describe('runChecks — project', () => {
|
|
|
138
138
|
const report = (0, checks_1.runChecks)({ machine: healthyMachine(), project: p });
|
|
139
139
|
const c = report.results.find((r) => r.id === 'project.context');
|
|
140
140
|
expect(c.status).toBe('warn');
|
|
141
|
-
expect(c.label).toBe('
|
|
141
|
+
expect(c.label).toBe('agent context (CLAUDE.md/AGENTS.md) missing');
|
|
142
142
|
expect(c.remedy).toEqual({ kind: 'skill', value: 'project-context-init' });
|
|
143
143
|
expect(report.overall).toBe('healthy');
|
|
144
144
|
});
|