From e59cc850cd1046bcd0ada082c38666704682f56a Mon Sep 17 00:00:00 2001 From: Kurt Overmier Date: Mon, 2 Mar 2026 17:54:54 -0600 Subject: [PATCH] fix(bootstrap): scaffold on-demand module stubs during ADF init phase Bootstrap's ADF init phase wrote manifest.adf referencing frontend.adf and backend.adf as ON_DEMAND modules but never created the files. This caused `charter doctor` to immediately warn after a fresh bootstrap. Now both greenfield and force-overwrite paths write frontend.adf and backend.adf alongside the DEFAULT_LOAD modules. Closes #4 Co-Authored-By: Claude Opus 4.6 --- packages/cli/src/commands/bootstrap.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/bootstrap.ts b/packages/cli/src/commands/bootstrap.ts index 107f0b0..06d5c77 100644 --- a/packages/cli/src/commands/bootstrap.ts +++ b/packages/cli/src/commands/bootstrap.ts @@ -28,6 +28,8 @@ import { MANIFEST_SCAFFOLD, CORE_SCAFFOLD, STATE_SCAFFOLD, + FRONTEND_SCAFFOLD, + BACKEND_SCAFFOLD, POINTER_CLAUDE_MD, POINTER_CURSORRULES, POINTER_AGENTS_MD, @@ -420,12 +422,14 @@ function runAdfInitPhase( const alreadyExists = fs.existsSync(manifestPath); const hasCustomContent = alreadyExists && hasCustomAdfContent(aiDir); if (!alreadyExists) { - // Greenfield: write scaffolds + // Greenfield: write scaffolds (including on-demand module stubs) fs.mkdirSync(aiDir, { recursive: true }); fs.writeFileSync(path.join(aiDir, 'manifest.adf'), MANIFEST_SCAFFOLD); fs.writeFileSync(path.join(aiDir, 'core.adf'), CORE_SCAFFOLD); fs.writeFileSync(path.join(aiDir, 'state.adf'), STATE_SCAFFOLD); - files.push('.ai/manifest.adf', '.ai/core.adf', '.ai/state.adf'); + fs.writeFileSync(path.join(aiDir, 'frontend.adf'), FRONTEND_SCAFFOLD); + fs.writeFileSync(path.join(aiDir, 'backend.adf'), BACKEND_SCAFFOLD); + files.push('.ai/manifest.adf', '.ai/core.adf', '.ai/state.adf', '.ai/frontend.adf', '.ai/backend.adf'); // Write .adf.lock const lockData: Record = {}; @@ -440,12 +444,14 @@ function runAdfInitPhase( warnings.push('.ai/ contains custom ADF content; skipping scaffold overwrite'); warnings.push("Run 'charter adf migrate' to consolidate agent configs into ADF"); } else if (force) { - // Force overwrite + // Force overwrite (including on-demand module stubs) fs.mkdirSync(aiDir, { recursive: true }); fs.writeFileSync(path.join(aiDir, 'manifest.adf'), MANIFEST_SCAFFOLD); fs.writeFileSync(path.join(aiDir, 'core.adf'), CORE_SCAFFOLD); fs.writeFileSync(path.join(aiDir, 'state.adf'), STATE_SCAFFOLD); - files.push('.ai/manifest.adf', '.ai/core.adf', '.ai/state.adf'); + fs.writeFileSync(path.join(aiDir, 'frontend.adf'), FRONTEND_SCAFFOLD); + fs.writeFileSync(path.join(aiDir, 'backend.adf'), BACKEND_SCAFFOLD); + files.push('.ai/manifest.adf', '.ai/core.adf', '.ai/state.adf', '.ai/frontend.adf', '.ai/backend.adf'); const lockData: Record = {}; for (const mod of ['core.adf', 'state.adf']) {