eb46f0ff54
CI / push-validation (push) Successful in 40s
CI / helm (push) Successful in 44s
CI / build (push) Successful in 1m14s
CI / lint (push) Successful in 1m18s
CI / quality (push) Successful in 1m36s
CI / e2e_tests (push) Successful in 1m19s
CI / typecheck (push) Successful in 2m22s
CI / security (push) Successful in 2m23s
CI / benchmark-regression (push) Failing after 41s
CI / integration_tests (push) Successful in 4m46s
CI / unit_tests (push) Failing after 20m13s
CI / benchmark-publish (push) Failing after 28m28s
CI / coverage (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / status-check (push) Has been cancelled
## Summary This PR fixes issue #10878 where architecture reviews were truncated because the regex pattern for parsing file output would stop at the first ``` encountered in the Markdown report. ## Changes - Change file delimiters from ``` to >>>>>>>/<<<<<<< to avoid Markdown conflicts - Add tier hydration before strategize phase in plan_executor.py - Increase max_tokens to 16384 in llm_actors.py for longer outputs - Increase context_max_tokens_hot from 16000 to 32000 in settings.py - Fix get_hot_view → get_hot_fragments in strategy_actor.py and plan_executor.py - Add opencode to skip directories in context_tier_hydrator.py - Change sandbox output location to plan-output/ directory in plan.py - Add get_context_summary stub method to acms_service.py ## Testing Run architecture review action and verify the output report is complete with all sections. Reviewed-on: #10938
216 lines
6.2 KiB
Python
216 lines
6.2 KiB
Python
"""Robot Framework helper for apply pipeline smoke tests.
|
|
|
|
Provides a CLI-style interface for Robot to invoke validation-gated
|
|
apply operations. Exit code 0 = success, 1 = failure.
|
|
|
|
Usage:
|
|
python robot/helper_apply_pipeline.py apply-passes
|
|
python robot/helper_apply_pipeline.py apply-blocked
|
|
python robot/helper_apply_pipeline.py already-applied
|
|
python robot/helper_apply_pipeline.py empty-changeset
|
|
python robot/helper_apply_pipeline.py model-checks
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
from unittest.mock import MagicMock
|
|
|
|
# Ensure the src directory is on the import path.
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
from cleveragents.application.services.plan_apply_service import ( # noqa: E402
|
|
ApplyOutcome,
|
|
ApplyResult,
|
|
PlanApplyService,
|
|
)
|
|
from cleveragents.domain.models.core.change import ( # noqa: E402
|
|
ChangeEntry,
|
|
ChangeOperation,
|
|
SpecChangeSet,
|
|
)
|
|
from cleveragents.domain.models.core.plan import ( # noqa: E402
|
|
PlanPhase,
|
|
PlanTimestamps,
|
|
ProcessingState,
|
|
)
|
|
|
|
_PLAN_ID = "01PLANTEST000000000000001"
|
|
|
|
|
|
def _make_plan(
|
|
*,
|
|
phase: PlanPhase = PlanPhase.EXECUTE,
|
|
state: ProcessingState = ProcessingState.COMPLETE,
|
|
changeset_id: str | None = "CS001",
|
|
validation_summary: dict[str, Any] | None = None,
|
|
is_terminal: bool = False,
|
|
) -> MagicMock:
|
|
plan = MagicMock()
|
|
plan.identity.plan_id = _PLAN_ID
|
|
plan.phase = phase
|
|
plan.processing_state = state
|
|
plan.changeset_id = changeset_id
|
|
plan.validation_summary = validation_summary
|
|
plan.is_terminal = is_terminal
|
|
plan.error_details = None
|
|
plan.timestamps = PlanTimestamps()
|
|
return plan
|
|
|
|
|
|
def _make_changeset(n: int = 1) -> SpecChangeSet:
|
|
cs = SpecChangeSet(plan_id=_PLAN_ID)
|
|
for i in range(n):
|
|
cs.add_change(
|
|
ChangeEntry(
|
|
plan_id=_PLAN_ID,
|
|
resource_id="RES001",
|
|
tool_name="builtin/test-tool",
|
|
operation=ChangeOperation.MODIFY,
|
|
path=f"src/file_{i}.py",
|
|
before_hash=f"b{i}",
|
|
after_hash=f"a{i}",
|
|
)
|
|
)
|
|
return cs
|
|
|
|
|
|
def _make_service(
|
|
plan: MagicMock, changeset: SpecChangeSet | None = None
|
|
) -> PlanApplyService:
|
|
lifecycle = MagicMock()
|
|
lifecycle.get_plan.return_value = plan
|
|
lifecycle.complete_apply.return_value = plan
|
|
lifecycle.constrain_apply.return_value = plan
|
|
lifecycle.commit_plan = MagicMock()
|
|
store = MagicMock()
|
|
store.get.return_value = changeset
|
|
return PlanApplyService(lifecycle_service=lifecycle, changeset_store=store)
|
|
|
|
|
|
def _cmd_apply_passes() -> int:
|
|
"""Apply with all validations passing."""
|
|
cs = _make_changeset(3)
|
|
plan = _make_plan(
|
|
changeset_id=cs.changeset_id,
|
|
validation_summary={
|
|
"total": 2,
|
|
"required_passed": 2,
|
|
"required_failed": 0,
|
|
},
|
|
)
|
|
svc = _make_service(plan, cs)
|
|
result = svc.apply_with_validation_gate(_PLAN_ID)
|
|
assert result.outcome == ApplyOutcome.APPLIED, f"Got {result.outcome}"
|
|
assert result.files_changed == 3
|
|
assert "applied successfully" in result.message
|
|
print("apply-passes-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_apply_blocked() -> int:
|
|
"""Apply blocked by validation failure."""
|
|
cs = _make_changeset(2)
|
|
plan = _make_plan(
|
|
changeset_id=cs.changeset_id,
|
|
validation_summary={
|
|
"total": 3,
|
|
"required_passed": 1,
|
|
"required_failed": 2,
|
|
},
|
|
)
|
|
svc = _make_service(plan, cs)
|
|
result = svc.apply_with_validation_gate(_PLAN_ID)
|
|
assert result.outcome == ApplyOutcome.CONSTRAINED, f"Got {result.outcome}"
|
|
assert result.validations_failed == 2
|
|
assert "Apply refused" in result.message
|
|
print("apply-blocked-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_already_applied() -> int:
|
|
"""Re-apply on already applied plan."""
|
|
cs = _make_changeset(1)
|
|
plan = _make_plan(
|
|
phase=PlanPhase.APPLY,
|
|
state=ProcessingState.APPLIED,
|
|
is_terminal=True,
|
|
)
|
|
svc = _make_service(plan, cs)
|
|
result = svc.apply_with_validation_gate(_PLAN_ID)
|
|
assert result.outcome == ApplyOutcome.ALREADY_APPLIED, f"Got {result.outcome}"
|
|
assert "already been applied" in result.message
|
|
print("already-applied-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_empty_changeset() -> int:
|
|
"""Apply blocked on empty changeset."""
|
|
cs = _make_changeset(0)
|
|
plan = _make_plan(changeset_id=cs.changeset_id)
|
|
svc = _make_service(plan, cs)
|
|
result = svc.apply_with_validation_gate(_PLAN_ID)
|
|
assert result.outcome == ApplyOutcome.BLOCKED_EMPTY, f"Got {result.outcome}"
|
|
assert "empty ChangeSet" in result.message
|
|
print("empty-changeset-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_model_checks() -> int:
|
|
"""Verify ApplyOutcome and ApplyResult models."""
|
|
# Check all enum values exist
|
|
assert ApplyOutcome.APPLIED == "applied"
|
|
assert ApplyOutcome.CONSTRAINED == "constrained"
|
|
assert ApplyOutcome.ALREADY_APPLIED == "already_applied"
|
|
assert ApplyOutcome.BLOCKED_EMPTY == "blocked_empty"
|
|
|
|
# Check ApplyResult construction
|
|
result = ApplyResult(
|
|
outcome=ApplyOutcome.APPLIED,
|
|
plan_id="TEST",
|
|
message="ok",
|
|
files_changed=5,
|
|
validations_total=3,
|
|
validations_passed=3,
|
|
validations_failed=0,
|
|
)
|
|
assert result.outcome == ApplyOutcome.APPLIED
|
|
assert result.plan_id == "TEST"
|
|
assert result.files_changed == 5
|
|
|
|
print("model-checks-ok")
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
if len(sys.argv) < 2:
|
|
print(
|
|
"Usage: helper_apply_pipeline.py "
|
|
"<apply-passes|apply-blocked|already-applied|"
|
|
"empty-changeset|model-checks>"
|
|
)
|
|
return 1
|
|
|
|
cmd = sys.argv[1]
|
|
if cmd == "apply-passes":
|
|
return _cmd_apply_passes()
|
|
if cmd == "apply-blocked":
|
|
return _cmd_apply_blocked()
|
|
if cmd == "already-applied":
|
|
return _cmd_already_applied()
|
|
if cmd == "empty-changeset":
|
|
return _cmd_empty_changeset()
|
|
if cmd == "model-checks":
|
|
return _cmd_model_checks()
|
|
|
|
print(f"Unknown command: {cmd}")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|