blob: 1f0afa6d946cb388f4a0393f67952d63afbf7801 [file]
import { createHash } from 'node:crypto';
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import type { ResultRecord } from './contracts.js';
import {
auditSelfCheckPlanConsistency,
isAcceptedHeavyTaskSelfCheck,
} from './heavy-task-self-check.js';
import {
isTerminalTaskRunStatus,
type AutonomousResultTaxonomy,
type HeavyTaskSelfCheckPlanAuditSummary,
type ScoreResult,
type TaskEvent,
type VerifierResult,
} from './task-contracts.js';
import { resultRecordFromTaskRunProjection } from './task-run-adapter.js';
import type { TaskRunProjection } from './task-run-projection.js';
export interface TaskRunExport {
schemaVersion: 'maka.task_run_export.v1';
exportedAt: string;
taskRun: {
taskRunId: string;
taskId: string;
configId: string;
status: TaskRunProjection['status'];
startedAt?: number;
finishedAt?: number;
result?: TaskRunProjection['result'];
error?: TaskRunProjection['error'];
};
runtime: {
sessionId?: string;
agentRunId?: string;
attempts: TaskRunProjection['attempts'];
runtimeRefs?: unknown;
trajectoryRefs: {
sessionId?: string;
agentRunId?: string;
runtimeEventIds?: string[];
};
};
workspace: {
lease?: TaskRunProjection['workspaceLease'];
submittedSnapshot?: unknown;
primaryWorkspacePath?: string;
diff: {
status: 'present' | 'not_captured';
artifactRef?: string;
path?: string;
hash?: string;
};
};
artifacts: {
primaryWorkspacePath?: string;
items: TaskRunProjection['artifacts'];
byKind: Record<string, TaskRunProjection['artifacts']>;
};
verifier?: VerifierResult & { benchmark?: Record<string, unknown> };
score?: ScoreResult;
budget?: Record<string, unknown>;
economy?: {
tokens?: Record<string, unknown>;
tools?: Record<string, unknown>;
};
policy?: {
heavyTask?: TaskRunProjection['heavyTaskMode'];
economyTask?: TaskRunProjection['economyTaskMode'];
};
heavyTask?: {
mode?: TaskRunProjection['heavyTaskMode'];
completion: NonNullable<TaskRunProjection['heavyTaskCompletion']>;
selfCheckGate?: NonNullable<TaskRunProjection['latestHeavyTaskSelfCheckGate']>;
selfCheckPlan?: {
latest?: NonNullable<TaskRunProjection['latestHeavyTaskSelfCheckPlan']>;
audit?: HeavyTaskSelfCheckPlanAuditSummary;
};
};
progress?: {
inventory?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskInventory']>;
historyCount: number;
};
todos?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskTodos']>;
historyCount: number;
};
selfChecks?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskSelfCheck']>;
historyCount: number;
};
selfCheckPlans?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskSelfCheckPlan']>;
historyCount: number;
audit?: HeavyTaskSelfCheckPlanAuditSummary;
};
selfCheckGates?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskSelfCheckGate']>;
historyCount: number;
};
evidence?: {
latest: NonNullable<TaskRunProjection['latestHeavyTaskEvidence']>;
recent: TaskRunProjection['heavyTaskEvidence'];
historyCount: number;
};
};
isolation: {
policy?: TaskRunProjection['isolation'];
toolExecutors: TaskRunProjection['toolExecutors'];
permissions: {
requests: TaskRunProjection['permissionRequests'];
grants: TaskRunProjection['permissionGrants'];
};
};
inbox: {
parked?: TaskRunProjection['parked'];
items: TaskRunProjection['inboxItems'];
};
taxonomy: {
value: AutonomousResultTaxonomy | string;
passed: boolean;
scored?: boolean;
eligible?: boolean;
errorClass?: string;
excludedReason?: string;
};
warnings: string[];
legacyResultRecord: ResultRecord;
}
export interface WriteTaskRunExportOptions {
includeEvents?: boolean;
exportedAt?: string;
/** Defaults to events.jsonl. AHE uses task-events.jsonl to avoid confusing Task and Runtime ledgers. */
eventsFileName?: string;
}
export interface WriteTaskRunExportResult {
export: TaskRunExport;
files: {
taskRunJson: string;
resultJson: string;
resultMd: string;
eventsJsonl?: string;
};
}
export async function writeTaskRunExport(
outDir: string,
projection: TaskRunProjection,
options: WriteTaskRunExportOptions = {},
): Promise<WriteTaskRunExportResult> {
await mkdir(outDir, { recursive: true });
const rendered = taskRunExportFromProjection(projection, { exportedAt: options.exportedAt });
const files: WriteTaskRunExportResult['files'] = {
taskRunJson: join(outDir, 'task-run.json'),
resultJson: join(outDir, 'result.json'),
resultMd: join(outDir, 'result.md'),
};
await writeFile(files.taskRunJson, `${JSON.stringify(rendered, null, 2)}\n`, 'utf8');
await writeFile(
files.resultJson,
`${JSON.stringify(compactResultView(rendered), null, 2)}\n`,
'utf8',
);
await writeFile(files.resultMd, renderTaskRunMarkdown(rendered), 'utf8');
if (options.includeEvents) {
files.eventsJsonl = join(outDir, options.eventsFileName ?? 'events.jsonl');
await writeFile(files.eventsJsonl, eventsJsonl(projection.events), 'utf8');
}
return { export: rendered, files };
}
export function taskRunExportFromProjection(
projection: TaskRunProjection,
options: { exportedAt?: string } = {},
): TaskRunExport {
const legacyResultRecord = resultRecordFromTaskRunProjection(projection);
const score = projection.latestScoreResult;
const verifier = projection.latestVerifierResult;
const scoreDetails = score?.details ?? {};
const runtimeRefs = scoreDetails.runtimeRefs ?? runtimeRefsFromFeedback(projection);
const runtimeEventIds = runtimeEventIdsFrom(runtimeRefs);
const benchmark = verifierBenchmark(verifier);
const taxonomy =
score?.taxonomy ??
projection.result?.taxonomy ??
legacyResultRecord.errorClass ??
projection.status;
const primaryWorkspacePath = primaryWorkspacePathFromArtifacts(projection.artifacts);
const policy = policyFromProjection(projection);
const heavyTask = projection.heavyTaskCompletion
? {
mode: projection.heavyTaskMode,
completion: projection.heavyTaskCompletion,
...(projection.latestHeavyTaskSelfCheckGate
? { selfCheckGate: projection.latestHeavyTaskSelfCheckGate }
: {}),
...(projection.latestHeavyTaskSelfCheckPlan || projection.latestHeavyTaskSelfCheck
? {
selfCheckPlan: {
...(projection.latestHeavyTaskSelfCheckPlan
? { latest: projection.latestHeavyTaskSelfCheckPlan }
: {}),
audit: auditSelfCheckPlanConsistency(
projection.latestHeavyTaskSelfCheckPlan,
projection.latestHeavyTaskSelfCheck,
),
},
}
: {}),
}
: undefined;
const progress = progressFromProjection(projection);
return {
schemaVersion: 'maka.task_run_export.v1',
exportedAt: options.exportedAt ?? new Date().toISOString(),
taskRun: {
taskRunId: projection.taskRunId,
taskId: projection.taskId,
configId: projection.configId,
status: projection.status,
startedAt: projection.startedAt,
finishedAt: projection.finishedAt,
result: projection.result,
error: projection.error,
},
runtime: {
sessionId: projection.sessionId,
agentRunId: projection.agentRunId,
attempts: projection.attempts,
runtimeRefs,
trajectoryRefs: {
sessionId: projection.sessionId,
agentRunId: projection.agentRunId,
...(runtimeEventIds.length > 0 ? { runtimeEventIds } : {}),
},
},
workspace: {
lease: projection.workspaceLease,
submittedSnapshot: scoreDetails.submittedSnapshot ?? submittedSnapshotRef(verifier),
...(primaryWorkspacePath ? { primaryWorkspacePath } : {}),
diff: diffMetadata(scoreDetails, projection.artifacts),
},
artifacts: {
...(primaryWorkspacePath ? { primaryWorkspacePath } : {}),
items: projection.artifacts,
byKind: artifactsByKind(projection.artifacts),
},
verifier: verifier
? {
...verifier,
...(benchmark ? { benchmark } : {}),
}
: undefined,
score,
budget: recordValue(scoreDetails.budget)
? (scoreDetails.budget as Record<string, unknown>)
: undefined,
economy: economyFromDetails(scoreDetails),
policy,
heavyTask,
progress,
isolation: {
policy: projection.isolation,
toolExecutors: projection.toolExecutors,
permissions: {
requests: projection.permissionRequests,
grants: projection.permissionGrants,
},
},
inbox: {
parked: projection.parked,
items: projection.inboxItems,
},
taxonomy: {
value: taxonomy,
passed: score?.passed ?? projection.result?.passed ?? legacyResultRecord.passed,
scored: score?.scored ?? legacyResultRecord.scored,
eligible: score?.eligible ?? legacyResultRecord.eligible,
errorClass:
score?.errorClass ??
verifier?.errorClass ??
projection.error?.class ??
legacyResultRecord.errorClass,
excludedReason: score?.excludedReason ?? legacyResultRecord.excludedReason,
},
warnings: projection.warnings,
legacyResultRecord,
};
}
export function renderTaskRunMarkdown(exported: TaskRunExport): string {
const score = exported.score;
const verifier = exported.verifier;
const lines = [
`# Task Run ${md(exported.taskRun.taskRunId)}`,
'',
`- task: ${md(exported.taskRun.taskId)}`,
`- config: ${md(exported.taskRun.configId)}`,
`- status: ${md(exported.taskRun.status)}`,
`- taxonomy: ${md(String(exported.taxonomy.value))}`,
`- passed: ${exported.taxonomy.passed ? 'true' : 'false'}`,
`- scored: ${score?.scored === undefined ? 'unknown' : String(score.scored)}`,
`- eligible: ${score?.eligible === undefined ? 'unknown' : String(score.eligible)}`,
`- verifier: ${verifier ? md(verifier.kind) : 'none'}`,
`- verifier_exit_code: ${verifier?.exitCode ?? 'null'}`,
`- score: ${scoreValue(score)}`,
`- verifier_authority: ${authorityValue(verifier?.authority)}`,
`- submitted_snapshot: ${snapshotValue(exported.workspace.submittedSnapshot)}`,
`- diff: ${exported.workspace.diff.status}`,
`- artifacts: ${exported.artifacts.items.length}`,
`- tool_calls: ${exported.economy?.tools?.actualToolCalls ?? 'unknown'}`,
`- tokens: ${exported.economy?.tokens?.total ?? 'unknown'}`,
'',
];
if (exported.artifacts.items.length > 0) {
lines.push(
'## artifacts',
'',
...exported.artifacts.items.map(
(artifact) =>
`- ${md(artifact.kind)} ${md(artifact.workspacePath ?? artifact.path ?? artifact.artifactRef ?? artifact.artifactId)}`,
),
'',
);
}
if (verifier?.stdout) {
lines.push('## verifier_stdout', '', fence(verifier.stdout), '');
}
if (verifier?.stderr) {
lines.push('## verifier_stderr', '', fence(verifier.stderr), '');
}
if (exported.warnings.length > 0) {
lines.push('## warnings', '', ...exported.warnings.map((warning) => `- ${md(warning)}`), '');
}
return `${lines.join('\n')}\n`;
}
function compactResultView(exported: TaskRunExport): Record<string, unknown> {
return {
schemaVersion: exported.schemaVersion,
taskRun: exported.taskRun,
taxonomy: exported.taxonomy,
verifier: exported.verifier
? {
id: exported.verifier.id,
kind: exported.verifier.kind,
passed: exported.verifier.passed,
exitCode: exported.verifier.exitCode ?? null,
errorClass: exported.verifier.errorClass,
authority: exported.verifier.authority,
benchmark: exported.verifier.benchmark,
}
: undefined,
score: exported.score,
economy: exported.economy,
policy: exported.policy,
heavyTask: exported.heavyTask,
progress: exported.progress,
workspace: exported.workspace,
artifacts: exported.artifacts,
legacyResultRecord: exported.legacyResultRecord,
};
}
function runtimeRefsFromFeedback(projection: TaskRunProjection): unknown {
return projection.feedback.find((observation) => recordValue(observation.details?.runtimeRefs))
?.details?.runtimeRefs;
}
function progressFromProjection(projection: TaskRunProjection): TaskRunExport['progress'] {
const progress: NonNullable<TaskRunExport['progress']> = {};
if (projection.latestHeavyTaskInventory) {
progress.inventory = {
latest: projection.latestHeavyTaskInventory,
historyCount: projection.heavyTaskInventory.length,
};
}
if (projection.latestHeavyTaskTodos) {
progress.todos = {
latest: projection.latestHeavyTaskTodos,
historyCount: projection.heavyTaskTodoStates.length,
};
}
if (projection.latestHeavyTaskSelfCheck) {
progress.selfChecks = {
latest: projection.latestHeavyTaskSelfCheck,
historyCount: projection.heavyTaskSelfChecks.length,
};
}
if (projection.latestHeavyTaskSelfCheckPlan) {
progress.selfCheckPlans = {
latest: projection.latestHeavyTaskSelfCheckPlan,
historyCount: projection.heavyTaskSelfCheckPlans.length,
audit: auditSelfCheckPlanConsistency(
projection.latestHeavyTaskSelfCheckPlan,
projection.latestHeavyTaskSelfCheck,
),
};
}
if (projection.latestHeavyTaskSelfCheckGate) {
progress.selfCheckGates = {
latest: projection.latestHeavyTaskSelfCheckGate,
historyCount: projection.heavyTaskSelfCheckGates.length,
};
}
if (projection.latestHeavyTaskEvidence) {
progress.evidence = {
latest: projection.latestHeavyTaskEvidence,
recent: projection.heavyTaskEvidence.slice(-25),
historyCount: projection.heavyTaskEvidence.length,
};
}
return progress.inventory ||
progress.todos ||
progress.selfChecks ||
progress.selfCheckPlans ||
progress.selfCheckGates ||
progress.evidence
? progress
: undefined;
}
function runtimeEventIdsFrom(runtimeRefs: unknown): string[] {
if (!recordValue(runtimeRefs) || !Array.isArray(runtimeRefs.runtimeEventIds)) return [];
return runtimeRefs.runtimeEventIds.filter((value): value is string => typeof value === 'string');
}
function submittedSnapshotRef(
verifier: VerifierResult | undefined,
): Record<string, unknown> | undefined {
return verifier?.submittedSnapshotId ? { id: verifier.submittedSnapshotId } : undefined;
}
function diffMetadata(
details: Record<string, unknown>,
artifacts: TaskRunProjection['artifacts'],
): TaskRunExport['workspace']['diff'] {
const diff = details.diff;
if (!recordValue(diff)) {
const artifact = artifacts.find((item) => item.kind === 'workspace_diff');
if (!artifact) return { status: 'not_captured' };
return {
status: 'present',
...(artifact.artifactRef ? { artifactRef: artifact.artifactRef } : {}),
...(artifact.path ? { path: artifact.path } : {}),
...(artifact.hash ? { hash: artifact.hash } : {}),
};
}
return {
status: 'present',
...(typeof diff.artifactRef === 'string' ? { artifactRef: diff.artifactRef } : {}),
...(typeof diff.path === 'string' ? { path: diff.path } : {}),
...(typeof diff.hash === 'string' ? { hash: diff.hash } : {}),
};
}
function primaryWorkspacePathFromArtifacts(
artifacts: TaskRunProjection['artifacts'],
): string | undefined {
return artifacts.find(
(artifact) => artifact.kind === 'container_workspace' && artifact.workspacePath,
)?.workspacePath;
}
function artifactsByKind(
artifacts: TaskRunProjection['artifacts'],
): Record<string, TaskRunProjection['artifacts']> {
const grouped: Record<string, TaskRunProjection['artifacts']> = {};
for (const artifact of artifacts) {
grouped[artifact.kind] = [...(grouped[artifact.kind] ?? []), artifact];
}
return grouped;
}
function verifierBenchmark(
verifier: VerifierResult | undefined,
): Record<string, unknown> | undefined {
if (!verifier?.details) return undefined;
return verifier.details;
}
function eventsJsonl(events: readonly TaskEvent[]): string {
const body = events
.flatMap(exportableTaskEvents)
.map((event) => JSON.stringify(event))
.join('\n');
return body.length > 0 ? `${body}\n` : '';
}
export function exportableTaskEvents(event: TaskEvent): TaskEvent[] {
if (event.type === 'heavy_task_self_check_plan_recorded') {
return event.plan.guard.status === 'accepted' ? [event] : [];
}
if (event.type === 'heavy_task_self_check_recorded') {
return isAcceptedHeavyTaskSelfCheck(event.selfCheck) ? [event] : [];
}
if (event.type === 'heavy_task_evidence_recorded') {
return event.evidence.public === true ? [event] : [];
}
return [event];
}
export function exportContentHash(value: unknown): string {
return `sha256:${createHash('sha256').update(JSON.stringify(value)).digest('hex')}`;
}
function scoreValue(score: ScoreResult | undefined): string {
if (!score) return 'none';
if (score.score !== undefined || score.maxScore !== undefined)
return `${score.score ?? 'unknown'}/${score.maxScore ?? 'unknown'}`;
return score.passed ? 'pass' : 'fail';
}
function authorityValue(authority: VerifierResult['authority']): string {
if (!authority) return 'none';
return `${authority.source} authoritative=${authority.authoritative ? 'true' : 'false'}`;
}
function snapshotValue(value: unknown): string {
if (!recordValue(value)) return 'none';
return typeof value.id === 'string' ? value.id : exportContentHash(value);
}
function fence(value: string): string {
return `\`\`\`\n${value.replace(/```/g, '``\\`')}\n\`\`\``;
}
function md(value: string): string {
return value.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
}
function economyFromDetails(scoreDetails: Record<string, unknown>): TaskRunExport['economy'] {
const budget = recordValue(scoreDetails.budget) ? scoreDetails.budget : undefined;
const tools = recordValue(scoreDetails.tools) ? scoreDetails.tools : undefined;
if (!budget && !tools) return undefined;
return {
...(recordValue(budget) && recordValue(budget.totals)
? { tokens: budget.totals as Record<string, unknown> }
: {}),
...(tools ? { tools } : {}),
};
}
function policyFromProjection(projection: TaskRunProjection): TaskRunExport['policy'] {
const policy: NonNullable<TaskRunExport['policy']> = {};
if (projection.heavyTaskMode?.enabled) {
policy.heavyTask = projection.heavyTaskMode;
}
if (projection.economyTaskMode?.enabled) {
policy.economyTask = projection.economyTaskMode;
}
return Object.keys(policy).length > 0 ? policy : undefined;
}
function recordValue(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}