Compare commits

...

19 Commits

Author SHA1 Message Date
hamza.khyari db1d9fbd56 fix(test): address CoreRasurae review findings for M4 E2E
CI / build (pull_request) Successful in 26s
CI / helm (pull_request) Successful in 31s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m43s
CI / typecheck (pull_request) Successful in 3m57s
CI / security (pull_request) Successful in 4m9s
CI / unit_tests (pull_request) Successful in 9m4s
CI / docker (pull_request) Successful in 1m33s
CI / coverage (pull_request) Successful in 12m44s
CI / e2e_tests (pull_request) Successful in 19m51s
CI / integration_tests (pull_request) Successful in 24m27s
CI / status-check (pull_request) Successful in 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 54m56s
H-1: Wait Until Plan Terminal now Fails on timeout (not WARN).
H-2: Added post-rollback state verification (asserts not
     errored/cancelled before lifecycle-apply).
M-2: Correction assertions tightened to mode-specific keywords
     only (revert/supersed for revert, append for append).
M-4: Added non-empty output assertion on execute phase.
L-1: Added non-empty output assertion on rollback.
L-2: Documented JSON ordering assumption for post-revert
     decision selection.

M-1 (merge LLM-dependent) and M-3 (subplan status tracking)
are valid but require infrastructure not yet available.
M-5 (GEMINI in PR description) is a docs fix, not code.

ISSUES CLOSED: #744
2026-04-02 11:30:14 +00:00
hamza.khyari 3a05d5132f fix(test): use tdd_issue tags per CONTRIBUTING.md convention
CI / lint (pull_request) Successful in 19s
CI / typecheck (pull_request) Successful in 50s
CI / helm (pull_request) Successful in 21s
CI / build (pull_request) Successful in 25s
CI / quality (pull_request) Successful in 3m40s
CI / security (pull_request) Successful in 4m12s
CI / unit_tests (pull_request) Successful in 9m7s
CI / docker (pull_request) Successful in 1m32s
CI / e2e_tests (pull_request) Successful in 21m7s
CI / benchmark-regression (pull_request) Waiting to run
CI / benchmark-publish (pull_request) Waiting to run
CI / integration_tests (pull_request) Successful in 24m22s
CI / coverage (pull_request) Successful in 12m29s
CI / status-check (pull_request) Successful in 1s
tdd_expected_fail requires tdd_issue + tdd_issue_<N>, not
tdd_bug + tdd_bug_<N>.

ISSUES CLOSED: #744
2026-04-02 09:24:16 +00:00
hamza.khyari 2f7795a435 fix(test): address follow-up review findings for M4 E2E
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 19s
CI / build (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 1m2s
CI / security (pull_request) Successful in 4m8s
CI / unit_tests (pull_request) Successful in 6m8s
CI / docker (pull_request) Successful in 1m23s
CI / coverage (pull_request) Successful in 9m21s
CI / e2e_tests (pull_request) Failing after 18m8s
CI / integration_tests (pull_request) Successful in 21m19s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-regression (pull_request) Successful in 54m57s
Major-1: Subplan/merge assertions now parse JSON structure:
  subplan checked via decision type field and non-empty children
  array (not generic keyword matching). Merge checked via merge
  decision type or merge in chosen text.

Major-2: Append correction now re-fetches tree after revert and
  selects the last (most recent, non-superseded) decision ID
  instead of using stale pre-revert decision list.

Minor-3: Added Fail If Command Failed keyword that truncates
  stdout/stderr to 500 chars in failure messages. All CLI steps
  now use this keyword instead of inline Fail with raw output.

Minor-4: Added timeout=60s on_timeout=kill to all git subprocess
  calls (add, commit, rev-parse).

ISSUES CLOSED: #744
2026-04-02 00:29:02 +00:00
hamza.khyari 461c11d29a fix(test): update M4 E2E tags from tdd_bug to tdd_issue per listener convention
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 39s
CI / quality (pull_request) Successful in 3m45s
CI / typecheck (pull_request) Successful in 3m58s
CI / security (pull_request) Successful in 4m8s
CI / unit_tests (pull_request) Successful in 9m7s
CI / docker (pull_request) Successful in 1m46s
CI / e2e_tests (pull_request) Failing after 12m56s
CI / coverage (pull_request) Successful in 9m17s
CI / integration_tests (pull_request) Successful in 21m52s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-regression (pull_request) Has been cancelled
The tdd_expected_fail_listener requires tdd_issue + tdd_issue_<N>,
not tdd_bug + tdd_bug_<N>.  The tag naming convention was updated
in the listener.

ISSUES CLOSED: #744
2026-04-01 23:50:06 +00:00
hamza.khyari 1848a9763f fix(test): tag M4 E2E as tdd_expected_fail pending bug #1253
CI / build (pull_request) Successful in 16s
CI / helm (pull_request) Successful in 22s
CI / lint (pull_request) Successful in 3m18s
CI / quality (pull_request) Successful in 3m44s
CI / typecheck (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m6s
CI / unit_tests (pull_request) Successful in 8m54s
CI / docker (pull_request) Successful in 1m26s
CI / coverage (pull_request) Successful in 9m23s
CI / benchmark-publish (pull_request) Has been skipped
CI / e2e_tests (pull_request) Failing after 15m52s
CI / integration_tests (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
CheckpointManager is not wired into PlanExecutor — no checkpoints
are created during execution (see #1253 for root cause analysis).
The hard checkpoint assertion correctly fails. Tagged with
tdd_expected_fail so CI passes while the infrastructure bug is
tracked.

ISSUES CLOSED: #744
2026-04-01 23:32:53 +00:00
hamza.khyari ca494eacb9 revert: remove out-of-scope actor-selection changes from WF12/WF17/WF18
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 18s
CI / build (pull_request) Successful in 20s
CI / helm (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 34s
CI / security (pull_request) Successful in 1m0s
CI / typecheck (pull_request) Successful in 3m58s
CI / unit_tests (pull_request) Successful in 5m45s
CI / docker (pull_request) Successful in 1m34s
CI / coverage (pull_request) Successful in 12m29s
CI / e2e_tests (pull_request) Failing after 16m49s
CI / integration_tests (pull_request) Successful in 22m27s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-regression (pull_request) Has been cancelled
Per reviewer P2 feedback, these files are outside the scope of
ticket #744 (M4 acceptance). Reverted to master versions.
2026-04-01 22:55:46 +00:00
hamza.khyari 3e9e04c0bb fix(test): harden M4 E2E per reviewer P1 findings
P1-1: Subplan/merge checks now assert (not just log).
      Action YAML crafted to encourage decomposition.
      Asserts subplan/children indicators and merge/strategy
      keywords in decision tree.

P1-2: Correction steps now require rc=0 (Fail on non-zero).
      Assert correction-specific output keywords (revert,
      correction, decision, append).

P1-3: Checkpoint existence is now hard-asserted after execution.
      Rollback requires rc=0 (Fail on non-zero).
      No more conditional skip or WARN tolerance.

P1-4: Added Wait Until Plan Terminal keyword (polls every 10s
      for up to 3min). Final status asserts specifically
      'applied' — no longer accepts errored/cancelled/queued.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 3ccb07c347 fix(test): add missing agents init to M4 E2E suite
M4 was failing at the first CLI command (resource add) with
sqlite3.OperationalError because the database file did not exist.
All other passing E2E suites (WF12/WF17/WF18/M5/M6) call
'agents init --force --yes' before running CLI commands. M4 was
missing this step.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 1757e1b0d6 fix(test): surface exact failing command in M4 E2E
Switch major M4 CLI steps to expected_rc=None and explicit failure
messages with stdout/stderr so CI reports the exact failing command
instead of the generic Run CleverAgents Command assertion.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 4d68abd99a fix(test): prefer OpenAI first in failing E2E suites
Switch WF12, WF17, and WF18 actor selection to prefer OPENAI_API_KEY
when both OpenAI and Anthropic credentials are present. This avoids
Anthropic quota failures in CI environments where Anthropic keys exist
but lack credits.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 3748b0ff08 fix(test): address all review findings for M4 E2E test
- C-1: Merge conflict marker already resolved by rebase
- H-1: ULID regex now targets 'decision_id' JSON keys specifically
- H-2: Revert and append use different decisions when available
- H-3: Correction commands use expected_rc=None with WARN logging
- H-4: Dynamic actor selection (openai/gpt-4o-mini or anthropic/claude)
- H-5: Merge strategy indicators checked in decision tree
- M-3: Git operations checked for return codes
- M-4: --format plain added to correction and apply commands
- M-5: Plan diff asserts non-empty output
- M-6: Correction impact covered by non-empty + no-Traceback checks
- M-7: Processing state regex includes all valid Apply states
- L-1: Test timeout increased to 20 minutes
- L-2: Comment fixed to 'Plan lifecycle-apply'

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari a93b31f953 fix(test): remove tdd_expected_fail after blocking bugs closed
Bugs #822, #1023, #1024, #1025 are all closed. Remove
tdd_expected_fail tags and clean up TODO comments that referenced
them. Subplan assertion remains diagnostic (LLM-dependent).
Checkpoint rollback assertion kept conditional with regression
warning.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 2e2f09ca6e fix(test): add Skip If No LLM Keys guard and document deferred AC assertions
Address review findings from @brent.edwards:

P1-1: Add Skip If No LLM Keys as the first step so CI without API
keys gracefully skips instead of hard-failing.

P1-2/P1-3: Add TODO comments documenting that checkpoint and subplan
assertions should be hardened when tdd_expected_fail is removed after
infra bugs #1023/#1024/#1025 are fixed.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 171a1494e5 refactor(test): remove workarounds, use tdd_expected_fail for M4 E2E test
Strip runtime workarounds (init step, --plan flag, workspace name) that
masked infra bugs #1023/#1024/#1025.  The test now expresses intended
behavior without workarounds and relies on tdd_expected_fail to pass CI
while the infra bugs are open.

When #1023/#1024/#1025 are fixed, remove tdd_expected_fail and the test
passes on its own.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 7e3e676b32 fix(test): pass explicit workspace name to init to avoid Pydantic validation error
The E2E Suite Setup creates SUITE_HOME with dots in the basename
(e.g., E2E.M4_Acceptance). When init derives the project name from
the directory basename, the dot triggers a Pydantic validation error.
Pass an explicit name argument to avoid this.

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 81f4642229 fix(test): make M4 E2E test pass in isolated environments
- Add init step with --path ${SUITE_HOME} for DB creation (#1023)
- Pass --plan explicitly to plan correct for isolated env (#1025)
- Fix terminal state assertion: lifecycle-apply produces apply/queued not applied
- Tag test with tdd_bug_1023, tdd_bug_1024, tdd_bug_1025 for infra bug tracking

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 35c7bea4d9 fix(test): address round-2 review findings for M4 E2E test
- Remove redundant Library imports (String, Collections already in common_e2e.resource)
- Add missing INTERNAL error check on plan status JSON steps (8 and 15)
- Fix is_terminal assertion to verify value is true, not just key presence

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
hamza.khyari 4db4d78519 fix(test): address review findings for M4 E2E acceptance test
- Add checkpoint rollback testing via plan status JSON + plan rollback
- Add subplan verification via decision tree type inspection
- Add terminal state assertion after lifecycle-apply (is_terminal + processing_state)
- Add INTERNAL error checks on all CLI invocations (consistent with M2 pattern)
- Add Should Not Be Empty on strategize, execute, correction, and apply output
- Add --format plain for consistent output parsing
- Fix ULID regex to Crockford Base32 [0-9A-HJ-NP-Z]{26}
- Add CHANGELOG entry for #744
- Remove out-of-scope review_playbook.md change (resolved by rebase)

ISSUES CLOSED: #744
2026-04-01 22:55:46 +00:00
freemo 62c786cbed test(e2e): E2E acceptance criteria for M4 (v3.3.0) — corrections, subplans, and checkpoints
Implements end-to-end acceptance test exercising the complete M4 feature set:
subplan spawning, correction flows (revert/append modes), checkpoint creation,
decision tree inspection, and plan lifecycle with real LLM API keys.

ISSUES CLOSED: #744
2026-04-01 22:55:11 +00:00
2 changed files with 299 additions and 0 deletions
+4
View File
@@ -2,6 +2,10 @@
## Unreleased
- Added E2E acceptance test for M4 (v3.3.0): corrections, subplans,
and checkpoints. Robot Framework test suite `robot/e2e/m4_acceptance.robot`
tagged `E2E` exercises the complete M4 success criteria with real CLI
invocations and LLM API keys. (#744)
- Added a context-sensitive TUI help panel overlay toggled by `F1`, with
help content that varies for main-screen, slash-command, reference, and
shell prompt modes. Updated Behave and Robot coverage for help-panel
+295
View File
@@ -0,0 +1,295 @@
*** Settings ***
Documentation E2E acceptance test for M4 (v3.3.0): Corrections, Subplans, and Checkpoints.
...
... Exercises subplan spawning during plan execution, correction flows
... (revert and append modes), checkpoint creation and rollback through
... real CLI commands with real LLM API keys.
...
... Zero mocking — all CLI invocations use real providers.
Resource common_e2e.resource
Suite Setup E2E Suite Setup
Suite Teardown E2E Suite Teardown
*** Variables ***
${ACTION_NAME} local/m4-e2e-action
${RESOURCE_NAME} local/m4-e2e-repo
${PROJECT_NAME} local/m4-e2e-project
*** Test Cases ***
M4 Corrections Subplans And Checkpoints
[Documentation] End-to-end acceptance test for the M4 milestone.
...
... Tests subplan spawning, correction modes (revert/append),
... checkpoint creation, and rollback with real LLM API keys.
[Tags] E2E tdd_issue tdd_issue_1253 tdd_expected_fail
[Timeout] 20 minutes
# ---- Step 0: Skip gracefully if no LLM API keys are available ----
Skip If No LLM Keys
# ---- Step 0a: Initialise workspace (creates database) ----
${init}= Run CleverAgents Command init --force --yes
Should Be Equal As Integers ${init.rc} 0 msg=agents init failed
# ---- Step 0b: Select actor dynamically based on available API keys ----
${has_openai}= Evaluate bool(__import__('os').environ.get('OPENAI_API_KEY', ''))
IF ${has_openai}
${actor}= Set Variable openai/gpt-4o-mini
ELSE
${actor}= Set Variable anthropic/claude-sonnet-4-20250514
END
# ---- Step 1: Create temp git repo with sample project files ----
${repo_dir}= Create Temp Git Repo m4-acceptance-repo
Create Directory ${repo_dir}${/}src
Create File ${repo_dir}${/}src${/}main.py print("hello")\n
Create File ${repo_dir}${/}src${/}utils.py def helper(): return True\n
${git_add}= Run Process git add . cwd=${repo_dir} timeout=60s on_timeout=kill
Should Be Equal As Integers ${git_add.rc} 0 msg=git add failed
${git_commit}= Run Process git commit -m Add initial source files cwd=${repo_dir} timeout=60s on_timeout=kill
Should Be Equal As Integers ${git_commit.rc} 0 msg=git commit failed
${branch_result}= Run Process git rev-parse --abbrev-ref HEAD cwd=${repo_dir} timeout=60s on_timeout=kill
Should Be Equal As Integers ${branch_result.rc} 0 msg=git rev-parse failed
${branch}= Strip String ${branch_result.stdout}
# ---- Step 2: Register resource and project ----
${r_resource}= Run CleverAgents Command
... resource add git-checkout ${RESOURCE_NAME}
... --path ${repo_dir} --branch ${branch} --format plain
... expected_rc=None
Fail If Command Failed ${r_resource} resource add
${r_project}= Run CleverAgents Command
... project create ${PROJECT_NAME}
... --resource ${RESOURCE_NAME} --format plain
... expected_rc=None
Fail If Command Failed ${r_project} project create
Output Should Contain ${r_project} ${PROJECT_NAME}
# ---- Step 3: Create action that encourages decomposition ----
${action_yaml}= Catenate SEPARATOR=\n
... name: ${ACTION_NAME}
... description: |
... ${SPACE}${SPACE}Multi-phase project: Phase 1 - refactor main.py into modular classes.
... ${SPACE}${SPACE}Phase 2 - add comprehensive error handling to all modules.
... ${SPACE}${SPACE}Phase 3 - add unit tests for each module.
... ${SPACE}${SPACE}Each phase should be a separate subplan.
... definition_of_done: |
... ${SPACE}${SPACE}All three phases completed as separate subplans.
... ${SPACE}${SPACE}Each subplan produces file modifications.
... ${SPACE}${SPACE}Results merged using three-way merge strategy.
... strategy_actor: ${actor}
... execution_actor: ${actor}
${action_path}= Set Variable ${SUITE_HOME}${/}m4_action.yaml
Create File ${action_path} ${action_yaml}
${r_action}= Run CleverAgents Command
... action create --config ${action_path} --format plain
... expected_rc=None
Fail If Command Failed ${r_action} action create
# ---- Step 4: Plan use ----
${r_use}= Run CleverAgents Command
... plan use ${ACTION_NAME} ${PROJECT_NAME} --format plain
... expected_rc=None
Fail If Command Failed ${r_use} plan use
${plan_ids}= Get Regexp Matches ${r_use.stdout} [0-9A-HJ-NP-Z]{26}
Should Not Be Empty ${plan_ids} msg=Expected a ULID plan ID in plan use output
${plan_id}= Set Variable ${plan_ids}[0]
Log Plan ID: ${plan_id}
# ---- Step 5: Plan execute — strategize phase ----
${r_strat}= Run CleverAgents Command
... plan execute ${plan_id} --format plain
... timeout=180s expected_rc=None
Fail If Command Failed ${r_strat} plan execute (strategize)
# ---- Step 6: Inspect decision tree — assert subplans and merge ----
${r_tree}= Run CleverAgents Command
... plan tree ${plan_id} --format json
... timeout=60s expected_rc=None
Fail If Command Failed ${r_tree} plan tree
Log Decision tree: ${r_tree.stdout}
# Extract decision IDs from "decision_id" JSON keys
${decision_ids}= Get Regexp Matches ${r_tree.stdout}
... "decision_id"\\s*:\\s*"([0-9A-HJ-NP-Z]{26})" 1
${decision_count}= Get Length ${decision_ids}
Should Be True ${decision_count} >= 2
... msg=Expected at least 2 decisions in tree (root + child), found ${decision_count}
# Assert subplan decisions: look for decision type fields containing subplan
${subplan_type_matches}= Get Regexp Matches ${r_tree.stdout}
... "type"\\s*:\\s*"[^"]*subplan[^"]*"
${subplan_type_count}= Get Length ${subplan_type_matches}
# Also check for non-empty children arrays (structural proof of hierarchy)
${children_matches}= Get Regexp Matches ${r_tree.stdout}
... "children"\\s*:\\s*\\[\\s*\\{
${children_count}= Get Length ${children_matches}
${has_subplan_evidence}= Evaluate ${subplan_type_count} > 0 or ${children_count} > 0
Should Be True ${has_subplan_evidence}
... msg=No subplan evidence: need subplan decision type or non-empty children array (types=${subplan_type_count}, children=${children_count})
Log Subplan type decisions: ${subplan_type_count}, Non-empty children: ${children_count}
# Assert merge strategy: look for merge-specific JSON fields/values
${merge_type_matches}= Get Regexp Matches ${r_tree.stdout}
... "type"\\s*:\\s*"[^"]*merge[^"]*"
${merge_chosen_matches}= Get Regexp Matches ${r_tree.stdout}
... "chosen"\\s*:\\s*"[^"]*[Mm]erge[^"]*"
${merge_type_count}= Get Length ${merge_type_matches}
${merge_chosen_count}= Get Length ${merge_chosen_matches}
${has_merge_evidence}= Evaluate ${merge_type_count} > 0 or ${merge_chosen_count} > 0
Should Be True ${has_merge_evidence}
... msg=No merge evidence: need merge decision type or merge in chosen text (types=${merge_type_count}, chosen=${merge_chosen_count})
Log Merge type decisions: ${merge_type_count}, Merge in chosen: ${merge_chosen_count}
# ---- Step 7: Plan execute — execute phase ----
${r_exec}= Run CleverAgents Command
... plan execute ${plan_id} --format plain
... timeout=300s expected_rc=None
Fail If Command Failed ${r_exec} plan execute (execute)
Should Not Be Empty ${r_exec.stdout} msg=Execute phase produced no output
Log Execute output: ${r_exec.stdout}
# ---- Step 8: Assert checkpoint exists after execution ----
${r_status_json}= Run CleverAgents Command
... plan status ${plan_id} --format json
... timeout=60s expected_rc=None
Fail If Command Failed ${r_status_json} plan status (json)
Log Plan status JSON: ${r_status_json.stdout}
${checkpoint_matches}= Get Regexp Matches ${r_status_json.stdout}
... "last_checkpoint_id"\\s*:\\s*"([^"]+)" 1
${has_checkpoint}= Get Length ${checkpoint_matches}
Should Be True ${has_checkpoint} > 0
... msg=No checkpoint ID found — M4 AC requires checkpoint creation after execution (bug #1253)
# ---- Step 9: Exercise correction — revert mode ----
${decision_id_revert}= Set Variable ${decision_ids}[0]
${r_correct_revert}= Run CleverAgents Command
... plan correct ${decision_id_revert}
... --mode revert
... --guidance Improve implementation approach
... --yes --format plain
... timeout=180s expected_rc=None
Fail If Command Failed ${r_correct_revert} plan correct (revert)
# Assert correction-specific output
${revert_lower}= Evaluate ($r_correct_revert.stdout).lower()
${has_revert_kw}= Evaluate 'revert' in $revert_lower or 'supersed' in $revert_lower
Should Be True ${has_revert_kw}
... msg=Revert correction output should contain correction-specific keywords
# ---- Step 10: Re-fetch tree after revert, select active decision for append ----
${r_tree_post}= Run CleverAgents Command
... plan tree ${plan_id} --format json
... timeout=60s expected_rc=None
Fail If Command Failed ${r_tree_post} plan tree (post-revert)
Log Post-revert tree: ${r_tree_post.stdout}
# Extract active (non-superseded) decision IDs
${post_decision_ids}= Get Regexp Matches ${r_tree_post.stdout}
... "decision_id"\\s*:\\s*"([0-9A-HJ-NP-Z]{26})" 1
${post_count}= Get Length ${post_decision_ids}
Should Be True ${post_count} > 0
... msg=No decisions found in post-revert tree
# Use the last decision ID in JSON output order. In the current
# plan tree serialization, non-superseded decisions appear after
# superseded ones because revert appends new decisions at the end.
# If this assumption breaks, filter by "superseded": false instead.
${last_idx}= Evaluate len($post_decision_ids) - 1
${decision_id_append}= Set Variable ${post_decision_ids}[${last_idx}]
# Exercise append correction on the active decision
${r_correct_append}= Run CleverAgents Command
... plan correct ${decision_id_append}
... --mode append
... --guidance Add error handling to implementation
... --yes --format plain
... timeout=180s expected_rc=None
Fail If Command Failed ${r_correct_append} plan correct (append)
${append_lower}= Evaluate ($r_correct_append.stdout).lower()
${has_append_kw}= Evaluate 'append' in $append_lower
Should Be True ${has_append_kw}
... msg=Append correction output should contain correction-specific keywords
# ---- Step 11: Exercise checkpoint rollback ----
Exercise Checkpoint Rollback ${plan_id} ${checkpoint_matches}[0]
# ---- Step 11b: Verify plan state is compatible with lifecycle-apply after rollback ----
${r_post_rollback}= Run CleverAgents Command
... plan status ${plan_id} --format json
... timeout=60s expected_rc=None
Fail If Command Failed ${r_post_rollback} plan status (post-rollback)
Log Post-rollback status: ${r_post_rollback.stdout}
# Plan should not be in a terminal/errored state after rollback
Should Not Match Regexp ${r_post_rollback.stdout}
... "processing_state"\\s*:\\s*"(errored|cancelled)"
... msg=Plan is in errored/cancelled state after rollback — lifecycle-apply will fail
# ---- Step 12: Plan status — verify plan ID ----
${r_status}= Run CleverAgents Command
... plan status ${plan_id} --format plain
... timeout=60s expected_rc=None
Fail If Command Failed ${r_status} plan status (plain)
Output Should Contain ${r_status} ${plan_id}
# ---- Step 13: Plan diff ----
${r_diff}= Run CleverAgents Command
... plan diff ${plan_id} --format plain
... timeout=60s expected_rc=None
Fail If Command Failed ${r_diff} plan diff
Should Not Be Empty ${r_diff.stdout} msg=Plan diff produced no output
# ---- Step 14: Plan lifecycle-apply ----
${r_apply}= Run CleverAgents Command
... plan lifecycle-apply ${plan_id} --format plain
... timeout=120s expected_rc=None
Fail If Command Failed ${r_apply} plan lifecycle-apply
# ---- Step 15: Poll until terminal state and assert 'applied' ----
Wait Until Plan Terminal ${plan_id}
${r_final}= Run CleverAgents Command
... plan status ${plan_id} --format json
... timeout=60s expected_rc=None
Fail If Command Failed ${r_final} final plan status
Log Final plan status JSON: ${r_final.stdout}
Should Match Regexp ${r_final.stdout}
... "phase"\\s*:\\s*"apply"
... msg=Plan did not reach Apply phase after lifecycle-apply
Should Match Regexp ${r_final.stdout}
... "processing_state"\\s*:\\s*"applied"
... msg=Plan did not reach 'applied' terminal state — got a non-success state
*** Keywords ***
Fail If Command Failed
[Documentation] Fail with truncated diagnostic output if command returned non-zero rc.
... Keeps failure messages CI-safe by truncating stdout/stderr to 500 chars.
[Arguments] ${result} ${label}
Should Not Contain ${result.stdout}${result.stderr} Traceback
Should Not Contain ${result.stdout}${result.stderr} INTERNAL
IF ${result.rc} != 0
${out_trunc}= Evaluate ($result.stdout)[:500]
${err_trunc}= Evaluate ($result.stderr)[:500]
Fail ${label} failed (rc=${result.rc}) stdout=${out_trunc} stderr=${err_trunc}
END
Exercise Checkpoint Rollback
[Documentation] Rollback to a checkpoint and require success (rc=0).
[Arguments] ${plan_id} ${checkpoint_id}
Log Exercising rollback to checkpoint: ${checkpoint_id}
${r_rollback}= Run CleverAgents Command
... plan rollback ${plan_id} ${checkpoint_id}
... --yes --format plain
... timeout=120s expected_rc=None
Fail If Command Failed ${r_rollback} plan rollback
Should Not Be Empty ${r_rollback.stdout} msg=Rollback produced no output
Log Rollback output: ${r_rollback.stdout}
Wait Until Plan Terminal
[Documentation] Poll plan status until it reaches a terminal state.
... Polls every 10 seconds for up to 3 minutes.
[Arguments] ${plan_id}
FOR ${i} IN RANGE 18
${poll}= Run CleverAgents Command
... plan status ${plan_id} --format json
... timeout=30s expected_rc=None
${is_terminal}= Get Regexp Matches ${poll.stdout}
... "is_terminal"\\s*:\\s*true
${terminal_count}= Get Length ${is_terminal}
IF ${terminal_count} > 0 RETURN
Sleep 10s Waiting for plan to reach terminal state...
END
Fail Plan did not reach terminal state within 3 minutes (polled 18 times)