commit 968dd162a6143d910e784ef26ae49cf35a8121ff
parent ef89d816b56c77ec2b4f1d7bdde073690a413200
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Fri, 9 Oct 2026 10:17:19 -0400
umtool: articles and the notes inbox declare kinds on the registry, never by id
links.mjs reads kindLinksArticles(); the decisions inbox takes the project's
kind from listNotesFiles. projects.spec's registry rule holds again.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/umtool/lib/annotations/targets.mjs b/umtool/lib/annotations/targets.mjs
@@ -164,7 +164,7 @@ export async function listNotesFiles({ sitesDir = SITES_DIR, reportsRoot = REPOR
if (!kindTakesNotes(p.kind)) continue;
const file = path.join(/* turbopackIgnore: true */ p.dir, NOTES_FILENAME);
if (!(await exists(file))) continue;
- out.push({ kind: "video-project", id: p.id, file, ...(await readNotes(file)) });
+ out.push({ kind: "video-project", id: p.id, projectKind: p.kind, file, ...(await readNotes(file)) });
}
return out.sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id));
}
diff --git a/umtool/lib/articles/links.mjs b/umtool/lib/articles/links.mjs
@@ -19,6 +19,7 @@ import os from "node:os";
import path from "node:path";
import { REPORTS_ROOT } from "../paths.mjs";
import { projectRefs } from "../projects/core.mjs";
+import { kindLinksArticles } from "../projects/kinds.mjs";
import { idKeys } from "./sources.mjs";
const CACHE_MS = 30_000;
@@ -43,7 +44,7 @@ export function videoProjects(reportsRoot = REPORTS_ROOT) {
const value = (async () => {
const out = [];
for (const p of await projectRefs(reportsRoot)) {
- if (p.kind !== "report-video") continue;
+ if (!kindLinksArticles(p.kind)) continue;
let m = {};
try {
m = JSON.parse(await readFile(/* turbopackIgnore: true */ path.join(/* turbopackIgnore: true */ p.dir, "video.manifest.json"), "utf8"));
diff --git a/umtool/lib/decisions.ts b/umtool/lib/decisions.ts
@@ -348,7 +348,7 @@ export async function noteDecisions(): Promise<Decision[]> {
out.push({
kind: "unreadable-notes",
project,
- projectKind: article ? "article" : "report-video",
+ projectKind: article ? "article" : ((f as { projectKind?: string }).projectKind ?? "project"),
target: "notes.json",
why: `notes.json does not parse (${f.error ?? "unknown"}); nothing will write to it until it is fixed`,
href: page,
@@ -364,7 +364,7 @@ export async function noteDecisions(): Promise<Decision[]> {
out.push({
kind: "open-note",
project,
- projectKind: article ? "article" : "report-video",
+ projectKind: article ? "article" : ((f as { projectKind?: string }).projectKind ?? "project"),
target: anchorLabel(n.anchor as { kind: string }),
why: `${firstLine(n.text)}${replies}`,
href: `${page}?note=${encodeURIComponent(n.id)}`,
diff --git a/umtool/lib/projects/kinds.mjs b/umtool/lib/projects/kinds.mjs
@@ -107,6 +107,9 @@ export const PROJECT_KINDS = [
// Takes a notes.json beside its manifest (lib/annotations/targets.mjs):
// timed notes on its cuts, row notes, take notes, edit notes.
notes: true,
+ // Its manifest can be an ARTICLE's video (lib/articles/links.mjs): a
+ // top-level `article`, else its slug against the report id.
+ linksArticles: true,
},
{
id: "song",
@@ -188,6 +191,9 @@ export const kindById = (id) => PROJECT_KINDS.find((k) => k.id === id) ?? null;
/** Does a project of this kind keep a notes.json (lib/annotations)? Declared on the kind, never branched on its id. */
export const kindTakesNotes = (id) => kindById(id)?.notes === true;
+/** Can a project of this kind be an article's video (lib/articles/links.mjs)? Declared on the kind. */
+export const kindLinksArticles = (id) => kindById(id)?.linksArticles === true;
+
/** What a client component needs, with none of what it must not have. */
export const kindMeta = (k) => ({
id: k.id,