agentxchain 2.35.0 → 2.36.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/dashboard/app.js
CHANGED
|
@@ -16,7 +16,7 @@ import { render as renderBlockers } from './components/blockers.js';
|
|
|
16
16
|
import { render as renderArtifacts } from './components/artifacts.js';
|
|
17
17
|
|
|
18
18
|
const VIEWS = {
|
|
19
|
-
timeline: { fetch: ['state', 'history', 'audit', 'annotations'], render: renderTimeline },
|
|
19
|
+
timeline: { fetch: ['state', 'continuity', 'history', 'audit', 'annotations'], render: renderTimeline },
|
|
20
20
|
ledger: { fetch: ['ledger'], render: renderLedger },
|
|
21
21
|
hooks: { fetch: ['audit', 'annotations'], render: renderHooks },
|
|
22
22
|
blocked: { fetch: ['state', 'audit', 'coordinatorState', 'coordinatorAudit'], render: renderBlocked },
|
|
@@ -29,6 +29,7 @@ const VIEWS = {
|
|
|
29
29
|
|
|
30
30
|
const API_MAP = {
|
|
31
31
|
state: '/api/state',
|
|
32
|
+
continuity: '/api/continuity',
|
|
32
33
|
history: '/api/history',
|
|
33
34
|
ledger: '/api/ledger',
|
|
34
35
|
audit: '/api/hooks/audit',
|
|
@@ -132,7 +132,41 @@ function renderTurnDetailPanel(turnId, annotations, audit) {
|
|
|
132
132
|
return html;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
function renderContinuityPanel(continuity) {
|
|
136
|
+
if (!continuity) return '';
|
|
137
|
+
|
|
138
|
+
const checkpoint = continuity.checkpoint;
|
|
139
|
+
const checkpointSummary = checkpoint?.last_checkpoint_at
|
|
140
|
+
? `${checkpoint.checkpoint_reason || 'unknown'} at ${checkpoint.last_checkpoint_at}`
|
|
141
|
+
: (checkpoint?.checkpoint_reason || 'No session checkpoint recorded');
|
|
142
|
+
|
|
143
|
+
let html = `<div class="section continuity-section"><h3>Continuity</h3><div class="turn-card">`;
|
|
144
|
+
|
|
145
|
+
if (checkpoint) {
|
|
146
|
+
html += `<div class="turn-detail"><span class="detail-label">Session:</span> <span class="mono">${esc(checkpoint.session_id || 'unknown')}</span></div>`;
|
|
147
|
+
html += `<div class="turn-detail"><span class="detail-label">Checkpoint:</span> ${esc(checkpointSummary)}</div>`;
|
|
148
|
+
html += `<div class="turn-detail"><span class="detail-label">Last turn:</span> <span class="mono">${esc(checkpoint.last_turn_id || 'none')}</span></div>`;
|
|
149
|
+
html += `<div class="turn-detail"><span class="detail-label">Last role:</span> ${esc(checkpoint.last_role || 'unknown')}</div>`;
|
|
150
|
+
if (continuity.stale_checkpoint) {
|
|
151
|
+
html += `<div class="turn-detail risks"><span class="detail-label">Warning:</span> checkpoint tracks <span class="mono">${esc(checkpoint.run_id || 'unknown')}</span>, but state.json remains source of truth.</div>`;
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
html += `<div class="turn-detail"><span class="detail-label">Checkpoint:</span> No session checkpoint recorded</div>`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (continuity.restart_recommended) {
|
|
158
|
+
html += `<div class="turn-detail"><span class="detail-label">Restart:</span> <span class="mono">agentxchain restart</span></div>`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (continuity.recovery_report_path) {
|
|
162
|
+
html += `<div class="turn-detail"><span class="detail-label">Report:</span> <span class="mono">${esc(continuity.recovery_report_path)}</span></div>`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
html += `</div></div>`;
|
|
166
|
+
return html;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function render({ state, continuity, history, annotations, audit }) {
|
|
136
170
|
if (!state) {
|
|
137
171
|
return `<div class="placeholder"><h2>No Run</h2><p>No governed run found. Start one with <code class="mono">agentxchain init --governed</code></p></div>`;
|
|
138
172
|
}
|
|
@@ -152,6 +186,8 @@ export function render({ state, history, annotations, audit }) {
|
|
|
152
186
|
</div>
|
|
153
187
|
</div>`;
|
|
154
188
|
|
|
189
|
+
html += renderContinuityPanel(continuity);
|
|
190
|
+
|
|
155
191
|
// Active turns
|
|
156
192
|
if (activeTurns.length > 0) {
|
|
157
193
|
html += `<div class="section"><h3>Active Turns</h3><div class="turn-list">`;
|
package/package.json
CHANGED
package/scripts/release-bump.sh
CHANGED
|
@@ -56,6 +56,8 @@ ALLOWED_RELEASE_PATHS=(
|
|
|
56
56
|
".agentxchain-conformance/capabilities.json"
|
|
57
57
|
"website-v2/docs/protocol-implementor-guide.mdx"
|
|
58
58
|
".planning/LAUNCH_EVIDENCE_REPORT.md"
|
|
59
|
+
"cli/homebrew/agentxchain.rb"
|
|
60
|
+
"cli/homebrew/README.md"
|
|
59
61
|
)
|
|
60
62
|
|
|
61
63
|
is_allowed_release_path() {
|
|
@@ -162,6 +164,25 @@ if ! grep -qE "^# Launch Evidence Report — AgentXchain v${ESCAPED_VERSION}" "$
|
|
|
162
164
|
SURFACE_ERRORS+=("LAUNCH_EVIDENCE_REPORT.md title does not carry v${TARGET_VERSION}")
|
|
163
165
|
fi
|
|
164
166
|
|
|
167
|
+
# 4h. Homebrew mirror formula version
|
|
168
|
+
HOMEBREW_MIRROR="${REPO_ROOT}/cli/homebrew/agentxchain.rb"
|
|
169
|
+
if [[ -f "$HOMEBREW_MIRROR" ]]; then
|
|
170
|
+
if ! grep -q "agentxchain-${TARGET_VERSION}\.tgz" "$HOMEBREW_MIRROR" 2>/dev/null; then
|
|
171
|
+
SURFACE_ERRORS+=("homebrew mirror formula does not reference agentxchain-${TARGET_VERSION}.tgz")
|
|
172
|
+
fi
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# 4i. Homebrew mirror maintainer README version
|
|
176
|
+
HOMEBREW_MIRROR_README="${REPO_ROOT}/cli/homebrew/README.md"
|
|
177
|
+
if [[ -f "$HOMEBREW_MIRROR_README" ]]; then
|
|
178
|
+
if ! grep -q -- "- version: \`${TARGET_VERSION}\`" "$HOMEBREW_MIRROR_README" 2>/dev/null; then
|
|
179
|
+
SURFACE_ERRORS+=("homebrew mirror README does not declare version ${TARGET_VERSION}")
|
|
180
|
+
fi
|
|
181
|
+
if ! grep -q "agentxchain-${TARGET_VERSION}\.tgz" "$HOMEBREW_MIRROR_README" 2>/dev/null; then
|
|
182
|
+
SURFACE_ERRORS+=("homebrew mirror README does not reference agentxchain-${TARGET_VERSION}.tgz")
|
|
183
|
+
fi
|
|
184
|
+
fi
|
|
185
|
+
|
|
165
186
|
if [[ "${#SURFACE_ERRORS[@]}" -gt 0 ]]; then
|
|
166
187
|
echo "FAIL: ${#SURFACE_ERRORS[@]} version-surface(s) not aligned to ${TARGET_VERSION}:" >&2
|
|
167
188
|
printf ' - %s\n' "${SURFACE_ERRORS[@]}" >&2
|
|
@@ -170,7 +191,7 @@ if [[ "${#SURFACE_ERRORS[@]}" -gt 0 ]]; then
|
|
|
170
191
|
echo "create release identity when governed surfaces are stale." >&2
|
|
171
192
|
exit 1
|
|
172
193
|
fi
|
|
173
|
-
echo " OK: all
|
|
194
|
+
echo " OK: all 10 governed version surfaces reference ${TARGET_VERSION}"
|
|
174
195
|
|
|
175
196
|
# 5. Update version files (no git operations)
|
|
176
197
|
echo "[5/8] Updating version files..."
|
package/src/commands/status.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
1
|
import chalk from 'chalk';
|
|
4
2
|
import { loadConfig, loadLock, loadProjectContext, loadProjectState, loadState } from '../lib/config.js';
|
|
5
3
|
import { deriveRecoveryDescriptor } from '../lib/blocked-state.js';
|
|
6
4
|
import { getActiveTurn, getActiveTurnCount, getActiveTurns } from '../lib/governed-state.js';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
const SESSION_RECOVERY_PATH = '.agentxchain/SESSION_RECOVERY.md';
|
|
5
|
+
import { getContinuityStatus } from '../lib/continuity-status.js';
|
|
10
6
|
|
|
11
7
|
export async function statusCommand(opts) {
|
|
12
8
|
const context = loadProjectContext();
|
|
@@ -247,28 +243,6 @@ function renderGovernedStatus(context, opts) {
|
|
|
247
243
|
console.log('');
|
|
248
244
|
}
|
|
249
245
|
|
|
250
|
-
function getContinuityStatus(root, state) {
|
|
251
|
-
const checkpoint = readSessionCheckpoint(root);
|
|
252
|
-
const recoveryReportPath = existsSync(join(root, SESSION_RECOVERY_PATH))
|
|
253
|
-
? SESSION_RECOVERY_PATH
|
|
254
|
-
: null;
|
|
255
|
-
|
|
256
|
-
if (!checkpoint && !recoveryReportPath) return null;
|
|
257
|
-
|
|
258
|
-
const staleCheckpoint = !!(
|
|
259
|
-
checkpoint?.run_id
|
|
260
|
-
&& state?.run_id
|
|
261
|
-
&& checkpoint.run_id !== state.run_id
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
checkpoint,
|
|
266
|
-
stale_checkpoint: staleCheckpoint,
|
|
267
|
-
recovery_report_path: recoveryReportPath,
|
|
268
|
-
restart_recommended: !!state && !['blocked', 'completed', 'failed'].includes(state.status),
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
246
|
function renderContinuityStatus(continuity, state) {
|
|
273
247
|
if (!continuity) return;
|
|
274
248
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { readSessionCheckpoint } from './session-checkpoint.js';
|
|
4
|
+
|
|
5
|
+
export const SESSION_RECOVERY_PATH = '.agentxchain/SESSION_RECOVERY.md';
|
|
6
|
+
|
|
7
|
+
export function getContinuityStatus(root, state) {
|
|
8
|
+
const checkpoint = readSessionCheckpoint(root);
|
|
9
|
+
const recoveryReportPath = existsSync(join(root, SESSION_RECOVERY_PATH))
|
|
10
|
+
? SESSION_RECOVERY_PATH
|
|
11
|
+
: null;
|
|
12
|
+
|
|
13
|
+
if (!checkpoint && !recoveryReportPath) return null;
|
|
14
|
+
|
|
15
|
+
const staleCheckpoint = !!(
|
|
16
|
+
checkpoint?.run_id
|
|
17
|
+
&& state?.run_id
|
|
18
|
+
&& checkpoint.run_id !== state.run_id
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
checkpoint,
|
|
23
|
+
stale_checkpoint: staleCheckpoint,
|
|
24
|
+
recovery_report_path: recoveryReportPath,
|
|
25
|
+
restart_recommended: !!state && !['blocked', 'completed', 'failed'].includes(state.status),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { readFileSync, existsSync } from 'fs';
|
|
10
|
-
import { join, normalize } from 'path';
|
|
10
|
+
import { join, normalize, resolve } from 'path';
|
|
11
|
+
import { getContinuityStatus } from '../continuity-status.js';
|
|
11
12
|
|
|
12
13
|
const STATE_FILE = 'state.json';
|
|
13
14
|
const SESSION_FILE = 'session.json';
|
|
15
|
+
const SESSION_RECOVERY_FILE = 'SESSION_RECOVERY.md';
|
|
14
16
|
const HISTORY_FILE = 'history.jsonl';
|
|
15
17
|
const LEDGER_FILE = 'decision-ledger.jsonl';
|
|
16
18
|
const HOOK_AUDIT_FILE = 'hook-audit.jsonl';
|
|
@@ -44,6 +46,7 @@ export const RESOURCE_MAP = {
|
|
|
44
46
|
export const FILE_TO_RESOURCE = Object.fromEntries(
|
|
45
47
|
Object.entries(RESOURCE_MAP).map(([resource, file]) => [normalizeRelativePath(file), resource])
|
|
46
48
|
);
|
|
49
|
+
FILE_TO_RESOURCE[normalizeRelativePath(SESSION_RECOVERY_FILE)] = '/api/continuity';
|
|
47
50
|
|
|
48
51
|
export const WATCH_DIRECTORIES = [
|
|
49
52
|
'',
|
|
@@ -86,6 +89,13 @@ export function readJsonlFile(agentxchainDir, filename) {
|
|
|
86
89
|
* Read a resource by its API path. Returns { data, format } or null.
|
|
87
90
|
*/
|
|
88
91
|
export function readResource(agentxchainDir, resourcePath) {
|
|
92
|
+
if (resourcePath === '/api/continuity') {
|
|
93
|
+
const root = resolve(agentxchainDir, '..');
|
|
94
|
+
const state = readJsonFile(agentxchainDir, STATE_FILE);
|
|
95
|
+
const data = getContinuityStatus(root, state);
|
|
96
|
+
return { data, format: 'json' };
|
|
97
|
+
}
|
|
98
|
+
|
|
89
99
|
const filename = RESOURCE_MAP[resourcePath];
|
|
90
100
|
if (!filename) return null;
|
|
91
101
|
|