Files
roboco/alembic/versions/078_project_codegen_command.py
T
5f42a93b4f feat(git): auto-regenerate + commit codegen drift before push (#632)
A project that checks in generated artifacts (RoboCo's lifecycle renders,
verb tables) drifts whenever their source changes. The agent pre-submit gate
(make gate) omits foundation-check, so drift is invisible at the desk and only
fails on CI's drift gate — a failure with no link back to the task, which made
one live task thrash 8 revision rounds.

New per-project codegen_command (migration 078): run in the task's worktree
right before push, and any drift committed into the same push, so CI never
sees stale artifacts. Fail-open — a broken/timeout codegen command logs and
lets the push proceed (CI's drift gate is the safety net); a null command
(every project without checked-in codegen) is a pure no-op. Hooked at both
push_branch (open_pr's first push, the PR head CI grades) and push_task_branch
(later re-pushes). RoboCo sets codegen_command='make codegen' (a new Makefile
target — the write counterpart to foundation-check's read) via the panel.

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-21 16:38:07 +02:00

38 lines
1.3 KiB
Python

"""Per-project codegen-drift regeneration command.
Some projects check in generated artifacts (rendered docs, generated verb/prompt
tables, ...) that drift whenever their source changes. The agent pre-submit
gate (``quality_command``, e.g. ``make gate``) never regenerates them, so drift
only ever surfaces later as CI's own foundation-check-style `git diff
--exit-code` hard-fail — a failure an agent has no way to trace back to its own
task. ``codegen_command`` (e.g. ``make codegen``) is run in the task's
workspace before every push; any resulting drift is committed so the pushed PR
head is never stale. Additive and nullable — null (the default) is a pure
no-op for projects with no generated artifacts, mirroring ``quality_command``.
Revision ID: 078_project_codegen_command
Revises: 077_github_app
Create Date: 2026-07-21
"""
from __future__ import annotations
import sqlalchemy as sa
from alembic import op
revision = "078_project_codegen_command"
down_revision = "077_github_app"
branch_labels: dict[str, str] | None = None
depends_on: dict[str, str] | None = None
def upgrade() -> None:
op.add_column(
"projects",
sa.Column("codegen_command", sa.String(length=500), nullable=True),
)
def downgrade() -> None:
op.drop_column("projects", "codegen_command")