agentic-workflow-manager 6.2.0 → 6.2.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/core/diagnostics/provider-checks.js +12 -9
- package/dist/src/core/profile.js +15 -1
- package/dist/src/core/update-check.js +5 -1
- package/dist/tests/core/diagnostics/provider-tier.test.js +3 -3
- package/dist/tests/core/profile.test.js +9 -2
- package/dist/tests/core/update-check.test.js +34 -3
- package/package.json +1 -1
|
@@ -124,20 +124,24 @@ function skillsGlobalCheck(dir, owners, integrity, renderer, artifacts) {
|
|
|
124
124
|
// generados NO: quedan con el contenido de la version anterior hasta que alguien
|
|
125
125
|
// corra `awm sync`, y hasta ahora nada lo decia.
|
|
126
126
|
const stale = staleRendered(dir, artifacts);
|
|
127
|
+
const names = stale.map((r) => path_1.default.basename(r.targetPath));
|
|
127
128
|
return {
|
|
128
129
|
id: 'skills.global',
|
|
129
130
|
state: stale.length > 0 ? 'stale' : 'supported',
|
|
130
131
|
target: dir,
|
|
131
132
|
owners: owners.length > 1 ? owners : undefined,
|
|
132
133
|
detail: stale.length > 0
|
|
133
|
-
? `${stale.length} rendered file(s) no longer match the installed registry (${
|
|
134
|
+
? `${stale.length} rendered file(s) no longer match the installed registry (${names.slice(0, 3).join(', ')})`
|
|
135
|
+
: undefined,
|
|
136
|
+
// El remedio depende del ALCANCE, y se midio cual funciona en cada uno:
|
|
137
|
+
// `awm update` reconcilia los artefactos de maquina, `awm sync` los que el
|
|
138
|
+
// profile del proyecto declara. Ofrecer el equivocado seria mandar al usuario
|
|
139
|
+
// a un comando que corre limpio sin cambiar nada — el defecto que ya tuvo
|
|
140
|
+
// `open-hooks-trust` (D-010), y que la primera version de ESTE chequeo
|
|
141
|
+
// repitio: ofrecia `reinstall-bundle` porque dos mediciones mias estaban mal.
|
|
142
|
+
remediationCode: stale.length > 0
|
|
143
|
+
? (stale.some((r) => r.scope === 'local') ? 'awm-sync' : 'awm-update')
|
|
134
144
|
: undefined,
|
|
135
|
-
// `reinstall-bundle`, y NO `awm-sync` ni `awm-init`: se midio cual de los
|
|
136
|
-
// cuatro comandos refresca de verdad un renderizado viejo, y solo `awm add`
|
|
137
|
-
// lo hace. `init` y `sync` son idempotentes por presencia —ven el archivo y
|
|
138
|
-
// no lo tocan— y `update` refresca el registry, no lo derivado de el. Ofrecer
|
|
139
|
-
// un remedio que corre limpio sin cambiar nada es peor que no ofrecer ninguno.
|
|
140
|
-
remediationCode: stale.length > 0 ? 'reinstall-bundle' : undefined,
|
|
141
145
|
};
|
|
142
146
|
}
|
|
143
147
|
const shared = owners.length > 1;
|
|
@@ -213,8 +217,7 @@ function staleRendered(dir, records) {
|
|
|
213
217
|
// corresponden. Aca "no puedo comparar" no se convierte en "esta viejo".
|
|
214
218
|
return false;
|
|
215
219
|
}
|
|
216
|
-
})
|
|
217
|
-
.map((r) => path_1.default.basename(r.targetPath));
|
|
220
|
+
});
|
|
218
221
|
}
|
|
219
222
|
function corruptRendered(dir, files, renderer) {
|
|
220
223
|
const marker = (0, registry_1.rendererIntegrityMarker)(renderer);
|
package/dist/src/core/profile.js
CHANGED
|
@@ -154,5 +154,19 @@ function ensureSkillsGitignored(root, agents) {
|
|
|
154
154
|
* project extensions and stay out of `.awm/profile.json`.
|
|
155
155
|
*/
|
|
156
156
|
function shouldRecordExtension(bundleScope, effective) {
|
|
157
|
-
|
|
157
|
+
// El criterio es el ALCANCE EFECTIVO, no el del bundle.
|
|
158
|
+
//
|
|
159
|
+
// Antes exigia ademas `bundleScope === 'project'`, asi que un bundle baseline
|
|
160
|
+
// instalado explicitamente con `--scope local` no quedaba registrado en ningun lado:
|
|
161
|
+
// `awm sync` reconcilia lo que declara el profile, y esos artefactos no estaban ahi.
|
|
162
|
+
// Resultado: nadie los refrescaba nunca. `update` cubre lo global y `sync` lo del
|
|
163
|
+
// profile; eso caia en el medio.
|
|
164
|
+
//
|
|
165
|
+
// Y no es un caso raro: `awm add dev --scope local` es exactamente lo que el playbook
|
|
166
|
+
// de aceptacion (AG-03) le pide correr a cualquiera que verifique un proveedor.
|
|
167
|
+
//
|
|
168
|
+
// Si alguien pidio artefactos de proyecto, el profile lo dice — que es lo que hace
|
|
169
|
+
// que un companero que clona el repo y corre `awm sync` obtenga lo mismo.
|
|
170
|
+
void bundleScope;
|
|
171
|
+
return effective === 'local';
|
|
158
172
|
}
|
|
@@ -83,7 +83,11 @@ function maybeNotifyUpdate(opts) {
|
|
|
83
83
|
const spawnWorker = opts?.spawnWorker ?? spawnRefreshWorker;
|
|
84
84
|
const cache = readUpdateCache();
|
|
85
85
|
if (cache?.latest && isNewer(cache.latest, (0, cli_version_1.cliVersion)())) {
|
|
86
|
-
|
|
86
|
+
// stderr, NO stdout. Este aviso se imprime al final de CUALQUIER comando, asi
|
|
87
|
+
// que en stdout se mezclaba con la salida de `--json` y rompia a cualquiera que
|
|
88
|
+
// parsee: `awm doctor --json | jq` fallaba con un SyntaxError que no menciona la
|
|
89
|
+
// causa. stdout es la interfaz de maquina; los avisos al humano van por stderr.
|
|
90
|
+
process.stderr.write(picocolors_1.default.dim(`\n⬆ awm v${cache.latest} available → npm i -g ${cli_version_1.CLI_PACKAGE_NAME}\n`));
|
|
87
91
|
}
|
|
88
92
|
if (!cache || now - cache.lastCheck > TTL_MS)
|
|
89
93
|
spawnWorker();
|
|
@@ -277,9 +277,9 @@ describe('skillsGlobalCheck — renderer-aware (Task 4.4 / deferred Task 4.3 fin
|
|
|
277
277
|
.checks.find((c) => c.id === 'skills.global');
|
|
278
278
|
expect(stale?.state).toBe('stale');
|
|
279
279
|
expect(stale?.detail).toContain('using-awm.mdc');
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
expect(stale?.remediationCode).toBe('
|
|
280
|
+
// El remedio depende del alcance, y se midio: `awm update` reconcilia los
|
|
281
|
+
// artefactos de maquina; `awm sync`, los que declara el profile del proyecto.
|
|
282
|
+
expect(stale?.remediationCode).toBe('awm-update');
|
|
283
283
|
fs_1.default.rmSync(source, { recursive: true, force: true });
|
|
284
284
|
});
|
|
285
285
|
it('non-link renderer with an empty/missing dir reports absent, not a false healthy', () => {
|
|
@@ -100,11 +100,18 @@ describe('ensureSkillsGitignored', () => {
|
|
|
100
100
|
});
|
|
101
101
|
});
|
|
102
102
|
describe('shouldRecordExtension', () => {
|
|
103
|
-
it('
|
|
103
|
+
it('no registra nada instalado a nivel maquina, sea cual sea el bundle', () => {
|
|
104
104
|
expect((0, profile_1.shouldRecordExtension)('project', 'local')).toBe(true);
|
|
105
105
|
expect((0, profile_1.shouldRecordExtension)('project', 'global')).toBe(false);
|
|
106
106
|
expect((0, profile_1.shouldRecordExtension)('baseline', 'global')).toBe(false);
|
|
107
|
-
expect((0, profile_1.shouldRecordExtension)('baseline', 'local')).toBe(false);
|
|
108
107
|
expect((0, profile_1.shouldRecordExtension)('ambient', 'global')).toBe(false);
|
|
109
108
|
});
|
|
109
|
+
it('records a BASELINE bundle too when it was installed with --scope local', () => {
|
|
110
|
+
// Antes devolvia false, y esos artefactos quedaban fuera del profile: `awm sync`
|
|
111
|
+
// reconcilia lo que el profile declara, asi que nadie los refrescaba nunca —
|
|
112
|
+
// `update` cubre lo global y esto caia en el medio. No es un caso raro:
|
|
113
|
+
// `awm add dev --scope local` es lo que el playbook AG-03 pide correr.
|
|
114
|
+
expect((0, profile_1.shouldRecordExtension)('baseline', 'local')).toBe(true);
|
|
115
|
+
expect((0, profile_1.shouldRecordExtension)('ambient', 'local')).toBe(true);
|
|
116
|
+
});
|
|
110
117
|
});
|
|
@@ -59,12 +59,14 @@ describe('update-check', () => {
|
|
|
59
59
|
it('maybeNotifyUpdate avisa si el cache trae versión más nueva y NO refresca cache fresco', () => {
|
|
60
60
|
const m = require('../../src/core/update-check');
|
|
61
61
|
m.writeUpdateCache({ lastCheck: 1_000_000, latest: '99.0.0' });
|
|
62
|
-
|
|
62
|
+
// stderr, no stdout: el aviso sale al final de cualquier comando y en stdout
|
|
63
|
+
// rompia la salida de `--json`.
|
|
64
|
+
const err = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
63
65
|
const spawnWorker = jest.fn();
|
|
64
66
|
m.maybeNotifyUpdate({ now: 1_000_000 + 1000, spawnWorker });
|
|
65
|
-
expect(
|
|
67
|
+
expect(err.mock.calls.flat().join('\n')).toContain('99.0.0');
|
|
66
68
|
expect(spawnWorker).not.toHaveBeenCalled();
|
|
67
|
-
|
|
69
|
+
err.mockRestore();
|
|
68
70
|
});
|
|
69
71
|
it('cache viejo (>24h) dispara refresh en background', () => {
|
|
70
72
|
const m = require('../../src/core/update-check');
|
|
@@ -104,3 +106,32 @@ describe('update-check', () => {
|
|
|
104
106
|
expect(cache.lastCheck).toBeGreaterThan(0);
|
|
105
107
|
});
|
|
106
108
|
});
|
|
109
|
+
// El aviso de version nueva va por stderr, no por stdout.
|
|
110
|
+
//
|
|
111
|
+
// Se imprime al final de CUALQUIER comando, asi que en stdout se mezclaba con la salida
|
|
112
|
+
// de `--json` y rompia a cualquiera que parsee. Encontrado tropezando con el:
|
|
113
|
+
// `awm doctor --json | node -e 'JSON.parse(...)'` fallaba con un SyntaxError que no
|
|
114
|
+
// menciona la causa. stdout es la interfaz de maquina.
|
|
115
|
+
describe('the update banner never contaminates stdout', () => {
|
|
116
|
+
it('writes to stderr so `--json` output stays parseable', () => {
|
|
117
|
+
const stdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
118
|
+
const stderr = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
119
|
+
const log = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
120
|
+
try {
|
|
121
|
+
const { maybeNotifyUpdate } = require('../../src/core/update-check');
|
|
122
|
+
maybeNotifyUpdate({ spawnWorker: () => { } });
|
|
123
|
+
const onStdout = stdout.mock.calls.map((c) => String(c[0])).join('')
|
|
124
|
+
+ log.mock.calls.map((c) => String(c[0])).join('');
|
|
125
|
+
expect(onStdout).not.toContain('available');
|
|
126
|
+
// Y si habia aviso, salio por stderr — no se perdio, se movio.
|
|
127
|
+
const emitted = stderr.mock.calls.map((c) => String(c[0])).join('');
|
|
128
|
+
if (emitted.length > 0)
|
|
129
|
+
expect(emitted).toContain('available');
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
stdout.mockRestore();
|
|
133
|
+
stderr.mockRestore();
|
|
134
|
+
log.mockRestore();
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|