peaks-loop 4.0.0-beta.11 → 4.0.0-beta.12
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 +11 -2
- package/dist/cli/index.js +55 -3
- package/dist/cli/program.js +34 -0
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
## 4.0.0-beta.
|
|
5
|
+
## 4.0.0-beta.12 — 2026-07-16
|
|
6
6
|
|
|
7
|
-
### Status: RELEASED (
|
|
7
|
+
### Status: RELEASED (follow-up to `4.0.0-beta.11`; D-013 wrapper exit-code fix)
|
|
8
|
+
|
|
9
|
+
> **This CHANGELOG entry documents the D-013 follow-up release.
|
|
10
|
+
> Same source tree as `4.0.0-beta.11`; pure fix for the wrapper
|
|
11
|
+
> exit-code bug that previously caused `peaks <unknown>` and
|
|
12
|
+
> `peaks <unknown> --help` to exit 0 with the help banner.
|
|
13
|
+
>
|
|
14
|
+
> **Verdict**: All 4 regression paths now exit 1 with a
|
|
15
|
+
> `COMMAND_NOT_FOUND` JSON envelope. ice-cola baseline 27/27 PASS
|
|
16
|
+
> (AC3.9/AC3.10 now functionally correct).
|
|
8
17
|
|
|
9
18
|
> **This CHANGELOG entry documents the SHIPPED 4.0.0-beta.11.
|
|
10
19
|
> It is the post-implementation release of the 4.0.0-beta.10 contract
|
package/dist/cli/index.js
CHANGED
|
@@ -1,18 +1,70 @@
|
|
|
1
1
|
import { CommanderError } from 'commander';
|
|
2
2
|
import { createProgram } from './program.js';
|
|
3
3
|
import { getErrorMessage } from '../shared/result.js';
|
|
4
|
+
// D-013 wrapper exit-code fix (PART 2): Commander's `--help` short-circuit
|
|
5
|
+
// fires BEFORE `commander.unknownCommand` is raised, so `peaks xxx --help`
|
|
6
|
+
// (where `xxx` is not a registered command) prints the help banner and
|
|
7
|
+
// exits 0 instead of 1. Detect this case BEFORE Commander runs by scanning
|
|
8
|
+
// `process.argv` for a non-option positional token. If present AND
|
|
9
|
+
// `--help` is also present, the user asked for help on an unknown command
|
|
10
|
+
// — emit `COMMAND_NOT_FOUND` envelope + exit 1.
|
|
11
|
+
//
|
|
12
|
+
// This pre-check is intentionally conservative: only fires when BOTH a
|
|
13
|
+
// positional token AND `--help`/`-h` are present. Bare `--help` (no
|
|
14
|
+
// positional) is legitimate help → exit 0. Positional without `--help`
|
|
15
|
+
// is handled by the root `.action()` in `program.ts`.
|
|
16
|
+
const argv = process.argv.slice(2);
|
|
17
|
+
const hasHelp = argv.some((arg) => arg === '--help' || arg === '-h');
|
|
18
|
+
const firstPositional = argv.find((arg) => !arg.startsWith('-'));
|
|
19
|
+
if (hasHelp && firstPositional !== undefined) {
|
|
20
|
+
// Defer the check by 0ms so Commander's own help handler runs first
|
|
21
|
+
// (it will print help text + try to exit 0). We then override.
|
|
22
|
+
setImmediate(() => {
|
|
23
|
+
console.error(JSON.stringify({
|
|
24
|
+
ok: false,
|
|
25
|
+
command: 'cli',
|
|
26
|
+
code: 'COMMAND_NOT_FOUND',
|
|
27
|
+
message: `Unknown command: ${firstPositional}. Run \`peaks --help\` for available commands.`,
|
|
28
|
+
data: { argv: firstPositional, combinedWithHelp: true },
|
|
29
|
+
warnings: [],
|
|
30
|
+
nextActions: ['Run `peaks --help` to list available commands.']
|
|
31
|
+
}, null, 2));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
4
35
|
createProgram().parseAsync(process.argv).catch((error) => {
|
|
5
36
|
if (error instanceof CommanderError && error.code === 'commander.version') {
|
|
6
37
|
return;
|
|
7
38
|
}
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// (
|
|
39
|
+
// D-013 wrapper exit-code fix: distinguish "bare `peaks --help` /
|
|
40
|
+
// `peaks help <cmd>`" (legitimate help, exit 0) from
|
|
41
|
+
// "`peaks <unknown> --help`" (user typed a non-existent command,
|
|
42
|
+
// even if they added --help, the command itself is invalid → exit 1).
|
|
43
|
+
// Commander only emits `commander.helpDisplayed` for the LEGITIMATE
|
|
44
|
+
// help path (bare `--help` or a registered subcommand's help). For
|
|
45
|
+
// unknown commands, Commander throws `commander.unknownCommand`
|
|
46
|
+
// BEFORE the help text is rendered, so we route that case to the
|
|
47
|
+
// unknownCommand branch below. This preserves the historical behavior
|
|
48
|
+
// for valid help while fixing the unknown-command exit code.
|
|
11
49
|
if (error instanceof CommanderError) {
|
|
12
50
|
if (error.code === 'commander.help' || error.code === 'commander.helpDisplayed') {
|
|
13
51
|
return;
|
|
14
52
|
}
|
|
15
53
|
if (error.code === 'commander.missingArgument' || error.code === 'commander.unknownCommand' || error.code === 'commander.unknownOption') {
|
|
54
|
+
// Emit a `COMMAND_NOT_FOUND` JSON envelope for the unknown-command
|
|
55
|
+
// path. The error text already went to stderr via Commander's
|
|
56
|
+
// default handler; we add a structured envelope for LLM-side
|
|
57
|
+
// consumers (Human-NL-Choice-Only: don't tell the human to type
|
|
58
|
+
// a CLI verb — say what the LLM can coordinate).
|
|
59
|
+
console.error(JSON.stringify({
|
|
60
|
+
ok: false,
|
|
61
|
+
command: 'cli',
|
|
62
|
+
code: 'COMMAND_NOT_FOUND',
|
|
63
|
+
message: getErrorMessage(error),
|
|
64
|
+
data: {},
|
|
65
|
+
warnings: [],
|
|
66
|
+
nextActions: ['Run `peaks --help` to list available commands.']
|
|
67
|
+
}, null, 2));
|
|
16
68
|
process.exitCode = 1;
|
|
17
69
|
return;
|
|
18
70
|
}
|
package/dist/cli/program.js
CHANGED
|
@@ -207,6 +207,40 @@ Run peaks (no arguments) for a quickstart. You likely want one of:
|
|
|
207
207
|
}
|
|
208
208
|
})
|
|
209
209
|
.action(() => {
|
|
210
|
+
// D-013 wrapper exit-code fix: when the user typed a command token but
|
|
211
|
+
// it didn't match any registered subcommand, exit non-zero with a JSON
|
|
212
|
+
// `COMMAND_NOT_FOUND` envelope. Without this check, Commander's root
|
|
213
|
+
// `.action()` runs whenever no subcommand matches (including unknown
|
|
214
|
+
// commands) and prints the help banner with exit 0 — which violates
|
|
215
|
+
// the PRD AC3.9/AC3.10 contract for `peaks agent run/list` and any
|
|
216
|
+
// other deleted/hidden command.
|
|
217
|
+
//
|
|
218
|
+
// Detection: use `program.args` (Commander's parsed argv) for the
|
|
219
|
+
// first non-option token. If it's present and Commander didn't route
|
|
220
|
+
// to a subcommand (we got here, so it didn't), the user typed an
|
|
221
|
+
// unknown command. Exit 1. `program.args` works correctly under both
|
|
222
|
+
// `parseAsync(['node', 'peaks', ...])` (real CLI) and direct in-process
|
|
223
|
+
// calls (vitest integration tests), unlike `process.argv` which is
|
|
224
|
+
// the test runner's argv.
|
|
225
|
+
//
|
|
226
|
+
// --help and --version bypass this path entirely (handled below).
|
|
227
|
+
const firstNonOption = program.args.find((arg) => !arg.startsWith('-'));
|
|
228
|
+
if (firstNonOption !== undefined) {
|
|
229
|
+
// Commander reached this `.action()` despite a positional token,
|
|
230
|
+
// which means the token was NOT routed to any subcommand. This is
|
|
231
|
+
// the unknown-command path. Emit a JSON envelope + exit 1.
|
|
232
|
+
io.stdout(JSON.stringify({
|
|
233
|
+
ok: false,
|
|
234
|
+
command: 'cli',
|
|
235
|
+
code: 'COMMAND_NOT_FOUND',
|
|
236
|
+
message: `Unknown command: ${firstNonOption}. Run \`peaks --help\` for available commands.`,
|
|
237
|
+
data: { argv: firstNonOption },
|
|
238
|
+
warnings: [],
|
|
239
|
+
nextActions: ['Run `peaks --help` to list available commands.']
|
|
240
|
+
}, null, 2));
|
|
241
|
+
process.exitCode = 1;
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
210
244
|
const opts = program.opts();
|
|
211
245
|
if (opts.V || opts.version) {
|
|
212
246
|
// AC1: write the peaks-loop start log line BEFORE printing the
|
package/dist/shared/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "4.0.0-beta.
|
|
1
|
+
export declare const CLI_VERSION = "4.0.0-beta.12";
|
package/dist/shared/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "4.0.0-beta.
|
|
1
|
+
export const CLI_VERSION = "4.0.0-beta.12";
|
package/package.json
CHANGED