269 lines
8.8 KiB
TypeScript
269 lines
8.8 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
export const COUNCIL_SCHEMA_VERSION = '1.0.0';
|
|
export const COUNCIL_PIPELINE_VERSION = '1.0.0';
|
|
|
|
export const councilGroupSchema = z.enum(['D', 'P']);
|
|
export type CouncilGroup = z.infer<typeof councilGroupSchema>;
|
|
|
|
export const stopReasonSchema = z.enum([
|
|
'max_rounds',
|
|
'convergence',
|
|
'bridge_validation_failed',
|
|
'grounding_failed',
|
|
'meta_validation_failed',
|
|
]);
|
|
|
|
export const validationFailureReasonSchema = z.enum([
|
|
'schema_invalid',
|
|
'unknown_id',
|
|
'cap_exceeded',
|
|
'repair_failed',
|
|
'parse_failed',
|
|
]);
|
|
|
|
export const droppedReasonSchema = z.enum([
|
|
'cap_top_ideas',
|
|
'cap_field_bullets',
|
|
'cap_entry_chars',
|
|
'cap_total_chars',
|
|
'invalid_reference',
|
|
'grounding_failed',
|
|
]);
|
|
|
|
export const rejectionReasonCodeSchema = z.enum([
|
|
'low_score',
|
|
'high_risk',
|
|
'insufficient_grounding',
|
|
'duplicate',
|
|
'out_of_scope',
|
|
'unknown_id',
|
|
'other',
|
|
]);
|
|
|
|
const schemaVersionField = z.literal(COUNCIL_SCHEMA_VERSION);
|
|
|
|
export const ideaContentSchema = z.object({
|
|
title: z.string().min(1),
|
|
hypothesis: z.string().min(1),
|
|
mechanism: z.string().min(1),
|
|
expected_outcome: z.string().min(1),
|
|
}).strict();
|
|
|
|
export const ideaGroundingSchema = z.object({
|
|
mve: z.string().min(1),
|
|
constraints: z.array(z.string().min(1)).min(1),
|
|
falsifiability_checks: z.array(z.string().min(1)).min(1),
|
|
}).strict();
|
|
|
|
export const ideaCardSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
idea_id: z.string().min(1),
|
|
group: councilGroupSchema,
|
|
round: z.number().int().min(1),
|
|
content: ideaContentSchema,
|
|
grounding: ideaGroundingSchema.optional(),
|
|
grounding_failed: z.boolean().optional(),
|
|
}).strict();
|
|
|
|
export const scoreSetSchema = z.object({
|
|
novelty: z.number().int().min(0).max(100),
|
|
feasibility: z.number().int().min(0).max(100),
|
|
impact: z.number().int().min(0).max(100),
|
|
testability: z.number().int().min(0).max(100),
|
|
}).strict();
|
|
|
|
export const ideaAssessmentSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
idea_id: z.string().min(1),
|
|
scores: scoreSetSchema,
|
|
decision: z.enum(['shortlist', 'hold', 'reject']),
|
|
notes: z.string().min(1),
|
|
}).strict();
|
|
|
|
export const bridgeIdeaSchema = z.object({
|
|
idea_id: z.string().min(1),
|
|
mechanism: z.string().min(1),
|
|
rationale: z.string().min(1),
|
|
}).strict();
|
|
|
|
export const bridgePacketSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
from_group: councilGroupSchema,
|
|
to_group: councilGroupSchema,
|
|
round: z.number().int().min(1),
|
|
top_ideas: z.array(bridgeIdeaSchema),
|
|
assumptions: z.array(z.string().min(1)),
|
|
risks: z.array(z.string().min(1)),
|
|
asks: z.array(z.string().min(1)),
|
|
what_to_steal: z.array(z.string().min(1)),
|
|
}).strict();
|
|
|
|
export const councilBriefSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
group: councilGroupSchema,
|
|
round: z.number().int().min(1),
|
|
ideas: z.array(ideaCardSchema),
|
|
assessments: z.array(ideaAssessmentSchema),
|
|
shortlist: z.array(z.string().min(1)),
|
|
assumptions: z.array(z.string().min(1)),
|
|
risks: z.array(z.string().min(1)),
|
|
asks: z.array(z.string().min(1)),
|
|
what_to_steal: z.array(z.string().min(1)),
|
|
convergence_signal: z.boolean(),
|
|
novelty_score: z.number().int().min(0).max(100),
|
|
repetition_rate: z.number().int().min(0).max(100),
|
|
}).strict();
|
|
|
|
export const councilDiffSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
group: councilGroupSchema,
|
|
from_round: z.number().int().min(1),
|
|
to_round: z.number().int().min(1),
|
|
idea_added: z.array(z.string().min(1)),
|
|
idea_removed: z.array(z.string().min(1)),
|
|
shortlist_added: z.array(z.string().min(1)),
|
|
shortlist_removed: z.array(z.string().min(1)),
|
|
score_changes: z.array(z.object({
|
|
idea_id: z.string().min(1),
|
|
from_total: z.number().int(),
|
|
to_total: z.number().int(),
|
|
}).strict()),
|
|
assumptions_added: z.array(z.string().min(1)),
|
|
assumptions_removed: z.array(z.string().min(1)),
|
|
mve_changed: z.array(z.string().min(1)),
|
|
}).strict();
|
|
|
|
export const mergeRecordSchema = z.object({
|
|
sources: z.array(z.string().min(1)).min(2),
|
|
result_title: z.string().min(1),
|
|
rationale: z.string().min(1),
|
|
}).strict();
|
|
|
|
export const metaSelectionSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
selected_primary: z.array(z.string().min(1)),
|
|
selected_secondary: z.array(z.string().min(1)),
|
|
merges: z.array(mergeRecordSchema).optional(),
|
|
rejections: z.array(z.object({
|
|
idea_id: z.string().min(1),
|
|
reason_code: rejectionReasonCodeSchema,
|
|
}).strict()),
|
|
open_questions: z.array(z.string().min(1)),
|
|
next_experiments: z.array(z.string().min(1)),
|
|
}).strict();
|
|
|
|
export const councilTraceEventSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
event_id: z.string().min(1),
|
|
phase_index: z.number().int().min(1),
|
|
call_id: z.string().min(1),
|
|
group: councilGroupSchema.optional(),
|
|
round: z.number().int().min(1).optional(),
|
|
prompt_payload_hash: z.string().length(64),
|
|
artifact_hash: z.string().length(64).optional(),
|
|
token_usage: z.object({
|
|
inputTokens: z.number().int().min(0),
|
|
outputTokens: z.number().int().min(0),
|
|
}).strict().optional(),
|
|
latency_ms: z.number().int().min(0).optional(),
|
|
dropped_reason: droppedReasonSchema.optional(),
|
|
validation_failure: validationFailureReasonSchema.optional(),
|
|
}).strict();
|
|
|
|
export const councilConversationTurnSchema = z.object({
|
|
schema_version: schemaVersionField,
|
|
phase_index: z.number().int().min(1),
|
|
call_id: z.string().min(1),
|
|
agent: z.string().min(1),
|
|
tier: z.enum(['fast', 'default', 'complex', 'local']),
|
|
group: councilGroupSchema.optional(),
|
|
round: z.number().int().min(1).optional(),
|
|
prompt_payload: z.record(z.string(), z.unknown()),
|
|
response: z.string(),
|
|
usage: z.object({
|
|
inputTokens: z.number().int().min(0),
|
|
outputTokens: z.number().int().min(0),
|
|
}).strict(),
|
|
}).strict();
|
|
|
|
export const stopSnapshotSchema = z.object({
|
|
stop_reason: stopReasonSchema,
|
|
round_reached: z.number().int().min(1),
|
|
final_shortlist_D: z.array(z.string().min(1)),
|
|
final_shortlist_P: z.array(z.string().min(1)),
|
|
bridge_validated: z.boolean(),
|
|
grounding_failures_count: z.number().int().min(0),
|
|
}).strict();
|
|
|
|
export const councilRunResultSchema = z.object({
|
|
pipeline_version: z.literal(COUNCIL_PIPELINE_VERSION),
|
|
input_hash: z.string().length(64),
|
|
brief_D_v1: councilBriefSchema,
|
|
brief_P_v1: councilBriefSchema,
|
|
brief_D_v2: councilBriefSchema,
|
|
brief_P_v2: councilBriefSchema,
|
|
diff_D: councilDiffSchema,
|
|
diff_P: councilDiffSchema,
|
|
bridge_D_to_P: bridgePacketSchema,
|
|
bridge_P_to_D: bridgePacketSchema,
|
|
meta: metaSelectionSchema,
|
|
stop_snapshot: stopSnapshotSchema,
|
|
trace: z.array(councilTraceEventSchema),
|
|
conversations: z.array(councilConversationTurnSchema),
|
|
}).strict();
|
|
|
|
export const councilRunInputSchema = z.object({
|
|
task: z.string().min(1),
|
|
constraints: z.union([z.string().min(1), z.record(z.string(), z.unknown())]).optional(),
|
|
success_definition: z.string().min(1).optional(),
|
|
budget: z.record(z.string(), z.unknown()).optional(),
|
|
timebox: z.union([z.string().min(1), z.number().positive()]).optional(),
|
|
output_format: z.string().min(1).optional(),
|
|
max_rounds: z.number().int().min(1).max(6).optional(),
|
|
session_id: z.string().min(1).optional(),
|
|
}).strict();
|
|
|
|
export const ideationOutputSchema = z.object({
|
|
ideas: z.array(ideaContentSchema).min(1),
|
|
}).strict();
|
|
|
|
export const assessmentOutputSchema = z.object({
|
|
assessments: z.array(z.object({
|
|
idea_id: z.string().min(1),
|
|
scores: scoreSetSchema,
|
|
decision: z.enum(['shortlist', 'hold', 'reject']),
|
|
notes: z.string().min(1),
|
|
}).strict()),
|
|
assumptions: z.array(z.string().min(1)),
|
|
risks: z.array(z.string().min(1)),
|
|
asks: z.array(z.string().min(1)),
|
|
what_to_steal: z.array(z.string().min(1)),
|
|
convergence_signal: z.boolean(),
|
|
novelty_score: z.number().int().min(0).max(100),
|
|
repetition_rate: z.number().int().min(0).max(100),
|
|
}).strict();
|
|
|
|
export const groundingOutputSchema = z.object({
|
|
grounded: z.array(z.object({
|
|
idea_id: z.string().min(1),
|
|
mve: z.string().min(1),
|
|
constraints: z.array(z.string().min(1)).min(1),
|
|
falsifiability_checks: z.array(z.string().min(1)).min(1),
|
|
}).strict()),
|
|
}).strict();
|
|
|
|
export type StopReason = z.infer<typeof stopReasonSchema>;
|
|
export type ValidationFailureReason = z.infer<typeof validationFailureReasonSchema>;
|
|
export type DroppedReason = z.infer<typeof droppedReasonSchema>;
|
|
export type IdeaCard = z.infer<typeof ideaCardSchema>;
|
|
export type IdeaAssessment = z.infer<typeof ideaAssessmentSchema>;
|
|
export type BridgePacket = z.infer<typeof bridgePacketSchema>;
|
|
export type CouncilBrief = z.infer<typeof councilBriefSchema>;
|
|
export type CouncilDiff = z.infer<typeof councilDiffSchema>;
|
|
export type CouncilRunInput = z.infer<typeof councilRunInputSchema>;
|
|
export type CouncilRunResult = z.infer<typeof councilRunResultSchema>;
|
|
export type CouncilTraceEvent = z.infer<typeof councilTraceEventSchema>;
|
|
export type CouncilConversationTurn = z.infer<typeof councilConversationTurnSchema>;
|
|
export type MetaSelection = z.infer<typeof metaSelectionSchema>;
|