2026 03 19 Vitto Unified Autonomy Engine
Documentation for Plans
Vitto Unified Autonomy Engine — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Wire VM execution, adaptive trust, proactive intelligence, and crash recovery into a unified autonomy layer for Vitto.
Architecture: Three independent services (TrustScoringService, TierResolverService, TriggerEngineService) feed a read-only AutonomyContext assembled by an AutonomyGateService. VM execution uses the existing per-user snapshot infrastructure via a new VmApiClientService chain through backend-ai-api to sandbox-orchestrator. Trust scores are materialized in MongoDB, updated event-driven on outcomes. Proactive triggers live in a dedicated collection. Task recovery uses genome-based checkpoints.
Tech Stack: NestJS, MongoDB/Mongoose, Firecracker VMs, Angular 20+ (standalone, signals, OnPush), NGXS-free (signals + flash-persistence), RxJS Observables (no Promises)
Spec: docs/superpowers/specs/2026-03-19-vitto-unified-autonomy-engine-design.md
File Structure
New Files (Backend)
APIs/backend-vitto-api/src/app/engine/
autonomy/
autonomy-context.ts # AutonomyContext interface + TaskEvaluation
autonomy-gate.service.ts # Gate: assembles context from 3 services
autonomy-gate.service.spec.ts # Unit tests
trust-scoring.service.ts # Adaptive trust engine (0-100, domain-scoped)
trust-scoring.service.spec.ts # Unit tests
tier-resolver.service.ts # Dynamic tier selection + VM acquisition
tier-resolver.service.spec.ts # Unit tests
schemas/
trust-score.schema.ts # Mongoose schema for vitto-trust-scores
vm/
vm-api-client.service.ts # HTTP client to ai-api sandbox endpoints
vm-api-client.service.spec.ts # Unit tests
sandboxed-tool-proxy.service.ts # Routes tool calls to VM (structured API)
sandboxed-tool-proxy.service.spec.ts # Unit tests
vm-session-manager.service.ts # Per-user VM lifecycle (snapshot-based)
vm-session-manager.service.spec.ts # Unit tests
vm-credential-injector.service.ts # Deploy key injection via structured API
recovery/
task-recovery.service.ts # Genome-based checkpoint save/recover
task-recovery.service.spec.ts # Unit tests
schemas/
task-recovery.schema.ts # Mongoose schema (24h TTL)
APIs/backend-vitto-api/src/app/proactive/
trigger-engine.service.ts # Learned trigger detection and execution
trigger-engine.service.spec.ts # Unit tests
schemas/
trigger-pattern.schema.ts # Mongoose schema for vitto-triggers
APIs/backend-ai-api/src/app/infrastructure/
controllers/
sandbox-proxy.controller.ts # 9 new endpoints proxying SelfHostedProvider
sandbox-proxy.controller.spec.ts # Unit tests
APIs/sandbox-orchestrator/src/app/sandbox/
file-ops.controller.ts # write-file, read-file, inject-ssh-key
file-ops.controller.spec.ts # Unit tests
deployment/sandbox-orchestrator/
Dockerfile.rootfs-developer # Headless developer VM image
vm-init-developer.sh # SSH-only init script
Existing Files to Modify (Backend)
APIs/backend-vitto-api/src/app/engine/
sub-vitto-orchestrator.service.ts:20,110,146-156 # MAX_DEPTH, orchestrate, browser fallback
agent-loop.service.ts:132 # run() add VM-aware tool routing
autonomy.service.ts:206-258 # shouldProceed read dynamic trust
trust-escalation.service.ts:31-324 # Deprecate, migrate to TrustScoringService
vitto-engine.service.ts:134,183 # Add checkpoint hooks
APIs/backend-vitto-api/src/app/strategy/
cost-guard.service.ts:38-59 # Add depth-aware budget inheritance
APIs/backend-vitto-api/src/app/proactive/
proactive-dispatcher.service.ts:55 # Wire trigger execution
APIs/backend-vitto-api/src/app/types/
vitto.types.ts:23,100,102-114 # Add new interfaces, extend SubVittoTask
APIs/backend-vitto-api/src/app/mind/
outcome-feedback.service.ts:32 # Wire trust score updates
Frontend Files to Create/Modify
libs/libs-ai/vitto-chat/src/lib/components/tool-renderers/renderers/
sub-vitto-orchestration-renderer/ # Update: VM status, tier badge, degradation
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/
vm-execution-card.component.ts # NEW: VM task progress card
vm-execution-card.component.html
vm-execution-card.component.scss
trust-update-card.component.ts # NEW: Trust score change card
trust-update-card.component.html
trust-update-card.component.scss
proactive-trigger-card.component.ts # NEW: Learned trigger suggestion card
proactive-trigger-card.component.html
proactive-trigger-card.component.scss
libs/libs-ai/vitto-hub/src/lib/components/
observatory-panel/trust-dashboard/ # Update: domain-scoped trust, trajectory
libs/libs-ai/agent-mind/src/lib/components/
autonomy-slider/autonomy-slider.component.ts # Update: show adaptive trust score
libs/libs-ai/gograb-ai-lib/src/lib/types/
vitto.types.ts # Update: add VM, trust, trigger types
libs/libs-ai/vitto-core/src/lib/types/
observatory-dtos.ts # Update: domain-scoped TrustScore
libs/libs-ai/vitto-core/src/lib/services/
vitto-api.service.ts # Update: add trust/trigger API methods
libs/libs-ai/vitto-core/src/lib/utils/
autonomy-level-mapper.ts # NEW: backend to frontend level mapping
Phase 0: Configuration & Prerequisites
Task 0.1: Environment Variables and MongoDB Collections
Files:
Modify:
APIs/backend-vitto-api/.env.local(or.env.example)Modify:
APIs/sandbox-orchestrator/.env.local(or.env.example)Step 1: Add new env vars to backend-vitto-api .env.local:
# Trust Engine
VITTO_TRUST_DEFAULT_SCORE=25
VITTO_TRUST_MAX_ESCALATION_PER_WEEK=1
VITTO_TRUST_FAILURE_PENALTY=5
VITTO_TRUST_CRITICAL_PENALTY=15
# VM Execution
VITTO_VM_DEVELOPER_TEMPLATE=developer
VITTO_VM_REUSE_ACTIVE=true
VITTO_VM_SNAPSHOT_ON_RELEASE=true
# Triggers
VITTO_TRIGGER_MIN_OCCURRENCES=3
VITTO_TRIGGER_DETECTION_WINDOW_DAYS=14
VITTO_TRIGGER_AUTO_EXECUTE_CONFIDENCE=0.8
VITTO_TRIGGER_DISABLE_THRESHOLD=0.3
# Checkpoints
VITTO_CHECKPOINT_ENABLED=true
VITTO_CHECKPOINT_TTL_HOURS=24
# Nesting
VITTO_MAX_NESTING_DEPTH=2
VITTO_DEPTH2_BUDGET_RATIO=0.5
VITTO_DEPTH2_MAX_TOOLS=5
- Step 2: Create MongoDB indexes for new collections (run in MongoDB shell or Atlas UI):
// vitto-mind database
db.createCollection('vitto-trust-scores');
db.getCollection('vitto-trust-scores').createIndex({ userId: 1, domain: 1 }, { unique: true });
db.createCollection('vitto-triggers');
db.getCollection('vitto-triggers').createIndex({ userId: 1, enabled: 1, confidence: 1 });
db.createCollection('vitto-checkpoints');
db.getCollection('vitto-checkpoints').createIndex({ savedAt: 1 }, { expireAfterSeconds: 86400 });
db.getCollection('vitto-checkpoints').createIndex({ taskId: 1 }, { unique: true });
- Step 3: Commit
Phase 1: Sandbox-Orchestrator Structured Endpoints (Session 1)
Task 1.1: Structured File Operations Controller
Files:
Create:
APIs/sandbox-orchestrator/src/app/sandbox/file-ops.controller.tsCreate:
APIs/sandbox-orchestrator/src/app/sandbox/file-ops.controller.spec.tsModify:
APIs/sandbox-orchestrator/src/app/sandbox/sandbox.module.tsModify:
APIs/sandbox-orchestrator/src/app/sandbox/vm-executor.service.tsStep 1: Write failing test for write-file endpoint
describe('FileOpsController', () => {
describe('POST /sandboxes/:id/write-file', () => {
it('should write file content via SFTP without shell interpolation', async () => {
const mockExecutor = { execSftp: jest.fn().mockResolvedValue(undefined) };
const mockManager = { getSandbox: jest.fn().mockReturnValue({ vmIp: '172.16.0.2', status: 'running' }) };
const controller = new FileOpsController(mockManager as any, mockExecutor as any);
const result = await controller.writeFile('sandbox-1', { path: '/home/user/test.txt', content: 'hello world' });
expect(mockExecutor.execSftp).toHaveBeenCalledWith('172.16.0.2', 'write', { path: '/home/user/test.txt', content: 'hello world' });
expect(result).toEqual({ success: true, path: '/home/user/test.txt' });
});
});
describe('POST /sandboxes/:id/read-file', () => {
it('should read file content via SSH cat', async () => {
const mockExecutor = { execSftp: jest.fn().mockResolvedValue('file contents') };
const mockManager = { getSandbox: jest.fn().mockReturnValue({ vmIp: '172.16.0.2', status: 'running' }) };
const controller = new FileOpsController(mockManager as any, mockExecutor as any);
const result = await controller.readFile('sandbox-1', { path: '/home/user/test.txt' });
expect(result).toEqual({ success: true, content: 'file contents' });
});
});
describe('POST /sandboxes/:id/inject-ssh-key', () => {
it('should inject SSH key via tmpfs without shell history', async () => {
const mockExecutor = { injectSshKey: jest.fn().mockResolvedValue(undefined) };
const mockManager = { getSandbox: jest.fn().mockReturnValue({ vmIp: '172.16.0.2', status: 'running' }) };
const controller = new FileOpsController(mockManager as any, mockExecutor as any);
const result = await controller.injectSshKey('sandbox-1', { keyContent: 'key-data', repoUrl: '[email protected]:org/repo' });
expect(mockExecutor.injectSshKey).toHaveBeenCalledWith('172.16.0.2', 'key-data', '[email protected]:org/repo');
expect(result).toEqual({ success: true });
});
});
});
- Step 2: Run test to verify it fails
Run: cd APIs/sandbox-orchestrator && npx jest file-ops --no-coverage
Expected: FAIL with "FileOpsController not defined"
- Step 3: Implement FileOpsController
import { Controller, Post, Param, Body, UseGuards, NotFoundException } from '@nestjs/common';
import { ApiKeyGuard } from '../auth/api-key.guard';
import { SandboxManagerService } from './sandbox-manager.service';
import { VmExecutorService } from './vm-executor.service';
@Controller('sandboxes')
@UseGuards(ApiKeyGuard)
export class FileOpsController {
constructor(
private readonly manager: SandboxManagerService,
private readonly executor: VmExecutorService,
) {}
@Post(':id/write-file')
async writeFile(@Param('id') sandboxId: string, @Body() body: { path: string; content: string }) {
const sandbox = this.manager.getSandbox(sandboxId);
if (!sandbox || sandbox.status !== 'running') throw new NotFoundException(`Sandbox ${sandboxId} not found or not running`);
await this.executor.execSftp(sandbox.vmIp, 'write', body);
return { success: true, path: body.path };
}
@Post(':id/read-file')
async readFile(@Param('id') sandboxId: string, @Body() body: { path: string }) {
const sandbox = this.manager.getSandbox(sandboxId);
if (!sandbox || sandbox.status !== 'running') throw new NotFoundException(`Sandbox ${sandboxId} not found or not running`);
const content = await this.executor.execSftp(sandbox.vmIp, 'read', body);
return { success: true, content };
}
@Post(':id/inject-ssh-key')
async injectSshKey(@Param('id') sandboxId: string, @Body() body: { keyContent: string; repoUrl: string }) {
const sandbox = this.manager.getSandbox(sandboxId);
if (!sandbox || sandbox.status !== 'running') throw new NotFoundException(`Sandbox ${sandboxId} not found or not running`);
await this.executor.injectSshKey(sandbox.vmIp, body.keyContent, body.repoUrl);
return { success: true };
}
}
- Step 4: Add execSftp and injectSshKey methods to VmExecutorService
Add to APIs/sandbox-orchestrator/src/app/sandbox/vm-executor.service.ts:
async execSftp(vmIp: string, operation: 'read' | 'write', params: { path: string; content?: string }): Promise<string | void> {
const sshKeyPath = this.getSshKeyPath(vmIp);
if (operation === 'write') {
const tmpFile = `/tmp/sftp-upload-${Date.now()}`;
await fs.promises.writeFile(tmpFile, params.content || '');
try {
await execFilePromise('scp', ['-i', sshKeyPath, '-o', 'StrictHostKeyChecking=no', tmpFile, `user@${vmIp}:${params.path}`]);
} finally {
await fs.promises.unlink(tmpFile).catch(() => {});
}
} else {
const { stdout } = await execFilePromise('ssh', ['-i', sshKeyPath, '-o', 'StrictHostKeyChecking=no', `user@${vmIp}`, 'cat', params.path]);
return stdout;
}
}
async injectSshKey(vmIp: string, keyContent: string, repoUrl: string): Promise<void> {
const sshKeyPath = this.getSshKeyPath(vmIp);
// Key is piped via stdin, never appears in command args or shell history
await execFilePromise('ssh', [
'-i', sshKeyPath, '-o', 'StrictHostKeyChecking=no', `user@${vmIp}`,
'bash', '-c', 'cat > /dev/shm/dk && chmod 600 /dev/shm/dk && eval $(ssh-agent -s) && ssh-add /dev/shm/dk && rm -f /dev/shm/dk',
], { input: keyContent });
}
- Step 5: Register FileOpsController in SandboxModule
- Step 6: Run full test suite:
cd APIs/sandbox-orchestrator && npx jest --no-coverage - Step 7: Commit
Phase 2: Backend-AI-API Sandbox Proxy (Session 1-2)
Task 2.1: Sandbox Proxy Controller (9 endpoints)
Files:
Create:
APIs/backend-ai-api/src/app/infrastructure/controllers/sandbox-proxy.controller.tsCreate:
APIs/backend-ai-api/src/app/infrastructure/controllers/sandbox-proxy.controller.spec.tsModify:
APIs/backend-ai-api/src/app/infrastructure/infrastructure.module.tsStep 1: Write failing tests for create, getUserVmState, restore, snapshot, destroy, exec, write-file, read-file, inject-ssh-key
Step 2: Implement SandboxProxyController proxying each method to
SelfHostedProvider(path:APIs/backend-ai-api/src/app/infrastructure/services/sandbox/self-hosted.provider.ts). Guard withInternalTokenGuard. Route prefix:infrastructure/sandbox.Step 3: Run tests, verify pass
Step 4: Register in InfrastructureModule
Step 5: Commit
Phase 3: VM Execution Layer in Vitto-API (Sessions 2-3)
Task 3.1: VmApiClientService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/vm/vm-api-client.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/vm/vm-api-client.service.spec.tsStep 1: Write failing tests (createSandbox, getUserVmState, restoreFromSnapshot, snapshotAndSuspend, destroySandbox, sandboxExec, sandboxWriteFile, sandboxReadFile, injectSshKey)
Step 2: Implement all 9 HTTP methods using
HttpService(NestJS), hittingAI_API_URL+/infrastructure/sandbox/*, withBACKEND_API_INTERNAL_TOKENBearer auth. Timeouts: 120s for exec, 30s for file ops, 60s for snapshot.Step 3: Run tests, verify pass
Step 4: Commit
Task 3.2: VmSessionManagerService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/vm/vm-session-manager.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/vm/vm-session-manager.service.spec.tsStep 1: Write failing tests (reuse active session, restore from snapshot, cold boot, snapshot-and-suspend on release, destroy on error release)
Step 2: Implement per spec Section 3.5. Uses
VmApiClientService. Tracks active sessions inMap<string, VmSession>.Step 3: Run tests, verify pass
Step 4: Commit
Task 3.3: SandboxedToolProxyService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/vm/sandboxed-tool-proxy.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/vm/sandboxed-tool-proxy.service.spec.tsStep 1: Write failing tests (run_command via sandboxExec, write_file via structured API, read_file via structured API, search_code with proper escaping, unknown tool throws error)
Step 2: Implement per spec Section 3.4. Uses
VmApiClientService. No shell interpolation for file ops.Step 3: Run tests, verify pass
Step 4: Commit
Task 3.4: VmCredentialInjectorService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/vm/vm-credential-injector.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/vm/vm-credential-injector.service.spec.tsStep 1: Write test for deploy key injection via structured API
Step 2: Implement per spec Section 3.6. Uses
SecretVaultService+VmApiClientService.injectSshKey().Step 3: Run tests, verify pass
Step 4: Commit
Task 3.5: Wire VM into SubVittoOrchestrator + AgentLoop
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/sub-vitto-orchestrator.service.ts:146-156Modify:
APIs/backend-vitto-api/src/app/engine/agent-loop.service.ts:132Step 1: Write integration test verifying sub-Vitto with tier=vm routes run_command to SandboxedToolProxy
Step 2: Remove browser fallback at lines 146-156 of sub-vitto-orchestrator.service.ts
Step 3: Inject VmSessionManagerService + SandboxedToolProxyService into SubVittoOrchestratorService
Step 4: In orchestrate(), call
vmSessionManager.acquire()when tier='vm', pass vmId to agent loop, callvmSessionManager.release()on completionStep 5: In AgentLoopService, add VM-aware tool routing: check if tool is VM tool + tier=vm, then delegate to
SandboxedToolProxyService.executeOnVm(). If tier is degraded (vm unavailable), route VM tools throughProcessSandboxService(existing local sandbox with ulimits). browser_ tools do NOT degrade* — returntool_unavailableerror if VM/browser tier not available.Step 6: Run tests
Step 7: Commit
Phase 4: Adaptive Trust Engine (Sessions 3-4)
Task 4.1: Trust Score Schema + AutonomyContext Types
Files:
Create:
APIs/backend-vitto-api/src/app/engine/autonomy/schemas/trust-score.schema.tsCreate:
APIs/backend-vitto-api/src/app/engine/autonomy/autonomy-context.tsModify:
APIs/backend-vitto-api/src/app/types/vitto.types.ts:23,100,102-114Step 1: Create TrustScore Mongoose schema (per spec Section 4.2). Collection:
vitto-trust-scoresinvitto-minddb.Step 2: Create AutonomyContext + TaskEvaluation interfaces (per spec Section 2)
Step 3: Add ActionDomain type to vitto.types.ts:
'code_execution' | 'web_search' | 'messaging' | 'deployment' | 'knowledge' | 'delegation' | 'system'Step 4: Add LEVEL_ORDER constant to vitto.types.ts:
{ OBSERVE: 0, SUGGEST: 1, DIRECT: 2, AUTONOMOUS: 3 }Step 5: Extend SubVittoTask with
role,complexity,parentTaskId,userId,depthfieldsStep 6: Commit
Task 4.2: TrustScoringService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/autonomy/trust-scoring.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/autonomy/trust-scoring.service.spec.tsStep 1: Write failing tests: default score 25, score-to-level mapping using LEVEL_ORDER (not string comparison), user floor, +3/+2/+1 for complex/moderate/simple success, -5 failure, -15 critical, floor at 10, 1-level-per-7-days cap, trajectory computation
Step 2: Implement per spec Section 4.1
Step 3: Run tests, verify pass
Step 4: Commit
Task 4.3: TierResolverService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/autonomy/tier-resolver.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/autonomy/tier-resolver.service.spec.tsStep 1: Write failing tests: in-process for no VM tools, infer vm from run_command, acquire VM, graceful degradation on failure
Step 2: Implement per spec Section 5.1
Step 3: Run tests, verify pass
Step 4: Commit
Task 4.4: AutonomyGateService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/autonomy/autonomy-gate.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/autonomy/autonomy-gate.service.spec.tsStep 1: Write failing tests: assembles context in parallel, caches per task (max 5min), invalidates on critical trust drop
Step 2: Implement per spec Section 2
Step 3: Run tests, verify pass
Step 4: Commit
Task 4.5: Wire Trust into AutonomyService + OutcomeFeedback + SubVitto Outcomes
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/autonomy.service.ts:206-258Modify:
APIs/backend-vitto-api/src/app/mind/outcome-feedback.service.ts:32Modify:
APIs/backend-vitto-api/src/app/engine/sub-vitto-orchestrator.service.tsStep 1: In AutonomyService.shouldProceed(), read from TrustScoringService first, fall back to TrustEscalationService
Step 2: In OutcomeFeedbackService, add call to
TrustScoringService.updateFromOutcome()after outcome reportStep 3: In SubVittoOrchestratorService, after sub-Vitto completion call OutcomeFeedbackService with sub-Vitto metadata (role, tier, tools, success, complexity). Implement
inferDomain()helper that maps tool categories to ActionDomain (e.g., run_command/write_file -> 'code_execution', web_search -> 'web_search', send_message -> 'messaging').Step 4: Run existing tests to verify no regressions
Step 5: Commit
Phase 5: Proactive Intelligence (Sessions 5-6)
Task 5.1: Trigger Pattern Schema + TriggerEngineService
Files:
Create:
APIs/backend-vitto-api/src/app/proactive/schemas/trigger-pattern.schema.tsCreate:
APIs/backend-vitto-api/src/app/proactive/trigger-engine.service.tsCreate:
APIs/backend-vitto-api/src/app/proactive/trigger-engine.service.spec.tsStep 1: Create TriggerPattern Mongoose schema (per spec Section 6.2). Collection:
vitto-triggers.Step 2: Write failing tests: detectPattern (< 3 similar = no detect, first detect = confidence 0.5, repeat = +0.1), handleResponse (engaged +0.15, dismissed -0.2, auto-disable at 0.3), executeProactively (auto at >= 0.8 + DIRECT, suggest otherwise), checkTriggers (returns matching, not disabled)
Step 3: Implement. Note:
countSimilarTasksmatches by tool-sequence hash (tools used in same order), not natural language.Step 4: Run tests, verify pass
Step 5: Commit
Task 5.2: Wire Triggers into Task Completion + Dispatch
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/vitto-engine.service.ts:183Modify:
APIs/backend-vitto-api/src/app/proactive/proactive-dispatcher.service.ts:55Step 1: After task completion in VittoEngineService, call
TriggerEngineService.detectPattern()Step 2: In ProactiveDispatcherService, wire
TriggerEngineService.executeProactively()for matched triggersStep 3: Test E2E: 3 similar tasks then trigger created, 4th task gets suggestion
Step 4: Commit
Phase 6: Checkpoint Recovery + Agent Nesting (Sessions 6-7)
Task 6.1: TaskRecoveryService
Files:
Create:
APIs/backend-vitto-api/src/app/engine/recovery/task-recovery.service.tsCreate:
APIs/backend-vitto-api/src/app/engine/recovery/schemas/task-recovery.schema.tsCreate:
APIs/backend-vitto-api/src/app/engine/recovery/task-recovery.service.spec.tsStep 1: Create Mongoose schema with 24h TTL index on
savedAtfieldStep 2: Write failing tests: save checkpoint (genome + last 3 tools), recover within 24h, return null for stale, build resume message, restore VM on recovery
Step 3: Implement per spec Section 7.1. Named
TaskRecoveryService(not CheckpointService) to avoid DI collision with existingengine/checkpoint.service.ts.Step 4: Run tests, verify pass
Step 5: Commit
Task 6.2: Wire Recovery into Agent Loop + Engine
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/agent-loop.service.tsModify:
APIs/backend-vitto-api/src/app/engine/vitto-engine.service.ts:134Step 1: In AgentLoopService, save checkpoint via TaskRecoveryService after each successful tool execution
Step 2: In VittoEngineService BullMQ processor, attempt
TaskRecoveryService.recover()before starting freshStep 3: Test: simulate crash mid-task, verify recovery from checkpoint
Step 4: Commit
Task 6.3: Agent Nesting (Depth-2)
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/sub-vitto-orchestrator.service.ts:20Modify:
APIs/backend-vitto-api/src/app/strategy/cost-guard.service.ts:38-59Step 1: Write tests: depth-1 can nest, depth-2 restricted to in-process only, depth-2 gets 50% remaining budget, depth-2 max 5 tools, depth-3 blocked
Step 2: Change
MAX_DEPTH = 1toMAX_DEPTH = 2at line 20Step 3: Implement
getDepthRestrictions()in SubVittoOrchestratorService with tier, tool, and budget limits per depthStep 4: In CostGuardService, add method to expose remaining budget for depth inheritance
Step 5: Run tests, verify pass
Step 6: Commit
Phase 7: E2E Tests (Sessions 8-9)
Task 7.1: VM Execution E2E
Files:
Create:
APIs/backend-vitto-api/src/app/engine/__tests__/vm-execution.e2e.spec.tsStep 1: Test sub-Vitto with vm tier dispatching run_command to Firecracker VM and returning stdout
Step 2: Test graceful degradation to in-process when VM unavailable
Step 3: Test active VM session reuse for same user
Step 4: Test snapshot-and-suspend on task completion
Step 5: Commit
Task 7.2: Trust Scoring E2E
Files:
Create:
APIs/backend-vitto-api/src/app/engine/__tests__/trust-scoring.e2e.spec.tsStep 1: Test full lifecycle: new user (25/SUGGEST) -> repeated successes -> escalation to DIRECT -> failure drop -> recovery
Step 2: Test 1-level-per-7-days cap prevents gaming via trivial tasks
Step 3: Test floor at 10 prevents OBSERVE dead-end
Step 4: Test domain scoping: trust for code_execution independent of trust for messaging
Step 5: Commit
Task 7.3: Proactive Trigger E2E
Files:
Create:
APIs/backend-vitto-api/src/app/proactive/__tests__/trigger-engine.e2e.spec.tsStep 1: Test pattern detection after 3 similar tasks
Step 2: Test confidence escalation on engagement and decay on dismissal
Step 3: Test auto-execution at high confidence + DIRECT trust
Step 4: Test auto-disable below 0.3 confidence
Step 5: Commit
Task 7.4: Checkpoint Recovery E2E
Files:
Create:
APIs/backend-vitto-api/src/app/engine/__tests__/task-recovery.e2e.spec.tsStep 1: Test save after tool execution and successful recovery with resume message
Step 2: Test stale checkpoint (>24h) returns null
Step 3: Test VM snapshot restore on recovery
Step 4: Commit
Task 7.5: Agent Nesting E2E
Files:
Create:
APIs/backend-vitto-api/src/app/engine/__tests__/agent-nesting.e2e.spec.tsStep 1: Test depth-1 spawning depth-2 with restricted budget and in-process only
Step 2: Test depth-3 is blocked
Step 3: Commit
Phase 8: Frontend NX Libs, UI Components, and Deprecation Cleanup (Sessions 9-12)
Task 8.1: Verify Backend Types (Additive to Task 4.1)
Note: Task 4.1 already adds ActionDomain, LEVEL_ORDER, and extends SubVittoTask. This task only adds types NOT covered in Phase 4.
Files:
Modify:
APIs/backend-vitto-api/src/app/types/vitto.types.tsStep 1: Verify ActionDomain, LEVEL_ORDER, and SubVittoTask extensions exist (added in Task 4.1)
Step 2: Add any remaining types: TrustResult, TierResolution, VmSession (if not already added)
Step 3: Commit (only if changes were needed)
Task 8.2: Update Frontend Types
Files:
Modify:
libs/libs-ai/gograb-ai-lib/src/lib/types/vitto.types.tsModify:
libs/libs-ai/vitto-core/src/lib/types/observatory-dtos.tsStep 1: Add to gograb-ai-lib vitto.types.ts: ActionDomain, TrustTrajectory, VmExecutionStatus, TriggerPattern frontend types
Step 2: Update observatory-dtos.ts TrustScore: add domain, trajectory, history fields
Step 3: Commit
Task 8.3: Create AutonomyLevel Mapper Utility
Files:
- Create:
libs/libs-ai/vitto-core/src/lib/utils/autonomy-level-mapper.ts
Two AutonomyLevel definitions exist:
Backend:
'OBSERVE' | 'SUGGEST' | 'DIRECT' | 'AUTONOMOUS'Frontend UX (
agent-experience.types.ts):'manual' | 'guided' | 'collaborative' | 'autonomous'Step 1: Create mapping utility
export const BACKEND_TO_FRONTEND: Record<string, string> = {
OBSERVE: 'manual', SUGGEST: 'guided', DIRECT: 'collaborative', AUTONOMOUS: 'autonomous',
};
export const FRONTEND_TO_BACKEND: Record<string, string> = {
manual: 'OBSERVE', guided: 'SUGGEST', collaborative: 'DIRECT', autonomous: 'AUTONOMOUS',
};
export function mapBackendToFrontend(level: string): string { return BACKEND_TO_FRONTEND[level] || 'manual'; }
export function mapFrontendToBackend(level: string): string { return FRONTEND_TO_BACKEND[level] || 'OBSERVE'; }
- Step 2: Export from vitto-core barrel
- Step 3: Add JSDoc to
agent-experience.types.tsAutonomyLevel explaining it's the frontend display variant - Step 4: Commit
Task 8.4: Update VittoApiService
Files:
Modify:
libs/libs-ai/vitto-core/src/lib/services/vitto-api.service.tsStep 1: Add trust score API methods (
getTrustScores,getTriggers,respondToTrigger) usingVITTO_API_URL(port 3003)Step 2: Commit
Task 8.5: Update Sub-Vitto Orchestration Renderer
Files:
Modify:
libs/libs-ai/vitto-chat/src/lib/components/tool-renderers/renderers/sub-vitto-orchestration-renderer/sub-vitto-orchestration-renderer.component.tsModify:
libs/libs-ai/vitto-chat/src/lib/components/tool-renderers/renderers/sub-vitto-orchestration-renderer/sub-vitto-orchestration-renderer.component.htmlStep 1: Add tier badge (in-process / vm / vm degraded to in-process warning)
Step 2: Add VM metadata (restored from snapshot, acquire time) when tier=vm
Step 3: Add depth indicator for nested agents
Step 4: Commit
Task 8.6: Create VM Execution Activity Card
Files:
Create:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/vm-execution-card.component.tsCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/vm-execution-card.component.htmlCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/vm-execution-card.component.scssModify:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/activity-card-registry.tsStep 1: Create standalone component (Angular 20+, OnPush, signal
input.required<VmExecutionStatus>())Step 2: Template: VM ID, restored status, tier, running time, degradation warning
Step 3: Register in activity-card-registry.ts
Step 4: Commit
Task 8.7: Create Trust Update Activity Card
Files:
Create:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/trust-update-card.component.tsCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/trust-update-card.component.htmlCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/trust-update-card.component.scssStep 1: Create standalone component showing score change, domain, trajectory arrow
Step 2: Register in activity-card-registry.ts
Step 3: Commit
Task 8.8: Create Proactive Trigger Card
Files:
Create:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/proactive-trigger-card.component.tsCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/proactive-trigger-card.component.htmlCreate:
libs/libs-ai/vitto-chat/src/lib/components/activity-cards/cards/proactive-trigger-card.component.scssStep 1: Create standalone component with "Yes, do it" / "Not now" action buttons
Step 2: Wire buttons to
VittoApiService.respondToTrigger()via RxJS ObservableStep 3: Register in activity-card-registry.ts
Step 4: Commit
Task 8.9: Update Trust Dashboard
Files:
Modify:
libs/libs-ai/vitto-hub/src/lib/components/observatory-panel/trust-dashboard/Step 1: Show domain-scoped scores (one row per ActionDomain)
Step 2: Add trajectory indicator (rising/stable/declining with arrow icons)
Step 3: Show score history chart per domain
Step 4: Commit
Task 8.10: Update Autonomy Slider
Files:
Modify:
libs/libs-ai/agent-mind/src/lib/components/autonomy-slider/autonomy-slider.component.tsStep 1: Add read-only adaptive trust score indicator alongside manual slider. Slider sets FLOOR, trust engine can go above. Use
mapBackendToFrontend()mapper.Step 2: Add "Adaptive trust active" label when trust score differs from floor
Step 3: Commit
Task 8.11: Wire SSE Events for New Event Types
Files:
Modify:
libs/libs-ai/vitto-hub/src/lib/services/vitto-conscience.service.tsModify:
libs/libs-ai/vitto-hub/src/lib/services/vitto-introspection.service.tsModify:
libs/libs-ai/vitto-chat/src/lib/services/vitto-chat-engine.service.tsStep 1: Add handlers for:
subvitto.vm_acquired,subvitto.vm_degraded,trust.updated,trigger.detected,trigger.executedStep 2: Wire events to corresponding activity card components
Step 3: Commit
Task 8.12: Deprecation Cleanup — TrustEscalationService
Files:
Modify:
APIs/backend-vitto-api/src/app/engine/trust-escalation.service.tsModify:
APIs/backend-vitto-api/src/app/engine/autonomy.service.tsStep 1: Write migration script to copy ActionTrustScore documents to vitto-trust-scores (map successRate 0-1 to currentScore 0-100)
Step 2: Remove TrustEscalationService from AutonomyService (TrustScoringService is sole provider)
Step 3: Add
@deprecatedJSDoc to trust-escalation.service.ts with forwarding methodsStep 4: Remove all direct imports of TrustEscalationService across the codebase
Step 5: Commit
Task 8.13: Deprecation Cleanup — WorkflowSSEClientService
Files:
Check:
libs/libs-ai/gograb-ai-lib/src/lib/services/workflow-sse-client.service.tsStep 1: Verify zero active imports (
grep -r "WorkflowSSEClientService" libs/ --include="*.ts" -l)Step 2: If zero: delete file and remove from module exports
Step 3: If still imported: update consumers to VittoMonitorService or VittoChatStreamingService
Step 4: Commit
Task 8.14: Deprecation Cleanup — Legacy chat-input-bar
Files:
Check:
libs/libs-ai/vitto-chat/src/lib/components/chat-input-bar/Step 1: Verify fully replaced by unified-input-bar (
grep -r "chat-input-bar" libs/ --include="*.ts" -l)Step 2: If zero imports: delete the directory
Step 3: If still imported: trace consumers, update to unified-input-bar
Step 4: Commit
Task 8.15: Developer Rootfs Image Build
Ordering note: This is placed in Phase 8 because Phases 1-7 use mocked VMs in unit and E2E tests. For real VM integration testing, deploy this rootfs to Hetzner after Phase 8 and run manual integration tests. The rootfs is NOT a blocking dependency for the test phases.
Files:
Create:
deployment/sandbox-orchestrator/Dockerfile.rootfs-developerCreate:
deployment/sandbox-orchestrator/vm-init-developer.shStep 1: Create Dockerfile.rootfs-developer (headless: Ubuntu 22.04, Node 20 LTS, yarn, Python 3, pip, Git, build-essential, SSH server, no desktop/VNC/Chrome)
Step 2: Create vm-init-developer.sh (mount proc/sys/dev/shm, seed entropy, configure network from kernel args, setup SSH keys, start sshd, keep-alive loop)
Step 3: Test local build:
cd deployment/sandbox-orchestrator && docker build -f Dockerfile.rootfs-developer -t rootfs-developer .Step 4: Commit
Task 8.16: Final Integration Verification
- Step 1: Run backend-vitto-api full test suite:
cd APIs/backend-vitto-api && npx jest --no-coverage --forceExit - Step 2: Run sandbox-orchestrator test suite:
cd APIs/sandbox-orchestrator && npx jest --no-coverage - Step 3: Run affected NX libs tests:
yarn nx affected:test --base=main - Step 4: Verify no deprecated service has active imports:
grep -r "TrustEscalationService" libs/ APIs/ --include="*.ts" -l
grep -r "WorkflowSSEClientService" libs/ --include="*.ts" -l
grep -r "chat-input-bar" libs/ --include="*.ts" -l
Each should return 0 results (or only the deprecated file itself with @deprecated annotation).
- Step 5: Run Angular build for affected apps:
yarn nx affected:build --base=main - Step 6: Commit any final fixes
Summary
| Phase | Tasks | Sessions | Focus |
|---|---|---|---|
| 0. Configuration & Prerequisites | 1 | 0.5 | Env vars, MongoDB collections/indexes |
| 1. Sandbox-Orchestrator Endpoints | 1 | 1 | Structured file ops + SSH key injection |
| 2. Backend-AI-API Proxy | 1 | 1 | 9 endpoints proxying SelfHostedProvider |
| 3. VM Execution Layer | 5 | 2 | VmApiClient, SessionManager, ToolProxy, wiring |
| 4. Adaptive Trust | 5 | 2 | TrustScoring, TierResolver, AutonomyGate, wiring |
| 5. Proactive Intelligence | 2 | 1 | TriggerEngine, pattern detection, dispatch |
| 6. Checkpoint + Nesting | 3 | 1 | TaskRecovery, depth-2 nesting |
| 7. E2E Tests | 5 | 2 | VM, trust, triggers, recovery, nesting E2E |
| 8. Frontend + Deprecation Cleanup | 16 | 3 | Types, components, cards, SSE, deprecation removal |
| Total | 39 | ~13.5 |