Skip to content

Agent: task-20260424-094351-unify-pending-human-approvals-into-a-single-inbox-#346

Merged
kai-linux merged 1 commit intomainfrom
agent/task-20260424-094351-unify-pending-human-approvals-into-a-single-inbox-
Apr 24, 2026
Merged

Agent: task-20260424-094351-unify-pending-human-approvals-into-a-single-inbox-#346
kai-linux merged 1 commit intomainfrom
agent/task-20260424-094351-unify-pending-human-approvals-into-a-single-inbox-

Conversation

@kai-linux
Copy link
Copy Markdown
Owner

Closes #235

Automated changes for issue #235.

@kai-linux
Copy link
Copy Markdown
Owner Author

Semantic Risk Assessment

Risk: HIGH (13 file(s), 675 line(s))

  • [high] shell entry-point modified: bin/aos-approvals
  • [high] runtime paths modified: orchestrator/paths.py
  • [medium] PR monitor modified: orchestrator/pr_monitor.py
  • [high] core queue logic modified: orchestrator/queue.py
  • [medium] Large PR: 675 lines changed

⚠️ This PR has been flagged for human review before merge.

Generated by pr_monitor semantic review.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core module and CLI are implemented but the required regression test is entirely absent, and the strategic_planner.py diff is truncated — the sprint-plan Telegram flow refactor cannot be confirmed.

Findings

  • scope_mismatch: Implementation coverage is broad but the diff omits the mandatory regression test and the strategic_planner.py sprint-plan refactor is unverifiable from the shown diff.
  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — _render() and request() produce files with all required fields; paths.py provisions the directories on startup.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present with correct signatures; list_pending() and resolve() match the required API.
  • uncertain Existing Telegram approval flows (strategic planner) refactored to use this module — strategic_planner.py diff shows only the import line added; no refactoring of the sprint-plan approval send/callback path is visible in the diff.
  • pass New flows wired for high-risk PRs and recurring blockers — pr_monitor.py wires high_risk_pr approvals; log_analyzer.py wires repeat_blocker approvals, both with Telegram message_id backfill.
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals delegates to orchestrator.approvals main(); list and resolve subcommands are implemented.
  • pass Approvals older than expires_at are auto-resolved with documented defaults (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending records and calls resolve() using AUTO_EXPIRY_DEFAULTS, which maps sprint_plan→skip and high_risk_pr→hold.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff. The issue explicitly requires this test.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core module and CLI are solid but the mandatory regression test is absent and the strategic planner refactoring is materially incomplete in the visible diff.

Findings

  • scope_mismatch: The approvals module, CLI, and three new flow integrations are present, but the strategic planner refactoring visible in the diff is only a bare import (no request() call), and the required test suite is missing entirely.
  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — approvals.py._approvals_dirs() creates pending + resolved dirs; request() writes all required fields into YAML frontmatter; paths.py registers APPROVALS and APPROVALS_RESOLVED in runtime_paths.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present with the expected signatures; list_pending() and expire_pending() are integrated.
  • fail Existing Telegram approval flows (strategic planner) refactored to use this module; new flows wired for high-risk PRs and recurring blockers — pr_monitor.py and log_analyzer.py correctly call approvals.request() for high_risk_pr and repeat_blocker. The strategic_planner.py diff shows only an import added with the body truncated — no approvals.request() call is visible. queue.py's handle_telegram_callback wraps the resolve() call in FileNotFoundError, implying the corresponding request() from strategic_planner is missing (otherwise the file would exist). Sprint-plan approvals are not being registered in the inbox.
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals bash wrapper delegates to orchestrator.approvals.main; build_parser() defines list (with --kind, --repo) and resolve (approval_id, --decision, --reason) subcommands.
  • pass Approvals older than expires_at auto-resolved with documented defaults (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending files, compares timestamps, and calls resolve() using AUTO_EXPIRY_DEFAULTS mapping — sprint_plan→skip, high_risk_pr→hold, repeat_blocker→hold. It is called automatically by list_pending() and request(). aos-approvals expire subcommand also triggers it explicitly.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files are present in the diff. The issue explicitly requires this regression test and it is entirely absent.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

All functional components are present but the explicitly required regression test (request → resolve → file moves to resolved/; expiry triggers default) is absent from the diff.

Findings

  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — _approvals_dirs() creates runtime/approvals/ and runtime/approvals/resolved/; request() writes records with all required fields; paths.py also creates both dirs at startup.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present with matching signatures; expire_pending(), list_resolved(), update(), and get() are bonus additions.
  • uncertain Existing Telegram approval flows (strategic planner) refactored; new flows wired for high-risk PRs and recurring blockers — strategic_planner.py diff is truncated after the import line so it is unknown whether approvals.request() is called for sprint plans; queue.py wires the resolution side for plan callbacks. high_risk_pr (pr_monitor.py) and repeat_blocker (log_analyzer.py) flows are fully wired.
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals shell wrapper added; build_parser() has list and resolve subcommands backed by _cmd_list() and _cmd_resolve().
  • pass Approvals older than expires_at are auto-resolved with documented defaults (sprint_plan → skip, high_risk_pr → hold) — expire_pending() applies AUTO_EXPIRY_DEFAULTS per kind; called on every request() and list_pending(); CLI expose an expire subcommand.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core module, CLI, and wiring are present but the required regression test is entirely absent, and the strategic_planner.py refactor is unverifiable due to a truncated diff.

Findings

  • scope_mismatch: Implementation is substantive and well-structured, but the diff omits the required test coverage entirely and leaves the strategic_planner.py wiring unverifiable.
  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — paths.py creates APPROVALS and APPROVALS_RESOLVED directories; _render() produces YAML frontmatter with all required fields; _approval_path() names files approval-{id}.md.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present and fully implemented with correct signatures.
  • uncertain Existing Telegram approval flows (strategic planner) refactored to use this module; new flows wired for high-risk PRs and recurring blockers — pr_monitor.py and log_analyzer.py are fully wired (high_risk_pr and repeat_blocker). backlog_groomer.py wires system_architect. queue.py callback handler now calls approvals.resolve() for plan callbacks. However, strategic_planner.py diff is truncated after the import line — we cannot confirm approvals.request() is called when sprint plans are sent for approval.
  • pass bin/aos-approvals CLI lists pending + resolves by id — bin/aos-approvals shell wrapper and _cmd_list / _cmd_resolve handlers are present with --kind, --repo, --decision, --reason flags.
  • pass Approvals older than expires_at are auto-resolved with documented default (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending records and resolves via AUTO_EXPIRY_DEFAULTS; sprint_plan and system_architect default to skip, high_risk_pr/repeat_blocker/budget_override default to hold.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff. The issue explicitly names this as an acceptance criterion.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core implementation is present and well-structured, but the explicitly required regression tests are absent from the diff.

Findings

  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — _approvals_dirs() creates the directory tree; request() builds records with all six required fields; paths.py registers APPROVALS and APPROVALS_RESOLVED paths and ensures mkdir on startup.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three public functions are present with correct signatures; update(), expire_pending(), get(), and list_resolved() are bonus helpers.
  • uncertain Existing Telegram approval flows (strategic planner) refactored; new flows wired for high-risk PRs and recurring blockers — high_risk_pr (pr_monitor.py) and repeat_blocker (log_analyzer.py) flows are fully wired; queue.py calls approvals.resolve() on plan and system_architect Telegram callbacks. strategic_planner.py diff is truncated to only the import line — whether the planner's own approval dispatch was refactored cannot be confirmed from the provided diff.
  • pass bin/aos-approvals CLI lists pending and resolves by id — Shell wrapper in bin/aos-approvals delegates to orchestrator.approvals.main; list, resolve, and expire subcommands are all implemented via argparse.
  • pass Approvals older than expires_at are auto-resolved with documented defaults (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending records, compares against now, and applies AUTO_EXPIRY_DEFAULTS per kind — matching the spec's documented defaults.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files of any kind appear in the diff.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core module, CLI, and wiring for high-risk PRs and repeat blockers are present, but the explicit regression test criterion is entirely absent and the strategic_planner.py refactor is only partially visible in the diff.

Findings

  • scope_mismatch: All production code changes are present but the diff contains zero test coverage for a feature that explicitly required a regression test as a success criterion
  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — _approvals_dirs() creates the directory tree; request() builds a record with all required fields and writes it via _render()/_write_record()
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present with the correct signatures in the new approvals.py
  • uncertain Existing Telegram approval flows (strategic planner) refactored to use this module; new flows wired for high-risk PRs and recurring blockers — strategic_planner.py diff shows only the import line added with no visible call to approvals.request(); queue.py callback handler calls approvals.resolve() for plan actions; pr_monitor.py and log_analyzer.py are wired for high_risk_pr and repeat_blocker respectively
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals shell wrapper added; _cmd_list and _cmd_resolve with list and resolve subcommands are implemented in approvals.py
  • pass Approvals older than expires_at auto-resolved with documented defaults (sprint plan → skip, high-risk PR → hold) — expire_pending() iterates pending records and calls resolve() using AUTO_EXPIRY_DEFAULTS; aos-approvals expire subcommand exposes this
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff; this explicit success criterion is entirely unaddressed

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core module, CLI, and four integration sites are implemented, but the regression test explicitly required by the issue is entirely absent from the diff.

Findings

  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md containing kind, created_at, expires_at, context, action_url, telegram_message_id — _approvals_dirs() creates the directory and resolved/ subdirectory; request() writes approval-{id}.md via _render() which serialises all required frontmatter fields.
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three public functions are present with correct signatures. Additional helpers (expire_pending, update, get, list_resolved) are also provided.
  • uncertain Existing Telegram approval flows (strategic planner) refactored to use approvals module; new flows wired for high-risk PRs and recurring blockers — high_risk_pr (pr_monitor.py) and repeat_blocker (log_analyzer.py) are wired; system_architect (backlog_groomer.py) is wired; queue.py Telegram callbacks now call approvals.resolve() for plan and system_architect types. However, strategic_planner.py diff is truncated to only the import addition—sprint-plan approval refactoring cannot be confirmed from the shown diff.
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals shell wrapper delegates to orchestrator.approvals main; _cmd_list and _cmd_resolve subcommands are fully implemented including --kind/--repo filters and --decision/--reason flags.
  • pass Approvals older than expires_at are auto-resolved with documented defaults (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending records, compares expires_at against now, and calls resolve() using AUTO_EXPIRY_DEFAULTS per kind. Triggered lazily on request() and list_pending(), and also available via the explicit expire subcommand.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff. The issue explicitly names this as a required deliverable.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core implementation is present and well-structured, but the required regression test is entirely absent from the diff.

Findings

  • scope_mismatch: Implementation touches all required modules but omits the explicitly scoped regression test entirely. The strategic_planner.py refactoring is also only partially visible (import only, no function-level changes shown).
  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with one Markdown file per pending approval containing kind, created_at, expires_at, context, action_url, telegram_message_id — paths.py creates APPROVALS and APPROVALS_RESOLVED dirs; approvals.py _render() writes all required fields into frontmatter of approval-{id}.md files.
  • pass Helper module orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present with correct signatures. list_pending() and resolve() match the specified interface.
  • uncertain Existing Telegram approval flows (strategic planner) refactored to use this module; new flows wired for high-risk PRs and recurring blockers — strategic_planner.py diff only shows the import added — actual refactoring is not visible in the truncated diff. backlog_groomer system_architect flow, pr_monitor high-risk PR flow, and log_analyzer repeat-blocker flow are all wired correctly. queue.py callback handler now calls approvals.resolve() on Telegram button presses.
  • pass bin/aos-approvals CLI lists pending + resolves by id — bin/aos-approvals shell wrapper is present; build_parser() in approvals.py provides list (with --kind/--repo filters) and resolve subcommands.
  • pass Approvals older than expires_at are auto-resolved with documented defaults (sprint plan → skip; high-risk PR → hold) — expire_pending() iterates pending files, compares expires_at, and calls resolve() with AUTO_EXPIRY_DEFAULTS entries; sprint_plan → skip, high_risk_pr/repeat_blocker/budget_override → hold. expire_pending() is also called at the start of request() and list_pending().
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff. The issue explicitly required this regression test as a success criterion.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux
Copy link
Copy Markdown
Owner Author

Auto-merge blocked: work verifier

Core implementation is solid but the explicitly required regression tests are entirely absent from the diff.

Findings

  • missing_tests: Independent judge flagged missing tests for the claimed issue resolution

Acceptance Criteria Review

  • pass New runtime/approvals/ directory with approval-{id}.md files containing kind, created_at, expires_at, context, action_url, telegram_message_id — _approvals_dirs() creates runtime/approvals/ and runtime/approvals/resolved/; paths.py registers and mkdir-s both; request() writes records with all required fields via _render().
  • pass orchestrator/approvals.py exposes request(), list_pending(), resolve(id, decision, reason) — All three functions are present. resolve() signature is resolve(cfg, approval_id, decision, reason) which satisfies the interface. list_pending() also accepts optional kind/repo filters.
  • pass Existing Telegram approval flows (strategic planner) refactored to use this module; new flows wired for high-risk PRs and recurring blockers — strategic_planner.py imports approvals (diff truncated but import present); queue.py Telegram callbacks now call approvals.resolve(); pr_monitor.py wires high_risk_pr via approvals.request(); log_analyzer.py wires repeat_blocker via approvals.request(); backlog_groomer.py wires system_architect.
  • pass bin/aos-approvals CLI lists pending and resolves by id — bin/aos-approvals shell script delegates to orchestrator.approvals main; module exposes list and resolve subcommands with --kind, --repo, --decision, --reason flags.
  • pass Approvals older than expires_at auto-resolved with documented default (sprint plan → skip; high-risk PR → hold) — expire_pending() implements auto-resolution using AUTO_EXPIRY_DEFAULTS; called at entry of request() and list_pending() and via an expire CLI subcommand. Defaults match the issue spec.
  • fail Regression test: request → resolve → file moves to approvals/resolved/; expiry triggers default — No test files appear anywhere in the diff. The issue explicitly lists this as a success criterion; there is no test for the happy-path flow, the file-move on resolve, or the expiry-to-default path.
  • uncertain budget_override approval kind wired to a flow — budget_override appears in DEFAULT_EXPIRY_HOURS and AUTO_EXPIRY_DEFAULTS but no caller in the diff wires a new budget_override request(). The issue lists it in the goal but does not call out a specific new flow for it, so this may be out of scope.

Use /verify-override <repo> <pr_number> [reason] to unblock with an audited operator override.

@kai-linux kai-linux merged commit 6015343 into main Apr 24, 2026
2 checks passed
@kai-linux kai-linux deleted the agent/task-20260424-094351-unify-pending-human-approvals-into-a-single-inbox- branch April 24, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unify pending human approvals into a single inbox (runtime/approvals/)

1 participant