Submatter/packages/shared/src/convoy-lifecycle/schemas.ts
Randall Stillwell 6ccb060bea feat(second-brain): open self-hosted Obsidian for crews — harness-agnostic v0.1
- MCP create-backlog-item for natural language Plan/Epic/Task authoring
- Worker non-code: optional worktree + per-harness allowlist + doc_review→published
- Harness registry: harness_providers/role_harness_routes, WorkerAdapter (minimal|crewai|langgraph|remote-ag-ui), AG-UI POST /api/ag-ui, Settings → Harnesses with Test
- Plans tree: backlog.listTree + createPlan/Epic/Task + Start→Convoy, web CRUD without CLI
- Fleet: /fleet rollup across workspaces + SSE /api/fleet/events

Decision: docs/decisions/2026-08-25-second-brain-os-pivot.md
Convoy: .convoys/second-brain-os-v01

Co-authored-by: orchestrator
2026-08-25 16:20:53 -05:00

92 lines
2.4 KiB
TypeScript

import { z } from "zod";
import { convoyModelPolicySchema } from "../model-routing/schemas";
export const convoyStatusSchema = z.enum([
"draft",
"convoy_review",
"ready",
"in_progress",
"pr_review",
"doc_review",
"merged",
"published",
"released",
"blocked",
"cancelled",
]);
export type ConvoyStatus = z.infer<typeof convoyStatusSchema>;
export const convoyClassificationSchema = z.enum([
"feature",
"hotfix",
"docs-only",
"infra-only",
"server-only",
"config-only",
]);
export type ConvoyClassification = z.infer<typeof convoyClassificationSchema>;
export const convoyFileStatusSchema = z.enum([
"open",
"in-progress",
"merged",
"shipped",
"abandoned",
]);
export type ConvoyFileStatus = z.infer<typeof convoyFileStatusSchema>;
export const convoyActorSchema = z.string().min(1).max(64);
export const convoyEventTypeSchema = z.enum([
"role_complete",
"status_change",
"brief_created",
"reconcile",
]);
export type ConvoyEventType = z.infer<typeof convoyEventTypeSchema>;
export const convoyObjectContentSchema = z.object({
convoySlug: z.string().min(1).max(120),
classification: convoyClassificationSchema,
skipFlags: z.array(z.string()).default([]),
successMetric: z.string().min(1),
modelPolicy: convoyModelPolicySchema.optional(),
backlogItemId: z.string().uuid().optional(),
repoPath: z.string().min(1).optional(),
planSlug: z.string().min(1).optional(),
epicSlug: z.string().min(1).optional(),
briefFiles: z.array(z.string()).optional(),
});
export type ConvoyObjectContent = z.infer<typeof convoyObjectContentSchema>;
export const briefObjectContentSchema = z.object({
briefNumber: z.number().int().positive(),
files: z.array(z.string()).default([]),
sliceDependencies: z.array(z.number().int().positive()).default([]),
acceptance: z.string().optional(),
});
export type BriefObjectContent = z.infer<typeof briefObjectContentSchema>;
export const transitionConvoyInputSchema = z.object({
convoyId: z.string().uuid(),
toStatus: convoyStatusSchema,
actor: convoyActorSchema,
reason: z.string().min(1).max(2_000).optional(),
});
export type TransitionConvoyInput = z.infer<typeof transitionConvoyInputSchema>;
export const convoyTransitionErrorCodeSchema = z.enum([
"INVALID_TRANSITION",
"FORBIDDEN_ACTOR",
"REASON_REQUIRED",
]);
export type ConvoyTransitionErrorCode = z.infer<typeof convoyTransitionErrorCodeSchema>;