Route every document save through one lifecycle pipeline
Desktop IPC saves used to fire only automation and the reviewer wake, while HTTP API saves fired automation, thread integration, checkpoint engine, deliverable-review approval, and the reviewer wake. Two divergent paths produced two different lifecycle states for the same document, and a future fix to either branch would miss the other. Introduce `document-lifecycle.ts` as the single owner of document creation side effects: save, derive task binding from the originating run, fan out to automation/thread/checkpoint, wake the reviewer, then raise a deliverable-review approval when the document qualifies. The HTTP route and the IPC handler both call the pipeline — the API server's `onDocumentCreated` callback is replaced with a `createDocument` hook that delegates to the pipeline. Wire `checkpointEngine` through `bootstrap-application` → `main-runtime` → `main-runtime-support` so the IPC handler bag carries both thread integration and the checkpoint engine required by the pipeline. The document-run-provenance integration test harness is updated to pass a `createDocument` implementation backed by the same pipeline the production path uses.
This commit is contained in:
1 parent
ff9a52324e
commit
686140ae55
10 files changed
+357
-91
No files matched your search
@@ -7,6 +7,11 @@ import type { createServiceGraph } from "../service-graph";
|
||||
import type { createThreadIntegration } from "../thread-integration";
|
||||
import type { createCheckpointEngine } from "../checkpoint-engine";
|
||||
import type { AutomationEventContext } from "../automation/types";
|
||||
import {
|
||||
createDocumentWithLifecycle,
|
||||
type DocumentLifecycleInput,
|
||||
type DocumentLifecycleOutcome,
|
||||
} from "../document-lifecycle";
|
||||
|
||||
type ServiceGraph = ReturnType<typeof createServiceGraph>;
|
||||
type ThreadIntegration = ReturnType<typeof createThreadIntegration>;
|
||||
@@ -21,7 +26,7 @@ export interface CreateApiServerFn {
|
||||
onCommentPosted: (taskId: string, companyId: string, authorAgentId: string | null) => void;
|
||||
onApprovalCreated: (approvalId: string, companyId: string, taskId: string | null, approvalType: string, summary: string) => void;
|
||||
onApprovalResolved: (approvalId: string, companyId: string, decision: string) => void;
|
||||
onDocumentCreated: (companyId: string, authorAgentId: string | null, projectId: string | null, documentId: string, documentTitle: string, documentType: string, taskId: string | null) => void;
|
||||
createDocument: (input: DocumentLifecycleInput) => DocumentLifecycleOutcome;
|
||||
onAutoAssignTask: (taskId: string, companyId: string) => string | null;
|
||||
onHumanMessage: (companyId: string, toAgentId?: string | null, threadId?: string | null, waitStateId?: string | null) => void;
|
||||
injectRuntimeMessage: (recipientAgentId: string, companyId: string, message: AgentMessageRecord) => boolean;
|
||||
@@ -99,11 +104,19 @@ export function wireApiServer(deps: WireApiServerDeps): AgentApiServer {
|
||||
deps.threadIntegration.onApprovalCreated(approvalId, companyId, taskId, approvalType, summary);
|
||||
},
|
||||
onApprovalResolved,
|
||||
onDocumentCreated: (companyId, authorAgentId, projectId, documentId, documentTitle, documentType, taskId) => {
|
||||
dispatchAutomation("document_created", { companyId, agentId: authorAgentId ?? undefined, projectId: projectId ?? undefined });
|
||||
deps.threadIntegration.onDocumentCreated(companyId, authorAgentId, taskId, documentTitle);
|
||||
deps.checkpointEngine.onDocumentDrafted(companyId, documentId, documentTitle, documentType, authorAgentId, taskId);
|
||||
},
|
||||
createDocument: (input) =>
|
||||
createDocumentWithLifecycle(
|
||||
{
|
||||
db: deps.db,
|
||||
threadIntegration: deps.threadIntegration,
|
||||
checkpointEngine: deps.checkpointEngine,
|
||||
dispatchAutomation,
|
||||
wakeAgentIfPossible,
|
||||
publishDomainChanged: deps.publishDomainChanged,
|
||||
logger: log,
|
||||
},
|
||||
input,
|
||||
),
|
||||
onAutoAssignTask: (taskId, companyId) => deps.db.autoAssignTask(taskId, companyId),
|
||||
onHumanMessage: (companyId, toAgentId, threadId, waitStateId) => {
|
||||
deps.threadIntegration.onHumanMessage(companyId, toAgentId, threadId, waitStateId);
|
||||
|
||||
Reference in new issue
Block a user