feat(schema): card brief, transcript and size band

This commit is contained in:
Dave 2026-09-16 18:04:22 +02:00
parent 0c25a3e6a1
commit 05ce52a6bf
2 changed files with 52 additions and 0 deletions

View file

@ -235,6 +235,50 @@ async function ensureCommitSummaryFields(pb: PocketBase): Promise<void> {
* *
* Re-runs are safe: fields are not duplicated. * Re-runs are safe: fields are not duplicated.
*/ */
/**
* Add the `brief`, `transcript`, `size_band` fields used by Phase 4b's intake.
*
* `brief` is the JSON object the client confirmed in the wizard, kept verbatim
* after re-parsing through the same parseBrief whitelist. `transcript` is the
* question-and-answer pairs. `size_band` is derived in code from the
* decomposition, never taken from the model's output.
*
* Re-runs are safe: fields are not duplicated.
*/
async function ensureCardIntakeFields(pb: PocketBase): Promise<void> {
const cards = await pb.collections.getOne("cards");
const have = new Set(cards.fields.map((f: { name: string }) => f.name));
const additions = [
{ name: "brief", type: "json", required: false, maxSize: 200_000 },
{ name: "transcript", type: "json", required: false, maxSize: 200_000 },
{
name: "size_band",
type: "select",
required: false,
maxSelect: 1,
values: ["small", "medium", "large"],
},
];
const fields = [...(cards.fields as unknown[])];
let changed = false;
for (const field of additions) {
if (!have.has(field.name)) {
fields.push({ ...field, presentable: false, hidden: false, system: false });
changed = true;
}
}
if (changed) {
await pb.collections.update(cards.id, { fields });
console.log(" + cards fields: brief, transcript, size_band");
} else {
console.log(" = card intake fields already present");
}
}
async function ensureCardNarrativeFields(pb: PocketBase): Promise<void> { async function ensureCardNarrativeFields(pb: PocketBase): Promise<void> {
const cards = await pb.collections.getOne("cards"); const cards = await pb.collections.getOne("cards");
const have = new Set(cards.fields.map((f: { name: string }) => f.name)); const have = new Set(cards.fields.map((f: { name: string }) => f.name));
@ -862,6 +906,9 @@ async function main(): Promise<void> {
// Add the AI-generated card narrative fields used by Phase 3c. // Add the AI-generated card narrative fields used by Phase 3c.
await ensureCardNarrativeFields(pb); await ensureCardNarrativeFields(pb);
// Add the intake wizard's fields (brief, transcript, size_band) for Phase 4b.
await ensureCardIntakeFields(pb);
console.log("Done."); console.log("Done.");
} }

View file

@ -87,6 +87,11 @@ export interface CardRecord extends BaseRecord {
narrative_version: number; narrative_version: number;
/** Fingerprint of the commit set the narrative was written from. */ /** Fingerprint of the commit set the narrative was written from. */
narrative_shas: string; narrative_shas: string;
/** The intake brief, when this card came from the wizard. */
brief: unknown;
/** The interview question-and-answer pairs. */
transcript: unknown;
size_band: "small" | "medium" | "large" | "";
} }
export interface SubtaskRecord extends BaseRecord { export interface SubtaskRecord extends BaseRecord {