agentera 3.0.0-dev.3 → 3.0.0-dev.5

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.
Files changed (131) hide show
  1. package/README.md +39 -6
  2. package/bundle/.agentera-npx-bundle.json +1 -1
  3. package/bundle/references/cli/agent-ready-state-contract.yaml +20 -17
  4. package/bundle/references/cli/bundle-skill-vocabulary.yaml +1 -1
  5. package/bundle/references/cli/capability-instruction-contract.yaml +98 -57
  6. package/bundle/references/cli/routing-execution-vocabulary.yaml +6 -6
  7. package/bundle/references/cli/update-channels.yaml +27 -7
  8. package/bundle/references/cli/vocabulary-index.yaml +3 -3
  9. package/bundle/references/cli/vocabulary.md +28 -19
  10. package/bundle/registry.json +1 -1
  11. package/bundle/skills/agentera/SKILL.md +38 -21
  12. package/bundle/skills/agentera/agents/dokumentera.toml +1 -1
  13. package/bundle/skills/agentera/agents/hej.toml +1 -1
  14. package/bundle/skills/agentera/agents/inspektera.toml +1 -1
  15. package/bundle/skills/agentera/agents/inspirera.toml +1 -1
  16. package/bundle/skills/agentera/agents/optimera.toml +1 -1
  17. package/bundle/skills/agentera/agents/orkestrera.toml +1 -1
  18. package/bundle/skills/agentera/agents/planera.toml +1 -1
  19. package/bundle/skills/agentera/agents/profilera.toml +1 -1
  20. package/bundle/skills/agentera/agents/realisera.toml +1 -1
  21. package/bundle/skills/agentera/agents/resonera.toml +1 -1
  22. package/bundle/skills/agentera/agents/visionera.toml +1 -1
  23. package/bundle/skills/agentera/agents/visualisera.toml +1 -1
  24. package/bundle/skills/agentera/capabilities/orkestrera/schemas/validation.yaml +26 -13
  25. package/bundle/skills/agentera/capability_schema_contract.yaml +33 -14
  26. package/bundle/skills/agentera/references/contract.md +2 -2
  27. package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +1 -1
  28. package/bundle/skills/agentera/schemas/artifacts/progress.yaml +15 -36
  29. package/bundle/skills/agentera/schemas/artifacts/todo.yaml +14 -0
  30. package/bundle/skills/hej/SKILL.md +1 -1
  31. package/dist/analytics/usageStats.js +23 -1
  32. package/dist/analytics/usageStats.js.map +1 -1
  33. package/dist/capabilities/dokumentera/instructions.js +6 -0
  34. package/dist/capabilities/dokumentera/instructions.js.map +1 -0
  35. package/dist/capabilities/hej/instructions.js +6 -0
  36. package/dist/capabilities/hej/instructions.js.map +1 -0
  37. package/dist/capabilities/index.js +38 -0
  38. package/dist/capabilities/index.js.map +1 -0
  39. package/dist/capabilities/inspektera/instructions.js +6 -0
  40. package/dist/capabilities/inspektera/instructions.js.map +1 -0
  41. package/dist/capabilities/inspirera/instructions.js +6 -0
  42. package/dist/capabilities/inspirera/instructions.js.map +1 -0
  43. package/dist/capabilities/optimera/instructions.js +6 -0
  44. package/dist/capabilities/optimera/instructions.js.map +1 -0
  45. package/dist/capabilities/orkestrera/instructions.js +6 -0
  46. package/dist/capabilities/orkestrera/instructions.js.map +1 -0
  47. package/dist/capabilities/planera/instructions.js +6 -0
  48. package/dist/capabilities/planera/instructions.js.map +1 -0
  49. package/dist/capabilities/profilera/instructions.js +6 -0
  50. package/dist/capabilities/profilera/instructions.js.map +1 -0
  51. package/dist/capabilities/realisera/instructions.js +6 -0
  52. package/dist/capabilities/realisera/instructions.js.map +1 -0
  53. package/dist/capabilities/resonera/instructions.js +6 -0
  54. package/dist/capabilities/resonera/instructions.js.map +1 -0
  55. package/dist/capabilities/visionera/instructions.js +6 -0
  56. package/dist/capabilities/visionera/instructions.js.map +1 -0
  57. package/dist/capabilities/visualisera/instructions.js +6 -0
  58. package/dist/capabilities/visualisera/instructions.js.map +1 -0
  59. package/dist/cli/capabilityContext.js +92 -26
  60. package/dist/cli/capabilityContext.js.map +1 -1
  61. package/dist/cli/commands/capability.js +1 -8
  62. package/dist/cli/commands/capability.js.map +1 -1
  63. package/dist/cli/commands/doctor.js +42 -3
  64. package/dist/cli/commands/doctor.js.map +1 -1
  65. package/dist/cli/commands/report.js +5 -1
  66. package/dist/cli/commands/report.js.map +1 -1
  67. package/dist/cli/commands/state.js +22 -11
  68. package/dist/cli/commands/state.js.map +1 -1
  69. package/dist/cli/commands/validate.js +12 -2
  70. package/dist/cli/commands/validate.js.map +1 -1
  71. package/dist/cli/commands/verify.js +6 -0
  72. package/dist/cli/commands/verify.js.map +1 -1
  73. package/dist/cli/dispatch.js +508 -172
  74. package/dist/cli/dispatch.js.map +1 -1
  75. package/dist/cli/errors.js +53 -0
  76. package/dist/cli/errors.js.map +1 -0
  77. package/dist/cli/help.js +201 -0
  78. package/dist/cli/help.js.map +1 -0
  79. package/dist/cli/orientation.js +9 -6
  80. package/dist/cli/orientation.js.map +1 -1
  81. package/dist/cli/stateQuery.js +7 -0
  82. package/dist/cli/stateQuery.js.map +1 -1
  83. package/dist/cli/todoMarkdown.js +33 -0
  84. package/dist/cli/todoMarkdown.js.map +1 -0
  85. package/dist/hooks/common.js +0 -2
  86. package/dist/hooks/common.js.map +1 -1
  87. package/dist/hooks/validateArtifact.js +10 -8
  88. package/dist/hooks/validateArtifact.js.map +1 -1
  89. package/dist/registries/capabilityContract.js +12 -11
  90. package/dist/registries/capabilityContract.js.map +1 -1
  91. package/dist/registries/evaluatorHandoffContract.js +171 -0
  92. package/dist/registries/evaluatorHandoffContract.js.map +1 -0
  93. package/dist/setup/codex.js +146 -5
  94. package/dist/setup/codex.js.map +1 -1
  95. package/dist/setup/doctor.js +22 -1
  96. package/dist/setup/doctor.js.map +1 -1
  97. package/dist/setup/smokeChecks.js +111 -0
  98. package/dist/setup/smokeChecks.js.map +1 -0
  99. package/dist/upgrade/channels.js +9 -3
  100. package/dist/upgrade/channels.js.map +1 -1
  101. package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -1
  102. package/dist/upgrade/migrateArtifactsV1ToV2.js.map +1 -1
  103. package/dist/upgrade/nextMajorDoctor.js +121 -0
  104. package/dist/upgrade/nextMajorDoctor.js.map +1 -0
  105. package/dist/upgrade/runtimeMigration.js +19 -3
  106. package/dist/upgrade/runtimeMigration.js.map +1 -1
  107. package/dist/upgrade/versionResolution.js +4 -4
  108. package/dist/upgrade/versionResolution.js.map +1 -1
  109. package/dist/validate/appHomeContract.js +1 -1
  110. package/dist/validate/appHomeContract.js.map +1 -1
  111. package/dist/validate/capability.js +11 -3
  112. package/dist/validate/capability.js.map +1 -1
  113. package/package.json +3 -3
  114. package/bundle/skills/agentera/capabilities/dokumentera/instructions.md +0 -428
  115. package/bundle/skills/agentera/capabilities/hej/instructions.md +0 -331
  116. package/bundle/skills/agentera/capabilities/inspektera/instructions.md +0 -514
  117. package/bundle/skills/agentera/capabilities/inspirera/instructions.md +0 -280
  118. package/bundle/skills/agentera/capabilities/optimera/instructions.md +0 -437
  119. package/bundle/skills/agentera/capabilities/orkestrera/instructions.md +0 -433
  120. package/bundle/skills/agentera/capabilities/planera/instructions.md +0 -368
  121. package/bundle/skills/agentera/capabilities/profilera/instructions.md +0 -419
  122. package/bundle/skills/agentera/capabilities/realisera/instructions.md +0 -403
  123. package/bundle/skills/agentera/capabilities/resonera/instructions.md +0 -329
  124. package/bundle/skills/agentera/capabilities/visionera/instructions.md +0 -309
  125. package/bundle/skills/agentera/capabilities/visualisera/instructions.md +0 -400
  126. package/dist/cli/commands/backfill.js +0 -84
  127. package/dist/cli/commands/backfill.js.map +0 -1
  128. package/dist/core/git.js +0 -43
  129. package/dist/core/git.js.map +0 -1
  130. package/dist/state/progressCommit.js +0 -289
  131. package/dist/state/progressCommit.js.map +0 -1
@@ -1,6 +1,5 @@
1
1
  import { cmdPrime } from "./commands/prime.js";
2
2
  import { cmdLint } from "./commands/lint.js";
3
- import { cmdBackfill } from "./commands/backfill.js";
4
3
  import { cmdState, isPortedStateCommand } from "./commands/state.js";
5
4
  import { COMMAND_FILTERS } from "./stateQuery.js";
6
5
  import { cmdQuery } from "./commands/query.js";
@@ -18,11 +17,73 @@ import { HookCliAdapter } from "../hooks/validateArtifact.js";
18
17
  import fsForHooks from "node:fs";
19
18
  import { usageMain } from "../analytics/usageStats.js";
20
19
  import { validatePathValue } from "./argvalidate.js";
20
+ import { emitInvalidInput, } from "./errors.js";
21
21
  import { cmdCapability, CAPABILITY_ROUTING_NAMES } from "./commands/capability.js";
22
+ import { printCommandHelp, printDoctorHelp, printTopLevelHelp, printUpgradeHelp, splitHelpArgs, wantsHelp, } from "./help.js";
22
23
  import { cmdValidate, cmdValidateCapability, cmdValidateCapabilityContract, cmdValidateArtifact, cmdValidateDescriptors, isDelegatedValidateFamily, } from "./commands/validate.js";
23
24
  function emitDeprecationAlias(legacy, canonical, err) {
24
25
  err(`Deprecation: agentera ${legacy} is deprecated; use agentera ${canonical}\n`);
25
26
  }
27
+ /**
28
+ * Map a legacy parse-error string (the kind returned by `parse*Args`) to the
29
+ * canonical invalid-input envelope body. Lets the parse functions keep their
30
+ * simple `{ error: string }` shape while every surface's error path still
31
+ * funnels through `emitInvalidInput` for the frozen envelope contract.
32
+ */
33
+ function classifyParseError(raw) {
34
+ const required = /^the following arguments are required: (.+)$/.exec(raw);
35
+ if (required) {
36
+ return { class: "missing_argument", message: raw };
37
+ }
38
+ const unrecognized = /^unrecognized arguments: (.+)$/.exec(raw);
39
+ if (unrecognized) {
40
+ return { class: "unrecognized_argument", message: raw };
41
+ }
42
+ const choice = /^argument (--[\w-]+): invalid choice: '([^']+)' \(choose from (.+)\)$/.exec(raw);
43
+ if (choice) {
44
+ const validValues = [...choice[3].matchAll(/'([^']+)'/g)].map((m) => m[1]);
45
+ return {
46
+ class: "invalid_choice",
47
+ message: raw,
48
+ valid_values: validValues,
49
+ };
50
+ }
51
+ const intBad = /^argument (--[\w-]+): invalid int value: '([^']+)'$/.exec(raw);
52
+ if (intBad) {
53
+ return { class: "invalid_int", message: raw };
54
+ }
55
+ const mutex = /^argument (--[\w-]+): not allowed with argument (--[\w-]+)$/.exec(raw);
56
+ if (mutex) {
57
+ return { class: "mutually_exclusive", message: raw };
58
+ }
59
+ return { class: "unrecognized_argument", message: raw };
60
+ }
61
+ /** Coerce the loose `string` format field on parsed args to the literal union. */
62
+ function asEnvelopeFormat(format) {
63
+ return format === "json" ? "json" : "text";
64
+ }
65
+ /**
66
+ * Scan a top-level argv slice for `--format json` (or `--format=json`) so
67
+ * main() can decide whether to route its error envelope to stdout or stderr.
68
+ * Unknown format values fall through to "text" — the user will discover the
69
+ * mis-spelling when the underlying command runs.
70
+ */
71
+ function detectTopLevelFormat(args) {
72
+ for (let i = 0; i < args.length; i++) {
73
+ const a = args[i];
74
+ if (a === "--format") {
75
+ const v = args[++i];
76
+ if (v === "json" || v === "text" || v === "yaml")
77
+ return v === "json" ? "json" : "text";
78
+ }
79
+ else if (a.startsWith("--format=")) {
80
+ const v = a.slice("--format=".length);
81
+ if (v === "json" || v === "text" || v === "yaml")
82
+ return v === "json" ? "json" : "text";
83
+ }
84
+ }
85
+ return "text";
86
+ }
26
87
  /** Minimal flag parser for the `lint` command surface. */
27
88
  function parseLintArgs(argv) {
28
89
  const args = { artifact: "", file: null, text: null, strict: false, format: "text" };
@@ -68,73 +129,21 @@ function parseLintArgs(argv) {
68
129
  return args;
69
130
  }
70
131
  function runLint(argv, io, prog = "agentera lint") {
71
- const err = io.err ?? ((t) => process.stderr.write(t));
72
132
  const parsed = parseLintArgs(argv);
73
133
  if ("error" in parsed) {
74
- err(`${prog}: error: ${parsed.error}\n`);
75
- return 2;
134
+ return emitInvalidInput(io, {
135
+ format: "text",
136
+ body: classifyParseError(parsed.error),
137
+ });
76
138
  }
77
139
  try {
78
140
  return cmdLint(parsed, io);
79
141
  }
80
142
  catch (exc) {
81
- err(`Error: ${exc.message}\n`);
82
- return 2;
83
- }
84
- }
85
- function parseBackfillArgs(argv) {
86
- const args = { project: null, mode: "check", commit: null, cycle: null, format: "text" };
87
- for (let i = 0; i < argv.length; i++) {
88
- const a = argv[i];
89
- const value = (name) => {
90
- if (a === name)
91
- return argv[++i];
92
- if (a.startsWith(name + "="))
93
- return a.slice(name.length + 1);
94
- return null;
95
- };
96
- let v;
97
- if ((v = value("--project")) !== null)
98
- args.project = v;
99
- else if ((v = value("--mode")) !== null) {
100
- if (v !== "check" && v !== "fix") {
101
- return { error: `argument --mode: invalid choice: '${v}' (choose from 'check', 'fix')` };
102
- }
103
- args.mode = v;
104
- }
105
- else if ((v = value("--commit")) !== null)
106
- args.commit = v;
107
- else if ((v = value("--cycle")) !== null) {
108
- const n = Number(v);
109
- if (!Number.isInteger(n))
110
- return { error: `argument --cycle: invalid int value: '${v}'` };
111
- args.cycle = n;
112
- }
113
- else if ((v = value("--format")) !== null) {
114
- if (v !== "text" && v !== "json") {
115
- return { error: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')` };
116
- }
117
- args.format = v;
118
- }
119
- else {
120
- return { error: `unrecognized arguments: ${a}` };
121
- }
122
- }
123
- return args;
124
- }
125
- function runBackfill(argv, io, prog = "agentera backfill") {
126
- const err = io.err ?? ((t) => process.stderr.write(t));
127
- const parsed = parseBackfillArgs(argv);
128
- if ("error" in parsed) {
129
- err(`${prog}: error: ${parsed.error}\n`);
130
- return 2;
131
- }
132
- try {
133
- return cmdBackfill(parsed, io);
134
- }
135
- catch (exc) {
136
- err(`Error: ${exc.message}\n`);
137
- return 2;
143
+ return emitInvalidInput(io, {
144
+ format: asEnvelopeFormat(parsed.format),
145
+ body: { class: "unsupported_target", message: exc.message },
146
+ });
138
147
  }
139
148
  }
140
149
  function parseStateArgs(command, argv) {
@@ -190,13 +199,22 @@ function parseStateArgs(command, argv) {
190
199
  return args;
191
200
  }
192
201
  function runState(command, argv, io, prog) {
193
- const err = io.err ?? ((t) => process.stderr.write(t));
194
202
  const parsed = parseStateArgs(command, argv);
195
203
  if ("error" in parsed) {
196
- err(`${prog}: error: ${parsed.error}\n`);
197
- return 2;
204
+ return emitInvalidInput(io, {
205
+ format: "text",
206
+ body: classifyParseError(parsed.error),
207
+ });
208
+ }
209
+ try {
210
+ return cmdState(parsed, io);
211
+ }
212
+ catch (exc) {
213
+ return emitInvalidInput(io, {
214
+ format: asEnvelopeFormat(parsed.format),
215
+ body: { class: "unsupported_target", message: exc.message },
216
+ });
198
217
  }
199
- return cmdState(parsed, io);
200
218
  }
201
219
  function parseQueryArgs(argv) {
202
220
  const args = {
@@ -254,22 +272,27 @@ function parseQueryArgs(argv) {
254
272
  return args;
255
273
  }
256
274
  function runQuery(argv, io, prog) {
257
- const err = io.err ?? ((t) => process.stderr.write(t));
258
275
  const parsed = parseQueryArgs(argv);
259
276
  if ("error" in parsed) {
260
- err(`${prog}: error: ${parsed.error}\n`);
261
- return 2;
277
+ return emitInvalidInput(io, {
278
+ format: "text",
279
+ body: classifyParseError(parsed.error),
280
+ });
262
281
  }
263
282
  try {
264
283
  return cmdQuery(parsed, io);
265
284
  }
266
285
  catch (exc) {
267
- err(`Error: ${exc.message}\n`);
268
- return 2;
286
+ return emitInvalidInput(io, {
287
+ format: asEnvelopeFormat(parsed.format),
288
+ body: { class: "unsupported_target", message: exc.message },
289
+ });
269
290
  }
270
291
  }
271
292
  function compactModeOf(argv) {
272
293
  for (let i = 0; i < argv.length; i++) {
294
+ if (argv[i] === "--apply")
295
+ return "fix";
273
296
  if (argv[i] === "--mode")
274
297
  return argv[i + 1] ?? "check";
275
298
  if (argv[i].startsWith("--mode="))
@@ -289,7 +312,10 @@ function parseCompactArgs(argv) {
289
312
  return null;
290
313
  };
291
314
  let v;
292
- if ((v = value("--project")) !== null)
315
+ if (a === "--apply") {
316
+ args.mode = "fix";
317
+ }
318
+ else if ((v = value("--project")) !== null)
293
319
  args.project = v;
294
320
  else if ((v = value("--mode")) !== null) {
295
321
  if (v !== "check" && v !== "fix") {
@@ -309,22 +335,24 @@ function parseCompactArgs(argv) {
309
335
  return args;
310
336
  }
311
337
  function runCompact(argv, io, prog) {
312
- const err = io.err ?? ((t) => process.stderr.write(t));
313
338
  const parsed = parseCompactArgs(argv);
314
339
  if ("error" in parsed) {
315
- err(`${prog}: error: ${parsed.error}\n`);
316
- return 2;
340
+ return emitInvalidInput(io, {
341
+ format: "text",
342
+ body: classifyParseError(parsed.error),
343
+ });
317
344
  }
318
345
  try {
319
346
  return cmdCompact(parsed, io);
320
347
  }
321
348
  catch (exc) {
322
- err(`Error: ${exc.message}\n`);
323
- return 2;
349
+ return emitInvalidInput(io, {
350
+ format: asEnvelopeFormat(parsed.format),
351
+ body: { class: "unsupported_target", message: exc.message },
352
+ });
324
353
  }
325
354
  }
326
355
  function runValidate(argv, io, prog) {
327
- const err = io.err ?? ((t) => process.stderr.write(t));
328
356
  let family = null;
329
357
  let capabilityTarget = null;
330
358
  let artifactFlag = null;
@@ -336,16 +364,28 @@ function runValidate(argv, io, prog) {
336
364
  if (a === "--format") {
337
365
  const v = argv[++i];
338
366
  if (v !== "text" && v !== "json") {
339
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json')\n`);
340
- return 2;
367
+ return emitInvalidInput(io, {
368
+ format,
369
+ body: {
370
+ class: "invalid_choice",
371
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')`,
372
+ valid_values: ["text", "json"],
373
+ },
374
+ });
341
375
  }
342
376
  format = v;
343
377
  }
344
378
  else if (a.startsWith("--format=")) {
345
379
  const v = a.slice("--format=".length);
346
380
  if (v !== "text" && v !== "json") {
347
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json')\n`);
348
- return 2;
381
+ return emitInvalidInput(io, {
382
+ format,
383
+ body: {
384
+ class: "invalid_choice",
385
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')`,
386
+ valid_values: ["text", "json"],
387
+ },
388
+ });
349
389
  }
350
390
  format = v;
351
391
  }
@@ -359,8 +399,13 @@ function runValidate(argv, io, prog) {
359
399
  cwdFlag = a === "--cwd" ? argv[++i] : a.slice("--cwd=".length);
360
400
  }
361
401
  else if (a.startsWith("--")) {
362
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
363
- return 2;
402
+ return emitInvalidInput(io, {
403
+ format,
404
+ body: {
405
+ class: "unrecognized_argument",
406
+ message: `unrecognized arguments: ${a}`,
407
+ },
408
+ });
364
409
  }
365
410
  else if (family === null) {
366
411
  family = a;
@@ -369,19 +414,45 @@ function runValidate(argv, io, prog) {
369
414
  capabilityTarget = a;
370
415
  }
371
416
  else {
372
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
373
- return 2;
417
+ return emitInvalidInput(io, {
418
+ format,
419
+ body: {
420
+ class: "unrecognized_argument",
421
+ message: `unrecognized arguments: ${a}`,
422
+ },
423
+ });
374
424
  }
375
425
  }
376
426
  if (family === null) {
377
- err(`${prog}: error: the following arguments are required: validate_family\n`);
378
- return 2;
427
+ return emitInvalidInput(io, {
428
+ format,
429
+ body: {
430
+ class: "missing_argument",
431
+ message: "the following arguments are required: validate_family",
432
+ valid_values: [
433
+ "cross-capability",
434
+ "lifecycle-adapters",
435
+ "app-home-contract",
436
+ "capability",
437
+ "capability-contract",
438
+ "descriptors",
439
+ "artifact",
440
+ ],
441
+ example: "agentera check validate cross-capability",
442
+ },
443
+ });
379
444
  }
380
445
  try {
381
446
  if (family === "capability") {
382
447
  if (capabilityTarget === null) {
383
- err(`${prog} capability: error: the following arguments are required: target\n`);
384
- return 2;
448
+ return emitInvalidInput(io, {
449
+ format,
450
+ body: {
451
+ class: "missing_argument",
452
+ message: "the following arguments are required: target",
453
+ example: "agentera check validate capability planera",
454
+ },
455
+ });
385
456
  }
386
457
  return cmdValidateCapability(capabilityTarget, { format }, io);
387
458
  }
@@ -393,24 +464,48 @@ function runValidate(argv, io, prog) {
393
464
  }
394
465
  if (family === "artifact") {
395
466
  if (artifactFlag === null) {
396
- err(`${prog} artifact: error: the following arguments are required: --artifact\n`);
397
- return 2;
467
+ return emitInvalidInput(io, {
468
+ format,
469
+ body: {
470
+ class: "missing_argument",
471
+ message: "the following arguments are required: --artifact",
472
+ example: "agentera check validate artifact --artifact PLAN.md",
473
+ },
474
+ });
398
475
  }
399
476
  return cmdValidateArtifact({ artifact: artifactFlag, file: fileFlag, cwd: cwdFlag, format }, io);
400
477
  }
401
478
  if (isDelegatedValidateFamily(family)) {
402
479
  return cmdValidate(family, { format }, io);
403
480
  }
404
- err(`agentera: validate family not yet ported: ${family}\n`);
405
- return 1;
481
+ return emitInvalidInput(io, {
482
+ format,
483
+ body: {
484
+ class: "unsupported_target",
485
+ message: `validate family not yet ported: ${family}`,
486
+ valid_values: [
487
+ "cross-capability",
488
+ "lifecycle-adapters",
489
+ "app-home-contract",
490
+ "capability",
491
+ "capability-contract",
492
+ "descriptors",
493
+ "artifact",
494
+ ],
495
+ },
496
+ });
406
497
  }
407
498
  catch (exc) {
408
- err(`Error: ${exc.message}\n`);
409
- return 2;
499
+ return emitInvalidInput(io, {
500
+ format,
501
+ body: {
502
+ class: "unsupported_target",
503
+ message: exc.message,
504
+ },
505
+ });
410
506
  }
411
507
  }
412
508
  function runSchema(argv, io, prog) {
413
- const err = io.err ?? ((t) => process.stderr.write(t));
414
509
  let format = "json";
415
510
  for (let i = 0; i < argv.length; i++) {
416
511
  const a = argv[i];
@@ -420,12 +515,20 @@ function runSchema(argv, io, prog) {
420
515
  else if (a.startsWith("--format="))
421
516
  v = a.slice("--format=".length);
422
517
  else {
423
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
424
- return 2;
518
+ return emitInvalidInput(io, {
519
+ format: asEnvelopeFormat(format),
520
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
521
+ });
425
522
  }
426
523
  if (v !== "json" && v !== "yaml") {
427
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'json', 'yaml')\n`);
428
- return 2;
524
+ return emitInvalidInput(io, {
525
+ format: asEnvelopeFormat(format),
526
+ body: {
527
+ class: "invalid_choice",
528
+ message: `argument --format: invalid choice: '${v}' (choose from 'json', 'yaml')`,
529
+ valid_values: ["json", "yaml"],
530
+ },
531
+ });
429
532
  }
430
533
  format = v;
431
534
  }
@@ -433,12 +536,13 @@ function runSchema(argv, io, prog) {
433
536
  return cmdSchema({ format }, io);
434
537
  }
435
538
  catch (exc) {
436
- err(`Error: ${exc.message}\n`);
437
- return 2;
539
+ return emitInvalidInput(io, {
540
+ format: asEnvelopeFormat(format),
541
+ body: { class: "unsupported_target", message: exc.message },
542
+ });
438
543
  }
439
544
  }
440
545
  function runCapability(command, argv, io, prog) {
441
- const err = io.err ?? ((t) => process.stderr.write(t));
442
546
  let format = "text";
443
547
  for (let i = 0; i < argv.length; i++) {
444
548
  const a = argv[i];
@@ -454,19 +558,34 @@ function runCapability(command, argv, io, prog) {
454
558
  continue;
455
559
  }
456
560
  else {
457
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
458
- return 2;
561
+ return emitInvalidInput(io, {
562
+ format: asEnvelopeFormat(format),
563
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
564
+ });
459
565
  }
460
566
  if (v !== "text" && v !== "json" && v !== "yaml") {
461
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json', 'yaml')\n`);
462
- return 2;
567
+ return emitInvalidInput(io, {
568
+ format: asEnvelopeFormat(format),
569
+ body: {
570
+ class: "invalid_choice",
571
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json', 'yaml')`,
572
+ valid_values: ["text", "json", "yaml"],
573
+ },
574
+ });
463
575
  }
464
576
  format = v;
465
577
  }
466
- return cmdCapability(command, { format }, io);
578
+ try {
579
+ return cmdCapability(command, { format }, io);
580
+ }
581
+ catch (exc) {
582
+ return emitInvalidInput(io, {
583
+ format: asEnvelopeFormat(format),
584
+ body: { class: "unsupported_target", message: exc.message },
585
+ });
586
+ }
467
587
  }
468
588
  function runPrime(command, argv, io, prog) {
469
- const err = io.err ?? ((t) => process.stderr.write(t));
470
589
  const args = { command, guidance: false, context: null, dashboard: false, orientation: false, format: "text" };
471
590
  for (let i = 0; i < argv.length; i++) {
472
591
  const a = argv[i];
@@ -484,8 +603,14 @@ function runPrime(command, argv, io, prog) {
484
603
  else if (a === "--format" || a.startsWith("--format=")) {
485
604
  v = a === "--format" ? argv[++i] : a.slice("--format=".length);
486
605
  if (v !== "text" && v !== "json" && v !== "yaml") {
487
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json', 'yaml')\n`);
488
- return 2;
606
+ return emitInvalidInput(io, {
607
+ format: asEnvelopeFormat(args.format),
608
+ body: {
609
+ class: "invalid_choice",
610
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json', 'yaml')`,
611
+ valid_values: ["text", "json", "yaml"],
612
+ },
613
+ });
489
614
  }
490
615
  args.format = v;
491
616
  }
@@ -496,30 +621,57 @@ function runPrime(command, argv, io, prog) {
496
621
  args.fields = a.slice("--fields=".length);
497
622
  }
498
623
  else {
499
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
500
- return 2;
624
+ return emitInvalidInput(io, {
625
+ format: asEnvelopeFormat(args.format),
626
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
627
+ });
501
628
  }
502
629
  }
503
- return cmdPrime(args, io);
630
+ try {
631
+ return cmdPrime(args, io);
632
+ }
633
+ catch (exc) {
634
+ return emitInvalidInput(io, {
635
+ format: asEnvelopeFormat(args.format),
636
+ body: { class: "unsupported_target", message: exc.message },
637
+ });
638
+ }
504
639
  }
505
640
  function runGate(argv, io, prog) {
506
- const err = io.err ?? ((t) => process.stderr.write(t));
507
641
  const parsed = parseCompactArgs(argv);
508
642
  if ("error" in parsed) {
509
- err(`${prog}: error: ${parsed.error}\n`);
510
- return 2;
643
+ return emitInvalidInput(io, {
644
+ format: "text",
645
+ body: classifyParseError(parsed.error),
646
+ });
511
647
  }
512
648
  try {
513
649
  return cmdGate(parsed, io);
514
650
  }
515
651
  catch (exc) {
516
- err(`Error: ${exc.message}\n`);
517
- return 2;
652
+ return emitInvalidInput(io, {
653
+ format: asEnvelopeFormat(parsed.format),
654
+ body: { class: "unsupported_target", message: exc.message },
655
+ });
518
656
  }
519
657
  }
520
658
  function runDoctor(argv, io, prog) {
521
659
  const err = io.err ?? ((t) => process.stderr.write(t));
522
- const args = { installRoot: null, home: null, project: null, expectedVersion: null, expectCommand: [], format: "text" };
660
+ const out = io.out ?? ((t) => process.stdout.write(t));
661
+ if (wantsHelp(argv)) {
662
+ out(printDoctorHelp() + "\n");
663
+ return 0;
664
+ }
665
+ const args = {
666
+ installRoot: null,
667
+ home: null,
668
+ project: null,
669
+ expectedVersion: null,
670
+ expectCommand: [],
671
+ smoke: false,
672
+ allowLiveModel: false,
673
+ format: "text",
674
+ };
523
675
  let jsonFlag = false;
524
676
  for (let i = 0; i < argv.length; i++) {
525
677
  const a = argv[i];
@@ -543,23 +695,43 @@ function runDoctor(argv, io, prog) {
543
695
  args.expectCommand.push(v);
544
696
  else if ((v = value("--format")) !== null) {
545
697
  if (v !== "text" && v !== "json") {
546
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json')\n`);
547
- return 2;
698
+ return emitInvalidInput(io, {
699
+ format: asEnvelopeFormat(args.format),
700
+ body: {
701
+ class: "invalid_choice",
702
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')`,
703
+ valid_values: ["text", "json"],
704
+ },
705
+ });
548
706
  }
549
707
  args.format = v;
550
708
  }
551
709
  else if (a === "--json")
552
710
  jsonFlag = true;
711
+ else if (a === "--smoke")
712
+ args.smoke = true;
713
+ else if (a === "--allow-live-model")
714
+ args.allowLiveModel = true;
553
715
  else {
554
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
555
- return 2;
716
+ return emitInvalidInput(io, {
717
+ format: asEnvelopeFormat(args.format),
718
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
719
+ });
556
720
  }
557
721
  }
558
722
  if (jsonFlag) {
559
723
  emitDeprecationAlias("doctor --json", "doctor --format json", err);
560
724
  args.format = "json";
561
725
  }
562
- return cmdDoctor(args, io);
726
+ try {
727
+ return cmdDoctor(args, io);
728
+ }
729
+ catch (exc) {
730
+ return emitInvalidInput(io, {
731
+ format: asEnvelopeFormat(args.format),
732
+ body: { class: "unsupported_target", message: exc.message },
733
+ });
734
+ }
563
735
  }
564
736
  function readStdin() {
565
737
  try {
@@ -589,8 +761,20 @@ function runHook(name, argv, io) {
589
761
  return rc;
590
762
  }
591
763
  default:
592
- err(`agentera hook: unknown hook '${name}'\n`);
593
- return 2;
764
+ return emitInvalidInput(io, {
765
+ format: "text",
766
+ body: {
767
+ class: "unsupported_target",
768
+ message: `unknown hook '${name}'`,
769
+ valid_values: [
770
+ "session-start",
771
+ "session-stop",
772
+ "cursor-session-start",
773
+ "cursor-pre-tool-use",
774
+ "validate-artifact",
775
+ ],
776
+ },
777
+ });
594
778
  }
595
779
  }
596
780
  function runUsage(argv, io, prog) {
@@ -616,8 +800,10 @@ function runUsage(argv, io, prog) {
616
800
  else if ((v = value("--project")) !== null)
617
801
  project = v;
618
802
  else {
619
- realErr(`${prog}: error: unrecognized arguments: ${a}\n`);
620
- return 2;
803
+ return emitInvalidInput(io, {
804
+ format: asEnvelopeFormat(format),
805
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
806
+ });
621
807
  }
622
808
  }
623
809
  if (corpus !== null) {
@@ -625,16 +811,26 @@ function runUsage(argv, io, prog) {
625
811
  validatePathValue(corpus, "path");
626
812
  }
627
813
  catch (e) {
628
- realErr(`${prog}: error: argument --corpus: ${e.message}\n`);
629
- return 2;
814
+ return emitInvalidInput(io, {
815
+ format: asEnvelopeFormat(format),
816
+ body: {
817
+ class: "invalid_format",
818
+ message: `argument --corpus: ${e.message}`,
819
+ },
820
+ });
630
821
  }
631
822
  }
632
823
  if (format !== "text" && format !== "json") {
633
- const syntax = "agentera usage [--format text|json] [--corpus PATH] [--project VALUE]";
634
- const example = "agentera usage --format json --project agentera";
635
- realErr(`Error: unsupported usage format '${format}'; valid formats: text, json. ` +
636
- `Syntax: ${syntax}. Example: ${example}\n`);
637
- return 2;
824
+ return emitInvalidInput(io, {
825
+ format: asEnvelopeFormat(format),
826
+ body: {
827
+ class: "invalid_choice",
828
+ message: `unsupported usage format '${format}'; valid formats: text, json.`,
829
+ valid_values: ["text", "json"],
830
+ syntax: "agentera usage [--format text|json] [--corpus PATH] [--project VALUE]",
831
+ example: "agentera usage --format json --project agentera",
832
+ },
833
+ });
638
834
  }
639
835
  const engineArgv = [];
640
836
  if (corpus !== null)
@@ -650,6 +846,11 @@ function runUsage(argv, io, prog) {
650
846
  }
651
847
  function runUpgrade(argv, io, prog) {
652
848
  const err = io.err ?? ((t) => process.stderr.write(t));
849
+ const out = io.out ?? ((t) => process.stdout.write(t));
850
+ if (wantsHelp(argv)) {
851
+ out(printUpgradeHelp() + "\n");
852
+ return 0;
853
+ }
653
854
  const args = {
654
855
  installRoot: null,
655
856
  home: null,
@@ -685,15 +886,26 @@ function runUpgrade(argv, io, prog) {
685
886
  args.channel = v;
686
887
  else if ((v = value("--target-major")) !== null) {
687
888
  void v;
688
- err(`${prog}: error: --target-major was removed; use --channel with dry-run preview then --yes\n`);
689
- return 2;
889
+ return emitInvalidInput(io, {
890
+ format: asEnvelopeFormat(args.format),
891
+ body: {
892
+ class: "unsupported_target",
893
+ message: "--target-major was removed; use --channel with dry-run preview then --yes",
894
+ },
895
+ });
690
896
  }
691
897
  else if ((v = value("--runtime")) !== null)
692
898
  void v; // accepted; orchestrator uses fixture runtimes
693
899
  else if ((v = value("--only")) !== null) {
694
900
  if (v !== "artifacts" && v !== "runtime" && v !== "cleanup") {
695
- err(`${prog}: error: argument --only: invalid choice: '${v}' (choose from 'artifacts', 'runtime', 'cleanup')\n`);
696
- return 2;
901
+ return emitInvalidInput(io, {
902
+ format: asEnvelopeFormat(args.format),
903
+ body: {
904
+ class: "invalid_choice",
905
+ message: `argument --only: invalid choice: '${v}' (choose from 'artifacts', 'runtime', 'cleanup')`,
906
+ valid_values: ["artifacts", "runtime", "cleanup"],
907
+ },
908
+ });
697
909
  }
698
910
  args.only.push(v);
699
911
  }
@@ -711,22 +923,37 @@ function runUpgrade(argv, io, prog) {
711
923
  jsonFlag = true;
712
924
  else if ((v = value("--format")) !== null) {
713
925
  if (v !== "text" && v !== "json") {
714
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json')\n`);
715
- return 2;
926
+ return emitInvalidInput(io, {
927
+ format: asEnvelopeFormat(args.format),
928
+ body: {
929
+ class: "invalid_choice",
930
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')`,
931
+ valid_values: ["text", "json"],
932
+ },
933
+ });
716
934
  }
717
935
  args.format = v;
718
936
  }
719
937
  else {
720
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
721
- return 2;
938
+ return emitInvalidInput(io, {
939
+ format: asEnvelopeFormat(args.format),
940
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
941
+ });
722
942
  }
723
943
  }
724
944
  if (jsonFlag)
725
945
  args.format = "json";
726
- return cmdUpgrade(args, io);
946
+ try {
947
+ return cmdUpgrade(args, io);
948
+ }
949
+ catch (exc) {
950
+ return emitInvalidInput(io, {
951
+ format: asEnvelopeFormat(args.format),
952
+ body: { class: "unsupported_target", message: exc.message },
953
+ });
954
+ }
727
955
  }
728
956
  function runVerify(argv, io, prog) {
729
- const err = io.err ?? ((t) => process.stderr.write(t));
730
957
  const args = {
731
958
  family: null,
732
959
  target: null,
@@ -752,8 +979,14 @@ function runVerify(argv, io, prog) {
752
979
  let v;
753
980
  if ((v = value("--format")) !== null) {
754
981
  if (v !== "text" && v !== "json") {
755
- err(`${prog}: error: argument --format: invalid choice: '${v}' (choose from 'text', 'json')\n`);
756
- return 2;
982
+ return emitInvalidInput(io, {
983
+ format: asEnvelopeFormat(args.format),
984
+ body: {
985
+ class: "invalid_choice",
986
+ message: `argument --format: invalid choice: '${v}' (choose from 'text', 'json')`,
987
+ valid_values: ["text", "json"],
988
+ },
989
+ });
757
990
  }
758
991
  args.format = v;
759
992
  }
@@ -770,8 +1003,10 @@ function runVerify(argv, io, prog) {
770
1003
  else if (a === "--dry-run")
771
1004
  args.dryRun = true;
772
1005
  else if (a.startsWith("--")) {
773
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
774
- return 2;
1006
+ return emitInvalidInput(io, {
1007
+ format: asEnvelopeFormat(args.format),
1008
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
1009
+ });
775
1010
  }
776
1011
  else {
777
1012
  positionals.push(a);
@@ -780,10 +1015,17 @@ function runVerify(argv, io, prog) {
780
1015
  args.family = positionals[0] ?? null;
781
1016
  args.target = positionals[1] ?? null;
782
1017
  args.fixtures = positionals.slice(2);
783
- return cmdVerify(args, io);
1018
+ try {
1019
+ return cmdVerify(args, io);
1020
+ }
1021
+ catch (exc) {
1022
+ return emitInvalidInput(io, {
1023
+ format: asEnvelopeFormat(args.format),
1024
+ body: { class: "unsupported_target", message: exc.message },
1025
+ });
1026
+ }
784
1027
  }
785
1028
  function runReport(argv, io, prog) {
786
- const err = io.err ?? ((t) => process.stderr.write(t));
787
1029
  const args = {
788
1030
  action: null,
789
1031
  format: "text",
@@ -809,8 +1051,14 @@ function runReport(argv, io, prog) {
809
1051
  args.project = v;
810
1052
  else if ((v = value("--consent")) !== null) {
811
1053
  if (v !== "local-history") {
812
- err(`${prog}: error: argument --consent: invalid choice: '${v}' (choose from 'local-history')\n`);
813
- return 2;
1054
+ return emitInvalidInput(io, {
1055
+ format: asEnvelopeFormat(args.format),
1056
+ body: {
1057
+ class: "invalid_choice",
1058
+ message: `argument --consent: invalid choice: '${v}' (choose from 'local-history')`,
1059
+ valid_values: ["local-history"],
1060
+ },
1061
+ });
814
1062
  }
815
1063
  args.consent = v;
816
1064
  }
@@ -843,21 +1091,50 @@ function runReport(argv, io, prog) {
843
1091
  else if (a === "--dry-run")
844
1092
  args.dryRun = true;
845
1093
  else if (a.startsWith("--")) {
846
- err(`${prog}: error: unrecognized arguments: ${a}\n`);
847
- return 2;
1094
+ return emitInvalidInput(io, {
1095
+ format: asEnvelopeFormat(args.format),
1096
+ body: { class: "unrecognized_argument", message: `unrecognized arguments: ${a}` },
1097
+ });
848
1098
  }
849
1099
  else {
850
1100
  positionals.push(a);
851
1101
  }
852
1102
  }
853
1103
  args.action = positionals[0] ?? null;
854
- return cmdReport(args, io);
1104
+ try {
1105
+ return cmdReport(args, io);
1106
+ }
1107
+ catch (exc) {
1108
+ return emitInvalidInput(io, {
1109
+ format: asEnvelopeFormat(args.format),
1110
+ body: { class: "unsupported_target", message: exc.message },
1111
+ });
1112
+ }
855
1113
  }
856
1114
  export function main(argv, io = {}) {
857
1115
  const err = io.err ?? ((t) => process.stderr.write(t));
1116
+ const out = io.out ?? ((t) => process.stdout.write(t));
858
1117
  const args = argv.slice(2);
1118
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
1119
+ out(printTopLevelHelp() + "\n");
1120
+ return 0;
1121
+ }
859
1122
  const command = args[0];
860
- const rest = args.slice(1);
1123
+ const { args: rest, help } = splitHelpArgs(args.slice(1));
1124
+ if (help) {
1125
+ const text = printCommandHelp(command, rest);
1126
+ if (text) {
1127
+ out(text + "\n");
1128
+ return 0;
1129
+ }
1130
+ return emitInvalidInput(io, {
1131
+ format: "text",
1132
+ body: {
1133
+ class: "unsupported_target",
1134
+ message: `unknown or not-yet-ported command: ${command}`,
1135
+ },
1136
+ });
1137
+ }
861
1138
  switch (command) {
862
1139
  case "prime":
863
1140
  return runPrime("prime", rest, io, "agentera prime");
@@ -878,8 +1155,20 @@ export function main(argv, io = {}) {
878
1155
  case "hook": {
879
1156
  const name = rest[0];
880
1157
  if (!name) {
881
- err("agentera hook: error: the following arguments are required: hook_name\n");
882
- return 2;
1158
+ return emitInvalidInput(io, {
1159
+ format: "text",
1160
+ body: {
1161
+ class: "missing_argument",
1162
+ message: "the following arguments are required: hook_name",
1163
+ valid_values: [
1164
+ "session-start",
1165
+ "session-stop",
1166
+ "cursor-session-start",
1167
+ "cursor-pre-tool-use",
1168
+ "validate-artifact",
1169
+ ],
1170
+ },
1171
+ });
883
1172
  }
884
1173
  return runHook(name, rest.slice(1), io);
885
1174
  }
@@ -897,8 +1186,14 @@ export function main(argv, io = {}) {
897
1186
  case "check": {
898
1187
  const sub = rest[0];
899
1188
  if (!sub) {
900
- err("agentera check: error: the following arguments are required: check_command\n");
901
- return 2;
1189
+ return emitInvalidInput(io, {
1190
+ format: "text",
1191
+ body: {
1192
+ class: "missing_argument",
1193
+ message: "the following arguments are required: check_command",
1194
+ valid_values: ["validate", "verify", "lint", "compact"],
1195
+ },
1196
+ });
902
1197
  }
903
1198
  if (sub === "validate")
904
1199
  return runValidate(rest.slice(1), io, "agentera check validate");
@@ -906,8 +1201,6 @@ export function main(argv, io = {}) {
906
1201
  return runVerify(rest.slice(1), io, "agentera check verify");
907
1202
  if (sub === "lint")
908
1203
  return runLint(rest.slice(1), io, "agentera check lint");
909
- if (sub === "backfill")
910
- return runBackfill(rest.slice(1), io, "agentera check backfill");
911
1204
  if (sub === "compact") {
912
1205
  const subArgs = rest.slice(1);
913
1206
  const mode = compactModeOf(subArgs);
@@ -915,21 +1208,59 @@ export function main(argv, io = {}) {
915
1208
  return runCompact(subArgs, io, "agentera check compact");
916
1209
  return runGate(subArgs, io, "agentera check compact");
917
1210
  }
918
- err(`agentera: unknown or not-yet-ported check subcommand: ${sub}\n`);
919
- return 1;
1211
+ return emitInvalidInput(io, {
1212
+ format: "text",
1213
+ body: {
1214
+ class: "unsupported_target",
1215
+ message: `unknown or not-yet-ported check subcommand: ${sub}`,
1216
+ valid_values: ["validate", "verify", "lint", "compact"],
1217
+ },
1218
+ });
920
1219
  }
921
1220
  case "state": {
922
1221
  const sub = rest[0];
923
1222
  if (!sub) {
924
- err("agentera state: error: the following arguments are required: state_command\n");
925
- return 2;
1223
+ return emitInvalidInput(io, {
1224
+ format: "text",
1225
+ body: {
1226
+ class: "missing_argument",
1227
+ message: "the following arguments are required: state_command",
1228
+ valid_values: [
1229
+ "progress",
1230
+ "plan",
1231
+ "health",
1232
+ "docs",
1233
+ "objective",
1234
+ "experiments",
1235
+ "todo",
1236
+ "decisions",
1237
+ "query",
1238
+ ],
1239
+ },
1240
+ });
926
1241
  }
927
1242
  if (sub === "query")
928
1243
  return runQuery(rest.slice(1), io, "agentera state query");
929
1244
  if (isPortedStateCommand(sub))
930
1245
  return runState(sub, rest.slice(1), io, `agentera state ${sub}`);
931
- err(`agentera: unknown or not-yet-ported state subcommand: ${sub}\n`);
932
- return 1;
1246
+ return emitInvalidInput(io, {
1247
+ format: "text",
1248
+ body: {
1249
+ class: "unsupported_target",
1250
+ message: `unknown or not-yet-ported state subcommand: ${sub}`,
1251
+ valid_values: [
1252
+ "progress",
1253
+ "plan",
1254
+ "health",
1255
+ "docs",
1256
+ "objective",
1257
+ "experiments",
1258
+ "todo",
1259
+ "decisions",
1260
+ "query",
1261
+ ],
1262
+ },
1263
+ });
933
1264
  }
934
1265
  case "query":
935
1266
  emitDeprecationAlias("query", "state query", err);
@@ -951,8 +1282,13 @@ export function main(argv, io = {}) {
951
1282
  emitDeprecationAlias(command, `state ${command}`, err);
952
1283
  return runState(command, rest, io, `agentera ${command}`);
953
1284
  }
954
- err(`agentera: unknown or not-yet-ported command: ${command ?? "(none)"}\n`);
955
- return 1;
1285
+ return emitInvalidInput(io, {
1286
+ format: "text",
1287
+ body: {
1288
+ class: "unsupported_target",
1289
+ message: `unknown or not-yet-ported command: ${command ?? "(none)"}`,
1290
+ },
1291
+ });
956
1292
  }
957
1293
  }
958
1294
  //# sourceMappingURL=dispatch.js.map