agentxchain 2.59.0 → 2.60.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
@@ -74,7 +74,7 @@ agentxchain status
74
74
  agentxchain step --role pm
75
75
  ```
76
76
 
77
- If you skipped `--goal` during scaffold, set `project.goal` in `agentxchain.json` before the first governed turn instead of re-running init in place.
77
+ If you skipped `--goal` during scaffold, run `agentxchain config --set project.goal "Build an API change planner for release teams"` before the first governed turn instead of re-running init in place.
78
78
 
79
79
  The default governed dev runtime is `claude --print --dangerously-skip-permissions` with stdin prompt delivery. The non-interactive governed path needs write access, so do not pretend bare `claude --print` is sufficient for unattended implementation turns. If your local coding agent uses a different launch contract, set it during scaffold creation:
80
80
 
@@ -192,7 +192,7 @@ program
192
192
  .description('View or edit project configuration')
193
193
  .option('--add-agent', 'Add a new agent interactively')
194
194
  .option('--remove-agent <id>', 'Remove an agent by ID')
195
- .option('--set <key_value>', 'Set a config value (e.g. --set "rules.max_consecutive_claims 3")')
195
+ .option('--set <path_and_value...>', 'Set a config value (e.g. --set project.goal "Build a governed CLI")')
196
196
  .option('-j, --json', 'Output config as JSON')
197
197
  .action(configCommand);
198
198
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.59.0",
3
+ "version": "2.60.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,31 +2,43 @@ import { readFileSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import chalk from 'chalk';
4
4
  import inquirer from 'inquirer';
5
- import { loadConfig, CONFIG_FILE } from '../lib/config.js';
5
+ import { loadProjectContext, CONFIG_FILE } from '../lib/config.js';
6
6
  import { validateConfigSchema } from '../lib/schema.js';
7
+ import { validateV4Config } from '../lib/normalized-config.js';
7
8
 
8
9
  export async function configCommand(opts) {
9
- const result = loadConfig();
10
- if (!result) {
10
+ const context = loadProjectContext();
11
+ if (!context) {
11
12
  console.log(chalk.red(' No agentxchain.json found. Run `agentxchain init` first.'));
12
13
  process.exit(1);
13
14
  }
14
15
 
15
- const { root, config } = result;
16
+ const { root, rawConfig, version } = context;
17
+ const config = rawConfig;
16
18
  const configPath = join(root, CONFIG_FILE);
17
19
 
20
+ if (version === 4 && opts.addAgent) {
21
+ printLegacyOnlyMutationError('--add-agent');
22
+ return;
23
+ }
24
+
18
25
  if (opts.addAgent) {
19
26
  await addAgent(config, configPath);
20
27
  return;
21
28
  }
22
29
 
30
+ if (version === 4 && opts.removeAgent) {
31
+ printLegacyOnlyMutationError('--remove-agent');
32
+ return;
33
+ }
34
+
23
35
  if (opts.removeAgent) {
24
36
  removeAgent(config, configPath, opts.removeAgent);
25
37
  return;
26
38
  }
27
39
 
28
40
  if (opts.set) {
29
- setSetting(config, configPath, opts.set);
41
+ setSetting(config, configPath, opts.set, { version, root });
30
42
  return;
31
43
  }
32
44
 
@@ -35,10 +47,15 @@ export async function configCommand(opts) {
35
47
  return;
36
48
  }
37
49
 
38
- printConfig(config);
50
+ if (version === 4) {
51
+ printGovernedConfig(config);
52
+ return;
53
+ }
54
+
55
+ printLegacyConfig(config);
39
56
  }
40
57
 
41
- function printConfig(config) {
58
+ function printLegacyConfig(config) {
42
59
  console.log('');
43
60
  console.log(chalk.bold(' AgentXchain Config'));
44
61
  console.log(chalk.dim(' ' + '─'.repeat(40)));
@@ -69,6 +86,32 @@ function printConfig(config) {
69
86
  console.log('');
70
87
  }
71
88
 
89
+ function printGovernedConfig(config) {
90
+ console.log('');
91
+ console.log(chalk.bold(' AgentXchain Governed Config'));
92
+ console.log(chalk.dim(' ' + '─'.repeat(40)));
93
+ console.log('');
94
+ console.log(` ${chalk.dim('Project:')} ${config.project?.name || '(unknown)'}`);
95
+ console.log(` ${chalk.dim('Project ID:')} ${config.project?.id || '(unknown)'}`);
96
+ console.log(` ${chalk.dim('Goal:')} ${config.project?.goal || '(not set)'}`);
97
+ console.log(` ${chalk.dim('Template:')} ${config.template || 'generic'}`);
98
+ console.log(` ${chalk.dim('Roles:')} ${Object.keys(config.roles || {}).length}`);
99
+ console.log(` ${chalk.dim('Runtimes:')} ${Object.keys(config.runtimes || {}).length}`);
100
+ console.log('');
101
+ console.log(chalk.dim(' Commands:'));
102
+ console.log(` ${chalk.bold('agentxchain config --set project.goal "Build a ..."')} Set mission context without hand-editing JSON`);
103
+ console.log(` ${chalk.bold('agentxchain config --set roles.qa.runtime manual-qa')} Switch a governed role runtime`);
104
+ console.log(` ${chalk.bold('agentxchain config --json')} Output raw config`);
105
+ console.log('');
106
+ }
107
+
108
+ function printLegacyOnlyMutationError(flag) {
109
+ console.log(chalk.red(` ${flag} is legacy-only.`));
110
+ console.log(chalk.dim(' Governed repos use roles and runtimes instead of legacy v3 agents.'));
111
+ console.log(chalk.dim(' Use `agentxchain config --set <path> <value>` for governed config changes.'));
112
+ process.exit(1);
113
+ }
114
+
72
115
  async function addAgent(config, configPath) {
73
116
  const answers = await inquirer.prompt([
74
117
  {
@@ -117,16 +160,15 @@ function removeAgent(config, configPath, id) {
117
160
  console.log('');
118
161
  }
119
162
 
120
- function setSetting(config, configPath, keyValPair) {
121
- const parts = keyValPair.split(/\s+/);
122
- if (parts.length < 2) {
163
+ function setSetting(config, configPath, keyValPair, context) {
164
+ const parsed = parseSetInput(keyValPair);
165
+ if (!parsed) {
123
166
  console.log(chalk.red(' Usage: agentxchain config --set <key> <value>'));
124
- console.log(chalk.dim(' Example: agentxchain config --set rules.max_consecutive_claims 3'));
167
+ console.log(chalk.dim(' Example: agentxchain config --set project.goal "Build a governed CLI"'));
125
168
  process.exit(1);
126
169
  }
127
170
 
128
- const key = parts[0];
129
- const rawVal = parts.slice(1).join(' ');
171
+ const { key, rawVal } = parsed;
130
172
  const segments = key.split('.');
131
173
  const forbiddenKeys = new Set(['__proto__', 'prototype', 'constructor']);
132
174
 
@@ -152,7 +194,7 @@ function setSetting(config, configPath, keyValPair) {
152
194
  else if (!isNaN(rawVal) && rawVal !== '') val = Number(rawVal);
153
195
 
154
196
  target[lastKey] = val;
155
- const validation = validateConfigSchema(config);
197
+ const validation = validateEditedConfig(config, context);
156
198
  if (!validation.ok) {
157
199
  target[lastKey] = oldVal;
158
200
  if (oldVal === undefined) {
@@ -168,3 +210,34 @@ function setSetting(config, configPath, keyValPair) {
168
210
  if (oldVal !== undefined) console.log(chalk.dim(` (was: ${oldVal})`));
169
211
  console.log('');
170
212
  }
213
+
214
+ function parseSetInput(input) {
215
+ if (Array.isArray(input)) {
216
+ if (input.length >= 2) {
217
+ return { key: input[0], rawVal: input.slice(1).join(' ') };
218
+ }
219
+ if (input.length === 1 && typeof input[0] === 'string') {
220
+ const parts = input[0].trim().split(/\s+/);
221
+ if (parts.length >= 2) {
222
+ return { key: parts[0], rawVal: parts.slice(1).join(' ') };
223
+ }
224
+ }
225
+ return null;
226
+ }
227
+
228
+ if (typeof input === 'string') {
229
+ const parts = input.trim().split(/\s+/);
230
+ if (parts.length >= 2) {
231
+ return { key: parts[0], rawVal: parts.slice(1).join(' ') };
232
+ }
233
+ }
234
+
235
+ return null;
236
+ }
237
+
238
+ function validateEditedConfig(config, context) {
239
+ if (context.version === 4) {
240
+ return validateV4Config(config, context.root);
241
+ }
242
+ return validateConfigSchema(config);
243
+ }
@@ -978,7 +978,8 @@ async function initGoverned(opts) {
978
978
  console.log('');
979
979
  if (!config?.project?.goal) {
980
980
  console.log(` ${chalk.dim('Tip:')} Add a project goal to guide agent context:`);
981
- console.log(` ${chalk.bold('agentxchain init --governed --goal "Build a ..."')} ${chalk.dim('# or set project.goal in agentxchain.json')}`);
981
+ console.log(` ${chalk.bold('agentxchain init --governed --goal "Build a ..."')} ${chalk.dim('# preferred during scaffold')}`);
982
+ console.log(` ${chalk.bold('agentxchain config --set project.goal "Build a ..."')} ${chalk.dim('# add it later without hand-editing JSON')}`);
982
983
  console.log('');
983
984
  }
984
985
  console.log(` ${chalk.dim('Guide:')} https://agentxchain.dev/docs/getting-started`);