mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-02-12 17:22:50 +00:00
feat: copy deliverables to audit-logs for self-contained audit trail
This commit is contained in:
@@ -187,14 +187,49 @@ export async function fileExists(filePath: string): Promise<boolean> {
|
||||
|
||||
/**
|
||||
* Initialize audit directory structure for a session
|
||||
* Creates: audit-logs/{sessionId}/, agents/, prompts/
|
||||
* Creates: audit-logs/{sessionId}/, agents/, prompts/, deliverables/
|
||||
*/
|
||||
export async function initializeAuditStructure(sessionMetadata: SessionMetadata): Promise<void> {
|
||||
const auditPath = generateAuditPath(sessionMetadata);
|
||||
const agentsPath = path.join(auditPath, 'agents');
|
||||
const promptsPath = path.join(auditPath, 'prompts');
|
||||
const deliverablesPath = path.join(auditPath, 'deliverables');
|
||||
|
||||
await ensureDirectory(auditPath);
|
||||
await ensureDirectory(agentsPath);
|
||||
await ensureDirectory(promptsPath);
|
||||
await ensureDirectory(deliverablesPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy deliverable files from repo to audit-logs for self-contained audit trail.
|
||||
* No-ops if source directory doesn't exist. Idempotent and parallel-safe.
|
||||
*/
|
||||
export async function copyDeliverablesToAudit(
|
||||
sessionMetadata: SessionMetadata,
|
||||
repoPath: string
|
||||
): Promise<void> {
|
||||
const sourceDir = path.join(repoPath, 'deliverables');
|
||||
const destDir = path.join(generateAuditPath(sessionMetadata), 'deliverables');
|
||||
|
||||
let entries: string[];
|
||||
try {
|
||||
entries = await fs.readdir(sourceDir);
|
||||
} catch {
|
||||
// Source directory doesn't exist yet — nothing to copy
|
||||
return;
|
||||
}
|
||||
|
||||
await ensureDirectory(destDir);
|
||||
|
||||
for (const entry of entries) {
|
||||
const sourcePath = path.join(sourceDir, entry);
|
||||
const destPath = path.join(destDir, entry);
|
||||
|
||||
// Only copy files, skip subdirectories
|
||||
const stat = await fs.stat(sourcePath);
|
||||
if (stat.isFile()) {
|
||||
await fs.copyFile(sourcePath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ import type { WorkflowSummary } from '../audit/workflow-logger.js';
|
||||
import type { AgentName } from '../types/agents.js';
|
||||
import type { AgentMetrics } from './shared.js';
|
||||
import type { DistributedConfig } from '../types/config.js';
|
||||
import type { SessionMetadata } from '../audit/utils.js';
|
||||
import { copyDeliverablesToAudit, type SessionMetadata } from '../audit/utils.js';
|
||||
|
||||
const HEARTBEAT_INTERVAL_MS = 2000; // Must be < heartbeatTimeout (10min production, 5min testing)
|
||||
|
||||
@@ -251,6 +251,13 @@ async function runAgentActivity(
|
||||
});
|
||||
await commitGitSuccess(repoPath, agentName);
|
||||
|
||||
// 9.5. Copy deliverables to audit-logs (non-fatal)
|
||||
try {
|
||||
await copyDeliverablesToAudit(sessionMetadata, repoPath);
|
||||
} catch (copyErr) {
|
||||
console.error(`Failed to copy deliverables to audit-logs for ${agentName}:`, copyErr);
|
||||
}
|
||||
|
||||
// 10. Return metrics
|
||||
return {
|
||||
durationMs: Date.now() - startTime,
|
||||
|
||||
Reference in New Issue
Block a user