diff --git a/.project-docs/30-worklog/tasks/20260819-openmaic-prompt-template-8b4d.md b/.project-docs/30-worklog/tasks/20260819-openmaic-prompt-template-8b4d.md new file mode 100644 index 0000000..fd244f8 --- /dev/null +++ b/.project-docs/30-worklog/tasks/20260819-openmaic-prompt-template-8b4d.md @@ -0,0 +1,56 @@ +# Task: Diagnose missing interactive outline prompt template + +## Identity + +- Task ID: 20260819-openmaic-prompt-template-8b4d +- Mode: Feature +- Branch: codex/20260819-openmaic-prompt-template-8b4d-openmaic-prompt-template +- Worktree: D:\w\omprompt-8b4d +- Base commit: 58d1ddc2644f4c8631d62eb0e5423365af95ef66 +- Owner: codex +- Status: Ready-for-integration + +## Scope + +- Trace the production error `Interactive outline prompt template not found` from the classroom job runner to its runtime file dependency. +- Compare the runtime file path with the standalone Docker and learning-artifact packaging configuration. +- Provide a read-only Kubernetes check, implement the durable standalone packaging fix requested after diagnosis, and add a regression test. + +## Intent And Constraints + +- The user requested direct analysis without subagents. +- Preserve the existing dirty main worktree owned by `20260818-next-build-7f3a`; diagnosis ran in this isolated worktree at the same base commit. +- Distinguish source-level facts from the still-unverified contents of the deployed image. +- Keep the code change surgical: configure Next.js file tracing rather than duplicating copy rules across the Dockerfile and artifact builder. + +## Outcome + +- Confirmed that `lib/server/classroom-outline-mode.ts` raises the reported error only when the app prompt loader returns `null` for `interactive-outlines`. +- Confirmed that the loader reads Markdown dynamically from `/lib/prompts/templates/` and that both interactive-outline source files exist. Its broad catch also converts snippet-loading failures into the same outer error, while logging the original cause under `PromptLoader`. +- Confirmed that `interactive-outlines/system.md` includes three package-owned snippets (`image-instructions`, `video-instructions`, and `media-safety-guidelines`) that are dynamically read from `@openmaic/generation`. +- Confirmed that standalone output is enabled but `next.config.ts` has no `outputFileTracingIncludes`, while both the Docker runner and `build-learning-artifact.mjs` copy only standalone output, static assets, and public assets. +- Production root cause confirmed: the deployed Pod reports `ENOENT` for `/app/lib/prompts/templates/interactive-outlines/system.md`, and both `system.md` and `user.md` are absent while `cwd` is correctly `/app`. The standalone image omitted the app-owned prompt Markdown. +- A direct eval import of `@openmaic/generation` from `/app` also returned `ERR_MODULE_NOT_FOUND`. This is not the current first failure because template loading stops at the missing `system.md`; package snippet availability must be verified after the app templates are packaged, preferably through the built application or by inspecting the standalone trace/layout rather than assuming root-level package resolution. +- Added global standalone file-tracing includes for app-owned prompts, app PBL prompts, and the three package-owned generation prompt directories. +- Added `tests/config/standalone-prompt-assets.test.ts` to lock the runtime prompt asset contract. + +## Verification + +- Source template presence check: PASS (`system.md` and `user.md` exist). +- Packaging contract check: RED by design; source assets exist while neither file tracing includes nor an explicit runner copy is configured. +- Runtime path inspection: PASS (`WORKDIR /app` plus `process.cwd()/lib/prompts` resolves to `/app/lib/prompts`). +- Production Pod filesystem check: FAIL as expected; both interactive-outline files are missing from `/app` and the `PromptLoader` log records the exact `ENOENT` path. +- Targeted Vitest regression: PASS (1 test). +- ESLint on both changed product/test files: PASS. +- Prettier check on both changed product/test files: PASS. +- Learning-engine production build: webpack compilation PASS; final Next.js build FAILS on the pre-existing unrelated missing `@xmldom/xmldom` type declaration in `packages/@openmaic/importer/src/parser/XmlParser.ts`, before standalone output is emitted. + +## Follow-ups + +- Rebuild the image in an environment with the importer dependency installed, verify the prompt assets in the emitted standalone artifact, deploy, and rerun generation. +- Verify the package-owned snippets through a generation request; the root-level eval import is not a reliable proxy for bundled route resolution. +- Audit the other dynamically read app prompt directory `lib/pbl/v2/prompts` as part of the same packaging fix. + +## Promotion Candidates + +- None recorded. diff --git a/OpenMAIC/next.config.ts b/OpenMAIC/next.config.ts index 6358e9e..e4c2052 100644 --- a/OpenMAIC/next.config.ts +++ b/OpenMAIC/next.config.ts @@ -10,6 +10,17 @@ const nextConfig: NextConfig = { // default `.next`. distDir: process.env.NEXT_DIST_DIR || '.next', output: process.env.VERCEL ? undefined : 'standalone', + // Prompt loaders read Markdown dynamically at runtime, so Next.js cannot + // discover these assets from static imports when producing standalone output. + outputFileTracingIncludes: { + '/*': [ + './lib/prompts/**/*.md', + './lib/pbl/v2/prompts/**/*.md', + './packages/@openmaic/generation/templates/**/*.md', + './packages/@openmaic/generation/snippets/**/*.md', + './packages/@openmaic/generation/prompts-pbl/**/*.md', + ], + }, ...(basePath ? { basePath } : {}), env: { NEXT_PUBLIC_OPENMAIC_BASE_PATH: basePath, diff --git a/OpenMAIC/tests/config/standalone-prompt-assets.test.ts b/OpenMAIC/tests/config/standalone-prompt-assets.test.ts new file mode 100644 index 0000000..33bce43 --- /dev/null +++ b/OpenMAIC/tests/config/standalone-prompt-assets.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; + +import nextConfig from '../../next.config'; + +const runtimePromptGlobs = [ + './lib/prompts/**/*.md', + './lib/pbl/v2/prompts/**/*.md', + './packages/@openmaic/generation/templates/**/*.md', + './packages/@openmaic/generation/snippets/**/*.md', + './packages/@openmaic/generation/prompts-pbl/**/*.md', +]; + +describe('standalone prompt assets', () => { + it('includes every dynamically loaded prompt directory in output file tracing', () => { + expect(nextConfig.outputFileTracingIncludes?.['/*']).toEqual( + expect.arrayContaining(runtimePromptGlobs), + ); + }); +});