agentxchain 0.8.7 → 2.1.1
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 +123 -154
- package/bin/agentxchain.js +240 -8
- package/dashboard/app.js +305 -0
- package/dashboard/components/blocked.js +145 -0
- package/dashboard/components/cross-repo.js +126 -0
- package/dashboard/components/gate.js +311 -0
- package/dashboard/components/hooks.js +177 -0
- package/dashboard/components/initiative.js +147 -0
- package/dashboard/components/ledger.js +165 -0
- package/dashboard/components/timeline.js +222 -0
- package/dashboard/index.html +352 -0
- package/package.json +16 -7
- package/scripts/agentxchain-autonudge.applescript +32 -5
- package/scripts/live-api-proxy-preflight-smoke.sh +531 -0
- package/scripts/publish-from-tag.sh +88 -0
- package/scripts/release-postflight.sh +231 -0
- package/scripts/release-preflight.sh +167 -0
- package/scripts/run-autonudge.sh +1 -1
- package/src/adapters/claude-code.js +7 -14
- package/src/adapters/cursor-local.js +17 -16
- package/src/commands/accept-turn.js +160 -0
- package/src/commands/approve-completion.js +80 -0
- package/src/commands/approve-transition.js +85 -0
- package/src/commands/branch.js +2 -2
- package/src/commands/claim.js +84 -9
- package/src/commands/config.js +16 -0
- package/src/commands/dashboard.js +70 -0
- package/src/commands/doctor.js +9 -1
- package/src/commands/init.js +540 -5
- package/src/commands/migrate.js +348 -0
- package/src/commands/multi.js +549 -0
- package/src/commands/plugin.js +157 -0
- package/src/commands/reject-turn.js +204 -0
- package/src/commands/resume.js +389 -0
- package/src/commands/status.js +196 -3
- package/src/commands/step.js +947 -0
- package/src/commands/stop.js +65 -33
- package/src/commands/template-list.js +33 -0
- package/src/commands/template-set.js +279 -0
- package/src/commands/update.js +24 -3
- package/src/commands/validate.js +20 -11
- package/src/commands/verify.js +71 -0
- package/src/commands/watch.js +112 -25
- package/src/lib/adapters/api-proxy-adapter.js +1076 -0
- package/src/lib/adapters/local-cli-adapter.js +337 -0
- package/src/lib/adapters/manual-adapter.js +169 -0
- package/src/lib/blocked-state.js +94 -0
- package/src/lib/config.js +143 -12
- package/src/lib/context-compressor.js +121 -0
- package/src/lib/context-section-parser.js +220 -0
- package/src/lib/coordinator-acceptance.js +428 -0
- package/src/lib/coordinator-config.js +461 -0
- package/src/lib/coordinator-dispatch.js +276 -0
- package/src/lib/coordinator-gates.js +487 -0
- package/src/lib/coordinator-hooks.js +239 -0
- package/src/lib/coordinator-recovery.js +523 -0
- package/src/lib/coordinator-state.js +365 -0
- package/src/lib/cross-repo-context.js +247 -0
- package/src/lib/dashboard/bridge-server.js +284 -0
- package/src/lib/dashboard/file-watcher.js +93 -0
- package/src/lib/dashboard/state-reader.js +96 -0
- package/src/lib/dispatch-bundle.js +568 -0
- package/src/lib/dispatch-manifest.js +252 -0
- package/src/lib/filter-agents.js +12 -0
- package/src/lib/gate-evaluator.js +285 -0
- package/src/lib/generate-vscode.js +158 -68
- package/src/lib/governed-state.js +2139 -0
- package/src/lib/governed-templates.js +145 -0
- package/src/lib/hook-runner.js +788 -0
- package/src/lib/next-owner.js +61 -6
- package/src/lib/normalized-config.js +539 -0
- package/src/lib/notify.js +14 -12
- package/src/lib/plugin-config-schema.js +192 -0
- package/src/lib/plugins.js +692 -0
- package/src/lib/prompt-core.js +108 -0
- package/src/lib/protocol-conformance.js +291 -0
- package/src/lib/reference-conformance-adapter.js +717 -0
- package/src/lib/repo-observer.js +597 -0
- package/src/lib/repo.js +0 -31
- package/src/lib/safe-write.js +44 -0
- package/src/lib/schema.js +189 -0
- package/src/lib/schemas/turn-result.schema.json +205 -0
- package/src/lib/seed-prompt-polling.js +15 -73
- package/src/lib/seed-prompt.js +17 -63
- package/src/lib/token-budget.js +206 -0
- package/src/lib/token-counter.js +27 -0
- package/src/lib/turn-paths.js +67 -0
- package/src/lib/turn-result-validator.js +496 -0
- package/src/lib/validation.js +167 -19
- package/src/lib/verify-command.js +72 -0
- package/src/templates/governed/api-service.json +31 -0
- package/src/templates/governed/cli-tool.json +30 -0
- package/src/templates/governed/generic.json +10 -0
- package/src/templates/governed/web-app.json +30 -0
package/src/commands/status.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { loadConfig, loadLock, loadState } from '../lib/config.js';
|
|
2
|
+
import { loadConfig, loadLock, loadProjectContext, loadProjectState, loadState } from '../lib/config.js';
|
|
3
|
+
import { deriveRecoveryDescriptor } from '../lib/blocked-state.js';
|
|
4
|
+
import { getActiveTurn, getActiveTurnCount, getActiveTurns } from '../lib/governed-state.js';
|
|
3
5
|
|
|
4
6
|
export async function statusCommand(opts) {
|
|
5
|
-
const
|
|
6
|
-
if (!
|
|
7
|
+
const context = loadProjectContext();
|
|
8
|
+
if (!context) {
|
|
7
9
|
console.log(chalk.red('No agentxchain.json found. Run `agentxchain init` first.'));
|
|
8
10
|
process.exit(1);
|
|
9
11
|
}
|
|
10
12
|
|
|
13
|
+
if (context.config.protocol_mode === 'governed') {
|
|
14
|
+
return renderGovernedStatus(context, opts);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const result = loadConfig();
|
|
11
18
|
const { root, config } = result;
|
|
12
19
|
const lock = loadLock(root);
|
|
13
20
|
const state = loadState(root);
|
|
@@ -64,11 +71,192 @@ export async function statusCommand(opts) {
|
|
|
64
71
|
console.log('');
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
function renderGovernedStatus(context, opts) {
|
|
75
|
+
const { root, config, version } = context;
|
|
76
|
+
const state = loadProjectState(root, config);
|
|
77
|
+
|
|
78
|
+
if (opts.json) {
|
|
79
|
+
console.log(JSON.stringify({
|
|
80
|
+
version,
|
|
81
|
+
protocol_mode: config.protocol_mode,
|
|
82
|
+
template: config.template || 'generic',
|
|
83
|
+
config,
|
|
84
|
+
state,
|
|
85
|
+
}, null, 2));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log(chalk.bold(' AgentXchain Status'));
|
|
91
|
+
console.log(chalk.dim(' ' + '─'.repeat(44)));
|
|
92
|
+
console.log('');
|
|
93
|
+
|
|
94
|
+
console.log(` ${chalk.dim('Project:')} ${config.project.name}`);
|
|
95
|
+
console.log(` ${chalk.dim('Protocol:')} ${chalk.cyan(`governed (v${version})`)}`);
|
|
96
|
+
console.log(` ${chalk.dim('Template:')} ${config.template || 'generic'}`);
|
|
97
|
+
console.log(` ${chalk.dim('Phase:')} ${state?.phase ? formatGovernedPhase(state.phase) : chalk.dim('unknown')}`);
|
|
98
|
+
console.log(` ${chalk.dim('Run:')} ${formatRunStatus(state?.status)}`);
|
|
99
|
+
if (state?.accepted_integration_ref) {
|
|
100
|
+
console.log(` ${chalk.dim('Accepted:')} ${state.accepted_integration_ref}`);
|
|
101
|
+
}
|
|
102
|
+
console.log('');
|
|
103
|
+
|
|
104
|
+
const activeTurnCount = getActiveTurnCount(state);
|
|
105
|
+
const activeTurns = getActiveTurns(state);
|
|
106
|
+
const singleActiveTurn = getActiveTurn(state);
|
|
107
|
+
if (activeTurnCount > 1) {
|
|
108
|
+
console.log(` ${chalk.dim('Turns:')} ${activeTurnCount} active`);
|
|
109
|
+
for (const turn of Object.values(activeTurns)) {
|
|
110
|
+
const marker = turn.status === 'conflicted'
|
|
111
|
+
? chalk.red('✗')
|
|
112
|
+
: chalk.yellow('●');
|
|
113
|
+
const statusLabel = turn.status === 'conflicted'
|
|
114
|
+
? chalk.red('conflicted')
|
|
115
|
+
: turn.status;
|
|
116
|
+
console.log(` ${marker} ${turn.turn_id} — ${chalk.bold(turn.assigned_role)} (${statusLabel}) [attempt ${turn.attempt}]`);
|
|
117
|
+
if (turn.status === 'conflicted' && turn.conflict_state) {
|
|
118
|
+
const cs = turn.conflict_state;
|
|
119
|
+
const files = cs.conflict_error?.conflicting_files || [];
|
|
120
|
+
const count = cs.detection_count || 1;
|
|
121
|
+
console.log(` ${chalk.dim('Conflict:')} ${files.length} file(s) — detection #${count}`);
|
|
122
|
+
if (cs.conflict_error?.overlap_ratio != null) {
|
|
123
|
+
console.log(` ${chalk.dim('Overlap:')} ${(cs.conflict_error.overlap_ratio * 100).toFixed(0)}%`);
|
|
124
|
+
}
|
|
125
|
+
const suggestion = cs.conflict_error?.suggested_resolution || 'reject_and_reassign';
|
|
126
|
+
console.log(` ${chalk.dim('Suggested:')} ${suggestion}`);
|
|
127
|
+
console.log(` ${chalk.dim('Resolve:')} ${chalk.cyan(`agentxchain reject-turn --turn ${turn.turn_id} --reassign`)}`);
|
|
128
|
+
console.log(` ${chalk.dim(' or:')} ${chalk.cyan(`agentxchain accept-turn --turn ${turn.turn_id} --resolution human_merge`)}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} else if (singleActiveTurn) {
|
|
132
|
+
console.log(` ${chalk.dim('Turn:')} ${singleActiveTurn.turn_id}`);
|
|
133
|
+
console.log(` ${chalk.dim('Role:')} ${chalk.bold(singleActiveTurn.assigned_role)} (${singleActiveTurn.status})`);
|
|
134
|
+
console.log(` ${chalk.dim('Runtime:')} ${singleActiveTurn.runtime_id}`);
|
|
135
|
+
console.log(` ${chalk.dim('Attempt:')} ${singleActiveTurn.attempt}`);
|
|
136
|
+
if (singleActiveTurn.status === 'conflicted' && singleActiveTurn.conflict_state) {
|
|
137
|
+
const cs = singleActiveTurn.conflict_state;
|
|
138
|
+
const files = cs.conflict_error?.conflicting_files || [];
|
|
139
|
+
console.log(` ${chalk.dim('Conflict:')} ${chalk.red(`${files.length} file(s) conflicting`)} — detection #${cs.detection_count || 1}`);
|
|
140
|
+
console.log(` ${chalk.dim('Resolve:')} ${chalk.cyan('agentxchain reject-turn --reassign')}`);
|
|
141
|
+
console.log(` ${chalk.dim(' or:')} ${chalk.cyan('agentxchain accept-turn --resolution human_merge')}`);
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
console.log(` ${chalk.dim('Turn:')} ${chalk.yellow('No active turn')}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Queued phase/completion requests
|
|
148
|
+
if (state?.queued_phase_transition) {
|
|
149
|
+
const qt = state.queued_phase_transition;
|
|
150
|
+
console.log('');
|
|
151
|
+
console.log(` ${chalk.dim('Queued:')} Phase transition ${formatGovernedPhase(qt.from)} → ${formatGovernedPhase(qt.to)} (awaiting drain)`);
|
|
152
|
+
}
|
|
153
|
+
if (state?.queued_run_completion) {
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log(` ${chalk.dim('Queued:')} Run completion (awaiting drain)`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Per-turn budget reservations
|
|
159
|
+
if (state?.budget_reservations && Object.keys(state.budget_reservations).length > 0) {
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log(` ${chalk.dim('Budget reservations:')}`);
|
|
162
|
+
for (const [turnId, reservation] of Object.entries(state.budget_reservations)) {
|
|
163
|
+
const amt = reservation.reserved_usd != null ? `$${formatUsd(reservation.reserved_usd)}` : '(unknown)';
|
|
164
|
+
console.log(` ${chalk.dim('●')} ${turnId}: ${amt}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (state?.blocked_on) {
|
|
169
|
+
console.log('');
|
|
170
|
+
if (state.status === 'blocked') {
|
|
171
|
+
const recovery = deriveRecoveryDescriptor(state);
|
|
172
|
+
const detail = recovery?.detail || state.blocked_on;
|
|
173
|
+
console.log(` ${chalk.dim('Blocked:')} ${chalk.red.bold('BLOCKED')} — ${detail}`);
|
|
174
|
+
} else if (state.blocked_on.startsWith('human_approval:')) {
|
|
175
|
+
const gate = state.blocked_on.replace('human_approval:', '');
|
|
176
|
+
console.log(` ${chalk.dim('Blocked:')} ${chalk.yellow('AWAITING HUMAN APPROVAL')} — gate: ${chalk.bold(gate)}`);
|
|
177
|
+
} else {
|
|
178
|
+
console.log(` ${chalk.dim('Blocked:')} ${chalk.red(state.blocked_on)}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const recovery = deriveRecoveryDescriptor(state);
|
|
183
|
+
if (recovery) {
|
|
184
|
+
console.log('');
|
|
185
|
+
console.log(` ${chalk.dim('Reason:')} ${recovery.typed_reason}`);
|
|
186
|
+
console.log(` ${chalk.dim('Owner:')} ${recovery.owner}`);
|
|
187
|
+
console.log(` ${chalk.dim('Action:')} ${recovery.recovery_action}`);
|
|
188
|
+
console.log(` ${chalk.dim('Turn:')} ${recovery.turn_retained ? 'retained' : 'cleared'}`);
|
|
189
|
+
if (recovery.detail) {
|
|
190
|
+
console.log(` ${chalk.dim('Detail:')} ${recovery.detail}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (state?.pending_phase_transition) {
|
|
195
|
+
const pt = state.pending_phase_transition;
|
|
196
|
+
console.log(` ${chalk.dim('Pending:')} ${formatGovernedPhase(pt.from)} → ${formatGovernedPhase(pt.to)}`);
|
|
197
|
+
console.log(` ${chalk.dim('Gate:')} ${pt.gate} (requires human approval)`);
|
|
198
|
+
console.log(` ${chalk.dim('Action:')} Run ${chalk.cyan('agentxchain approve-transition')} to advance`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (state?.pending_run_completion) {
|
|
202
|
+
const pc = state.pending_run_completion;
|
|
203
|
+
console.log(` ${chalk.dim('Pending:')} ${chalk.bold('Run Completion')}`);
|
|
204
|
+
console.log(` ${chalk.dim('Gate:')} ${pc.gate} (requires human approval)`);
|
|
205
|
+
console.log(` ${chalk.dim('Action:')} Run ${chalk.cyan('agentxchain approve-completion')} to finalize`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (state?.status === 'completed') {
|
|
209
|
+
console.log('');
|
|
210
|
+
console.log(` ${chalk.green.bold('✓ Run completed')}`);
|
|
211
|
+
if (state.completed_at) {
|
|
212
|
+
console.log(` ${chalk.dim('Completed:')} ${state.completed_at}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (state?.phase_gate_status) {
|
|
217
|
+
console.log('');
|
|
218
|
+
console.log(` ${chalk.dim('Gates:')}`);
|
|
219
|
+
for (const [gate, status] of Object.entries(state.phase_gate_status)) {
|
|
220
|
+
const icon = status === 'passed' ? chalk.green('✓') : chalk.dim('○');
|
|
221
|
+
console.log(` ${icon} ${gate}: ${status}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (state?.budget_status) {
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(` ${chalk.dim('Budget:')} spent $${formatUsd(state.budget_status.spent_usd)} / remaining $${formatUsd(state.budget_status.remaining_usd)}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log(` ${chalk.dim('Roles:')} ${Object.keys(config.roles).length}`);
|
|
232
|
+
for (const [id, role] of Object.entries(config.roles)) {
|
|
233
|
+
const isAssigned = Object.values(getActiveTurns(state)).some(turn => turn.assigned_role === id);
|
|
234
|
+
const marker = isAssigned ? chalk.yellow('●') : chalk.dim('○');
|
|
235
|
+
const label = isAssigned ? chalk.bold(id) : id;
|
|
236
|
+
console.log(` ${marker} ${label} — ${role.title} [${role.write_authority}]`);
|
|
237
|
+
}
|
|
238
|
+
console.log('');
|
|
239
|
+
}
|
|
240
|
+
|
|
67
241
|
function formatPhase(phase) {
|
|
68
242
|
const colors = { discovery: chalk.blue, build: chalk.green, qa: chalk.yellow, deploy: chalk.magenta, blocked: chalk.red };
|
|
69
243
|
return (colors[phase] || chalk.white)(phase);
|
|
70
244
|
}
|
|
71
245
|
|
|
246
|
+
function formatGovernedPhase(phase) {
|
|
247
|
+
const colors = { planning: chalk.blue, implementation: chalk.green, qa: chalk.yellow, paused: chalk.magenta, failed: chalk.red };
|
|
248
|
+
return (colors[phase] || chalk.white)(phase);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function formatRunStatus(status) {
|
|
252
|
+
if (status === 'blocked') return chalk.red.bold('BLOCKED');
|
|
253
|
+
if (status === 'paused') return chalk.yellow.bold('PAUSED');
|
|
254
|
+
if (status === 'completed') return chalk.green.bold('COMPLETED');
|
|
255
|
+
if (status === 'active') return chalk.cyan('active');
|
|
256
|
+
if (status === 'idle') return chalk.dim('idle');
|
|
257
|
+
return status || chalk.dim('unknown');
|
|
258
|
+
}
|
|
259
|
+
|
|
72
260
|
function timeSince(iso) {
|
|
73
261
|
const ms = Date.now() - new Date(iso).getTime();
|
|
74
262
|
const sec = Math.floor(ms / 1000);
|
|
@@ -78,3 +266,8 @@ function timeSince(iso) {
|
|
|
78
266
|
const hr = Math.floor(min / 60);
|
|
79
267
|
return `${hr}h ${min % 60}m`;
|
|
80
268
|
}
|
|
269
|
+
|
|
270
|
+
function formatUsd(value) {
|
|
271
|
+
if (typeof value !== 'number' || Number.isNaN(value)) return '0.00';
|
|
272
|
+
return value.toFixed(2);
|
|
273
|
+
}
|