Trovella Wiki

Lifecycle Tracking

How skill executions are persisted, tracked, and queried -- the skill_execution table, log_skill_execution MCP tool, tRPC admin router, and metadata conventions.

Every research skill invocation is tracked from start to completion in the skill_execution table. This page covers the database schema, the MCP tool that writes records, the tRPC router that reads them, and the metadata conventions that make the data useful.

Database Schema

The skill_execution table is defined in packages/db/src/schema/research.ts:

export const skillExecution = pgTable(
  "skill_execution",
  {
    id: text("id").primaryKey(),
    organizationId: text("organization_id").notNull(),
    userId: text("user_id")
      .notNull()
      .references(() => user.id),
    skillName: text("skill_name").notNull(),
    status: skillExecutionStatusEnum("status").notNull().default("started"),
    planId: text("plan_id").references(() => researchPlan.id, { onDelete: "set null" }),
    metadata: jsonb("metadata").$type<Record<string, unknown>>(),
    errorMessage: text("error_message"),
    claudeCodeSessionId: text("claude_code_session_id"),
    startedAt: timestamp("started_at", { withTimezone: true }).defaultNow().notNull(),
    completedAt: timestamp("completed_at", { withTimezone: true }),
    durationMs: integer("duration_ms"),
    createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
  },
  // Indexes on organizationId, skillName, status, planId, createdAt
  // RLS via tenantPolicies("skill_execution", "organization_id")
);

Status Enum

Four statuses track the execution lifecycle:

StatusMeaningTerminal?
startedSkill invoked, interview/routing in progressNo
executingPlan created, step execution in progressNo
completedAll steps finished and output deliveredYes
failedExecution failed (step failure, user rejection, or error)Yes

Relationships

  • researchPlan -- one-to-one via planId. Set automatically by create_research_plan when the server auto-links the skill execution.
  • user -- many-to-one via userId.
  • mcpToolCallLog -- one-to-many. Each MCP tool call made during this execution is logged with a back-reference to the skill execution ID.

MCP Tool: log_skill_execution

Source: packages/mcp/src/tools/log-skill-execution.ts

This tool has dual behavior based on whether executionId is provided:

Create Mode (no executionId)

Called at the start of a skill invocation to create a new tracking record. Returns the generated executionId.

log_skill_execution({
  skillName: "research",     // "research" | "research-scan" | "research-deep"
  status: "started",
  metadata: { ... },         // interview data, routing rationale
  sessionId: "..."           // Claude Code session ID
})
// Returns: { executionId: "abc-123", skillName: "research", status: "started", stored: true }

Update Mode (with executionId)

Called to update status, link a plan, add metadata, or record completion/failure.

log_skill_execution({
  executionId: "abc-123",
  skillName: "research",
  status: "completed",
  metadata: { stepsCompleted: 3, artifactsStored: 2 }
})

Key Implementation Details

  • Metadata merging: Updates shallow-merge new metadata with existing metadata. Existing keys are overwritten by new values; keys not included in the update are preserved.
  • Duration calculation: When status transitions to completed or failed, the server calculates durationMs from startedAt to the current time and sets completedAt.
  • Tenant isolation: All operations go through withTenantContext(organizationId, userId, ...) for RLS enforcement.
  • Organization resolution: The user's active organization is resolved via resolveOrganizationId(auth.userId).

Auto-Linking via create_research_plan

The log_skill_execution update that links a plan to a skill execution is handled automatically by the create_research_plan tool. When create_research_plan receives a sessionId:

  1. Queries skill_execution for the most recent started row matching that session
  2. If found: updates planId, sets status = "executing", merges planDesignRationale into metadata
  3. If not found: no-op

This design eliminates a tool call that the AI platform might forget, ensuring plan linkage is guaranteed.

tRPC Admin Router

Source: packages/api/src/routers/skill-execution.ts

Three procedures provide read access for the admin UI, all gated by ctx.ability.cannot("read", "ResearchPlan"):

skillExecution.list

Paginated list with optional filters.

ParameterTypeDefaultDescription
limitnumber20Page size (1-100)
offsetnumber0Pagination offset
skillNamestring--Filter by skill name
statusenum--Filter by status

Returns { executions, total }. Each execution includes a left join to research_plan for planName and planStatus.

skillExecution.detail

Full detail for a single execution.

ParameterTypeDescription
executionIdstringThe execution ID

Returns { execution, plan, auditLog }:

  • execution -- the full skill execution row
  • plan -- the linked research plan (if planId is set)
  • auditLog -- plan audit log entries filtered by both planId and claudeCodeSessionId

skillExecution.summary

Aggregate KPIs for the dashboard.

Returns:

  • totalExecutions -- total count
  • byStatus -- counts grouped by status ({ started: 2, executing: 1, completed: 8, failed: 1 })
  • bySkill -- counts grouped by skill name ({ research: 5, "research-scan": 4, "research-deep": 3 })
  • avgDurationMs -- average duration of completed executions
  • recentFailures -- count of failures in the last 24 hours

Metadata Conventions

The metadata JSONB field stores all non-structural data about the skill invocation. Conventions are enforced by skill prompts, not by schema.

Phase 1 Interview Data

Stored on creation (log_skill_execution create call):

KeyTypeDescription
topicstringCore research subject
researchTypestringgeneral_topic, competitive_analysis, or decision_support
scopestringBreadth and depth boundaries
depthSignalsstringWords indicating desired depth
decisionContextstring or nullWhat decision this research informs
knownContextstring or nullWhat the user already knows
outputMediaTypestringconversation, markdown, html, word, excel, powerpoint
outputFormattingInstructionsstring or nullStyling/layout requirements
originalQuerystringUser's original message (up to 5000 chars)

Clarification Data

One of these is always present:

KeyTypeDescription
clarifyingQuestions[{ question, answer }]Questions asked and user responses
skipQuestionsReasonstringWhy questions were not needed

Routing Data

KeyTypeDescription
delegatedTo"scan" or "deep"Which mode was chosen
routingRationalestringFull explanation of the routing decision

Prior Research Check

Stored via update after search_sources:

KeyTypeDescription
priorResearchCheck.foundnumberCount of artifacts returned
priorResearchCheck.artifactIdsstring[]IDs of artifacts shown to user
priorResearchCheck.userConversationstringSummary of the user's response
priorResearchCheck.userDecisionstringuse_existing, refresh, or unique
priorResearchCheck.refreshContextstring or nullAdditional context for refresh
priorResearchCheck.closedReasonstring or nullReason session ended early

Completion Data

Stored via update when the skill completes:

KeyTypeDescription
stepsCompletednumberCount of completed plan steps
artifactsStorednumberCount of stored research artifacts
modestring"scan" or "deep"
checkpointFeedbackstring or nullSummary of checkpoint feedback (deep only)

Plan Design

Merged into metadata by the create_research_plan auto-link:

KeyTypeDescription
planDesignRationalestringWhy the plan was structured this way

Skill execution data connects to several other tables in the research schema:

TableRelationshipPurpose
research_planFK via planIdThe plan this skill execution created and drove
plan_stepVia planIndividual steps within the plan
plan_audit_logVia plan + sessionChronological event log filtered by session
mcp_tool_call_logFK via skill_execution_idEvery MCP tool call made during this execution
research_artifactVia planStored research outputs
research_outputVia planFinal deliverable
research_feedbackVia planUser satisfaction feedback

On this page