UNPKG

meld

Version:

Meld: A template language for LLM prompts

1,186 lines (959 loc) 147 kB
<User message_number="1"> You are an expert in building reliable and maintainable DSL systems, particularly in structuring state interpreters. You are passionate about SOLID architecture, taking methodical approaches, and making incremental and testable changes. You have created a thoughtfully structured plan for addressing some complex issues we have encountered. We are now asking for your help preparing a detailed plan which is written in order to maximize success based on it being carried out by an LLM developer. However we're at a point where we need some advice. I am going to provide you with some context: - Architecture documentation (slightly outdated) - Test setup - The plan you provided for strategically approaching resolving issues related to generating the final build output Then, below that, I'm going to provide the audit work completed so far. \======= CONTEXT \=== ARCHITECTURE # Meld Architecture ## INTRODUCTION Meld is a specialized, directive-based scripting language designed for embedding small "@directives" inside an otherwise plain text (e.g., Markdown-like) document. The code in this repository implements: • Meld grammar rules and token types (e.g., text directives, path directives, data directives). • The parsing layer that converts Meld content into an AST (Abstract Syntax Tree). • A directive interpretation layer that processes these AST nodes and manipulates internal "states" to store variables and more. • A resolution layer to handle variable references, path expansions, data manipulations, etc. • Testing utilities and an in-memory FS (memfs) to simulate filesystems for thorough testing. The main idea: 1. Meld code is parsed to an AST. 2. Each directive node is validated and interpreted, updating a shared "state" (variables, data structures, commands, etc.). 3. Optional transformations (e.g., output formatting) generate final representations (Markdown, LLM-friendly XML, etc.). Below is an overview of the directory and service-level architecture, referencing code from this codebase. ## DIRECTORY & FILE STRUCTURE At a high level, the project is arranged as follows (select key entries included): project-root/ ├─ api/ ← High-level API and tests │ ├─ api.test.ts │ └─ index.ts ├─ bin/ ← CLI entry point │ └─ meld.ts ├─ cli/ ← CLI implementation │ ├─ cli.test.ts │ └─ index.ts ├─ core/ ← Core utilities and types │ ├─ config/ ← Configuration (logging, etc.) │ ├─ errors/ ← Error class definitions │ ├─ types/ ← Core type definitions │ └─ utils/ ← Logging and utility modules ├─ services/ ← Core service implementations │ ├─ CLIService/ │ ├─ CircularityService/ │ ├─ DirectiveService/ │ │ ├─ handlers/ │ │ │ ├─ definition/ ← Handlers for definition directives │ │ │ └─ execution/ ← Handlers for execution directives │ │ └─ errors/ │ ├─ FileSystemService/ │ ├─ InterpreterService/ │ ├─ OutputService/ │ ├─ ParserService/ │ ├─ PathService/ │ ├─ ResolutionService/ │ │ ├─ resolvers/ ← Individual resolution handlers │ │ └─ errors/ │ ├─ StateService/ │ └─ ValidationService/ │ └─ validators/ ← Individual directive validators ├─ tests/ ← Test infrastructure │ ├─ fixtures/ ← Test fixture data │ ├─ mocks/ ← Test mock implementations │ ├─ services/ ← Service-specific tests │ └─ utils/ ← Test utilities and helpers │ ├─ FixtureManager.ts │ ├─ MemfsTestFileSystem.ts │ ├─ ProjectBuilder.ts │ ├─ TestContext.ts │ └─ TestSnapshot.ts ├─ docs/ ← Documentation ├─ package.json ├─ tsconfig.json ├─ tsup.config.ts └─ vitest.config.ts Key subfolders: • services/: Each service is a self-contained module with its implementation, interface, tests, and any service-specific utilities • core/: Central types, errors, and utilities used throughout the codebase • tests/utils/: Test infrastructure including the memfs implementation, fixture management, and test helpers • api/: High-level public API for using Meld programmatically • cli/: Command line interface for Meld ## CORE LIBRARIES & THEIR ROLE ### meld-ast • parse(content: string): MeldNode[] • Basic parsing that identifies directives vs. text nodes. • Produces an AST which other services manipulate. ### llmxml • Converts content to an LLM-friendly XML format or can parse partially. • OutputService may call it if user requests "llm" format. ### meld-spec • Contains interface definitions for MeldNode, DirectiveNode, TextNode, etc. • Contains directive kind enumerations. ## HIGH-LEVEL FLOW Below is a simplified flow of how Meld content is processed: ┌─────────────────────────────┐ │ Meld Source Document │ └─────────────────────────────┘ │ ▼ ┌─────────────────────────────┐ │ ParserService.parse(...) │ │ → uses meld-ast to parse │ └─────────────────────────────┘ │ AST (MeldNode[]) ▼ ┌─────────────────────────────────────────────────┐ │ InterpreterService.interpret(nodes, options) │ │ → For each node, pass to DirectiveService │ │ → Handles node transformations │ └─────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ DirectiveService │ │ → Routes to correct directive handler │ │ → Handlers can provide replacements │ └──────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────┐ │ StateService + ResolutionService + Others │ │ → Stores variables and transformed nodes │ │ → Path expansions, data lookups, etc. │ └───────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ OutputService │ │ → Uses transformed nodes for output │ │ → Generates clean, directive-free │ │ markdown, LLM XML, or other formats │ └──────────────────────────────────────────┘ ## MAJOR SERVICES (OVERVIEW) Below are the key "services" in the codebase. Each follows the single responsibility principle: ### CLIService - Provides command-line interface for running Meld - Handles file watching and reprocessing - Manages format selection and output options - Routes to appropriate services based on CLI flags ### ParserService - Wraps the meld-ast parse(content) function - Adds location information with file paths (parseWithLocations) - Produces an array of MeldNode objects ### DirectiveService - Routes directives to the correct directive handler - Validates directives using ValidationService - Calls ResolutionService for variable resolution - Updates StateService with directive execution results - Supports node transformation through DirectiveResult interface - Handlers can provide replacement nodes for transformed output ### InterpreterService - Orchestrates the main interpret(nodes) pipeline - For each AST node: a) If it's text, store it or pass it along b) If it's a directive: - Calls DirectiveService for processing - Handles node transformations if provided - Updates state with transformed nodes - Maintains the top-level process flow - Supports transformation mode through feature flags ### StateService - Stores variables in maps: • textVars (for @text) • dataVars (for @data) • pathVars (for @path) • commands (for @define) - Tracks both original and transformed MeldNodes - Provides transformation capabilities for directive processing - Maintains transformation state during cloning - Provides child states for nested imports - Supports immutability toggles ### ResolutionService - Handles all variable interpolation: • Text variables ("${var}") • Data references ("#{data.field}") • Path expansions ("$HOMEPATH/path") • Command references - Context-aware resolution - Circular reference detection - Sub-fragment parsing support ### CircularityService - Prevents infinite import loops - Detects circular variable references - Maintains dependency graphs ### PathService - Validates and normalizes paths - Enforces path security constraints - Handles path joining and manipulation - Supports test mode for path operations ### ValidationService - Validates directive syntax and constraints - Provides extensible validator registration - Throws MeldDirectiveError on validation failures - Tracks available directive kinds ### FileSystemService - Abstracts file operations (read, write) - Supports both real and test filesystems - Handles path resolution and validation ### OutputService - Converts final AST and state to desired format - Uses transformed nodes when available - Supports markdown and LLM XML output - Integrates with llmxml for LLM-friendly formatting - Handles format-specific transformations - Provides clean output without directive definitions ## TESTING INFRASTRUCTURE All tests are heavily reliant on a memory-based filesystem (memfs) for isolation and speed. The major testing utilities include: ### MemfsTestFileSystem – Thin wrapper around memfs – Offers readFile, writeFile, mkdir, etc. with in-memory data – Provides an ephemeral environment for all test IO ### TestContext – Central test harness that creates a new MemfsTestFileSystem – Provides references to all major services (ParserService, DirectiveService, etc.) – Allows writing files, snapshotting the FS, and comparing ### TestSnapshot – Takes "snapshots" of the current Memfs FS, storing a Map<filePath, content> – Compares snapshots to detect added/removed/modified files ### ProjectBuilder – Creates mock "projects" in the in-memory FS from JSON structure – Useful for complex, multi-file tests or large fixture-based testing ### Node Factories – Provides helper functions for creating AST nodes in tests – Supports creating directive, text, and code fence nodes – Includes location utilities for source mapping Testing Organization: • tests/utils/: Core test infrastructure (MemFS, snapshots, contexts) • tests/mocks/: Minimal mocks and test doubles • tests/fixtures/: JSON-based test data • tests/services/: Service-specific integration tests Testing Approach: • Each test uses a fresh TestContext or recreates MemfsTestFileSystem • Direct imports from core packages (meld-ast, meld-spec) for types • Factory functions for creating test nodes and data • Snapshots for tracking filesystem changes ## SERVICE RELATIONSHIPS Below is a more expanded ASCII diagram showing services with references: +---------------------+ | CLIService | | Entry point | +----------+----------+ | v +---------------------+ | ParserService | | meld-ast parsing | +----------+----------+ | v +------------+ +---------------------+ | Circularity| <-----------> | ResolutionService | | Service | | Variable/Path | +------------+ | Resolution | ^ | | v +------------+ +---------------------+ +-----------+ | Validation|-> | DirectiveService |->|StateService| | Service | | Node Transformation| |Original & | +------------+ +---------+-----------+ |Transformed| ^ | | | Nodes | | v v +-----------+ | +---------------+--------------+ +---------| Handler(s): text, data, | | embed, import, etc. | | (with node replacements) | +---------------+--------------+ | v +---------------------+ | InterpreterService | | Transform Pipeline | +----------+----------+ | v +---------------------+ | OutputService | | Clean Output Gen | +---------------------+ Key relationships: • InterpreterService orchestrates directive processing and transformation pipeline • DirectiveService processes directives and manages node transformations • Handlers can provide replacement nodes for transformed output • StateService maintains both original and transformed node states • OutputService uses transformed nodes for clean output generation ## EXAMPLE USAGE SCENARIO 1) Input: A .meld file with lines like: @text greeting = "Hello" @data config = { "value": 123 } @import [ path = "other.meld" ] 2) We load the file from disk. 3) ParserService → parse the content → AST. 4) InterpreterService → interpret(AST). a) For each directive, DirectiveService → validation → resolution → update StateService. b) If an import is encountered, CircularityService ensures no infinite loops. 5) Once done, the final StateService has textVars.greeting = "Hello", dataVars.config = { value: 123 }, etc. 6) OutputService can generate the final text or an LLM-XML representation. ## ERROR HANDLING • MeldDirectiveError thrown if a directive fails validation or interpretation. • MeldParseError if the parser cannot parse content. • PathValidationError for invalid paths. • ResolutionError for variable resolution issues. • MeldError as a base class for other specialized errors. These errors typically bubble up to the caller or test. ## CONCLUSION This codebase implements the entire Meld language pipeline: • Parsing Meld documents into an AST. • Validating & interpreting directives. • Storing data in a hierarchical state. • Resolving references (text, data, paths, commands). • (Optionally) generating final formatted output. Plus, it has a robust test environment with an in-memory FS, snapshots, and a test harness (TestContext) for integration and unit tests. Everything is layered to keep parsing, state management, directive logic, and resolution separate, adhering to SOLID design principles. The ASCII diagrams, modules, and file references in this overview represent the CURRENT code as it is: multiple specialized services collaborating to parse and interpret Meld scripts thoroughly—test coverage is facilitated by the in-memory mocking and snapshot-based verification. \=== TEST SETUP # Testing in Meld This document outlines the testing infrastructure and best practices for the Meld codebase. It serves as a practical guide for writing and maintaining tests. ## Directory Structure Tests are organized following these conventions: ``` project-root/ ├─ tests/ # Test infrastructure and shared resources │ ├─ utils/ # Test utilities and factories │ ├─ mocks/ # Shared mock implementations │ ├─ fixtures/ # Test fixture data │ └─ setup.ts # Global test setup └─ services/ # Service implementations with co-located tests └─ ServiceName/ ├─ ServiceName.test.ts # Unit tests ├─ ServiceName.integration.test.ts # Integration tests └─ handlers/ └─ HandlerName.test.ts # Handler-specific tests ``` ## Test Infrastructure ### Core Testing Utilities 1. **TestContext** - Central test harness providing access to all test utilities - Manages test state and cleanup - Available globally in tests as `testContext` 2. **Test Factories** - Located in `tests/utils/testFactories.ts` - Provides helper functions for creating test nodes and mocks - Ensures consistent test data creation Example usage: ```typescript import { createDefineDirective, createLocation, createMockStateService } from '@tests/utils/testFactories'; const node = createDefineDirective( 'greet', 'echo "Hello"', [], createLocation(1, 1, 1, 20) ); const mockState = createMockStateService(); ``` ### Mock Services The test factories provide mock implementations for all core services: ```typescript const mockServices = { stateService: createMockStateService(), validationService: createMockValidationService(), resolutionService: createMockResolutionService(), fileSystemService: createMockFileSystemService(), // ... etc }; ``` Each mock service implements the corresponding interface and provides sensible defaults. ## Writing Tests ### Service Tests Service tests should follow this structure: ```typescript describe('ServiceName', () => { let service: ServiceName; let dependencies: { stateService: IStateService; // ... other dependencies }; beforeEach(() => { dependencies = { stateService: createMockStateService(), // ... initialize other dependencies }; service = new ServiceName(dependencies); }); describe('core functionality', () => { it('should handle basic operations', async () => { // Arrange const input = // ... test input // Act const result = await service.operation(input); // Assert expect(result).toBeDefined(); expect(dependencies.stateService.someMethod) .toHaveBeenCalledWith(expectedArgs); }); }); describe('error handling', () => { it('should handle errors appropriately', async () => { // ... error test cases }); }); }); ``` ### Directive Handler Tests Directive handler tests should cover: 1. Value Processing - Basic value handling - Parameter processing - Edge cases 2. Validation Integration - Integration with ValidationService - Validation error handling 3. State Management - State updates - Command/variable storage - Original and transformed node states - Node replacement handling 4. Transformation Behavior - Node replacement generation - Transformation state preservation - Clean output verification 5. Error Handling - Validation errors - Resolution errors - State errors - Transformation errors Example structure: ```typescript describe('HandlerName', () => { let handler: HandlerName; let dependencies: { validationService: IValidationService; stateService: IStateService; resolutionService: IResolutionService; }; beforeEach(() => { dependencies = { validationService: createMockValidationService(), stateService: createMockStateService(), resolutionService: createMockResolutionService() }; handler = new HandlerName(dependencies); }); describe('value processing', () => { // Value processing tests }); describe('validation', () => { // Validation tests }); describe('state management', () => { // State management tests }); describe('transformation', () => { it('should provide correct replacement nodes', async () => { const node = createDirectiveNode('test', { value: 'example' }); const result = await handler.execute(node, context); expect(result.replacement).toBeDefined(); expect(result.replacement.type).toBe('Text'); expect(result.replacement.content).toBe('example'); }); it('should preserve location in transformed nodes', async () => { const node = createDirectiveNode('test', { value: 'example' }); const result = await handler.execute(node, context); expect(result.replacement.location).toEqual(node.location); }); }); describe('error handling', () => { // Error handling tests }); }); ``` ### Integration Tests Integration tests should focus on real-world scenarios and service interactions: ```typescript describe('Service Integration', () => { let services: { directiveService: DirectiveService; stateService: StateService; // ... other real service instances }; beforeEach(() => { services = { directiveService: new DirectiveService(), stateService: new StateService(), // ... initialize other services }; // Initialize service relationships services.directiveService.initialize( services.validationService, services.stateService, services.resolutionService ); }); it('should process complex scenarios', async () => { // Test end-to-end flows }); it('should generate clean output without directives', async () => { const input = ` @text greeting = "Hello" @run [echo ${greeting}] Regular text `; const result = await processDocument(input); expect(result).not.toContain('@text'); expect(result).not.toContain('@run'); expect(result).toContain('Hello'); expect(result).toContain('Regular text'); }); it('should maintain both original and transformed states', async () => { const state = await processDocument(input); expect(state.getOriginalNodes()).toHaveLength(3); expect(state.getTransformedNodes()).toHaveLength(2); }); }); ``` ## Best Practices 1. **Test Organization** - Co-locate tests with implementation files - Use clear, descriptive test names - Group related tests using `describe` blocks - Follow the Arrange-Act-Assert pattern 2. **Mock Usage** - Use the provided mock factories - Set up specific mock implementations in beforeEach - Clear all mocks between tests - Be explicit about mock expectations 3. **Error Testing** - Test both expected and unexpected errors - Verify error messages and types - Test error propagation - Include location information in errors 4. **Location Handling** - Always include location information in test nodes - Use `createLocation` helper for consistency - Test location propagation in errors - Verify location preservation in transformed nodes 5. **State Management** - Test state immutability - Verify state cloning - Test parent/child state relationships - Validate state updates - Test both original and transformed node states - Verify transformation state persistence 6. **Transformation Testing** - Test node replacement generation - Verify clean output formatting - Test transformation state inheritance - Validate directive removal in output - Test complex transformation scenarios ## Running Tests ```bash # Run all tests npm test # Run specific test file npm test services/DirectiveService/handlers/definition/DefineDirectiveHandler.test.ts # Run tests in watch mode npm test -- --watch # Run tests with coverage npm test -- --coverage ``` ## Test Coverage The project maintains high test coverage through: - Unit tests for all services and handlers - Integration tests for service interactions - Error case coverage - Edge case testing Coverage reports can be generated using: ```bash npm test -- --coverage ``` ## Debugging Tests 1. Use the `debug` logger in tests: ```typescript import { debug } from '@core/utils/logger'; it('should handle complex case', () => { debug('Test state:', someObject); }); ``` 2. Use Node.js debugger: - Add `debugger` statement in test - Run `npm test -- --inspect-brk` - Connect Chrome DevTools 3. Use Vitest UI: ```bash npm test -- --ui ``` \=== YOUR PLAN (VERY IMPORTANT CONTEXT) Below is a clarified, evidence-driven plan for methodically resolving the transformation issues, state management bugs, and mismatches between real and mock services—all while preserving passing tests as we proceed. It incorporates the high-level advice of instrumenting each step, auditing our interfaces, and aligning mocks with real services. It is broken into phases to ensure incremental progress without regressions. ──────────────────────────────────────────────────────────────────── PHASE 0: CONTEXT & GOALS ──────────────────────────────────────────────────────────────────── Before making any changes, we must align on what we are trying to accomplish and how it fits into our existing Meld architecture and testing approach. 1. Context: • Meld interprets directive-based text into an AST, processes directives (possibly transforming or removing them), and generates output (Markdown, XML, etc.). • "StateService" manages variables, transformations, and can clone its internal state for nested or repeated directive processing. • "DirectiveService" and its handlers produce results that may replace directives in the final AST (transformation mode). • The "OutputService" consumes nodes: if in transformation mode, it should see only text/code nodes and never see directive definitions. • Mocks in tests sometimes omit partial implementations (like "clone()"), leading to runtime errors in integration or API tests. 2. Key Goals: 1) Eliminate errors around missing or incorrect state methods (e.g. "currentState.clone is not a function"). 2) Ensure transformation mode consistently replaces directives with their processed output, so the final output shows "test output" instead of raw directives like "@run [echo test]." 3) Maintain high test coverage and pass existing tests (unless a test's expectation is flatly incorrect). 3. High-Level Purpose: This plan ensures a stable approach to directive transformation—replacing directives with textual or code content—while retaining a well-defined "StateService" interface and consistent test mocks. By the end of these phases, "run" directives, "embed" directives, and others should yield correct transformed nodes, and all code paths (API, integration, unit) should rely on consistent service initializations. 4. Critical Dependencies: • Service Initialization Order: - Proper initialization sequence (as shown in cli/index.ts) - Handling of circular dependencies between services - Transformation mode initialization timing • State Management: - StateService clone operation must preserve transformation state - Child states must inherit transformation settings - State merging must handle transformed nodes correctly • Handler Flow: - Handlers must check transformation mode before replacing nodes - Node replacement must preserve source locations - Error handling must work in both modes • Test Infrastructure: - TestContext initialization must support both modes - Mock services must implement full interfaces - Integration tests must use consistent service setup 5. Key Architectural Decisions Required: 1. Transformation Mode Scope: - Global vs per-directive setting - Inheritance rules for nested states - Default behavior and configuration 2. Transformation Completeness: - All-or-nothing vs partial transformation support - Mixing transformed and untransformed content - Backward compatibility requirements 3. Error Handling Strategy: - Location preservation in transformed nodes - Error reporting in transformation mode - Recovery options for partial failures ──────────────────────────────────────────────────────────────────── PHASE 1: AUDIT & ALIGNMENT ──────────────────────────────────────────────────────────────────── Objective: Rigorously align our service interfaces, the real implementations, and our test mocks before modifying any production code paths for transformation. This prevents repeated "ping-pong" fixes later. 1. Interface & Implementation Audit (IStateService): • Compare the real "StateService" methods to "IStateService." • Confirm that "clone()", "getTransformedNodes,", "isTransformationEnabled," etc. are declared exactly in both. • Check that every method used in production code is actually typed in the interface. • If any method is missing or partially typed, update "IStateService" accordingly. 2. Mock Services Audit: • For each critical mock (especially the StateService mock), confirm it either implements all "IStateService" methods or explicitly extends a real instance. • In a single doc or table, list each method (clone, addNode, transformNode, etc.), whether it is implemented in the real code, and whether it is implemented in the mock. • Add missing methods to the mocks where needed. • Validate that the mock returns data types consistent with the real service (e.g. "clone" returns a new valid mock, not a plain object). 3. Test-by-Test Check for Partial Mocks: • In the failing API integration tests and OutputService transformation tests, examine exactly how "StateService" (or its mocks) is created. • If any tests pass in one file but fail in another, note differences in mock usage so we can unify them later. • Do not change any production code yet—only refine or unify the mock definitions if they are incomplete. 4. Deliverables & Exit Criteria: • A short "Interface vs. Implementation" mapping document (even a simple table). • Updated "IStateService" that matches real usage in code. • Updated StateService mock(s) ensuring "clone" and "transformation" methods are properly defined. • All existing tests should still pass—this step is purely aligning definitions without changing production logic. Success Criteria: • All service interfaces are fully documented • Implementation gaps are identified • Mock implementations are validated • No production code changes • All existing tests remain passing Evidence Required: • Interface analysis documentation • Mock implementation audit • Test coverage analysis • Service interaction map ──────────────────────────────────────────────────────────────────── PHASE 2: EVIDENCE COLLECTION ──────────────────────────────────────────────────────────────────── Objective: Build small, targeted test suites to verify that the newly aligned real services and mocks behave as expected in isolation. This clarifies where transformation fails or where a "clone" method might be returning incomplete objects. 1. "StateService.clone.test.ts": • Create a minimal test file that: (a) Instantiates the real StateService. (b) Populates it with text/data variables, a small list of nodes, or a mock directive node. (c) Calls "clone()" and verifies each field (variables, commands, original nodes, transformed nodes) is copied properly. • Confirm any transformation flags are copied if they exist. • Confirm that the cloned state is not referencing the same arrays as the original. 2. "TransformationMode.test.ts" (Optional if not already present): • A minimal test that uses the real "DirectiveService," real or partial "RunDirectiveHandler," and real "StateService." • Creates a single directive node ("@run [echo test]") with transformation enabled. • Checks that after processing, "StateService.getTransformedNodes()" has replaced the directive node with the output ("test\n" or whatever is produced). • Confirms no directives remain in the "transformedNodes" array. 3. Basic Logging / Instrumentation: • In these mini tests, add a few console.logs or debug logs to confirm what "clone()" returns and that "transformedNodes" is updated. • This ensures our isolation environment lines up with real production expectations. 4. Deliverables & Exit Criteria: • Dedicated, passing isolation tests for "clone" and transformation. • Confidence that the real "StateService" does indeed replicate behavior we expect. • If these mini-tests fail, fix them before moving on. • Again, no major production code changes (besides possibly small fixes to "clone" if needed). All existing production tests should still pass. ──────────────────────────────────────────────────────────────────── PHASE 3: INSTRUMENT FAILING INTEGRATION TESTS ──────────────────────────────────────────────────────────────────── Objective: Now that we trust the "StateService" and mock setups, locate precisely where the failing large-scope tests (API integration, OutputService transformation) diverge from the proven mini-tests. 1. Identify All Failing Tests: • The user's context indicates 7 failing tests: (a) 4 in "api/api.test.ts" around "currentState.clone is not a function." (b) 3 in OutputService transformation mode. 2. Add Debug Logs: • For each failing test, inject logs that show: • The exact type of "currentState" or "state" object being passed around (e.g. use "console.log(state.constructor.name)"). • The presence or absence of "clone()" in that object or whether transformation is enabled. • The final array in "state.getTransformedNodes()" if we are in transformation mode. • This yields evidence: does the test accidentally inject some partial object? Does "getTransformedNodes()" come back empty? 3. Compare with Passing Tests: • If there is a closely related passing test (e.g. a simpler run directive test in OutputService), do a side-by-side to see how it configures the test harness vs. the failing test: (a) Does the passing test set "enableTransformation(true)" but the failing test does not? (b) Does the passing test create a real "StateService" while the failing test uses a stub? 4. Deliverables & Exit Criteria: • A short log output or debug capture for each failing test. • A clear note explaining which object or method is missing or incorrectly set up. • No code changes beyond inserting logs and debugging statements. At this point, we want the raw evidence. ──────────────────────────────────────────────────────────────────── PHASE 4: RESOLVE MISMATCHES AND ENSURE PRODUCTION-LIKE SETUP ──────────────────────────────────────────────────────────────────── Objective: Now that we see precisely which mocks or service initializations differ from production, we systematically fix them so the big tests pass. 1. Fix "StateService" Injection in Tests: • If logs show that "api/api.test.ts" uses a "fakeState" that lacks "clone," replace it with either (a) a proper mock that includes "clone()" or (b) the real "StateService" if we want a full integration test. • Ensure each test that needs transformation mode is actually enabling transformation the same way production code does (e.g. "context.state.enableTransformation(true)"). 2. Confirm DirectiveService -> StateService Flow: • In the "api/api.test.ts," check that "DirectiveService" is truly returning a new state object that also has "clone()." • If a partial mock is returned, unify it (likely remove partial mocks for full integration tests, or fully implement them so they match production). 3. OutputService Node Flow: • For the 3 failing OutputService tests, confirm that by the time "OutputService.convert" is called, "state.getTransformedNodes()" actually has the directive replaced. • If not, check "RunDirectiveHandler.execute" or "EmbedDirectiveHandler.execute" calls to see if they store the replacement node. • Correct the logic or the test setup as needed. This might mean ensuring we call "interpreterService.interpret([...], { transformation: true })" in the test. 4. Deliverables & Exit Criteria: • All 7 failing tests now pass (unless a test's expectation is truly incorrect). If the test's logic contradicts real architecture decisions, correct the test description or remove it. • No directive definitions or raw commands appear in the final output for transformation-based tests. • Feature parity with the mini-tests from Phase 2. By the end of this phase, the fundamental clones and transformation flows in integration tests will match what we already proved in isolation. ──────────────────────────────────────────────────────────────────── PHASE 5: DIRECTIVE & OUTPUT CONSISTENCY RULES ──────────────────────────────────────────────────────────────────── Objective: Confirm that the entire codebase has a unified rule on how directives should appear (or not appear) in output, plus handle any special edge cases (e.g., a directive intentionally kept). 1. Unify the Directive Transformation Rule: • Decide, once and for all, if seeing a "DirectiveNode" in transformation mode is a valid scenario or an error. • If it's always invalid, ensure each directive handler replaces itself with text/code. • If some directives are allowed, confirm which, under which conditions, and ensure all relevant handlers exhibit consistent logic. 2. Update Documentation & Comments: • In "docs/ARCHITECTURE.md" or a relevant doc, clarify that in transformation mode, all directive nodes are replaced by text/code nodes, or removed if they produce no user-visible output. • Document how test authors can expect "StateService" to store final, transformed nodes. 3. Adjust or Add Tests if Needed: • If we discover any contradictory test scenario (one expects a directive to remain, another demands it vanish), either unify the expectation or split them into two test modes with explicit rationales. • Add new coverage for corner cases: (a) A directive that has no output (like a pure definition). (b) A directive that partially modifies the text but remains. (c) Edge cases around error handling (e.g., directive fails to transform properly). 4. Deliverables & Exit Criteria: • A clear-coded "transformation contract" that every directive handler follows. • Documentation in the code (JSDoc or doc comments) plus test coverage verifying this rule. • No contradictions or confusion in the test suite about whether "@define," "@import," etc. should appear in final output. ──────────────────────────────────────────────────────────────────── PHASE 6: CLEANUP & LONG-TERM MAINTENANCE ──────────────────────────────────────────────────────────────────── Objective: With all tests passing and consistent transformation rules in place, remove any debugging artifacts, unify leftover flags, and ensure we have robust instructions for future maintainers. 1. Remove or Convert Debug Logs: • If you inserted "console.log" or "debugger" statements in integration tests, strip them out or convert them to a more permanent debugging facility (stop spamming test outputs). 2. Finalize Docs & Architecture Overviews: • Incorporate diagrams or bullet references in "docs/ARCHITECTURE.md," "docs/TESTS.md," or "services/StateService/README.md" explaining the transformation pipeline. • Summarize the "mini-tests" approach, so future devs can replicate it quickly when diagnosing new issues. 3. Ensure Ongoing Test Consistency: • Double-check that no new partial mocks slip in. • Possibly add a lint or code check that mocks must implement the entire "IStateService" if they claim to do so. 4. Deliverables & Exit Criteria: • A final, stable codebase with no transformation or state-management failures. • Thorough documentation for new devs to quickly see how we handle directive-to-text transformations. • All 484 tests passing consistently, plus the new mini-tests and any updated coverage. ──────────────────────────────────────────────────────────────────── SUMMARY OF HOW THIS IS INCREMENTAL ──────────────────────────────────────────────────────────────────── • Phases 1–2 do not alter any core business logic; they simply align interfaces and confirm they function in isolation, ensuring no existing tests break. • Phases 3–4 systematically address the failing integration tests by matching them to real-world usage (no partial mocks, correct transformation toggles). We expect to fix the 7 known failing tests here without breaking the other 400+ passing tests. • Phases 5–6 unify directive transformation rules in all docs/tests, then clean up leftover logs or toggles. This final step ensures a fully coherent design that new team members can easily follow. By following this plan in order—always focusing first on proven alignment before changing bigger test code—we avoid partial fixes that re-break existing functionality. This methodical approach uses evidence at each stage, verifying that "transformation mode" and "clone()" work as intended in isolation and in real integration flows. \======= END CONTEXT \======= AUDIT WORK COMPLETED The following documents were created by LLMs working on the audit advised by the plan. I'm concerned that they got a bit context drunk and I'm suspect of the accuracy of their information. We may need to take a different approach to completing the audit work. \==== ATTEMPT 1 part a # Meld Services Inventory & Audit ## Service Inventory Table ```ascii ┌────────────────────┬────────────────────────┬───────────────┬────────────────┐ │ Service │ Primary Role │ Dependencies │ Files To │ │ │ │ │ Review │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ CLIService │ Entry point │ All core │ cli/index.ts │ │ │ Pipeline orchestration │ services │ cli/cli.test.ts│ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ ParserService │ AST generation │ meld-ast │ services/ │ │ │ Location tracking │ │ ParserService/ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ InterpreterService│ Directive processing │ DirectiveServ │ services/ │ │ │ Node transformation │ StateService │ Interpreter │ │ │ Pipeline coordination │ Resolution │ Service/ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ DirectiveService │ Directive routing │ Validation │ services/ │ │ │ Handler management │ State │ DirectiveServ/ │ │ │ Node replacement │ Resolution │ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ StateService │ Variable storage │ None │ services/ │ │ │ Node state management │ │ StateService/ │ │ │ Transform tracking │ │ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ ResolutionService │ Variable resolution │ State │ services/ │ │ │ Path expansion │ Circularity │ Resolution │ │ │ Reference handling │ │ Service/ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ ValidationService │ Directive validation │ None │ services/ │ │ │ Constraint checking │ │ Validation │ │ │ │ │ Service/ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ CircularityService│ Import loop prevention │ None │ services/ │ │ │ Reference cycle detect │ │ Circularity │ │ │ │ │ Service/ │ ├────────────────────┼────────────────────────┼───────────────┼────────────────┤ │ OutputService │ Format conversion │ State │ services/ │ │ │ Clean output gen │ llmxml │ OutputService/ │ └────────────────────┴────────────────────────┴───────────────┴────────────────┘ ## Audit Progress ### StateService (In Progress) #### Mock Implementation Review 1. Multiple Mock Implementations Found: - `tests/mocks/state.ts`: Legacy `InterpreterState` class - `tests/utils/testFactories.ts`: Current `createMockStateService()` - `tests/utils/TestContext.ts`: Uses real `StateService` in test setup 2. Interface Alignment Status: - ✓ All interface methods present in `createMockStateService` - ✗ Legacy `InterpreterState` missing transformation methods - ⚠️ Mock implementations don't match real service behavior 3. Critical Gaps: - Transformation state inheritance not properly handled - Inconsistent state preservation in cloning - Child state creation doesn't match real implementation - State merging behavior differs between mocks and real service 4. Test Usage Patterns: - Some tests use legacy mock - Some tests use factory-created mock - Some tests use real service - No consistent pattern across test suite #### Next Steps 1. Complete interface alignment audit 2. Document transformation state lifecycle 3. Verify mock behavior matches real implementation 4. Plan migration from legacy mock to current mock ## Files Needing Review Critical files for initial audit: 1. Core Interfaces: - [x] services/StateService/IStateService.ts - [ ] services/DirectiveService/IDirectiveService.ts - [ ] services/InterpreterService/IInterpreterService.ts 2. Implementations: - [x] services/StateService/StateService.ts - [ ] services/DirectiveService/DirectiveService.ts - [ ] services/InterpreterService/InterpreterService.ts 3. Test Infrastructure: - [x] tests/utils/testFactories.ts - [x] tests/utils/TestContext.ts - [x] tests/mocks/state.ts 4. Failing Tests: - [ ] api/api.test.ts - [ ] services/OutputService/OutputService.test.ts - [ ] (other failing test files to be identified) ## Notes ### StateService Audit Findings 1. Interface Definition (`IStateService.ts`): - ✅ Well-defined interface with clear method groupings - ✅ Explicit transformation methods marked as "(new)" - ✅ Complete method signatures for all operations 2. Implementation (`StateService.ts`): - Core State Management: - Uses immutable `StateNode` pattern - Maintains state through `StateFactory` - All state updates go through `updateState()` - Transformation Implementation: - Private `_transformationEnabled` flag - Dual node arrays: `nodes` and `transformedNodes` - `transformedNodes` initialized as copy of `nodes` when enabled - Transformation operations properly check mutability 3. Mock Implementation Issues: - Multiple competing implementations - Inconsistent behavior with real service - Missing transformation state handling - State inheritance not properly implemented 4. Test Context Concerns: - Mixed usage of real and mock services - Inconsistent transformation state defaults - Potential source of test failures ## Next Steps 1. Review each interface file 2. Compare with implementation 3. Verify mock implementations 4. Document any gaps or misalignments 5. Propose fixes for identified issues ## Notes ### StateService Audit Findings 1. Interface Definition (`IStateService.ts`): - ✅ Well-defined interface with clear method groupings - ✅ Explicit transformation methods marked as "(new)" - ✅ Complete method signatures for all operations 2. Implementation (`StateService.ts`): - Core State Management: - Uses immutable `StateNode` pattern - Maintains state through `StateFactory` - All state updates go through `updateState()` - Transformation Implementation: - Private `_transformationEnabled` flag - Dual node arrays: `nodes` and `transformedNodes` - `transformedNodes` initialized as copy of `nodes` when enabled - Transformation operations properly check mutability 3. State Factory (`StateFactory.ts`): - Handles immutable state updates - Properly copies transformed nodes in: - `createState` - `createChildState` - `mergeStates` - `updateState` 4. Critical Findings: a) Clone Implementation: ```typescript clone(): IStateService { const cloned = new StateService(); cloned.currentState = this.stateFactory.createState({...}); cloned.updateState({ // ... other state ... transformedNodes: this.currentState.transformedNodes ? [...this.currentState.transformedNodes] : undefined, }, 'clone'); cloned._transformationEnabled = this._transformationEnabled; return cloned; } ``` - ✅ Creates new service instance - ✅ Copies transformation flag - ✅ Copies transformed nodes if they exist - ✅ Uses factory for state creation - ❓ Potential issue: Does `createState` properly handle all parent state? b) Transformation State Handling: - Transformation state is tracked in multiple places: 1. Service level: `_transformationEnabled` flag 2. State level: `transformedNodes` array 3. Factory level: Copied during state operations - This complexity could lead to inconsistencies 5. Test Coverage (`StateService.transformation.test.ts`): - ✅ Tests default transformation state - ✅ Tests node transformation - ✅ Tests state preservation in cloning - ✅ Tests immutability with transformations - ❓ Missing: Tests for complex state inheritance scenarios 6. Potential Issues: a) State Inheritance: - Complex interaction between parent/child states and transformation - Need to verify transformation state is properly inherited b) State Merging: - `mergeStates` handles transformed nodes, but logic mig