From 075cd765c5a1815dd1ef86950f71cd6401b09bf7 Mon Sep 17 00:00:00 2001 From: Kartios Date: Wed, 19 Aug 2026 02:22:15 -0700 Subject: [PATCH] Stop seeding illustrative Cap rows onto Learn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `supply` and `demand` concept tracks each carried one `DEMO — ` card embedding a public recording from the Cap instance at video.karti.ai. Both are gone, for two reasons that arrived together. One of the recordings is no longer there. `sjqqvthbfma27bm` now answers 404 on both `/s/` and `/embed/`, so "DEMO — What a hold takes off the board" promised six seconds of teaching and played a dead frame. That is precisely the failure the comment above these rows was written to record the last time it happened, and it came back — because the footage lives on an instance this repository does not control, so no amount of care in this file can keep the claim true. Checked just now rather than assumed: the surviving id, `1rqq9rk4dpp71fd`, still answers 200. The other reason is judgement. /learn is the page deliberately shown to people outside this company, and a `DEMO — ` card sitting beside genuine product footage makes the whole page read as half-placeholder to exactly the audience it exists to convince. The previous version of this file argued the opposite — that an empty track hides the shape of the page — and that was the wrong trade. An empty concept track renders an empty state saying nothing has been published to it yet, which is true, and true beats furnished. `seedLearn` and its call site go with them rather than being left as an empty array behind live machinery. If those tracks get purpose-shot recordings they belong in `HOSTED_LEARN_MANIFEST`, rendered by `scripts/learn-film.mjs` like the platform track, and served by PIG itself. The two rows were also deleted from production directly, matching what `clear()` does for prefixed learn rows, so the page is correct now rather than at the next reseed. The underlying Cap recording is untouched. --- packages/db/src/seed/demo/index.ts | 6 +- packages/db/src/seed/demo/learn.ts | 137 +++++------------------------ 2 files changed, 24 insertions(+), 119 deletions(-) diff --git a/packages/db/src/seed/demo/index.ts b/packages/db/src/seed/demo/index.ts index d3a2fbc..0632916 100644 --- a/packages/db/src/seed/demo/index.ts +++ b/packages/db/src/seed/demo/index.ts @@ -55,7 +55,7 @@ import { seedCalendar } from './calendar'; import { seedCompliance } from './compliance'; import { seedDemandPaper } from './contracts'; import { seedDemand } from './demand'; -import { seedHostedLearn, seedLearn } from './learn'; +import { seedHostedLearn } from './learn'; import { seedMotionEngagements } from './motion'; import { seedSupply } from './supply'; @@ -167,7 +167,6 @@ export async function seedDemo(context: DemoContext): Promise { const ownerUserId = owner?.id ?? null; const calendar = await seedCalendar(context, ownerUserId); - const learn = await seedLearn(context, ownerUserId); // The self-hosted set, which is real rather than invented — see the long // note on `seedHostedLearn`. Folded into the demo seed so one command gives @@ -220,9 +219,6 @@ export async function seedDemo(context: DemoContext): Promise { `${compliance.decisions.total} export-control decisions (allow, needs_review, block), ` + `${calendar.total} calendar entries (${calendar.added} new)`, ); - console.log( - ` ${learn.total} illustrative concept videos (${learn.added} new), members-only`, - ); console.log( ` ${motion.engagements} Motion engagement(s) with ${motion.artifacts} artefact(s) and ` + `${motion.scores} qualification score(s) — ${motion.promoted} artefact promoted back into ` + diff --git a/packages/db/src/seed/demo/learn.ts b/packages/db/src/seed/demo/learn.ts index 4b59060..d329e8e 100644 --- a/packages/db/src/seed/demo/learn.ts +++ b/packages/db/src/seed/demo/learn.ts @@ -1,10 +1,28 @@ /** - * The Learn library: the illustrative demo rows, and the PIG-hosted real ones. + * The Learn library: the PIG-hosted recordings. * - * They sit in one module because they write to one table and share the - * idempotency key, but they are not the same kind of data: the first set is - * invented and prefixed, the second is genuine product footage and survives - * `--clear`. + * There used to be two illustrative rows here as well, embedding public + * recordings from the Cap instance at video.karti.ai under `DEMO — ` titles, so + * that the `supply` and `demand` concept tracks were not empty. Both are gone, + * for two reasons that arrived together. + * + * One of the two recordings had since been removed from that instance: + * `sjqqvthbfma27bm` answers 404 on both `/s/` and `/embed/`, so the card + * promised six seconds of teaching and played a dead frame. That is the exact + * failure the previous version of this comment was written to record — an id + * that 404s behind a card that claims content — and it came back because the + * footage lives somewhere this repository does not control. + * + * The other is judgement: /learn is the page deliberately shown to outsiders, + * and a `DEMO — ` card sitting beside genuine product footage makes the whole + * page read as half-placeholder to exactly the audience it exists to convince. + * An empty concept track renders a proper empty state saying nothing has been + * published yet, which is true and says so. + * + * If `supply` and `demand` get purpose-shot recordings, they belong in + * `HOSTED_LEARN_MANIFEST` below and rendered by `scripts/learn-film.mjs` like + * the platform track, not embedded from an instance whose contents can change + * underneath this file. */ import { LEARN_MEDIA_PATH_PREFIX, isLearnMediaFilename, learnMediaContentType } from '@pig/core'; import { eq } from 'drizzle-orm'; @@ -13,115 +31,6 @@ import { resolve } from 'node:path'; import { learnResources, users } from '../../schema/index'; import type { DemoContext } from './index'; -/** - * Every id below is a REAL public recording on the Cap instance at - * video.karti.ai, and every duration is the MEASURED length of the file that - * embed plays. Both were re-checked against the instance — `/s/` and - * `/embed/` answer 200, and the recordings are 60.4s and 6.2s — because - * this list previously stated neither truthfully. - * - * It used to carry four rows, two of them sharing the id `0n6n9p83efnxbs2` - * under different titles and different stated lengths. That id is not a - * recording at all — it 404s, and the only other place it appears in this - * repository is as the fixture string in `apps/api/test/learn.test.ts`, which - * is almost certainly where it was copied from. So two cards each promised a - * quarter of an hour of teaching and played nothing, on the one page that is - * deliberately shown to outsiders. A card that lies about its own content is - * worse than a track with one card in it, and there are exactly two public - * recordings on that instance — so there are exactly two rows here, one per - * concept track. - * - * The titles remain illustrative and prefixed, which is the standing bargain - * for demo rows: the concepts they name are the ones this business actually - * teaches, and the footage behind them is whatever genuinely exists. The - * bargain only holds while the stated LENGTH is true, since that is the one - * claim a viewer can check before pressing play. - * - * PLATFORM rows are not seeded here. The five real recordings in - * HOSTED_LEARN_MANIFEST cover that track, and illustrative Cap rows beneath - * genuine ones made the page read as half-placeholder to the exact audience it - * is meant to convince. - * - * The concept rows stay: `supply` and `demand` have no purpose-shot recordings - * yet, and an empty track hides the shape of the page. They are - * `members`-visible, which the CHECK constraint enforces anyway — only - * `platform` may be `code`. - */ -export async function seedLearn( - context: DemoContext, - ownerUserId: string | null, -): Promise<{ total: number; added: number }> { - const { db, prefix } = context; - - const LEARN_RESOURCES = [ - { - track: 'supply' as const, - title: `${prefix}How neocloud capacity is actually priced`, - summary: 'Reserved versus on-demand, commitment length, and where the spread comes from.', - externalId: '1rqq9rk4dpp71fd', - visibility: 'members' as const, - // 60.4s on the wire, rounded down: a duration that overstates by a - // second is the same class of claim as one that overstates by minutes. - durationSeconds: 60, - sortOrder: 10, - }, - { - track: 'demand' as const, - title: `${prefix}What a hold takes off the board`, - summary: - 'A hold reserves hours nobody else can be quoted, and it is not revenue until it converts.', - externalId: 'sjqqvthbfma27bm', - visibility: 'members' as const, - durationSeconds: 6, - sortOrder: 10, - }, - ]; - - /* - * The unique key is (track, provider, external_id), so the SAME recording on - * TWO tracks inserts perfectly happily — which is how one id came to sit - * behind two different titles and two different stated durations for as long - * as it did. The database cannot catch that; this can. Thrown before any - * insert, and loudly, because it is a typo in a literal rather than a - * condition of the environment: there is nothing for an operator to fix at - * run time and nothing worth continuing past. - */ - const ids = LEARN_RESOURCES.map((resource) => resource.externalId); - if (new Set(ids).size !== ids.length) { - throw new Error( - 'Two demo learn resources share an external id — one of them would be a lie about its own content.', - ); - } - - let learnAdded = 0; - for (const resource of LEARN_RESOURCES) { - // Idempotent on the unique key rather than an existence check, which is - // the whole reason that constraint exists: onConflictDoNothing without one - // is a silent no-op and has duplicated seed data here twice before. - const inserted = await db - .insert(learnResources) - .values({ - track: resource.track, - title: resource.title, - summary: resource.summary, - url: `https://video.karti.ai/s/${resource.externalId}`, - provider: 'cap', - externalId: resource.externalId, - visibility: resource.visibility, - durationSeconds: resource.durationSeconds, - sortOrder: resource.sortOrder, - addedByUserId: ownerUserId, - }) - .onConflictDoNothing({ - target: [learnResources.track, learnResources.provider, learnResources.externalId], - }) - .returning({ id: learnResources.id }); - if (inserted.length) learnAdded += 1; - } - - return { total: LEARN_RESOURCES.length, added: learnAdded }; -} - // ------------------------------------------------------- PIG-hosted learn // // Real videos, served by PIG itself from PIG_MEDIA_DIR — not demo data. They