Skip to content

feat(recipe): add progress reporting banners and progress file lifecycle#3487

Merged
rysweet merged 1 commit intomainfrom
fix/recipe-progress-reporting
Mar 24, 2026
Merged

feat(recipe): add progress reporting banners and progress file lifecycle#3487
rysweet merged 1 commit intomainfrom
fix/recipe-progress-reporting

Conversation

@rysweet
Copy link
Owner

@rysweet rysweet commented Mar 24, 2026

Summary

  • Emit [recipe-runner] Preparing recipe '<name>'... and [recipe-runner] Launching recipe '<name>' (pid N)... banners to stderr so parent sessions can observe subprocess activity
  • Add _cleanup_progress_file() to remove progress files on recipe completion (best-effort, catches OSError)
  • Update existing progress file test to capture writes before cleanup removes the file

Redo of closed PR #3473.

Files changed (commit-only)

File Change
src/amplihack/recipes/rust_runner.py Preparing/Launching banners, _cleanup_progress_file(), cleanup in finally block
tests/recipes/test_rust_runner.py New - 12 tests: banners (3), progress file lifecycle (6), get_recipe_progress integration (3)
tests/recipes/test_rust_runner_execution.py Updated test_progress_mode_writes_progress_file to intercept writes before cleanup

No changes to models.py, parser.py, pyproject.toml, uv.lock, or any YAML recipe files.

What already existed (no changes needed)

  • _write_progress_file() and _stream_process_output_with_progress() in rust_runner_execution.py
  • get_recipe_progress() in dev_intent_router.py

Test evidence

tests/recipes/test_rust_runner.py ............                           [ 34%]
tests/recipes/test_rust_runner_execution.py .......................      [100%]
============================== 35 passed in 0.14s ==============================

All pre-commit hooks pass (ruff, pyright, ruff-format, secrets detection, print statement check).

Test plan

  • uv run python -m pytest tests/recipes/test_rust_runner.py -x -q -- 12 pass
  • uv run python -m pytest tests/recipes/test_rust_runner_execution.py -x -q -- 23 pass
  • Pre-commit hooks green
  • git diff-tree --name-only -r HEAD shows only 3 files
  • CI green
  • qa-team tests
  • quality-audit 3 cycles

🤖 Generated with Claude Code

Emit [recipe-runner] banners to stderr so parent sessions can observe
subprocess activity. Add progress file cleanup on completion, and tests
for banners, progress file creation/cleanup, and get_recipe_progress().

Changes:
- rust_runner.py: Preparing/Launching banners, _cleanup_progress_file()
- tests/recipes/test_rust_runner.py: new tests (banners, progress files,
  get_recipe_progress integration)
- tests/recipes/test_rust_runner_execution.py: updated progress file test
  to capture writes before cleanup removes the file

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Repo Guardian - Passed

All changed files are durable project artifacts — no ephemeral content detected.

File Type Assessment
src/amplihack/recipes/rust_runner.py Source code ✅ Core module — durable
tests/recipes/test_rust_runner.py Test file ✅ New test suite — durable
tests/recipes/test_rust_runner_execution.py Test file ✅ Updated tests — durable

No action required.

Generated by Repo Guardian for issue #3487 ·

@rysweet
Copy link
Owner Author

rysweet commented Mar 24, 2026

PR #3487 Merge Validation Report

1. Scope Check: PASS

Exactly 3 files changed (verified via git diff origin/main...origin/fix/recipe-progress-reporting --name-only):

  • src/amplihack/recipes/rust_runner.py (+21 lines)
  • tests/recipes/test_rust_runner.py (+337 lines, new file)
  • tests/recipes/test_rust_runner_execution.py (+31/-10 lines)

No changes to models.py, parser.py, pyproject.toml, or uv.lock. Confirmed clean.

2. QA-Team Outside-In Tests: PASS

Wrote and executed 2 gadugi YAML scenarios with a Python test harness (test_recipe_progress_reporting.py, 8 tests):

Scenario 1 — Progress banners to stderr (recipe-progress-banner-stderr.yaml):

  • [recipe-runner] Preparing recipe '<name>'... emitted to stderr
  • [recipe-runner] Launching recipe '<name>' (pid <pid>)... emitted to stderr
  • Preparing appears before Launching (ordering verified)
  • Banners go to stderr, NOT stdout (verified explicitly)

Scenario 2 — Progress file cleanup (recipe-progress-file-cleanup.yaml):

  • _write_progress_file creates valid JSON in tempdir
  • _cleanup_progress_file removes the file (no orphans)
  • Cleanup is no-op when file already absent (no exception)
  • Cleanup runs on success (finally block)
  • Cleanup runs on failure (finally block)
tests/gadugi/test_recipe_progress_reporting.py ........    [8 passed in 0.10s]

3. Quality Audit — 3 Cycles: PASS

Cycle 1 (SEEK/VALIDATE):

  • All 35 PR tests pass (test_rust_runner.py 12 + test_rust_runner_execution.py 23)
  • Ruff lint: All checks passed
  • except OSError: pass in _cleanup_progress_file is acceptable — best-effort cleanup in a finally block, not business logic error swallowing
  • Minor DRY concern: name sanitization logic duplicated between _cleanup_progress_file and _progress_file_path, but acceptable to avoid cross-module coupling for a simple cleanup function

Cycle 2 (SEEK/VALIDATE — edge cases & security):

  • Path traversal: re.sub(r"[^a-zA-Z0-9_]", "_", stem)[:64] sanitization prevents all injection
  • Empty names, null bytes, long names: all handled safely
  • No security issues found

Cycle 3 (SEEK/VALIDATE — integration):

  • All recipe tests pass (35/35)
  • Pre-existing failure in test_default_workflow_step19d_step21.py is unrelated (tests recipe YAML not touched by this PR)
  • No regressions in any PR-related tests
  • No FIX needed in any cycle

4. CI Status: PASS (with documented pre-existing exception)

Check Status
Validate Code PASS
GitGuardian Security Checks PASS
Root Directory Hygiene Checks PASS
Check Version Bump PASS
Check skill/agent drift PASS
Bot Detection PASS (SKIPPED — not a bot)
Dependabot Auto-Merge PASS
Repo Guardian PASS
Claude Code Plugin Test PASS
Invisible Character Scan SKIPPED
Atlas PR Impact Check FAIL (pre-existing)

Atlas failure explanation: The ast-lsp-bindings layer is stale because rust_runner.py was modified. However, the atlas was already stale on main after PR #3465 (fix(recipes): report workflow step progress) was merged without an atlas rebuild. This is NOT caused by this PR's changes — it's a pre-existing staleness condition. The atlas check would fail on any PR touching rust_runner.py until the atlas is rebuilt on main.

5. Verdict

READY TO MERGE

All merge criteria satisfied:

  • Scope: exactly 3 files, no unwanted changes
  • QA outside-in: 8 gadugi scenario tests pass
  • Quality audit: 3 cycles, 0 issues requiring fix
  • CI: all checks green except pre-existing Atlas staleness
  • Test evidence: 35 PR tests + 8 gadugi tests = 43 total, all passing

@github-actions
Copy link
Contributor

PR Triage Report

Risk: Low | Priority: Medium

Assessment

  • Type: Feature — progress reporting enhancement for recipe runner
  • Scope: 3 files — rust_runner.py (banners + cleanup), new test_rust_runner.py (12 tests), updated test_rust_runner_execution.py
  • CI Status: Passing — Validate Code ✅, GitGuardian ✅ (Atlas PR Impact Check failure is non-blocking/expected)
  • Test Coverage: 35 tests pass (12 new + 23 existing)

Findings

Recommendation

Ready for review and merge. Low risk, well-tested, clear scope. Unblocks parent session observability.

Generated by PR Triage Agent ·

@rysweet rysweet merged commit acbd410 into main Mar 24, 2026
24 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant