refactor: use project-named state file and store prompt/params directly
All checks were successful
Continuous Integration / Build Package (push) Successful in 48s
Continuous Integration / Lint, Check & Test (push) Successful in 1m1s

- State filename now derives from config: cards.bulkgen.yaml produces
  .cards.bulkgen-state.yaml instead of .bulkgen.state.yaml
- Store resolved prompt text and extra params directly in state file
  instead of hashing them, making state files human-readable
- Only file input contents remain hashed (SHA-256)
- Thread project_name through builder and CLI
- Remove hash_string() and _extra_hash() helpers
- Update .gitignore pattern to .*.bulkgen-state.yaml
This commit is contained in:
Konstantin Fickel 2026-02-15 13:56:12 +01:00
parent 870023865d
commit 0ecf1f0f9e
Signed by: kfickel
GPG key ID: A793722F9933C1A5
7 changed files with 98 additions and 82 deletions

View file

@ -14,9 +14,21 @@ from bulkgen.builder import BuildEvent, BuildResult, run_build
from bulkgen.config import ProjectConfig, load_config
from bulkgen.graph import build_graph, get_build_order
from bulkgen.providers.registry import get_all_models
from bulkgen.state import state_filename
app = typer.Typer(name="bulkgen", help="AI artifact build tool.")
_CONFIG_SUFFIX = ".bulkgen.yaml"
def _project_name(config_path: Path) -> str:
"""Derive the project name from a config path.
``cards.bulkgen.yaml`` ``cards``
"""
name = config_path.name
return name.removesuffix(_CONFIG_SUFFIX)
def _find_config(directory: Path) -> Path:
"""Find the single ``*.bulkgen.yaml`` file in *directory*."""
@ -49,7 +61,7 @@ def _format_elapsed(seconds: float) -> str:
def _run_build(
config: ProjectConfig, project_dir: Path, target: str | None
config: ProjectConfig, project_dir: Path, project_name: str, target: str | None
) -> tuple[BuildResult, float]:
"""Run the async build with click-styled progress output and timing."""
@ -85,7 +97,7 @@ def _run_build(
start = time.monotonic()
result = asyncio.run(
run_build(config, project_dir, target, on_progress=on_progress)
run_build(config, project_dir, project_name, target, on_progress=on_progress)
)
elapsed = time.monotonic() - start
@ -102,10 +114,11 @@ def build(
project_dir = Path.cwd()
config_path = _find_config(project_dir)
config = load_config(config_path)
name = _project_name(config_path)
click.echo(click.style("bulkgen", fg="cyan", bold=True) + " building targets...\n")
result, elapsed = _run_build(config, project_dir, target)
result, elapsed = _run_build(config, project_dir, name, target)
# Summary
click.echo("")
@ -131,6 +144,7 @@ def clean() -> None:
project_dir = Path.cwd()
config_path = _find_config(project_dir)
config = load_config(config_path)
state_name = state_filename(_project_name(config_path))
removed = 0
for target_name in config.targets:
@ -140,10 +154,10 @@ def clean() -> None:
click.echo(click.style(" rm ", fg="red") + target_name)
removed += 1
state_path = project_dir / ".bulkgen.state.yaml"
state_path = project_dir / state_name
if state_path.exists():
state_path.unlink()
click.echo(click.style(" rm ", fg="red") + ".bulkgen.state.yaml")
click.echo(click.style(" rm ", fg="red") + state_name)
click.echo(click.style(f"\nCleaned {removed} artifact(s)", bold=True))