# How to Use the Generation Status API for Tracking CAD Artifact Creation in Text-to-CAD

> Learn how to use the Generation Status API to track CAD artifact creation in text-to-CAD. Monitor long-running generation steps with this lightweight, file-based mechanism.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: api-reference
- Published: 2026-08-01

---

**The generation status API provides a lightweight, file-based mechanism for monitoring long-running CAD generation steps through JSON lock files that update every second during active processing.**

The earthtojake/text-to-cad repository implements a robust generation status API in [`packages/cadpy/src/cadpy/generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadpy/src/cadpy/generation_status.py) to track the creation of CAD artifacts without requiring a central service. This side-effect-free system uses atomic file operations to report progress on conversions like STEP to GLB or mesh sampling, enabling downstream tools to monitor pipeline status in real-time.

## Core Architecture of the Generation Status API

The API centers on two primary components: the `GenerationOutput` dataclass and the `track_generation_run` context manager.

### GenerationOutput Dataclass

Defined at lines 21-25 in [`generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/generation_status.py), the `GenerationOutput` dataclass encapsulates a single output artifact with its path and kind:

```python
@dataclass
class GenerationOutput:
    path: Path
    kind: str  # e.g., "step", "glb"

```

### track_generation_run Context Manager

The `track_generation_run` function (lines 32-45) returns a context manager that initializes the tracking infrastructure. When entered, it instantiates `_GenerationStatusTracker` and invokes its `run()` method (lines 74-89) to handle nesting, start the heartbeat thread, and guarantee cleanup upon exit.

## Lock File Mechanism and Heartbeat System

The generation status API creates hidden lock files alongside each declared output to communicate runtime state.

### Atomic File Writing

The `_write_status` function (lines 14-28) serializes a JSON payload containing the schema version, run ID, PID, timestamps, generator name, source path, and output list. It writes to a temporary file first, then atomically renames it to the final lock file path to prevent corruption during concurrent access.

### File Naming Convention

Lock files follow the pattern `.{output_name}.{run_id}.generation.lock.json` and reside in the same directory as their associated outputs. For example, generating `models/part.step` creates [`.part.step.12345-abcdef.generation.lock.json`](https://github.com/earthtojake/text-to-cad/blob/main/.part.step.12345-abcdef.generation.lock.json).

### Heartbeat Interval

A background thread calls `_write_status` every `_HEARTBEAT_INTERVAL_SEC` (defaulting to 1 second) to refresh the `updatedAt` timestamp. This heartbeat signals that the generation process remains active.

## Practical Implementation Examples

### Tracking a Single CAD Output

```python
from pathlib import Path
from cadpy.generation_status import GenerationOutput, track_generation_run

source = Path("models/part.py")
step = Path("models/part.step")

with track_generation_run(
    source_path=source,
    generator="gen_step",
    outputs=[GenerationOutput(step, "step")],
    repo_root=Path.cwd(),
):
    # Long-running STEP generation logic here

    generate_step_file(source, step)

```

### Monitoring Multiple Artifacts

```python
from pathlib import Path
from cadpy.generation_status import GenerationOutput, track_generation_run

step = Path("models/part.step")
glb = Path("models/part.glb")

with track_generation_run(
    source_path=None,
    generator="step_to_glb",
    outputs=[
        GenerationOutput(step, "step"),
        GenerationOutput(glb, "glb"),
    ],
):
    convert_step_to_glb(step, glb)

```

### Inspecting Lock File Contents

During active generation, the lock file contains:

```json
{
  "schemaVersion": 1,
  "id": "12345-abcdef...",
  "status": "running",
  "pid": 5678,
  "startedAt": "2026-08-01T12:34:56Z",
  "updatedAt": "2026-08-01T12:34:57Z",
  "sourcePath": "models/part.py",
  "generator": "gen_step",
  "outputs": [
    { "path": "models/part.step", "kind": "step" }
  ]
}

```

## Cleanup and Failure Handling

When the context manager exits successfully, the tracker removes all lock files. If removal fails due to race conditions or permissions, it writes a final payload with `"status": "finished"` before terminating. This ensures that downstream tooling can always discover the final state, even when file system operations encounter errors.

## Integration Across the Codebase

The generation status API appears in several locations within the repository:

- [`packages/cadpy/src/cadpy/generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadpy/src/cadpy/generation_status.py) - Core implementation containing `track_generation_run` and `_GenerationStatusTracker`
- [`tests/python/packages/cadpy/test_generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/tests/python/packages/cadpy/test_generation_status.py) - Unit tests demonstrating heartbeat and cleanup behavior
- [`viewer/packages/cadpy/src/cadpy/generation.py`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadpy/src/cadpy/generation.py) - High-level pipeline integration
- `skills/*/scripts/*/generation_status.py` - Symlinked copies for individual skill runtimes

## Summary

- The generation status API in [`cadpy/generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/cadpy/generation_status.py) provides file-based progress tracking without central services.
- The `track_generation_run` context manager creates JSON lock files that update every second via a background heartbeat thread.
- Lock files use atomic writes and follow the naming convention `.{output_name}.{run_id}.generation.lock.json`.
- The system gracefully handles failures by writing a final "finished" status if lock file removal fails.
- Multiple outputs can be tracked simultaneously using the `GenerationOutput` dataclass.

## Frequently Asked Questions

### Where is the generation status API implemented?

The generation status API is implemented in [`packages/cadpy/src/cadpy/generation_status.py`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadpy/src/cadpy/generation_status.py) within the earthtojake/text-to-cad repository. This module contains the `track_generation_run` context manager, `GenerationOutput` dataclass, and the internal `_GenerationStatusTracker` class that manages the heartbeat mechanism.

### How does the heartbeat mechanism work?

The heartbeat mechanism runs in a background thread started by `_GenerationStatusTracker.run()`. It calls `_write_status` every `_HEARTBEAT_INTERVAL_SEC` (default 1 second) to update the `updatedAt` timestamp in the JSON lock file. This allows external monitoring tools to verify that the generation process is still active and has not stalled or crashed.

### What happens if the generation process crashes?

If the process crashes or is killed, the heartbeat thread terminates and the lock file remains on disk with its last updated timestamp. Downstream tools can detect this by comparing the `updatedAt` field against the current time. If the difference exceeds the expected heartbeat interval, the generation is likely dead. The file will not be automatically cleaned up, providing forensic evidence of the failure point.

### Can I track multiple CAD outputs simultaneously?

Yes. Pass a list of `GenerationOutput` objects to the `outputs` parameter of `track_generation_run`. The API creates separate lock files for each output following the pattern `.{output_name}.{run_id}.generation.lock.json`. This allows independent monitoring of each artifact's generation status, useful for complex pipelines producing STEP files, GLB conversions, and mesh samples from a single source.