Require two materials for content schedules and scope readiness copy

The engine plans each production piece from a pair of documents, so a
summary, quiz or similar schedule with one material can never plan. Approving
such a plan is now blocked with a note to choose or upload another material,
and the engine's refusal on an existing schedule is explained in plain
language. Video and research schedules still work with one material.

The engine now checks only a schedule's own material before a run, so the
run error and Upload texts no longer say the whole Library or Brain is
checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Iqbal
2026-10-28 16:37:56 +07:00
parent d1492b9c76
commit a73a5a3fdf
6 changed files with 51 additions and 18 deletions

View File

@@ -3,7 +3,7 @@
// use run_schedule (one run per day or week; a video run renders one video).
import { opKey, request } from '../api/client'
import { listDocuments, type Agent, type RunSchedule } from '../api/engine'
import { getLang } from '../i18n'
import { getLang, t } from '../i18n'
import {
KINDS, LANGUAGES, SCHEDULABLE, videoCadence, weeklyTarget,
type ContentKind, type ContentRule, type OutputLanguage, type Per, type ResearchRule, type Rule,
@@ -110,6 +110,15 @@ export const listSchedules = () => expressAgents()
/** Schedules made of one engine run per slot (research, video), rather than weekly production plans. */
export const isRunSchedule = (rule: Rule) => rule.type === 'research' || rule.kind === 'video'
// The engine plans each production piece from a pair of documents, so a content schedule
// with fewer ready sources than this cannot plan anything. Video and research runs need one.
export const MIN_PRODUCTION_SOURCES = 2
export const needsTwoSources = (rule: Rule) => !isRunSchedule(rule)
const TOO_FEW_SOURCES = 'At least two ready sources with complementary evidence are required'
/** The engine's planner refusal, said in the UI language; any other message as it came. */
export const productionError = (message: string) =>
(message.includes(TOO_FEW_SOURCES) ? t('sch.tooFewSources', { n: MIN_PRODUCTION_SOURCES }) : message)
// Video length is fixed per schedule: 4 scenes, 40 seconds in all (the engine allows 4–15 s per scene).
export const VIDEO = { scenes: 4, seconds: 40 }
@@ -362,8 +371,8 @@ export interface RunSummary {
export const listRuns = (id: number) => request<RunSummary[]>(`${AGENTS}/${id}/runs`)
// What stops a run with knowledge_not_ready. The engine checks the whole Library, so a blocking
// document need not be part of the schedule's chosen material. This is the current state, not the run's.
// What stops a run with knowledge_not_ready: the schedule's own material that is not ready (the whole
// Library only for an agent with no material). This is the current state, not the run's.
export interface ReadinessIssue {
kind: 'document' | 'compose_set'
resource_id: number