Journal Entries

MECA Initiative - Phase III Project Plan

2025-06-11

The capstone phase: this plan details the implementation of the full MPI system for dynamic agent operations, a smart 'integrateExperiment' command, and the final 'promote' graduation pipeline to complete the core MECA workflow.

MECA Initiative: Completion of Phases I & II

2025-06-10

A memo from project management to the development team and stakeholders announcing the successful completion of Phases I and II of the MECA Initiative and the official kickoff of Phase III.

MECA Initiative - Phase II Project Plan

2025-06-09

Actionable plan to build the MECA engine. Covers the foundational transactional context (TxContext), the first AST-based helper (addImport), and the flagship 'createExperiment' operation to enable programmatic project scaffolding.

MECA Initiative - Phase I Project Plan

2025-06-08

Actionable plan to build the foundational MECA infrastructure. Covers workspace scaffolding, the core Project abstraction, and a 'hello-world' CLI to validate the entire toolchain.

Project Kickoff: The MECA Initiative

2025-06-07

Kickoff for the Metaprogramming-Enabled Component Architecture (MECA) Initiative

On the Care and Training of Digital Apprentices

2025-06-06

A wry examination of artificial intelligence through the eyes of someone who has seen many promised revolutions come and go.

MECA Initiative - Phase II Project Plan

2025-06-09

meca

project-plan

phase-2

transactional-engine

ast

ts-morph

scaffolding

Project Plan: MECA Initiative - Phase II

Project Objective

The objective of Phase II is to evolve the MECA framework from a read-only tool into a state-changing "engine." We will implement the foundational transactional system for managing safe file modifications and build our first high-level, programmatic scaffolding operation. This phase will deliver the first tangible productivity gain by automating the creation of new experiments.

Key Deliverables

  1. The Foundational TxContext: An initial implementation of a transactional context in meca-core capable of staging and committing file system operations.
  2. The First AST-Based Helper: A robust addImport helper function that uses ts-morph to safely add or modify import statements in a TypeScript file.
  3. The createExperiment Operation: A complete, end-to-end meca create experiment <name> command that uses the TxContext to scaffold a new, well-structured package in the sandbox.

Acceptance Criteria for Phase II

  • The meca create experiment <name> command executes successfully and creates a new package in the sandbox/ directory.
  • The newly created package directory contains the following files: package.json, src/index.ts, src/[ComponentName].tsx, and src/[ComponentName].meta.ts.
  • The addImport helper function is covered by unit tests within the meca-core package.
  • All file creation operations performed by createExperiment are managed through the TxContext.

Task 1: Implement the Transactional Context (TxContext)

This task creates the core engine for managing safe state changes. The initial version will focus on aggregating operations and executing them sequentially.

  • Step 1.1: In packages/meca-core/src/, create a new file transaction.ts.

  • Step 1.2: Define the interfaces for pending operations and the initial TxContext class.

    // packages/meca-core/src/transaction.ts
    import * as fs from 'fs/promises';
    import * as path from 'path';
    
    type PendingOperation =
      | { type: 'CREATE_FILE'; path: string; content: string }
      | { type: 'CREATE_DIRECTORY'; path: string };
    
    export class TxContext {
      private operations: PendingOperation[] = [];
    
      public stage(op: PendingOperation): void {
        this.operations.push(op);
      }
    
      public async commit(): Promise<void> {
        // NOTE: This initial implementation is not truly atomic.
        // It executes operations sequentially.
        console.log(`Committing ${this.operations.length} operations...`);
        for (const op of this.operations) {
          switch (op.type) {
            case 'CREATE_DIRECTORY':
              await fs.mkdir(op.path, { recursive: true });
              console.log(`  CREATED DIR: ${op.path}`);
              break;
            case 'CREATE_FILE':
              await fs.mkdir(path.dirname(op.path), { recursive: true });
              await fs.writeFile(op.path, op.content);
              console.log(`  CREATED FILE: ${op.path}`);
              break;
          }
        }
        this.operations = []; // Clear operations after commit
      }
    }
    
  • Step 1.3: Modify the Project class in packages/meca-core/src/index.ts to include the transaction method.

    // Add to Project class in packages/meca-core/src/index.ts
    import { TxContext } from './transaction';
    
    // ... inside the Project class
    public async transaction(run: (ctx: TxContext) => Promise<void>): Promise<void> {
        const context = new TxContext();
        await run(context);
        await context.commit();
    }
    

Task 2: Implement the First AST Helper

This task integrates ts-morph to build our first reusable, code-aware tool.

  • Step 2.1: Install ts-morph as a dependency in meca-core:

    pnpm add ts-morph -F @meca/core
    
  • Step 2.2: In packages/meca-core/src/, create ast-helpers.ts and implement the addImport function.

    // packages/meca-core/src/ast-helpers.ts
    import { SourceFile } from 'ts-morph';
    
    export interface AddImportParams {
      moduleSpecifier: string;
      namedImport?: string;
      isDefault?: boolean;
    }
    
    export function addImport(sourceFile: SourceFile, params: AddImportParams): void {
      const { moduleSpecifier, namedImport, isDefault } = params;
    
      const existingDeclaration = sourceFile.getImportDeclaration(moduleSpecifier);
    
      if (existingDeclaration) {
        if (isDefault && namedImport && !existingDeclaration.getDefaultImport()) {
          existingDeclaration.setDefaultImport(namedImport);
        } else if (namedImport) {
            const existingNamed = existingDeclaration.getNamedImports().map(ni => ni.getName());
            if (!existingNamed.includes(namedImport)) {
                existingDeclaration.addNamedImport(namedImport);
            }
        }
      } else {
        const newDeclaration = sourceFile.addImportDeclaration({ moduleSpecifier });
        if (isDefault && namedImport) {
          newDeclaration.setDefaultImport(namedImport);
        } else if (namedImport) {
          newDeclaration.addNamedImport(namedImport);
        }
      }
    }
    
  • Step 2.3: Create a corresponding unit test file ast-helpers.test.ts to validate the addImport logic under various conditions (new import, existing import, etc.).

Task 3: Implement the createExperiment Operation

This task uses the new TxContext to build the high-level scaffolding feature.

  • Step 3.1: In the Project class in packages/meca-core/src/index.ts, implement the createExperiment method.
    // Add to Project class in packages/meca-core/src/index.ts
    // ...
    public async createExperiment(name: string): Promise<void> {
        const componentName = name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, '');
        const experimentPath = path.join(this.rootPath, 'sandbox', name);
    
        await this.transaction(async (tx) => {
          // package.json
          tx.stage({
            type: 'CREATE_FILE',
            path: path.join(experimentPath, 'package.json'),
            content: JSON.stringify({ name: name, version: '0.1.0' }, null, 2)
          });
          // src/index.ts
          tx.stage({
            type: 'CREATE_FILE',
            path: path.join(experimentPath, 'src/index.ts'),
            content: `export * from './${componentName}';`
          });
          // src/[ComponentName].tsx
          tx.stage({
            type: 'CREATE_FILE',
            path: path.join(experimentPath, 'src', `${componentName}.tsx`),
            content: `export const ${componentName} = () => <div>${componentName}</div>;`
          });
          // src/[ComponentName].meta.ts
          tx.stage({
            type: 'CREATE_FILE',
            path: path.join(experimentPath, 'src', `${componentName}.meta.ts`),
            content: `// MPI operations for ${componentName} go here\nexport default {};`
          });
        });
    
        console.log(`Successfully created experiment '${name}' at ${experimentPath}`);
    }
    

Task 4: Integrate createExperiment into the CLI

This task exposes the new core functionality through the meca command.

  • Step 4.1: In packages/meca-cli/src/index.ts, add the new command to the commander program.
    // Add to packages/meca-cli/src/index.ts
    
    program
      .command('create:experiment <name>')
      .description('Scaffolds a new experiment package in the sandbox')
      .action(async (name: string) => {
        try {
          const project = await Project.load(process.cwd());
          await project.createExperiment(name);
        } catch (error) {
          console.error('An error occurred:', error);
          process.exit(1);
        }
      });
    

Task 5: Final Verification

This final task ensures all pieces of Phase II work together.

  • Step 5.1: From the project root, run pnpm install to ensure all dependencies are up to date.
  • Step 5.2: Build the updated packages: pnpm --filter "@meca/*" build.
  • Step 5.3: Execute the new CLI command: pnpm exec meca create:experiment my-new-timeline.
  • Step 5.4: Verify that a new directory sandbox/my-new-timeline exists and contains the four specified files (package.json, index.ts, MyNewTimeline.tsx, MyNewTimeline.meta.ts), confirming the successful completion of Phase II.

© 2025 screen.cam

Privacy PolicyTerms of Service