promote_memory_pack
Promotes a memory pack to a higher trust level after mandatory human review, upgrading EPHEMERAL packs to CASE or ORG packs.
Instructions
Promote a memory pack to a higher trust level after human review. This is how distilled EPHEMERAL packs become CASE or ORG packs. Requires MANDATORY gate.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pack_id | Yes | Pack ID to promote | |
| target_trust | Yes | Target trust level (must be higher) | |
| approved_by | Yes | Human approver | |
| approver_role | Yes | Role of the approver |
Implementation Reference
- src/mcp/tools/memory-packs.ts:866-1002 (handler)The handler function that executes the promote_memory_pack tool logic. It promotes a memory pack to a higher trust level (CASE, ORG, or SYSTEM) after human review. Validates pack exists, trust level is an upgrade, approver role has permission, creates a promoted pack (appends '-promoted' to ID), revokes the old pack, optionally enforces MANDATORY gate for SYSTEM/ORG promotions, and records everything to the ledger and telemetry.
export function registerPromoteMemoryPackTool(server: McpServer, engine: GovernanceEngine): void { server.tool( 'promote_memory_pack', 'Promote a memory pack to a higher trust level after human review. This is how distilled EPHEMERAL packs become CASE or ORG packs. Requires MANDATORY gate.', { pack_id: z.string().max(100).describe('Pack ID to promote'), target_trust: z.enum(['SYSTEM', 'ORG', 'CASE']).describe('Target trust level (must be higher)'), approved_by: z.string().max(100).describe('Human approver'), approver_role: z.string().max(100).describe('Role of the approver'), }, { title: 'Promote Memory Pack', readOnlyHint: false, idempotentHint: false, destructiveHint: true, openWorldHint: false }, async (input) => { const entry = engine.ledger.begin( 'promote-memory-pack', MaiClassification.MANDATORY, GiaLayer.MCP, input.approved_by ); entry.addMetadata('packId', input.pack_id); entry.addMetadata('targetTrust', input.target_trust); entry.addMetadata('approverRole', input.approver_role); try { await seedDefaults(); const pack = gmpPacks.get(input.pack_id); if (!pack) return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `Pack not found: ${input.pack_id}` }) }], isError: true }; if (pack.status === 'REVOKED') { const promotedId = `${input.pack_id}-promoted`; const promotedExists = gmpPacks.has(promotedId); return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Cannot promote revoked pack', hint: promotedExists ? `This pack was already promoted. The promoted version is: "${promotedId}" (status: ${gmpPacks.get(promotedId)?.status}, trust: ${gmpPacks.get(promotedId)?.trustLevel}). Use this ID for load_memory_pack or compose_memory_packs.` : 'This pack has been revoked. Re-seal a new pack with seal_memory_pack before promoting.', promotedPackId: promotedExists ? promotedId : undefined, }) }], isError: true }; } if (TRUST_RANK[input.target_trust] <= TRUST_RANK[pack.trustLevel]) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `Cannot promote: ${pack.trustLevel} → ${input.target_trust} is not an upgrade` }) }], isError: true }; } const allowed = TRUST_SEAL_ROLES[input.target_trust]; if (allowed.length > 0 && !allowed.includes(input.approver_role)) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `Role '${input.approver_role}' cannot seal ${input.target_trust} packs`, allowedRoles: allowed }) }], isError: true }; } const now = new Date().toISOString(); const promotedId = `${input.pack_id}-promoted`; const promoted: GMPPack = { ...pack, memoryPackId: promotedId, version: pack.version.replace('-draft', '-promoted'), trustLevel: input.target_trust, signedBy: input.approved_by, scope: pack.scope.filter(s => s !== 'requires-review'), ttlHours: TRUST_MAX_TTL[input.target_trust], hash: '', status: 'SEALED', audit: { createdAt: now, lastReviewed: now, expiresAt: new Date(Date.now() + TRUST_MAX_TTL[input.target_trust] * 3600000).toISOString(), usageCount: 0 }, }; promoted.hash = djb2Hash(canonicalize({ id: promoted.memoryPackId, version: promoted.version, type: promoted.type, trust: promoted.trustLevel, content: promoted.content })); gmpPacks.set(promotedId, promoted); persistPack(promoted); // Write-through: new promoted pack // Revoke old pack pack.status = 'REVOKED'; persistPack(pack); // Write-through: revoked status const promoteEvent = { event: 'GMP_PROMOTED', memoryPackId: promotedId, agentId: 'gia-promoter', runId: `promote:${input.pack_id}→${input.target_trust}`, hash: promoted.hash, approvedBy: input.approved_by, timestamp: now }; gmpUsageLog.push(promoteEvent); persistUsageEvent(promoteEvent); // MANDATORY gate enforcement — promotion to SYSTEM or ORG trust MUST // go through human-in-the-loop gate. This was identified as a vulnerability // during red-team testing (2026-04-11): poisoned EPHEMERAL packs could be // promoted to SYSTEM trust without gate enforcement. const requiresGate = input.target_trust === 'SYSTEM' || input.target_trust === 'ORG'; if (requiresGate) { const gateDecision = await engine.gate.enforce( MaiClassification.MANDATORY, `promote-memory-pack:${input.pack_id}→${input.target_trust}`, entry.id, ); entry.addMetadata('gateId', gateDecision.gateId); entry.addMetadata('gateStatus', gateDecision.status); if (gateDecision.status !== 'APPROVED') { const failedEntry = entry.fail( new Error(`MANDATORY gate ${gateDecision.status} for promotion to ${input.target_trust}`), MaiClassification.MANDATORY, ); engine.ledger.record(failedEntry); return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'GATE_REQUIRED', gateId: gateDecision.gateId, gateStatus: gateDecision.status, message: `Promoting to ${input.target_trust} trust requires MANDATORY gate approval. Use approve_gate tool with gate ID to approve.`, packId: input.pack_id, targetTrust: input.target_trust, contentPreview: promoted.content.principles?.slice(0, 3), }) }], isError: true }; } } const score = engine.scorer.scoreDefault('promote-memory-pack'); const completedEntry = entry.complete(score, { classification: MaiClassification.MANDATORY, confidence: 1.0, rationale: `Memory pack promoted to ${input.target_trust}: ${input.pack_id}`, requiresGate, }); engine.ledger.record(completedEntry); // Telemetry: promote success engine.telemetryService.emitToolCall('promote_memory_pack', entry.id, 'MANDATORY', true); return { content: [{ type: 'text' as const, text: JSON.stringify({ promoted: true, promotedPackId: promotedId, previousTrust: pack.trustLevel, newTrust: input.target_trust, hash: promoted.hash, ttlHours: promoted.ttlHours, expiresAt: promoted.audit.expiresAt, oldPackStatus: 'REVOKED', }, null, 2) }] }; } catch (error) { // Telemetry: promote failure engine.telemetryService.emitToolCall('promote_memory_pack', entry.id, 'MANDATORY', false); const failedEntry = entry.fail(error instanceof Error ? error : new Error('Promote failed'), MaiClassification.MANDATORY); engine.ledger.record(failedEntry); return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'PROMOTE_FAILED', message: String(error) }) }], isError: true }; } } ); - Zod schema defining the input parameters for promote_memory_pack: pack_id (string), target_trust (enum: SYSTEM/ORG/CASE), approved_by (human approver), and approver_role.
{ pack_id: z.string().max(100).describe('Pack ID to promote'), target_trust: z.enum(['SYSTEM', 'ORG', 'CASE']).describe('Target trust level (must be higher)'), approved_by: z.string().max(100).describe('Human approver'), approver_role: z.string().max(100).describe('Role of the approver'), }, - src/mcp/tools/memory-packs.ts:1008-1015 (registration)Registration function that registers all 6 GMP tools (including promote_memory_pack) with the MCP server.
export function registerMemoryPackTools(server: McpServer, engine: GovernanceEngine): void { registerSealMemoryPackTool(server, engine); registerLoadMemoryPackTool(server, engine); registerTransferMemoryPackTool(server, engine); registerComposeMemoryPacksTool(server, engine); registerDistillMemoryPackTool(server, engine); registerPromoteMemoryPackTool(server, engine); } - src/mcp/tools/memory-packs.ts:67-75 (helper)Helper constants used by promote_memory_pack: TRUST_RANK for validating upgrades, TRUST_MAX_TTL for setting promoted pack TTL, and TRUST_SEAL_ROLES for enforcing role-based sealing authority.
const TRUST_RANK: Record<string, number> = { SYSTEM: 4, ORG: 3, CASE: 2, EPHEMERAL: 1 }; const TRUST_MAX_TTL: Record<string, number> = { SYSTEM: 8760, ORG: 2160, CASE: 168, EPHEMERAL: 4 }; const TRUST_SEAL_ROLES: Record<string, string[]> = { SYSTEM: ['platform-owner', 'isso'], ORG: ['platform-owner', 'isso', 'supervisor', 'org-admin'], CASE: ['platform-owner', 'isso', 'supervisor', 'forensic-analyst', 'agent'], EPHEMERAL: [], };