agentxchain 2.56.0 → 2.57.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/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -976,6 +976,11 @@ async function initGoverned(opts) {
|
|
|
976
976
|
console.log(` ${chalk.bold('agentxchain step')} ${chalk.dim('# run the first governed turn')}`);
|
|
977
977
|
console.log(` ${chalk.bold('agentxchain status')} ${chalk.dim('# inspect phase, gate, and turn state')}`);
|
|
978
978
|
console.log('');
|
|
979
|
+
if (!config?.project?.goal) {
|
|
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')}`);
|
|
982
|
+
console.log('');
|
|
983
|
+
}
|
|
979
984
|
console.log(` ${chalk.dim('Guide:')} https://agentxchain.dev/docs/getting-started`);
|
|
980
985
|
console.log('');
|
|
981
986
|
}
|
|
@@ -57,6 +57,7 @@ export function buildInheritedContext(root, parentRunId) {
|
|
|
57
57
|
parent_phases_completed: parentEntry.phases_completed || [],
|
|
58
58
|
parent_roles_used: parentEntry.roles_used || [],
|
|
59
59
|
parent_blocked_reason: parentEntry.blocked_reason || null,
|
|
60
|
+
parent_retrospective: parentEntry.retrospective || null,
|
|
60
61
|
recent_decisions: recentDecisions,
|
|
61
62
|
recent_accepted_turns: acceptedTurns,
|
|
62
63
|
inherited_at: new Date().toISOString(),
|
|
@@ -93,6 +94,20 @@ export function renderInheritedContextMarkdown(inheritedContext, compact = false
|
|
|
93
94
|
}
|
|
94
95
|
lines.push('');
|
|
95
96
|
|
|
97
|
+
if (!compact && inheritedContext.parent_retrospective) {
|
|
98
|
+
lines.push('### Parent Retrospective');
|
|
99
|
+
lines.push('');
|
|
100
|
+
lines.push(`- **Headline:** ${inheritedContext.parent_retrospective.headline || 'n/a'}`);
|
|
101
|
+
lines.push(`- **Terminal reason:** ${inheritedContext.parent_retrospective.terminal_reason || 'unknown'}`);
|
|
102
|
+
if (inheritedContext.parent_retrospective.next_operator_action) {
|
|
103
|
+
lines.push(`- **Next operator action:** ${inheritedContext.parent_retrospective.next_operator_action}`);
|
|
104
|
+
}
|
|
105
|
+
if (inheritedContext.parent_retrospective.follow_on_hint) {
|
|
106
|
+
lines.push(`- **Follow-on hint:** ${inheritedContext.parent_retrospective.follow_on_hint}`);
|
|
107
|
+
}
|
|
108
|
+
lines.push('');
|
|
109
|
+
}
|
|
110
|
+
|
|
96
111
|
if (!compact && inheritedContext.recent_decisions?.length) {
|
|
97
112
|
lines.push('### Recent Decisions');
|
|
98
113
|
lines.push('');
|
|
@@ -153,6 +168,7 @@ function buildPartialContext(parentRunId, parentEntry, decisions, turns, warning
|
|
|
153
168
|
parent_phases_completed: parentEntry?.phases_completed || [],
|
|
154
169
|
parent_roles_used: parentEntry?.roles_used || [],
|
|
155
170
|
parent_blocked_reason: parentEntry?.blocked_reason || null,
|
|
171
|
+
parent_retrospective: parentEntry?.retrospective || null,
|
|
156
172
|
recent_decisions: decisions,
|
|
157
173
|
recent_accepted_turns: turns,
|
|
158
174
|
inherited_at: new Date().toISOString(),
|
package/src/lib/run-history.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { readFileSync, appendFileSync, existsSync, mkdirSync } from 'fs';
|
|
11
11
|
import { join, dirname } from 'path';
|
|
12
12
|
import { normalizeRunProvenance } from './run-provenance.js';
|
|
13
|
+
import { deriveRecoveryDescriptor } from './blocked-state.js';
|
|
13
14
|
|
|
14
15
|
const RUN_HISTORY_PATH = '.agentxchain/run-history.jsonl';
|
|
15
16
|
const HISTORY_PATH = '.agentxchain/history.jsonl';
|
|
@@ -83,6 +84,12 @@ export function recordRunHistory(root, state, config, status) {
|
|
|
83
84
|
connector_used: connectorUsed,
|
|
84
85
|
model_used: modelUsed,
|
|
85
86
|
provenance: normalizeRunProvenance(state?.provenance),
|
|
87
|
+
retrospective: buildRunRetrospective({
|
|
88
|
+
state,
|
|
89
|
+
config,
|
|
90
|
+
status,
|
|
91
|
+
historyEntries,
|
|
92
|
+
}),
|
|
86
93
|
inheritance_snapshot: {
|
|
87
94
|
recent_decisions: buildRecentDecisionSnapshot(ledgerEntries),
|
|
88
95
|
recent_accepted_turns: buildRecentAcceptedTurnSnapshot(historyEntries),
|
|
@@ -300,7 +307,7 @@ function buildRecentDecisionSnapshot(entries) {
|
|
|
300
307
|
|
|
301
308
|
function buildRecentAcceptedTurnSnapshot(entries) {
|
|
302
309
|
return entries
|
|
303
|
-
.filter((entry) => entry
|
|
310
|
+
.filter((entry) => entry?.status !== 'rejected' && typeof entry?.turn_id === 'string' && typeof entry?.role === 'string')
|
|
304
311
|
.slice(-MAX_INHERITANCE_TURNS)
|
|
305
312
|
.map((entry) => ({
|
|
306
313
|
turn_id: entry.turn_id || null,
|
|
@@ -309,3 +316,57 @@ function buildRecentAcceptedTurnSnapshot(entries) {
|
|
|
309
316
|
phase: entry.phase || null,
|
|
310
317
|
}));
|
|
311
318
|
}
|
|
319
|
+
|
|
320
|
+
function buildRunRetrospective({ state, config, status, historyEntries }) {
|
|
321
|
+
const acceptedTurns = historyEntries.filter((entry) => entry && typeof entry === 'object');
|
|
322
|
+
const lastAcceptedTurn = acceptedTurns[acceptedTurns.length - 1] || null;
|
|
323
|
+
const recovery = status === 'blocked'
|
|
324
|
+
? deriveRecoveryDescriptor(state, config)
|
|
325
|
+
: null;
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
headline: buildRetrospectiveHeadline({ status, lastAcceptedTurn, recovery, acceptedTurns }),
|
|
329
|
+
terminal_reason: status === 'completed'
|
|
330
|
+
? 'completed'
|
|
331
|
+
: recovery?.typed_reason || 'blocked',
|
|
332
|
+
next_operator_action: status === 'blocked'
|
|
333
|
+
? recovery?.recovery_action || null
|
|
334
|
+
: null,
|
|
335
|
+
follow_on_hint: status === 'completed'
|
|
336
|
+
? buildFollowOnHint(state, lastAcceptedTurn)
|
|
337
|
+
: null,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function buildRetrospectiveHeadline({ status, lastAcceptedTurn, recovery, acceptedTurns }) {
|
|
342
|
+
if (status === 'blocked') {
|
|
343
|
+
if (typeof recovery?.detail === 'string' && recovery.detail.trim()) {
|
|
344
|
+
return recovery.detail.trim();
|
|
345
|
+
}
|
|
346
|
+
if (typeof lastAcceptedTurn?.summary === 'string' && lastAcceptedTurn.summary.trim()) {
|
|
347
|
+
return `Run blocked after: ${lastAcceptedTurn.summary.trim()}`;
|
|
348
|
+
}
|
|
349
|
+
return 'Run blocked.';
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (typeof lastAcceptedTurn?.summary === 'string' && lastAcceptedTurn.summary.trim()) {
|
|
353
|
+
return lastAcceptedTurn.summary.trim();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return `Run completed after ${acceptedTurns.length} accepted turn(s).`;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function buildFollowOnHint(state, lastAcceptedTurn) {
|
|
360
|
+
const runId = state?.run_id;
|
|
361
|
+
if (typeof runId !== 'string' || !runId.trim()) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const base = `If more scope remains, start a child run with \`agentxchain run --continue-from ${runId} --inherit-context\`.`;
|
|
366
|
+
const suggestedRole = lastAcceptedTurn?.proposed_next_role;
|
|
367
|
+
if (typeof suggestedRole === 'string' && suggestedRole.trim() && suggestedRole !== 'human') {
|
|
368
|
+
return `${base} The last accepted turn suggested \`${suggestedRole}\` next.`;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return base;
|
|
372
|
+
}
|