scripts/verify-admin-ui.mjs
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env node
/**
* Prove the /admin configuration loop without Slack network access:
* 1. mount the real Hono admin routes against an in-memory SQLite store,
* 2. establish an exact Slack-bound Owner and authenticate as that principal,
* 3. create two Agents and publish both to one Channel through the additive grant API,
* 4. prove the Channel inventory exposes both grants without one replacing the other,
* 5. prove the one-body Agent memory contract and optimistic edits while the
* retired Channel/file/history memory surfaces remain unavailable.
*/
import {
assertNodeVersion,
loadTsModule,
} from './lib/offline-harness.mjs';
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const ADMIN_ORIGIN = 'https://admin-ui.example';
const WORKSPACE_ID = 'TADMINUI1';
const CHANNEL_ID = 'C_ADMIN_UI';
const CHANNEL_LABEL = 'eng-releases';
const AGENT_ID = 'agent_admin_ui';
const MODEL_SPECIFIER = 'local-stub/admin-ui-model';
const ROUTINE_ID = 'routine_admin_ui_release';
const results = [];
function record(name, passed, detail) {
results.push({ name, passed, detail });
console.log(`${passed ? 'PASS' : 'FAIL'} ${name}${detail ? ` - ${detail}` : ''}`);
}
async function adminJson(app, path, options = {}) {
const response = await app.request(path.startsWith('http') ? path : `${ADMIN_ORIGIN}${path}`, {
...options,
headers: {
origin: ADMIN_ORIGIN,
'sec-fetch-site': 'same-origin',
...(options.headers ?? {}),
},
});
const text = await response.text();
let body;
try {
body = text ? JSON.parse(text) : undefined;
} catch {
body = text;
}
return { status: response.status, body };
}
async function adminBody(app, method, path, body) {
return adminJson(app, path, {
method,
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
});
}
let store;
let settings;
let memory;
let routines;
let usage;
let work;
let identity;
try {
console.log(`node ${assertNodeVersion()}`);
const { Hono } = await import('hono');
const { createAdminRoutes } = await loadTsModule('src/admin/routes.ts');
const { SqliteConfigStore } = await loadTsModule('src/config/store.ts');
const { SqliteSettingsStore } = await loadTsModule('src/config/settings-store.ts');
const { SqliteMemoryStateStore } = await loadTsModule('src/memory/store.ts');
const { agentRoutineDeletion, SqliteRoutineStore } = await loadTsModule('src/routines/store.ts');
const { RoutineService } = await loadTsModule('src/routines/service.ts');
const { SqliteUsageStore } = await loadTsModule('src/usage/store.ts');
const { SqliteWorkStore } = await loadTsModule('src/work/store.ts');
const { SqliteIdentityStore } = await loadTsModule('src/identity/store.ts');
const statePath = join(mkdtempSync(join(tmpdir(), 'chickpea-admin-ui-')), 'state.db');
store = new SqliteConfigStore(statePath, agentRoutineDeletion, { agents: [], grants: [] });
settings = new SqliteSettingsStore(statePath);
memory = new SqliteMemoryStateStore(statePath);
routines = new SqliteRoutineStore(statePath);
usage = new SqliteUsageStore(statePath);
work = new SqliteWorkStore(statePath);
identity = new SqliteIdentityStore(statePath);
const ownerOperation = await identity.createAuthOperation({
id: 'first_owner_admin_ui', kind: 'first_owner_claim',
expectedSlackTeamId: 'TADMINUI1', expectedSlackUserId: 'UADMINUI1',
chickpeaRole: 'owner', capabilityHash: 'a'.repeat(64),
expiresAt: Date.now() + 60_000,
});
await identity.createOwnerClaim({
operationId: ownerOperation.id,
slackTeamId: 'TADMINUI1', slackUserId: 'UADMINUI1',
});
await identity.advanceAuthOperation({
operationId: ownerOperation.id, capabilityHash: 'a'.repeat(64), step: 1,
betterAuthUserId: 'ba_user_admin_ui',
betterAuthOrganizationId: '11111111-1111-4111-8111-111111111111',
betterAuthMembershipId: 'ba_member_admin_ui',
});
const owner = await identity.claimOwner({
operationId: ownerOperation.id, organizationId: 'org_oss',
slackTeamId: 'TADMINUI1', slackUserId: 'UADMINUI1', displayName: 'Admin UI Owner',
betterAuthUserId: 'ba_user_admin_ui', betterAuthMembershipId: 'ba_member_admin_ui',
});
await identity.updateOrganizationAuth({
organizationId: owner.membership.organizationId,
authMode: 'slack_active', canonicalAdminOrigin: ADMIN_ORIGIN,
});
const authControl = await identity.getAuthControl();
await identity.updateAuthControl({
expectedRevision: authControl.revision,
canonicalAdminOrigin: ADMIN_ORIGIN,
});
const usageNow = Date.now();
await work.admitShadowRun({
work: {
id: 'work_admin_ui_release', kind: 'conversation', maximumSensitivity: 'public',
createdAt: usageNow - 10_000,
},
binding: {
id: 'binding_admin_ui_release', workId: 'work_admin_ui_release', adapterKind: 'slack',
externalAccountId: 'account_admin_ui_release',
externalConversationId: 'conversation_admin_ui_release', generation: 1,
sourceVisibility: 'public', configMode: 'frozen_on_open',
orderingKey: 'ordering_admin_ui_release', createdAt: usageNow - 10_000,
},
run: {
id: 'run_admin_ui_release', workId: 'work_admin_ui_release',
bindingId: 'binding_admin_ui_release', kind: 'interactive',
triggerKind: 'admin_ui_verifier', triggerRef: 'trigger_admin_ui_release',
dedupeKey: 'dedupe_admin_ui_release', actorTrustTier: 'system',
effectiveCapabilityDigest: 'b'.repeat(64), executionAuthority: 'legacy',
coordinatorKind: 'interactive', authorityEpoch: 1, createdAt: usageNow - 10_000,
},
safeConfig: {
schemaVersion: 1, profileId: AGENT_ID, configuredModel: MODEL_SPECIFIER,
snapshotDigest: 'a'.repeat(64), capabilityDigest: 'b'.repeat(64),
skillNames: [], connectionIds: [], repositoryIds: [], memoryMode: 'public',
ceilings: { maxModelAttempts: 3, maxToolCalls: 20, maxActionAttempts: 0, timeoutMs: 120_000 },
},
triggerContent: { sensitivity: 'public', body: 'Admin UI Run trigger' },
auditEventId: 'audit_admin_ui_release',
auditIdempotencyKey: 'auditkey_admin_ui_release',
});
await usage.admitOperation({
operationId: 'usage_admin_ui_release',
runId: 'run_admin_ui_release',
operationKind: 'interactive_turn',
sourceId: 'slack:C_ADMIN_UI:usage',
startedAt: usageNow - 10_000,
installationId: 'admin-ui-installation',
workspaceId: WORKSPACE_ID,
agentId: AGENT_ID,
agentLabel: 'Admin UI Agent',
channelId: CHANNEL_ID,
channelLabel: CHANNEL_LABEL,
conversationKind: 'named_channel',
requestedProvider: 'openai',
requestedModel: 'gpt-4.1-mini',
credentialRefId: 'cred_openai_admin_ui',
credentialVersion: 1,
});
await usage.recordTerminal({
operationId: 'usage_admin_ui_release',
executionId: 'usage_exec_admin_ui_release',
status: 'completed',
finishedAt: usageNow - 5_000,
observedAt: usageNow - 5_000,
providerRoute: 'openai',
requestedProvider: 'openai',
requestedModel: 'gpt-4.1-mini',
returnedProvider: 'openai',
returnedModel: 'gpt-4.1-mini',
credentialRefId: 'cred_openai_admin_ui',
credentialVersion: 1,
usageCompleteness: 'complete',
inputTokens: 1_000,
outputTokens: 250,
totalTokens: 1_250,
usageUnknownReason: null,
estimateCompleteness: 'complete',
estimateAmountMicros: 800,
estimateCurrency: 'USD',
priceVersionId: 'openai_2026-07-28',
priceUnknownReason: null,
});
const routineService = new RoutineService(routines, {
now: Date.now,
routineId: () => ROUTINE_ID,
});
const routine = await routineService.save({
action: 'create',
actorId: 'U_ADMIN_UI_MEMBER',
workspaceId: WORKSPACE_ID,
channelId: CHANNEL_ID,
definition: {
name: 'Release readiness check',
description: 'Checks launch blockers every weekday.',
taskText: 'Review launch blockers and make safe progress.',
triggerKind: 'schedule',
scheduleInput: '0 9 * * 1-5',
scheduleJson: '{"version":1,"kind":"cron","expression":"0 9 * * 1-5"}',
timezone: 'America/Los_Angeles',
outputPolicy: 'post',
authorityMode: 'live_channel_v1',
},
nextRunAt: Date.now() + 3_600_000,
projectedDailyStarts: 5,
reservations: [{ windowStart: Date.now() + 3_600_000, count: 1 }],
sourceVisibility: 'public',
}, 'admin-ui-routine-create');
await routines.createOccurrence({
runId: 'rrun_admin_ui_release',
idempotencyKey: 'admin-ui-routine-run',
routineId: routine.id,
routineVersion: routine.version,
scheduledFor: Date.now(),
triggerSource: 'run_now',
requestedBy: 'U_ADMIN_UI_MEMBER',
queuedAt: Date.now(),
deadlineAt: Date.now() + 900_000,
});
const app = new Hono();
const userGroups = [];
const slackChannel = {
id: CHANNEL_ID, name: CHANNEL_LABEL, private: false, member: true, archived: false,
};
const slackTransport = {
mode: 'direct',
async lookupMember(userId) {
return { id: userId, teamId: WORKSPACE_ID, deleted: false, bot: false, appUser: false, restricted: false, ultraRestricted: false, stranger: false };
},
async lookupChannel() { return slackChannel; },
async listChannels() { return { channels: [slackChannel], truncated: false }; },
async channelHasMember() { return true; },
async openDirectConversation(userId) { return { ...slackChannel, id: `D_${userId}`, private: true }; },
async joinPublicChannel() { return slackChannel; },
async listUserGroups() { return [...userGroups]; },
async createUserGroup(input) {
const group = { id: `S${userGroups.length + 1}`, ...input, disabled: false, updatedAt: Math.floor(Date.now() / 1000) };
userGroups.push(group);
return group;
},
async updateUserGroup(id, patch) {
const group = userGroups.find((candidate) => candidate.id === id);
Object.assign(group, patch);
return group;
},
async disableUserGroup(id) { return this.updateUserGroup(id, { disabled: true }); },
async enableUserGroup(id) { return this.updateUserGroup(id, { disabled: false }); },
async publishAppHome() { return {}; },
async postMessage() { return { channelId: CHANNEL_ID, ts: '1.0' }; },
};
app.route(
'/',
createAdminRoutes({
store,
settings,
memory,
routines,
usage,
work,
identity,
usageAdminUi: true,
authService: {
async authenticateRequest() {
return {
userId: owner.user.id,
membershipId: owner.membership.id,
organizationId: owner.membership.organizationId,
role: 'owner',
authenticatorKind: 'better_auth',
credentialId: 'better_auth_session_admin_ui',
correlationId: 'request_admin_ui_verifier',
machine: false,
};
},
},
knownProviders: new Set(['local-stub']),
slackTransport,
routineCapability: () => ({
target: 'cloudflare',
available: true,
enabled: true,
reason: 'enabled',
}),
}),
);
const retiredLogin = await app.request(`${ADMIN_ORIGIN}/admin/login`, { method: 'POST' });
const pageResponse = await app.request(`${ADMIN_ORIGIN}/admin`);
const pageHtml = await pageResponse.text();
// Follow the production shell's asset references. Inspecting only the HTML
// silently lost the client application when it moved out of inline scripts.
const scriptPath = pageHtml.match(/<script src="(\/admin-ui\/admin\.js\?v=[^"]+)"/)?.[1];
const stylePath = pageHtml.match(/<link rel="stylesheet" href="(\/admin-ui\/admin\.css\?v=[^"]+)"/)?.[1];
const assetBodies = [];
let assetsReady = Boolean(scriptPath && stylePath);
for (const [assetPath, contentType] of [[scriptPath, 'javascript'], [stylePath, 'text/css']]) {
if (!assetPath) continue;
const response = await app.request(`${ADMIN_ORIGIN}${assetPath}`);
const body = await response.text();
assetsReady &&= response.status === 200
&& Boolean(response.headers.get('content-type')?.includes(contentType)) && body.length > 0;
assetBodies.push(body);
}
record('Admin shell references accessible versioned script and stylesheet', assetsReady);
const pageSource = [pageHtml, ...assetBodies].join('\n');
record(
'Slack-bound Owner opens Admin while the retired token login stays absent',
retiredLogin.status === 404 &&
pageResponse.status === 200 &&
pageResponse.headers.get('cache-control') === 'no-store' &&
pageSource.includes('Agents available here') &&
!pageSource.includes('Resolved configuration') &&
pageSource.includes('data-action="copy-channel-prompt"'),
`retiredLogin=${retiredLogin.status} page=${pageResponse.status}`,
);
record(
'admin page keeps Agent-owned Scheduled Work audit without Channel-memory navigation',
pageSource.includes('Audit logs') &&
!pageSource.includes('SESSIONS_ADMIN_UI') &&
!pageSource.includes('data-action="open-sessions"') &&
pageSource.includes('data-action="audit-tab-scheduled">Scheduled work') &&
!pageSource.includes('data-action="audit-tab-memory"') &&
pageSource.includes('aria-disabled="true" title="Coming later">Network events'),
);
record(
'workspace-default Slack setup has no browser credential paste-back surface',
pageSource.includes('Bot tokens are never pasted into Admin') &&
!pageSource.includes('data-action="slack-connect-form"') &&
!pageSource.includes('data-action="slack-update-open"') &&
!pageSource.includes('id="onboarding-signing-secret"') &&
!pageSource.includes('id="onboarding-bot-token"'),
);
record(
'visible Admin resources revalidate without polling or full-page reloads',
pageSource.includes('var visibleResources = {};') &&
pageSource.includes('function revalidateCurrentVisibleResources(') &&
pageSource.includes('window.addEventListener("focus"') &&
pageSource.includes('document.addEventListener("visibilitychange"') &&
pageSource.includes('function invalidateVisibleResource(name, ownerKey)') &&
pageSource.includes('promise.finally(function ()') &&
pageSource.includes('requestGeneration') &&
!pageSource.includes('setInterval(function () {\n revalidateCurrentVisibleResources()'),
);
record(
'Agent Schedules uses the compact Flat List and scoped controls only',
pageSource.includes('class="agent-schedule-list"') &&
pageSource.includes('data-action="agent-schedule-control"') &&
pageSource.includes('data-action="agent-schedule-delete-open"') &&
pageSource.includes('function invalidateAgentSchedules(agentId)') &&
pageSource.includes('invalidateAgentSchedules(agentId);') &&
!pageSource.includes('data-action="agent-schedule-create"') &&
!pageSource.includes('data-action="agent-schedule-edit"') &&
!pageSource.includes('data-action="agent-schedule-reassign"'),
);
const usageOverview = await adminJson(
app,
`/admin/api/usage/overview?from=${usageNow - 86_400_000}&to=${usageNow + 1}&groupBy=channel¤cy=USD`,
);
const usageMetadata = await adminJson(app, '/admin/api/usage/metadata');
const usageOperations = await adminJson(
app,
`/admin/api/usage/operations?from=${usageNow - 86_400_000}&to=${usageNow + 1}&limit=20`,
);
record(
'Usage exposes estimated spend, channel attribution, work detail, and provider-owned limits',
pageHtml.includes('"usageAdminUi":true') &&
usageOverview.status === 200 &&
usageOverview.body?.current?.totals?.operationCount === 1 &&
usageOverview.body?.current?.totals?.estimateAmountMicros === 800 &&
usageOverview.body?.current?.groups?.[0]?.key === CHANNEL_ID &&
usageOverview.body?.current?.groups?.[0]?.label === null &&
usageMetadata.status === 200 &&
usageMetadata.body?.contract?.providerBillingIncluded === false &&
usageMetadata.body?.contract?.limitsManagedByChickpea === false &&
usageOperations.status === 200 &&
usageOperations.body?.items?.[0]?.operation?.operationId === 'usage_admin_ui_release' &&
usageOperations.body?.items?.[0]?.operation?.runId === 'run_admin_ui_release' &&
!Object.hasOwn(usageOperations.body?.items?.[0] ?? {}, 'sessionDeepLink'),
`overview=${usageOverview.status} metadata=${usageMetadata.status} operations=${usageOperations.status}`,
);
const sessions = await adminJson(app, '/admin/api/sessions?limit=20');
const sessionDetail = await adminJson(app, '/admin/api/sessions/run_admin_ui_release');
const retiredSessionsPage = await adminJson(app, '/admin/sessions/run_admin_ui_release');
record(
'Run inspection APIs remain available without exposing a Sessions page',
sessions.status === 200 &&
sessions.body?.items?.[0]?.runId === 'run_admin_ui_release' &&
!Object.hasOwn(sessions.body?.items?.[0] ?? {}, 'deepLink') &&
sessionDetail.status === 200 &&
sessionDetail.body?.projection === 'public' &&
sessionDetail.body?.session?.status === 'admitted' &&
sessionDetail.body?.content?.trigger?.body === 'Admin UI Run trigger' &&
sessionDetail.body?.usage?.state === 'reported' &&
retiredSessionsPage.status === 302,
`list=${sessions.status} detail=${sessionDetail.status} page=${retiredSessionsPage.status}`,
);
const routineList = await adminJson(app, '/admin/api/audit/scheduled_work/routines?state=active');
const routineDetail = await adminJson(app, `/admin/api/audit/scheduled_work/routines/${ROUTINE_ID}`);
record(
'Scheduled Work lists definitions and safe occurrence detail through the real state store',
routineList.status === 200 &&
routineList.body?.routines?.[0]?.id === ROUTINE_ID &&
routineList.body?.routines?.[0]?.taskText === undefined &&
routineDetail.status === 200 &&
routineDetail.body?.routine?.taskText === 'Review launch blockers and make safe progress.' &&
routineDetail.body?.runs?.[0]?.id === 'rrun_admin_ui_release' &&
routineDetail.body?.runs?.[0]?.revision === undefined,
`list=${routineList.status} detail=${routineDetail.status}`,
);
const pausedRoutine = await adminJson(
app,
`/admin/api/audit/scheduled_work/routines/${ROUTINE_ID}/control`,
{
method: 'POST',
headers: { 'content-type': 'application/json', 'idempotency-key': 'admin-ui-routine-pause' },
body: JSON.stringify({ action: 'pause', expectedVersion: 1 }),
},
);
record(
'Scheduled Work control uses optimistic versioning and appends audit state',
pausedRoutine.status === 200 && pausedRoutine.body?.routine?.state === 'paused' &&
(await routines.listAuditEvents({ subjectId: ROUTINE_ID, limit: 20 })).length >= 2,
`status=${pausedRoutine.status}`,
);
const created = await adminBody(app, 'POST', '/admin/api/agents', {
id: AGENT_ID,
name: 'Admin UI Agent',
instructions: 'ADMIN_UI_AGENT_INSTRUCTIONS: answer from the admin-created Agent.',
enabled: true,
model: MODEL_SPECIFIER,
});
record(
'POST /admin/api/agents creates the Agent',
created.status === 201 && created.body?.agent?.id === AGENT_ID,
`status=${created.status}`,
);
const assigned = await adminBody(app, 'POST', `/admin/api/agents/${AGENT_ID}/channels`, {
workspaceId: WORKSPACE_ID,
channelId: CHANNEL_ID,
});
record(
'POST /admin/api/agents/:id/channels publishes the first Agent grant',
assigned.status === 201 && assigned.body?.grant?.agentId === AGENT_ID &&
assigned.body?.grant?.status === 'active',
`status=${assigned.status}`,
);
await store.putAgentScheduleReference({
scheduleId: ROUTINE_ID,
agentId: AGENT_ID,
workspaceId: WORKSPACE_ID,
channelId: CHANNEL_ID,
createdByMembershipId: owner.membership.id,
runsAsMembershipId: owner.membership.id,
authorityReceiptId: 'receipt_admin_ui_release',
requiredConnectionAccountIds: [],
state: 'active',
});
const agentSchedules = await adminJson(app, `/admin/api/agents/${AGENT_ID}/schedules`);
const resumedAgentSchedule = await adminJson(
app,
`/admin/api/agents/${AGENT_ID}/schedules/${ROUTINE_ID}/control`,
{
method: 'POST',
headers: { 'content-type': 'application/json', 'idempotency-key': 'admin-ui-agent-schedule-resume' },
body: JSON.stringify({ action: 'resume', expectedVersion: 2 }),
},
);
const deletedAgentSchedule = await adminJson(
app,
`/admin/api/agents/${AGENT_ID}/schedules/${ROUTINE_ID}/control`,
{
method: 'POST',
headers: { 'content-type': 'application/json', 'idempotency-key': 'admin-ui-agent-schedule-delete' },
body: JSON.stringify({
action: 'delete', expectedVersion: 3, acknowledgeIrreversible: true,
}),
},
);
const schedulesAfterDelete = await adminJson(app, `/admin/api/agents/${AGENT_ID}/schedules`);
record(
'Agent Schedules exposes the compact projection and scoped resume/delete controls',
agentSchedules.status === 200 &&
agentSchedules.body?.schedules?.[0]?.name === 'Release readiness check' &&
agentSchedules.body?.schedules?.[0]?.channelLabel === CHANNEL_LABEL &&
agentSchedules.body?.schedules?.[0]?.status === 'paused' &&
agentSchedules.body?.schedules?.[0]?.actions?.resume === true &&
agentSchedules.body?.schedules?.[0]?.taskText === undefined &&
resumedAgentSchedule.status === 200 && resumedAgentSchedule.body?.schedule?.status === 'active' &&
deletedAgentSchedule.status === 200 && deletedAgentSchedule.body?.irreversible === true &&
schedulesAfterDelete.status === 200 && schedulesAfterDelete.body?.schedules?.length === 0,
`list=${agentSchedules.status} resume=${resumedAgentSchedule.status} delete=${deletedAgentSchedule.status}`,
);
const secondAgentId = 'agent_admin_ui_two';
const secondCreated = await adminBody(app, 'POST', '/admin/api/agents', {
id: secondAgentId,
name: 'Release Analyst',
instructions: 'Review release risk.',
enabled: true,
model: MODEL_SPECIFIER,
});
const secondPublished = await adminBody(app, 'POST', `/admin/api/agents/${secondAgentId}/channels`, {
workspaceId: WORKSPACE_ID,
channelId: CHANNEL_ID,
});
const channelInventory = await adminJson(app, '/admin/api/channels');
const verifiedChannel = channelInventory.body?.channels?.find((channel) => channel.channelId === CHANNEL_ID);
record(
'Channel inventory keeps multiple additive Agent grants',
secondCreated.status === 201 && secondPublished.status === 201 && channelInventory.status === 200 &&
verifiedChannel?.grants?.length === 2 &&
verifiedChannel.grants.some((grant) => grant.agentId === AGENT_ID) &&
verifiedChannel.grants.some((grant) => grant.agentId === secondAgentId),
`create=${secondCreated.status} publish=${secondPublished.status} grants=${String(verifiedChannel?.grants?.length)}`,
);
const mcpClients = await adminJson(app, '/admin/api/mcp-clients');
record(
'Coding agents Settings reads the nine-client MCP table for this deployment',
mcpClients.status === 200 &&
Array.isArray(mcpClients.body?.clients) &&
mcpClients.body.clients.length === 9 &&
typeof mcpClients.body?.url === 'string' &&
mcpClients.body.url.endsWith('/mcp'),
`status=${mcpClients.status} clients=${String(mcpClients.body?.clients?.length)} url=${String(mcpClients.body?.url)}`,
);
const initialMemory = await adminBody(app, 'PUT', `/admin/api/agents/${AGENT_ID}/memory`, {
expectedRevision: 0,
body: 'Prefer small, reversible releases.',
});
const agentMemory = await adminJson(app, `/admin/api/agents/${AGENT_ID}/memory`);
const retiredOwners = await adminJson(app, `/admin/api/audit/memory/owners?workspaceId=${WORKSPACE_ID}`);
const channelFiles = await adminJson(
app,
`/admin/api/audit/memory/owners/channel/${WORKSPACE_ID}/${CHANNEL_ID}/files`,
);
record(
'Memory is one Agent-owned body and retired Channel/file indexes are unavailable',
initialMemory.status === 200 && initialMemory.body?.memory?.revision === 1 &&
agentMemory.status === 200 &&
agentMemory.body?.memory?.agentId === AGENT_ID &&
agentMemory.body?.memory?.body === 'Prefer small, reversible releases.' &&
retiredOwners.status === 404 && channelFiles.status === 403,
`put=${initialMemory.status} get=${agentMemory.status} owners=${retiredOwners.status} channel=${channelFiles.status}`,
);
const editBody = JSON.stringify({
expectedRevision: 1,
body: 'Run focused tests and the durability gate before release.',
});
const edit = await adminJson(app, `/admin/api/agents/${AGENT_ID}/memory`, {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: editBody,
});
const conflict = await adminJson(app, `/admin/api/agents/${AGENT_ID}/memory`, {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: editBody,
});
record(
'Memory edit is versioned and a stale draft receives 409 without overwrite',
edit.status === 200 && edit.body?.memory?.revision === 2 &&
conflict.status === 409 && conflict.body?.currentVersion === 2,
`edit=${edit.status} conflict=${conflict.status}`,
);
} catch (error) {
record('verification harness', false, error instanceof Error ? error.message : String(error));
} finally {
store?.close();
settings?.close();
memory?.close();
routines?.close();
usage?.close();
work?.close();
identity?.close();
}
const failed = results.filter((result) => !result.passed);
console.log(`\n${results.length - failed.length}/${results.length} checks passed`);
process.exit(failed.length === 0 ? 0 : 1);