---
model: accounts/fireworks/routers/kimi-k2p5-turbo
---

# Plan: `ask262Debug` Module for engine262

## Overview

Runtime execution tracker that records which ECMAScript spec sections are entered during execution. The Babel transform auto-injects `ask262Debug.mark()` at the start of every function body with URL comments — developer writes nothing. All metadata (sectionId, file, line) resolved at build time.

**Primary Use Case:** AI analysis of execution flow mapped to ECMAScript spec sections for understanding JavaScript engine behavior.

## Files to Change

| File | Action |
|------|--------|
| `engine262/src/ask262-debug.mts` | **CREATE** — the module with deduplication logic |
| `engine262/src/index.mts` | **MODIFY** — add named re-export |
| `engine262/scripts/transform.mts` | **MODIFY** — auto-inject `mark()` and import |
| `engine262/scripts/verify-ask262-debug.mts` | **CREATE** — post-build verification script |

## 1. `scripts/transform.mts` — Enhance the Babel Plugin

### 1a. Extend State Interface

Add `ask262Debug` to the `NeededNames` type and extend `State` interface:

```typescript
type NeededNames = 'Completion' | 'AbruptCompletion' | 'Assert' | 'Call' | 
                   'IteratorClose' | 'AsyncIteratorClose' | 'Value' | 
                   'skipDebugger' | 'ask262Debug';  // NEW

interface State extends PluginPass {
  needed: Partial<Record<NeededNames, boolean>>;
  fileRelativePath?: string;  // NEW: captured at Program enter
}
```

### 1b. Add Import Creator Function

Add alongside existing `createImport*` functions:

```typescript
function createImportAsk262Debug() {
  return template.ast(`
    import { ask262Debug } from "#self";
  `);
}
```

### 1c. Refactor `addSectionFromComments`

The current function (lines 101-133) handles only single URLs. Update to capture multiple section IDs and inject `mark()`:

```typescript
function addSectionFromComments(
  path: NodePath<t.FunctionDeclaration> | NodePath<t.VariableDeclaration> | 
        NodePath<t.ExportNamedDeclaration> | NodePath<t.ClassMethod> | NodePath<t.ObjectMethod>,
  state: State,
  getName: () => string,
  getBody: () => t.BlockStatement | null
) {
  if (!path.node.leadingComments) return;

  const sectionIds: string[] = [];
  let url = '';
  
  for (const c of path.node.leadingComments) {
    for (const line of c.value.split('\n')) {
      const matches = line.match(/#(sec-[a-zA-Z0-9._%-]+)/g);
      if (matches) {
        sectionIds.push(...matches.map(m => m.substring(1)));
        if (!url) {
          const section = line.split(' ').find(l => l.includes('#sec'));
          // Only capture external URLs (skip local/fragment references)
          if (section?.startsWith('https://')) {
            url = section;
          }
        }
      }
    }
  }
  
  if (sectionIds.length === 0) return;

  const name = getName();
  
  // 1. Keep existing .section (backward compat) - uses first URL
  // Only applies to named functions
  if (name && url) {
    path.insertAfter(template.ast(`${name}.section = '${url}';`));
  }

  // 2. Get function body via callback (node-type check done by caller)
  const body = getBody();

  // 3. Inject mark() at start of function body (only for block bodies)
  if (body?.type === 'BlockStatement') {
    const line = path.node.loc?.start.line ?? 0;
    const markCall = template.statement(
      `ask262Debug.mark(${JSON.stringify(sectionIds)}, ${JSON.stringify(state.fileRelativePath)}, ${line});`
    )();
    body.body.unshift(markCall);
    state.needed.ask262Debug = true;
  }
}
```

### 1d. Update Visitors

Update existing visitors to use new `addSectionFromComments` signature, and add new visitors for ClassMethod and ObjectMethod:

```typescript
return {
  visitor: {
    Program: {
      enter(path, state) {
        state.needed = {};
        // Capture relative file path from state.filename
        const absolutePath = state.filename || '';
        state.fileRelativePath = absolutePath.replace(/.*\/(src\/)/, '$1').replace(/\.mts$/, '.mts') || 'unknown.mts';
      },
      exit(path, state) {
        // ... existing imports (skipDebugger, Completion, etc.) ...
        // NEW: Add ask262Debug import if needed
        if (state.needed.ask262Debug) {
          path.unshiftContainer('body', createImportAsk262Debug());
        }
      },
    },
    FunctionDeclaration(path, state) {
      addSectionFromComments(
        path, state,
        () => path.node.id!.name,
        () => path.node.body
      );
    },
    VariableDeclaration(path, state) {
      const init = path.get('declarations.0.init');
      if (init.isFunctionExpression()) {
        const id = path.node.declarations[0].id as t.Identifier;
        addSectionFromComments(
          path, state,
          () => id.name,
          () => init.node.body
        );
      } else if (init.isArrowFunctionExpression()) {
        const id = path.node.declarations[0].id as t.Identifier;
        addSectionFromComments(
          path, state,
          () => id.name,
          () => init.node.body.type === 'BlockStatement' ? init.node.body : null
        );
      }
    },
    ExportNamedDeclaration(path, state) {
      const declaration = path.node.declaration;
      if (declaration?.type === 'FunctionDeclaration') {
        addSectionFromComments(
          path, state,
          () => declaration.id!.name,
          () => declaration.body
        );
      }
    },
    // NEW: Add ClassMethod visitor
    ClassMethod(path, state) {
      const key = path.node.key;
      if (key.type === 'Identifier') {
        addSectionFromComments(
          path, state,
          () => key.name,
          () => path.node.body
        );
      }
    },
    // NEW: Add ObjectMethod visitor
    ObjectMethod(path, state) {
      const key = path.node.key;
      if (key.type === 'Identifier') {
        addSectionFromComments(
          path, state,
          () => key.name,
          () => path.node.body
        );
      }
    },
    // ... rest of existing visitors (CallExpression, ThrowStatement, etc.) unchanged
  },
};
```

### 1e. Arrow Function Special Handling

The updated `addSectionFromComments` handles this automatically:
- Arrow with block body `() => { ... }`: `.section` + `mark()` injected
- Arrow with expression body `() => expr`: `.section` only, no `mark()`

## 2. `engine262/src/index.mts` — Add Named Re-export

Add the re-export alongside existing exports (around line 20):

```typescript
// Add to existing exports from './helpers.mts' or create new export section
export { ask262Debug, type MarkData } from './ask262-debug.mts';
```

## 3. `engine262/src/ask262-debug.mts` — The Module

Deduplicated data collection. No stack parsing, no `node:` imports, no decorators.

```typescript
export interface MarkData {
  readonly sectionIds: string[];
  readonly fileRelativePath: string;
  readonly lineNumber: number;
  readonly important: boolean;
}

interface MarkKey {
  readonly sectionIds: string;
  readonly file: string;
  readonly line: number;
}

class Ask262Debug {
  marks: MarkData[] = [];
  private _importantStack = false;
  private _markIndex = new Map<string, number>(); // key -> index in marks

  private _makeKey(sectionIds: string[], file: string, line: number): string {
    return `${sectionIds.join(',')}|${file}|${line}`;
  }

  mark(sectionIds: string[], file: string, line: number) {
    const key = this._makeKey(sectionIds, file, line);
    const existingIndex = this._markIndex.get(key);
    
    if (existingIndex !== undefined) {
      // Merge important flag
      const existing = this.marks[existingIndex];
      if (this._importantStack && !existing.important) {
        (this.marks[existingIndex] as any).important = true;
      }
      return;
    }
    
    const newMark: MarkData = {
      sectionIds: [...sectionIds], // defensive copy
      fileRelativePath: file,
      lineNumber: line,
      important: this._importantStack,
    };
    
    this._markIndex.set(key, this.marks.length);
    this.marks.push(newMark);
  }

  startImportant() {
    this._importantStack = true;
  }

  stopImportant() {
    this._importantStack = false;
  }
}

export const ask262Debug = new Ask262Debug();
```

### Key Behaviors

| Scenario | Behavior |
|----------|----------|
| Duplicate `(sectionIds, file, line)` | Keep one entry, merge `important` flags (OR logic) |
| Generator resumption | Mark on every `.next()` call (may create duplicates if same location) |
| Nested functions | Each entry adds its mark (chronological trace) |

## 4. `engine262/scripts/verify-ask262-debug.mts` — Verification Script

```typescript
#!/usr/bin/env node
import { ask262Debug, Agent, ManagedRealm } from '#self';

console.log('=== ask262Debug Verification ===\n');

// 1. Check export exists
console.log('1. Checking export...');
if (!ask262Debug) {
  console.error('FAIL: ask262Debug not exported');
  process.exit(1);
}
console.log('   ✓ ask262Debug exported\n');

// 2. Run code that hits known spec sections
console.log('2. Executing test code...');
const agent = new Agent();
const realm = new ManagedRealm({ agent });

realm.evaluateScript(`
  // Array.prototype.every - should hit sec-array.prototype.every
  [1, 2, 3].every(x => x > 0);
  
  // Proxy creation - should hit sec-proxycreate or similar
  new Proxy({}, {});
`);

// 4. Verify marks were captured
console.log('3. Checking marks...');
const marks = ask262Debug.marks;
console.log(`   Captured ${marks.length} unique marks\n`);

if (marks.length === 0) {
  console.error('FAIL: No marks captured');
  process.exit(1);
}

// 5. Show sample marks
console.log('4. Sample marks:');
marks.slice(0, 5).forEach((m, i) => {
  console.log(`   [${i}] ${m.sectionIds.join(', ')} @ ${m.fileRelativePath}:${m.lineNumber}${m.important ? ' [important]' : ''}`);
});

console.log('=== All Checks Passed ===');
```

## Key Design Decisions Summary

| Decision | Choice | Rationale |
|----------|--------|-----------|
| **Use case** | AI execution flow analysis | Map runtime to spec sections |
| **Import pattern** | `import { ask262Debug } from '#self'` | Uses existing pattern (315+ occurrences) |
| **Bundle strategy** | Included in engine262.mjs | Single artifact, no config changes needed |
| **Data structure** | Deduplicated array | Chronological trace with unique entries only |
| **Deduplication key** | `(sectionIds, file, line)` | Same location = same semantic entry |
| **Duplicate handling** | Merge `important` flags (OR) | If any call was important, mark it important |
| **All metadata** | From transform (build time) | No runtime stack parsing, no `node:` imports |
| **`mark()` injection** | Auto-injected at start of block body | Developer writes nothing |
| **Arrow functions** | Block body: `.section` + `mark()`, Expression: `.section` only | Can't inject statement in expression |
| **Multi-section** | Array of section IDs per function | Functions can implement multiple spec sections |
| **`.section`** | Kept (backward compat) | Used by test262-intrinsics |
| **Generators** | Mark on every `.next()` | Simpler, deduplication handles repeats |
| **Nested functions** | Mark all | Chronological trace for AI analysis |
| **`important`** | User-driven `startImportant()`/`stopImportant()` | Manual annotation of interesting sections |
| **Function types** | FunctionDeclaration + ClassMethod + ObjectMethod + VariableDeclaration | Covers all URL comment patterns |
| **Class/Object method keys** | Identifier names only | Simple, covers 99% of cases |
| **File paths** | Relative to `engine262/src/`, `.mts` extension | Maps to source, not compiled output |
| **Line numbers** | 1-indexed from Babel AST | Matches source file line numbers |

## Implementation Checklist

1. [ ] **Create** `engine262/src/ask262-debug.mts` with the module code
2. [ ] **Modify** `engine262/src/index.mts` - add re-export
3. [ ] **Modify** `engine262/scripts/transform.mts`:
   - [ ] Add `ask262Debug` to `NeededNames` type
   - [ ] Extend `State` interface with `fileRelativePath`
   - [ ] Add `createImportAsk262Debug()` function
   - [ ] Update `addSectionFromComments()` signature and logic
   - [ ] Update `Program.exit` to inject ask262Debug import
   - [ ] Update `FunctionDeclaration` visitor
   - [ ] Update `VariableDeclaration` visitor  
   - [ ] Update `ExportNamedDeclaration` visitor
   - [ ] Add `ClassMethod` visitor
   - [ ] Add `ObjectMethod` visitor
4. [ ] **Create** `engine262/scripts/verify-ask262-debug.mts`
5. [ ] **Type checking**: `cd engine262 && npx tsc -b .`
6. [ ] **Linting**: `cd engine262 && npm run lint`
7. [ ] **Build**: `cd engine262 && npm run build:engine`
8. [ ] **Verification**: `cd engine262 && node --enable-source-maps --disable-warning=ExperimentalWarning --experimental-strip-types scripts/verify-ask262-debug.mts`

## Expected Output from Verification

```
=== ask262Debug Verification ===

1. Checking export...
   ✓ ask262Debug exported

2. Executing test code...
3. Checking marks...
   Captured 47 unique marks

4. Sample marks:
   [0] sec-array.prototype.every @ intrinsics/ArrayPrototypeShared.mts:173
   [1] sec-proxycreate @ abstract-ops/proxy-objects.mts:540
   ...

=== All Checks Passed ===
```

## Troubleshooting

### Issue: No marks captured after build
**Cause:** Transform not injecting `mark()` calls
**Fix:** Check that functions have URL comments with `#sec-` patterns

### Issue: Build fails with "Cannot find module '#self'"
**Cause:** Rollup not resolving the import
**Fix:** Ensure babel transform runs before resolution in rollup config

### Issue: Line numbers are off
**Cause:** Babel source maps not configured
**Fix:** Check that `sourceMap: true` in babelOptions and `loc` is preserved

### Issue: Duplicate marks for same function
**Cause:** Generator resumption or recursion
**Fix:** This is expected behavior - deduplication happens on `(sectionIds, file, line)`
