@yemi33/minions 0.1.1861 → 0.1.1863

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1863 (2026-05-11)
4
+
5
+ ### Fixes
6
+ - push early + targeted-only verify, fully avoid runtime CLI crash trigger
7
+
8
+ ## 0.1.1862 (2026-05-11)
9
+
10
+ ### Fixes
11
+ - use 'exit' event for OS exit code + dedup sentinel; warn agents off .cmd shims
12
+
3
13
  ## 0.1.1861 (2026-05-10)
4
14
 
5
15
  ### Fixes
@@ -409,11 +409,38 @@ function main() {
409
409
  }, MCP_STARTUP_TIMEOUT);
410
410
  proc.stdout.once('data', () => { gotFirstOutput = true; clearTimeout(startupTimer); });
411
411
 
412
+ // Track the real OS exit code via the 'exit' event. Node's 'close' event
413
+ // can report code=0 on Windows when the OS-level exit was non-zero
414
+ // (observed empirically with both Claude Code CLI and Copilot CLI exiting
415
+ // with OS exit code 1 silently during long PowerShell tool calls — procdump
416
+ // captured the 1, but the engine's onAgentClose saw the spawn-agent's parent
417
+ // pipe report code=0). The 'exit' event fires earlier and carries the OS code
418
+ // more reliably; 'close' waits for stdio teardown which can race.
419
+ let realExitFromEvent = null;
420
+ let realSignalFromEvent = null;
421
+ let sentinelWritten = false;
422
+ proc.on('exit', (code, signal) => {
423
+ if (Number.isInteger(code)) realExitFromEvent = code;
424
+ if (signal) realSignalFromEvent = signal;
425
+ });
412
426
  proc.on('close', (code, signal) => {
413
427
  clearTimeout(startupTimer);
414
- const exitCode = normalizeRuntimeExit(code, signal);
415
- const sentinelResult = writeProcessExitSentinel({ exitCode, signal });
416
- fs.appendFileSync(debugPath, `EXIT: code=${exitCode}${signal ? ` signal=${signal}` : ''}\nSTDERR: ${stderrBuf.slice(0, 500)}\n`);
428
+ // Prefer the 'exit' event's code/signal when present — see note above.
429
+ const effectiveCode = (realExitFromEvent != null) ? realExitFromEvent : code;
430
+ const effectiveSignal = realSignalFromEvent || signal;
431
+ const exitCode = normalizeRuntimeExit(effectiveCode, effectiveSignal);
432
+ if (sentinelWritten) {
433
+ // Defense-in-depth: never write a duplicate sentinel. We observed pairs
434
+ // of [process-exit] code=0 lines in live-output.log across many failed
435
+ // runs, which suggests close has fired twice in some edge cases (e.g.,
436
+ // shim re-launch on Windows). One sentinel per spawn is the contract.
437
+ fs.appendFileSync(debugPath, `EXIT (duplicate close, skipping sentinel): code=${exitCode}${effectiveSignal ? ` signal=${effectiveSignal}` : ''}\n`);
438
+ process.exit(exitCode);
439
+ return;
440
+ }
441
+ sentinelWritten = true;
442
+ const sentinelResult = writeProcessExitSentinel({ exitCode, signal: effectiveSignal });
443
+ fs.appendFileSync(debugPath, `EXIT: code=${exitCode}${effectiveSignal ? ` signal=${effectiveSignal}` : ''} (close=${code} exit=${realExitFromEvent})\nSTDERR: ${stderrBuf.slice(0, 500)}\n`);
417
444
  if (!sentinelResult.fileWritten) {
418
445
  fs.appendFileSync(debugPath, `EXIT SENTINEL: file write failed for ${process.env.MINIONS_LIVE_OUTPUT_PATH}\n`);
419
446
  }
@@ -421,7 +448,10 @@ function main() {
421
448
  });
422
449
  proc.on('error', (err) => {
423
450
  fs.appendFileSync(debugPath, `ERROR: ${err.message}\n`);
424
- writeProcessExitSentinel({ exitCode: 1 });
451
+ if (!sentinelWritten) {
452
+ sentinelWritten = true;
453
+ writeProcessExitSentinel({ exitCode: 1 });
454
+ }
425
455
  process.exit(1);
426
456
  });
427
457
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1861",
3
+ "version": "0.1.1863",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"
@@ -59,21 +59,23 @@ Deliver this as if the user asked you directly in a CLI:
59
59
  You are already running in a git worktree on branch `{{branch_name}}`. Do NOT create additional worktrees — the engine pre-created one for you.
60
60
  Do NOT remove the worktree — the engine handles cleanup automatically.
61
61
 
62
- ## Validation
62
+ ## Validation — TARGETED ONLY, before publish
63
63
 
64
- Before publishing, prove the change with the repo's own documented checks:
64
+ Prove the change with the repo's own documented checks, BUT keep the
65
+ verification surface narrow:
65
66
 
66
67
  - Use the project's source of truth for commands: `CLAUDE.md`, README, package scripts, Makefile, or equivalent build config.
67
- - Run the checks that are relevant to this task, including tests that cover the changed behavior. Prefer the full suite when practical.
68
- - Capture the exact commands run and the meaningful result in the PR description or completion report. Do not summarize validation as "tests passed" without naming what ran.
69
- - Fix regressions you introduced. If failures are pre-existing or outside the task, capture the evidence and make that explicit in the PR.
70
- - Do not publish changes with a broken build or failing tests that you introduced.
68
+ - **Run only TARGETED tests covering the code you changed.** A single test file or a single test name is enough. Examples: `node test/unit/<my-file>.test.js`, `python -m pytest tests/test_my_module.py::test_my_case`, `cargo test --test my_test`.
69
+ - **Do NOT run the full project test suite (`node test/unit.test.js`, `npm test`, `yarn test`, etc.) as a verification step.** The full-suite run in a long agent session is the primary trigger for the runtime CLI crash documented in shared-rules.md. The engine and PR CI handle full-suite regression detection your job is to verify the code you wrote works, not to re-prove the entire suite.
70
+ - Use a quick `node --check <file>` (or equivalent) for syntax validation cheap and never crashes.
71
+ - Capture the exact targeted commands run and the meaningful result in the PR description or completion report.
72
+ - Do not publish changes with a broken build or failing tests that you introduced; if your targeted check fails, fix it before pushing.
71
73
 
72
74
  Long builds, dependency installs, and tests may be quiet for several minutes. Let the normal CLI command run naturally; do not add artificial heartbeat output or split commands just to show progress.
73
75
 
74
- ## Publish
76
+ ## Publish — push EARLY, before any expansion of verification scope
75
77
 
76
- After the change is validated or any unavoidable limitation is clearly documented, commit only the relevant files and push this branch:
78
+ After targeted validation passes, commit only the relevant files and push this branch IMMEDIATELY. This protects the work product: a runtime CLI crash on any later command cannot lose code that's already on the remote.
77
79
 
78
80
  ```bash
79
81
  git add <specific files>
@@ -74,6 +74,49 @@ Use `status: "failed"` plus an accurate `failure_class`, `retryable`, and `needs
74
74
 
75
75
  **No-op completions:** when you correctly decline to do the work — the change was already shipped on master, the dispatch premise is wrong, the flagged review comment is your own author-notes, etc. — write `status: "success"`, `pr: "N/A"`, AND add `"noop": true`. The engine treats `noop: true` as the canonical signal that no PR was expected, marks the work item done with the rationale surfaced in `_noopReason` for the dashboard, and skips the missing-PR-attachment failure. Without `noop: true`, an empty PR will still be flagged as a silent failure and auto-retried up to `maxRetries` times.
76
76
 
77
+ ## CRITICAL RULE: Never run `npm`/`yarn`/`pnpm` test scripts via the shell tool
78
+
79
+ **You will crash silently if you run `npm test`, `npm run <anything>`, `yarn test`,
80
+ `pnpm test`, `npx mocha`, `npx jest`, `npx vitest`, or any package-manager
81
+ script wrapper from your shell/PowerShell tool.** The runtime CLI (whether
82
+ Copilot CLI or Claude Code CLI) deterministically exits with OS code 1 mid-
83
+ conversation when invoking a `.cmd` shim that spawns a child node process
84
+ producing substantial stdout. This is confirmed by controlled reproductions
85
+ on both runtimes (2026-05-11) — including with full memory dumps. You will
86
+ NOT see an error message; the engine will mark your work as "phantom
87
+ completion" and the WI will fail with no PR.
88
+
89
+ This rule overrides any contradictory guidance you might find elsewhere
90
+ (including playbook instructions to "run the full suite"). The playbook
91
+ wants the test signal; it does NOT want you to crash trying to get it.
92
+ Use direct binary invocations every time:
93
+
94
+ | ❌ never | ✅ instead |
95
+ | --- | --- |
96
+ | `npm test` | `node test/unit.test.js` (or whatever the project's `test` script wraps) |
97
+ | `npm run <script>` | The underlying command — check `package.json` `scripts.<script>` |
98
+ | `yarn test`, `pnpm test` | Same — find the underlying `node ...` invocation |
99
+ | `npx mocha tests/` | `node node_modules/mocha/bin/mocha.js tests/` |
100
+ | `npx jest <file>` | `node node_modules/jest/bin/jest.js <file>` |
101
+ | `npx vitest run` | `node node_modules/vitest/vitest.mjs run` |
102
+
103
+ Non-`.cmd` test runners are safe (no shim chain):
104
+
105
+ - `python -m pytest tests/test_foo.py` ← Python uses `.exe`, not `.cmd`
106
+ - `cargo test --test foo` ← Rust cargo is `.exe`
107
+ - `dotnet test path/to/Project.Tests.csproj` ← .NET dotnet is `.exe`
108
+ - `go test ./...` ← Go is `.exe`
109
+
110
+ **Targeted single-file tests are STRONGLY preferred over full-suite runs**
111
+ regardless of how you invoke them. They're faster, smaller in output, and
112
+ produce the same regression signal for the code you actually changed.
113
+
114
+ If the project's test setup truly requires `npm test` (e.g., it sets env
115
+ vars in a hook), report this in your completion block and use the closest
116
+ direct equivalent anyway. Do not invoke the wrapper — verification you
117
+ don't get because you crashed is worse than verification you skipped
118
+ deliberately.
119
+
77
120
  ## Long-Running Commands
78
121
 
79
122
  Builds, dependency installs, tests, and local servers can be quiet for long periods. Run the repo's normal CLI commands and let them finish; do not add artificial progress output, heartbeat loops, or command-specific workarounds just to keep Minions active.