/** * modules/notes.ts — Notes as the first Papyrus-native registered module * (step 5 of the incremental refactor in reducing-papyrus-consumer-change-amplification-with-modules--pvdo, * combined with step 1 for a real proof-of-shape rather than an empty abstraction). * * Notes was chosen first because it owns no bespoke schema (it reuses the generic doc * table via NOTE_SUBTYPE) and has exactly six operations — the smallest real module to * prove the OperationRegistry shape against before extracting Tasks or Docs. * * This module does not import another module's infrastructure (src/task/task-service.ts, * src/docs/docs-service.ts, etc.) — only its own src/note/note-service.ts and the shared * OperationInput parsing helpers, matching the "module code does not import another * module's infrastructure" constraint. */ import type { OperationDefinition } from "../module-registry.ts"; import type { NoteEventDirection } from "../note/note-event.ts"; import type { NoteDisposition, Notes } from "../note/note-service.ts"; import { type OperationInput, optionalNumber, optionalString, string } from "./operation-input.ts"; const MODULE_ID = "notes"; /** This module's own operation names, the single source of truth src/service.ts's EXPECTED_OPERATION_NAMES spreads in rather than re-listing by hand. */ export const NOTES_OPERATION_NAMES = [ "notes.capture", "notes.list", "notes.list_page", "notes.show", "notes.history", "notes.consume", "notes.promote", "notes.archive", ] as const; /** Registers every notes.* operation against one Notes instance. Behavior is unchanged from the prior inline handlers in src/service.ts. */ export function notesOperations(notes: Notes): OperationDefinition[] { const define = (name: string, execute: (input: Input) => Output): OperationDefinition => ({ name, moduleId: MODULE_ID, execute, }); return [ define("notes.capture", (input: OperationInput) => notes.capture({ body: string(input, "body"), title: optionalString(input, "title"), projectRoot: string(input, "project_root"), actor: optionalString(input, "actor"), source: optionalString(input, "source"), sessionId: optionalString(input, "session_id"), }), ), define("notes.list", (input: OperationInput) => notes.list({ projectRoot: string(input, "project_root"), status: optionalString(input, "status") as "draft" | "active" | "archived" | undefined, text: optionalString(input, "text"), limit: optionalNumber(input, "limit"), }), ), define("notes.list_page", (input: OperationInput) => notes.listPage({ projectRoot: optionalString(input, "project_root"), status: optionalString(input, "status") as "draft" | "active" | "archived" | undefined, text: optionalString(input, "text"), limit: optionalNumber(input, "limit"), cursor: optionalString(input, "cursor"), }), ), define("notes.show", (input: OperationInput) => notes.show(string(input, "id"), string(input, "project_root"))), define("notes.history", (input: OperationInput) => notes.history(string(input, "id"), string(input, "project_root"), { limit: optionalNumber(input, "limit"), cursor: optionalNumber(input, "cursor"), direction: optionalString(input, "direction") as NoteEventDirection | undefined, }), ), define("notes.consume", (input: OperationInput) => notes.consume(string(input, "id"), { projectRoot: string(input, "project_root"), actor: optionalString(input, "actor"), source: optionalString(input, "source"), sessionId: optionalString(input, "session_id"), reason: optionalString(input, "reason"), }), ), define("notes.promote", (input: OperationInput) => notes.promote(string(input, "id"), string(input, "target_id"), { projectRoot: string(input, "project_root"), actor: optionalString(input, "actor"), source: optionalString(input, "source"), sessionId: optionalString(input, "session_id"), reason: optionalString(input, "reason"), }), ), define("notes.archive", (input: OperationInput) => notes.archive(string(input, "id"), { projectRoot: string(input, "project_root"), disposition: string(input, "disposition") as NoteDisposition, actor: optionalString(input, "actor"), source: optionalString(input, "source"), sessionId: optionalString(input, "session_id"), reason: optionalString(input, "reason"), }), ), ]; }