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` mirrors the exit code, so a consumer can branch on one field
274
- // instead of correlating stdout with $?: ok → 0, degraded 1, failed → 2.
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 result === 'ok' ? 0 : 1;
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 1 on a bare HOME and never prompts with --yes (cache stubbed)', async () => {
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
- expect(code).toBe(1); // cache/hook/devCore siguen ausentes (syncCache no-op) degradado
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
- expect(code).toBe(1);
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 () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-workflow-manager",
3
- "version": "4.1.1",
3
+ "version": "5.0.0",
4
4
  "main": "dist/src/index.js",
5
5
  "bin": {
6
6
  "awm": "./dist/src/index.js"