Skip to content

fix(periodic-report): bind approved delivery to Goal Channel Bot - #3755

Merged
huangruiteng merged 4 commits into
mainfrom
codex/periodic-report-goal-channel-identity
Aug 30, 2026
Merged

fix(periodic-report): bind approved delivery to Goal Channel Bot#3755
huangruiteng merged 4 commits into
mainfrom
codex/periodic-report-goal-channel-identity

Conversation

@huangruiteng

Copy link
Copy Markdown
Owner

Summary

  • create one blocked provider-delivery successor before the periodic-report approval gate, bind the gate to that exact Todo, and persist the frozen generation bundle for execution
  • add periodic-report deliver-goal-channel, which resolves destination and sender only from the enabled Goal Channel project_bot binding
  • require two ordered announcements (hosted report, then Lark document), send them as two independently idempotent messages, and verify distinct message ids, exact cards, chat ids, and native sender App ids
  • reject chat/profile/App/sender overrides and fail closed on local-user, default-Bot, missing membership, identity drift, or partial readback

Root cause

The governed consumer stopped at an approval Todo. Approval had no linked executable successor, so quota could legitimately return a quiet terminal or monitor state after the user approved the frozen payload. Separately, the Lark adapter treated message existence plus profile re-authentication as delivery proof; it did not prove that the message was in the Goal Channel or that the provider-native sender App matched the bound Bot.

Product and architecture judgment

This fixes the reusable capability boundary rather than special-casing one Goal. The periodic-report capability owns the frozen generation and approval-to-successor lifecycle; the bundled Lark extension owns provider identity, transport, and native readback. Destination and sender authority remain local-private Goal Channel configuration, not request fields. The two-message requirement is now typed execution input rather than Todo prose.

The main risk is external delivery and identity correctness. The command therefore previews without effects and executes only after extension activation, live Bot/chat/membership preflight, then exact readback for both messages. No user OAuth fallback, environment-default Bot, or caller-selected chat is permitted.

Future-facing pass: the change reuses the existing Goal Channel binding/target/transport helpers and the existing periodic-report sink adapter. No broader provider framework was added; further abstraction would be speculative until another provider needs the same native-sender proof contract.

Validation

  • focused periodic-report lifecycle/delivery suite: 58 passed
  • expanded periodic-report/capability suite: 777 passed, 4 skipped
  • TypeScript control-plane suite: 288 passed
  • periodic-report adapter smoke: passed
  • Ruff check and format check on changed Python: passed
  • Python compile and git diff --check: passed
  • loopx canary premerge --from-git-diff: passed, 17/17 selected checks, no holds
  • public/private boundary scan: clean across all 17 changed files

npm run typecheck:control-plane could not run because tsc is not installed in this checkout (sh: tsc: command not found). The TypeScript runtime test suite passed.

An earlier broad run without LOOPX_PYTHON selected macOS Python 3.9 in subprocess CLI tests; rerunning with the repository-supported Python 3.13 produced the 777-pass result above.

Boundaries and merge decision

  • no credentials, Bot profiles, chat ids, project report links, private Goal state, generated reports, or local absolute paths are committed
  • no production send is performed by tests or canaries
  • owner explicitly authorized self-merge after validation

Merge decision: self-merge after required GitHub checks pass. The external resend remains separately fail-closed until the exact Goal-bound Bot credential exists locally.

Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
@huangruiteng

Copy link
Copy Markdown
Owner Author

Findings

No blocking findings remain on the current head (4f336db4c).

Open questions / assumptions

  • Execution intentionally fails closed unless the Goal Channel has a complete local-private project_bot binding and the bound Lark CLI profile authenticates as the exact configured Bot App.
  • The command requires two distinct provider readbacks: hosted report first, Lark document second. A profile-auth check alone is deliberately insufficient.

Product / architecture judgment

The problem was not merely a bad sender option: approval produced no executable delivery successor, while provider routing was still caller-controlled. This PR fixes both owning boundaries. The capability consumer persists the frozen generation bundle and creates a blocked typed successor before the gate; approval resumes only that successor. The Lark extension then owns sender and destination resolution from the Goal Channel binding, forbids caller overrides, and verifies native App sender plus exact chat on readback.

This solves the operator-visible failure mode without placing Lark policy in generic quota code. The bounded companion refactor on the final commit isolates request normalization, Bot transport effects, and CLI routing, reducing cognitive complexity and keeping the next provider change localized. A broader generic delivery framework was considered unnecessary for this single shipped path.

Main residual risk is runtime configuration drift, which is fail-closed: no matching Bot profile means no send, and no environment-default or user-auth fallback is permitted.

Validation

  • Focused periodic-report suite: 58 passed.
  • Refactor-focused suite: 75 passed.
  • Expanded local suite: 777 passed, 4 skipped.
  • TypeScript control-plane suite: 288 passed.
  • Periodic-report smoke passed.
  • Ruff check/format, Python compile, and git diff --check passed.
  • Public/private boundary scan passed.
  • loopx canary premerge --from-git-diff: 17/17 passed, no holds.
  • GitHub required checks: 8 successful, 3 skipped, 0 failing or pending, including Linux pytest, Windows PowerShell, DCO, dependency review, builds, and both Sonar surfaces.
  • npm run typecheck:control-plane was unavailable locally because tsc was not installed; the GitHub TypeScript Effect qualification and kernel type-check steps passed.

Merge decision

Self-merge approved under explicit owner authorization. The change is single-purpose, public-safe, covered across capability lifecycle and provider boundaries, and performs no external report delivery during validation.

@huangruiteng
huangruiteng merged commit 331f529 into main Aug 30, 2026
11 checks passed
@huangruiteng
huangruiteng deleted the codex/periodic-report-goal-channel-identity branch August 30, 2026 11:18
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.

1 participant