agentic-workflow-manager 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -270,8 +270,20 @@ async function runInit(opts = {}) {
|
|
|
270
270
|
json: opts.json,
|
|
271
271
|
});
|
|
272
272
|
}
|
|
273
|
-
// `result`
|
|
274
|
-
//
|
|
273
|
+
// `result` distinguishes `ok` from `degraded` in the JSON; the EXIT CODE does
|
|
274
|
+
// not, on purpose (D-008).
|
|
275
|
+
//
|
|
276
|
+
// `degraded` used to exit `1`. It does not mean init failed — it means the
|
|
277
|
+
// harness still has `pending` steps, which is the NORMAL outcome of a first run:
|
|
278
|
+
// `CONSTITUTION.md` and `AGENTS.md` are written by an agent session, not by the
|
|
279
|
+
// CLI. So a run where nothing broke reported failure, and `awm init --yes && …`
|
|
280
|
+
// died under `set -e` — in the one command whose entire job is bootstrapping a
|
|
281
|
+
// script. Three independent readers called it a bug before it was one; the docs
|
|
282
|
+
// had grown a warning box asking people to ignore the exit code.
|
|
283
|
+
//
|
|
284
|
+
// The exit code now answers "did init do its job?". "Is the harness fully
|
|
285
|
+
// healthy?" is `awm doctor`'s question, and `result` still carries it here for
|
|
286
|
+
// any consumer that wants to branch on it.
|
|
275
287
|
const result = outcome.after.overall === 'healthy' ? 'ok' : 'degraded';
|
|
276
288
|
if (opts.json) {
|
|
277
289
|
process.stdout.write(JSON.stringify({ result, ...outcome }, null, 2) + '\n');
|
|
@@ -279,7 +291,7 @@ async function runInit(opts = {}) {
|
|
|
279
291
|
else {
|
|
280
292
|
process.stdout.write(renderInitOutcome(outcome) + '\n');
|
|
281
293
|
}
|
|
282
|
-
return
|
|
294
|
+
return 0;
|
|
283
295
|
}
|
|
284
296
|
// ---------------------------------------------------------------------------
|
|
285
297
|
// Extension confirmation factory
|
|
@@ -109,14 +109,17 @@ describe('runInit', () => {
|
|
|
109
109
|
expect(caveatCalls).toHaveLength(0);
|
|
110
110
|
});
|
|
111
111
|
});
|
|
112
|
-
it('returns exit
|
|
112
|
+
it('returns exit 0 on a bare HOME and never prompts with --yes (cache stubbed)', async () => {
|
|
113
113
|
const { runInit } = require('../../src/commands/init');
|
|
114
114
|
const code = await runInit({
|
|
115
115
|
cwd: tmpHome,
|
|
116
116
|
yes: true,
|
|
117
117
|
actions: { syncCache: async () => { }, installHook: () => ({ status: 'installed' }) },
|
|
118
118
|
});
|
|
119
|
-
|
|
119
|
+
// Degradado (cache/hook/devCore siguen ausentes con syncCache no-op) pero NADA
|
|
120
|
+
// fallo, y el exit code de `init` responde por init, no por la salud del
|
|
121
|
+
// harness — ver D-008. Esto salia 1 y rompia `awm init --yes && …` bajo `set -e`.
|
|
122
|
+
expect(code).toBe(0);
|
|
120
123
|
});
|
|
121
124
|
it('--json emits a parseable InitOutcome', async () => {
|
|
122
125
|
const { runInit } = require('../../src/commands/init');
|
|
@@ -131,7 +134,10 @@ describe('runInit', () => {
|
|
|
131
134
|
expect(Array.isArray(parsed.steps)).toBe(true);
|
|
132
135
|
expect(parsed.after.overall).toBe('degraded');
|
|
133
136
|
expect(parsed.result).toBe('degraded'); // success envelope is self-describing too
|
|
134
|
-
|
|
137
|
+
// El exit code deja de duplicar `result`: la distincion ok/degradado sigue
|
|
138
|
+
// disponible para quien la quiera, en el campo, no en `$?` (D-008).
|
|
139
|
+
expect(parsed.failed).toBe(0);
|
|
140
|
+
expect(code).toBe(0);
|
|
135
141
|
});
|
|
136
142
|
const prefsFile = () => path_1.default.join(process.env.AWM_HOME, 'preferences.json');
|
|
137
143
|
const readPreferences = () => JSON.parse(fs_1.default.readFileSync(prefsFile(), 'utf-8'));
|
|
@@ -239,6 +245,40 @@ describe('runInit', () => {
|
|
|
239
245
|
.toEqual(['claude-code', 'codex', 'opencode']);
|
|
240
246
|
});
|
|
241
247
|
// -----------------------------------------------------------------------
|
|
248
|
+
// D-008 — el exit code de `init` responde por init, no por la salud del harness
|
|
249
|
+
// -----------------------------------------------------------------------
|
|
250
|
+
//
|
|
251
|
+
// El contrato entero en un solo lugar, porque el sitio que lo rompia era el
|
|
252
|
+
// ausente: ningun test preguntaba "¿un script puede encadenar `awm init &&`?".
|
|
253
|
+
// Habia dos assertions de `toBe(1)`, y las dos *documentaban* el bug en vez de
|
|
254
|
+
// detenerlo. Tres lectores independientes lo reportaron como fallo antes de que
|
|
255
|
+
// lo fuera, y la doc habia crecido un recuadro pidiendo ignorar el exit code.
|
|
256
|
+
it('a degraded-but-successful run exits 0, so `awm init && next` survives set -e', async () => {
|
|
257
|
+
const { runInit } = require('../../src/commands/init');
|
|
258
|
+
const code = await runInit({
|
|
259
|
+
cwd: tmpHome,
|
|
260
|
+
yes: true,
|
|
261
|
+
json: true,
|
|
262
|
+
actions: { syncCache: async () => { }, installHook: () => ({ status: 'installed' }) },
|
|
263
|
+
});
|
|
264
|
+
const parsed = JSON.parse(writeSpy.mock.calls.map((c) => c[0]).join(''));
|
|
265
|
+
// Las tres afirmaciones juntas son el punto: degradado, sin nada fallado, exit 0.
|
|
266
|
+
// Cualquiera de las tres sola se puede satisfacer sin el fix.
|
|
267
|
+
expect(parsed.result).toBe('degraded');
|
|
268
|
+
expect(parsed.failed).toBe(0);
|
|
269
|
+
expect(code).toBe(0);
|
|
270
|
+
});
|
|
271
|
+
it('still refuses with exit 2 when a gate rejects — 0 does not mean "always succeed"', async () => {
|
|
272
|
+
const { runInit } = require('../../src/commands/init');
|
|
273
|
+
const code = await runInit({
|
|
274
|
+
cwd: tmpHome,
|
|
275
|
+
agent: 'codex',
|
|
276
|
+
yes: true,
|
|
277
|
+
assertProviderSupported: () => { throw new Error('requires Codex >= 0.145.0'); },
|
|
278
|
+
});
|
|
279
|
+
expect(code).toBe(2);
|
|
280
|
+
});
|
|
281
|
+
// -----------------------------------------------------------------------
|
|
242
282
|
// Step 1 — gate ordering, backup/rollback atomicity, Codex/Claude coexistence
|
|
243
283
|
// -----------------------------------------------------------------------
|
|
244
284
|
it('gates Codex before preferences or provider writes', async () => {
|