UNPKG

adpa-enterprise-framework-automation

Version:

Modular, standards-compliant Node.js/TypeScript automation framework for enterprise requirements, project, and data management. Provides CLI and API for BABOK v3, PMBOK 7th Edition, and DMBOK 2.0 (in progress). Production-ready Express.js API with TypeSpe

214 lines (173 loc) 10.1 kB
# Modular Processor Migration Plan **Version:** 1.4 **Date:** June 10, 2025 **Author:** Requirements Gathering Agent Team --- ## Purpose This document outlines the step-by-step plan for migrating from the legacy document processor structure to the new modular, category-based architecture in the Requirements Gathering Agent. --- ## Progress Update (as of June 10, 2025) ### Migration Status - **ProcessorFactory**: Refactored to support registry-based, config-driven processor loading with robust error handling and logger support. Unit and integration tests are passing. - **Processor Classes**: All processor and template files have been migrated to TypeScript, and imports updated to extensionless or `.ts` as appropriate. Legacy `.js` files have been removed. - **Configuration**: `processor-config.json` is in use for dynamic processor registration. - **Testing**: Jest test suite for `ProcessorFactory` is complete and passing. Integration with the generator is validated. - **TypeScript**: All build errors related to the migration have been resolved. All relevant types and interfaces are up to date. - **Generator Registry**: `index.ts` and related files now use the factory for processor access. No direct processor imports remain. - **Document Configuration**: All new document types and categories are registered and available for generation. - **Context Relationships**: Updated to include new document types and dependencies. - **Documentation**: This plan, `ARCHITECTURE.md`, and `STEPS-TO-IMPLEMENT-NEW-DOCS.md` have been updated to reflect the new architecture. - **Legacy Code**: All legacy processor files have been marked as deprecated or removed where safe. ### Findings & Lessons Learned - **ESM/TypeScript Compatibility**: All imports must be extensionless or use `.ts` in source, and `.js` in built output for Node ESM compatibility. This was a common source of runtime errors. - **Testing**: When mocking processor classes, all async methods must be present and return Promises to avoid Jest async teardown errors. - **Build Artifacts**: Ensuring all files are present in `dist/` is critical for runtime. Clean builds (`rm -rf dist && npm run build`) are recommended after major refactors. - **Pandoc PDF Generation**: For document conversion, a LaTeX distribution (e.g., MiKTeX) is required for PDF output. This is a common external dependency for users. - **Dynamic Imports**: Dynamic processor loading via config and `import()` is working well and provides flexibility for future extension. - **Backward Compatibility**: Adapter layers are in place for legacy import paths, but these will be removed after full migration. ### Next Steps - Complete migration of any remaining document types not yet modularized. - Continue to monitor for runtime or test regressions as new processors are added. - Remove all deprecated legacy code after final validation. - Continue to update documentation as the architecture evolves. --- ### Migration Steps #### 1. Establish Modular Directory Structure - For each document category (e.g., `strategic-statements`), create a subdirectory under `src/modules/documentTemplates/`. - Place all template, processor, and type declaration files for that category in this subdirectory. - **Example:** ``` src/modules/documentTemplates/strategic-statements/ strategicStatements.ts strategicStatementsProcessor.ts strategicStatementsProcessor.d.ts ``` #### 2. Move and Refactor Processors - Move processor logic from `src/modules/ai/processors/` (e.g., `StrategicStatementsProcessor.ts`) into the new subdirectory. - Refactor processors to: - Use the new template classes. - Accept and use the full project context. - Follow the new interface for AI calls and validation. - Remove or deprecate the legacy processor files after migration. #### 3. Create a Unified, Extensible Processor Factory - Create `src/modules/documentGenerator/ProcessorFactory.ts`. - Use a registry/map instead of a switch statement for extensibility. - **Explicit Interface for Processors:** ```typescript interface DocumentProcessor { process(context: ProjectContext): DocumentOutput; } interface ProcessorMap { [taskKey: string]: typeof DocumentProcessor; } ``` - **Revised Factory Example:** ```typescript import { ILogger } from '../logging/ILogger'; import { MissionVisionCoreValuesProcessor, ProjectPurposeProcessor } from '../documentTemplates/strategic-statements/strategicStatementsProcessor.ts'; // ... other imports ... export class ProcessorFactory { private processorMap: ProcessorMap = { 'mission-vision-core-values': MissionVisionCoreValuesProcessor, 'project-purpose': ProjectPurposeProcessor, }; constructor(private logger: ILogger) {} getProcessorForTask(taskKey: string, ...args: any[]): DocumentProcessor { const ProcessorClass = this.processorMap[taskKey]; if (ProcessorClass) { try { return new ProcessorClass(...args); } catch (error) { this.logger.error(`Error instantiating processor ${taskKey}: ${error}`); throw new ProcessorInstantiationError(`Failed to create processor for ${taskKey}`, error); } } else { this.logger.error(`Processor not found for taskKey: ${taskKey}.`); throw new ProcessorNotFoundError(`Processor not found for taskKey: ${taskKey}`); } } registerProcessor(taskKey: string, processorClass: typeof DocumentProcessor) { this.processorMap[taskKey] = processorClass; } } class ProcessorNotFoundError extends Error {} class ProcessorInstantiationError extends Error {} ``` - This allows for registering processors dynamically, perhaps during application startup by loading them from a configuration file. #### 4. Configuration-Driven Registration - Load the `processorMap` from a configuration file (e.g., JSON) during application startup for maximum flexibility. - **Example JSON config:** ```json { "mission-vision-core-values": "../documentTemplates/strategic-statements/strategicStatementsProcessor.ts#MissionVisionCoreValuesProcessor", "project-purpose": "../documentTemplates/strategic-statements/strategicStatementsProcessor.ts#ProjectPurposeProcessor" } ``` - **Example loader snippet:** ```typescript import processorConfig from './processor-config.json'; for (const [taskKey, modulePathAndClass] of Object.entries(processorConfig)) { const [modulePath, className] = modulePathAndClass.split('#'); import(modulePath).then(mod => { factory.registerProcessor(taskKey, mod[className]); }); } ``` #### 5. Dependency Injection - Use a dependency injection container (like [InversifyJS](https://inversify.io/)) or a simple service locator pattern for passing dependencies to processors. - Example (simplified service locator): ```typescript interface Dependencies { contextManager: ContextManager; aiService: AIService; } export class ProcessorFactory { constructor(private dependencies: Dependencies, private logger: ILogger) {} // ... (rest of the code using dependencies.contextManager etc.) } ``` #### 6. Testing the Factory - Add unit tests for the ProcessorFactory using a framework like Jest or Mocha. - **Benefits of Jest:** Mocking, snapshot testing, code coverage reporting. - Write unit tests for: - Successful processor retrieval and instantiation - Fallback to legacy processors - Error handling (including custom errors) - Add integration tests to check interaction with other modules. #### 7. Error Handling - Use custom error classes (e.g., `ProcessorNotFoundError`, `ProcessorInstantiationError`) for more granular error handling and easier debugging. - Log errors at a high level and throw when appropriate. #### 8. Backward Compatibility - Create a shim or adapter layer to handle calls to old import paths and redirect them to the new factory. - This allows a graceful transition period before removing legacy code entirely. #### 9. Performance (Optional/Future) - For very large numbers of processors, consider using dynamic imports (`import()`) to load processors only when needed. - This avoids loading unnecessary code during startup and can be implemented as a future optimization. #### 10. Update Generator Registry - In `src/modules/documentGenerator/index.ts`, remove direct processor imports. - Use the new factory to obtain processors as needed. - This keeps orchestration and processor wiring separate and scalable. #### 11. Update Document Configuration - In `src/modules/documentGenerator/generationTasks.ts`, ensure new document types and categories are registered and available for generation. #### 12. Update Context Relationships - In `src/modules/contextManager.ts`, update `initializeDocumentRelationships` to include new document types and their dependencies for context enrichment. #### 13. Test Thoroughly - Run the generator and validate that: - All new processors are invoked correctly. - Documents are generated with the correct context and structure. - No legacy processor code is being used for migrated document types. #### 14. Document the Change - Update `STEPS-TO-IMPLEMENT-NEW-DOCS.md` and `ARCHITECTURE.md` to reference the new factory and modular approach. - Add migration notes and troubleshooting for future contributors. #### 15. Deprecate Legacy Code - Mark legacy processor files as deprecated. - Remove them after confirming all document types have been migrated. --- ### Reference Implementation The `strategic-statements` category is the reference implementation for this migration. Follow its structure and integration as a model for all future migrations. --- ### Notes - This plan ensures a smooth, incremental migration to a scalable, maintainable, and modular document generation system. - Update this plan as new categories or requirements emerge. --- *End of Plan*