agentxchain 2.127.0 → 2.128.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.
package/README.md CHANGED
@@ -172,7 +172,8 @@ agentxchain step
172
172
  | `template validate` | Prove the template registry, workflow-kit scaffold contract, and planning artifact completeness (`--json` exposes a `workflow_kit` block) |
173
173
  | `verify turn` | Replay a staged turn's declared machine-evidence commands to confirm reproducibility before acceptance |
174
174
  | `replay turn` | Replay an accepted turn's machine-evidence commands from history for audit and drift detection |
175
- | `verify protocol` | Run the shipped protocol conformance suite against a target implementation |
175
+ | `conformance check` | Preferred front door for the shipped protocol conformance suite |
176
+ | `verify protocol` | Compatibility alias for the shipped protocol conformance suite |
176
177
  | `dashboard` | Open the live local governance dashboard in your browser for the current repo/workspace or multi-repo coordinator initiative, including pending gate approvals |
177
178
  | `run [--auto-approve] [--max-turns N] [--dry-run]` | Drive a governed run from start to completion — dispatches turns, handles gates, manages rejection/retry |
178
179
 
@@ -247,9 +248,11 @@ Partial coordinator artifacts are first-class here too: `audit` and `report` kee
247
248
  AgentXchain ships a conformance kit under `.agentxchain-conformance/`. Use it to prove a runner or fork still implements the governed workflow contract:
248
249
 
249
250
  ```bash
250
- agentxchain verify protocol --tier 3 --target .
251
+ agentxchain conformance check --tier 3 --target .
251
252
  ```
252
253
 
254
+ `agentxchain verify protocol` remains available as a compatibility alias.
255
+
253
256
  Useful flags:
254
257
 
255
258
  - `--tier 1|2|3`: maximum conformance tier to verify
@@ -542,6 +542,22 @@ program
542
542
  .option('-j, --json', 'Output as JSON')
543
543
  .action(validateCommand);
544
544
 
545
+ const conformanceCmd = program
546
+ .command('conformance')
547
+ .description('Run protocol conformance checks against local or remote implementations');
548
+
549
+ conformanceCmd
550
+ .command('check')
551
+ .description('Run the shipped protocol conformance fixture suite against a target implementation')
552
+ .option('--tier <tier>', 'Conformance tier to verify (1, 2, or 3)', '1')
553
+ .option('--surface <surface>', 'Restrict verification to a single surface')
554
+ .option('--target <path>', 'Target root containing .agentxchain-conformance/capabilities.json', '.')
555
+ .option('--remote <url>', 'Remote HTTP conformance endpoint base URL')
556
+ .option('--token <token>', 'Bearer token for remote HTTP conformance endpoint')
557
+ .option('--timeout <ms>', 'Per-fixture remote HTTP timeout in milliseconds', '30000')
558
+ .option('--format <format>', 'Output format: text or json', 'text')
559
+ .action(verifyProtocolCommand);
560
+
545
561
  const verifyCmd = program
546
562
  .command('verify')
547
563
  .description('Verify governed turns, export artifacts, and protocol conformance targets');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.127.0",
3
+ "version": "2.128.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -441,10 +441,20 @@ function commandHasPromptPlaceholder(parts = []) {
441
441
  return parts.some((part) => typeof part === 'string' && part.includes('{prompt}'));
442
442
  }
443
443
 
444
+ function normalizeGovernedDevCommand(parts = []) {
445
+ if (!Array.isArray(parts) || parts.length === 0) {
446
+ return null;
447
+ }
448
+ const [head, ...rest] = parts;
449
+ const normalizedHead = String(head || '').trim().split(/\s+/).filter(Boolean);
450
+ const normalizedRest = rest
451
+ .map((part) => String(part).trim())
452
+ .filter(Boolean);
453
+ return [...normalizedHead, ...normalizedRest];
454
+ }
455
+
444
456
  function resolveGovernedLocalDevRuntime(opts = {}) {
445
- const customCommand = Array.isArray(opts.devCommand)
446
- ? opts.devCommand.map((part) => String(part).trim()).filter(Boolean)
447
- : null;
457
+ const customCommand = normalizeGovernedDevCommand(opts.devCommand);
448
458
  const explicitTransport = typeof opts.devPromptTransport === 'string' && opts.devPromptTransport.trim()
449
459
  ? opts.devPromptTransport.trim()
450
460
  : null;
@@ -193,6 +193,19 @@ export async function executeGovernedRun(context, opts = {}) {
193
193
  const supported = rtType !== 'manual';
194
194
  log(` ${supported ? chalk.green('✓') : chalk.red('✗')} ${rid} → ${rtType}${supported ? '' : ' (not supported in run mode)'}`);
195
195
  }
196
+ // Warn if the first-dispatched role in the current phase is manual
197
+ if (roleId) {
198
+ const firstRole = config.roles?.[roleId];
199
+ const firstRtId = firstRole?.runtime;
200
+ const firstRt = config.runtimes?.[firstRtId];
201
+ const firstRtType = firstRt?.type || firstRole?.runtime_class || 'manual';
202
+ if (firstRtType === 'manual') {
203
+ log('');
204
+ log(chalk.yellow(` ⚠ The current phase's first role (${roleId}) is manual.`));
205
+ log(chalk.yellow(` "run" will block immediately. Complete manual turns via "agentxchain step" first,`));
206
+ log(chalk.yellow(` or configure ${roleId} with an automatable runtime.`));
207
+ }
208
+ }
196
209
  return { exitCode: 0, result: null };
197
210
  }
198
211
 
@@ -278,7 +278,13 @@ function resolveCommand(runtime, fullPrompt) {
278
278
 
279
279
  // Shape 1: command is an array
280
280
  if (Array.isArray(runtime.command)) {
281
- const [cmd, ...rest] = runtime.command;
281
+ // Normalize: if the first element contains spaces (e.g., ["echo test"]), split it
282
+ // into binary + args. Only the first element is split — later elements may contain
283
+ // legitimate spaces (e.g., script text for `node -e "..."`).
284
+ const first = runtime.command[0] || '';
285
+ const headParts = typeof first === 'string' && first.includes(' ') ? first.split(/\s+/) : [first];
286
+ const [cmd, ...headArgs] = headParts;
287
+ const rest = [...headArgs, ...runtime.command.slice(1)];
282
288
  const args = transport === 'argv'
283
289
  ? rest.map(arg => arg === '{prompt}' ? fullPrompt : arg)
284
290
  : rest.filter(arg => arg !== '{prompt}');
@@ -38,7 +38,9 @@ function formatTarget(runtime) {
38
38
 
39
39
  function commandHead(runtime) {
40
40
  if (Array.isArray(runtime?.command)) {
41
- return runtime.command[0] || null;
41
+ const first = runtime.command[0] || null;
42
+ if (first && first.includes(' ')) return first.split(/\s+/)[0];
43
+ return first;
42
44
  }
43
45
  if (typeof runtime?.command === 'string' && runtime.command.trim()) {
44
46
  return runtime.command.trim().split(/\s+/)[0];