Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ea8ad9e
docs(channels): propose scheduled task delivery design
BenGuanRan Jul 18, 2026
3e72ea8
feat(channels): expose proactive delivery boundary
BenGuanRan Jul 18, 2026
15d3628
feat(daemon): define channel delivery IPC
BenGuanRan Jul 18, 2026
6877584
feat(daemon): route channel delivery to workers
BenGuanRan Jul 18, 2026
fc1e6f6
feat(channels): deliver daemon messages in worker
BenGuanRan Jul 18, 2026
990eda6
docs(channels): refine scheduled delivery rollout
BenGuanRan Jul 18, 2026
1a07bdc
feat(scheduler): persist admitted channel targets
BenGuanRan Jul 18, 2026
0f3a52f
feat(scheduler): queue completed channel deliveries
BenGuanRan Jul 18, 2026
2c75639
feat(daemon): dispatch scheduled channel deliveries
BenGuanRan Jul 18, 2026
996eed0
feat(channels): back daemon loops with durable tasks
BenGuanRan Jul 18, 2026
735bb7b
feat(webui): type scheduled channel delivery
BenGuanRan Jul 18, 2026
75bd058
docs(channels): align delivery draft with runtime
BenGuanRan Jul 18, 2026
f63f518
fix(scheduler): preserve delivery completion semantics
BenGuanRan Jul 18, 2026
fbc9424
feat(daemon): admit observed channel delivery targets
BenGuanRan Jul 18, 2026
bb0b830
fix(channels): harden scheduled delivery routing
BenGuanRan Jul 18, 2026
d963ba0
fix(channels): refresh proactive delivery credentials
BenGuanRan Jul 18, 2026
8e42d1a
docs(web-shell): define scheduled delivery target picker
BenGuanRan Jul 18, 2026
bad84dc
docs(web-shell): plan scheduled delivery picker
BenGuanRan Jul 18, 2026
ddf87ec
feat(webui): read observed channel delivery targets
BenGuanRan Jul 18, 2026
7d419b3
fix(webui): export observed channel contact types
BenGuanRan Jul 18, 2026
f9f8a71
feat(web-shell): map observed delivery destinations
BenGuanRan Jul 18, 2026
1e0a82f
feat(web-shell): select scheduled delivery destinations
BenGuanRan Jul 18, 2026
d358ab8
fix(channels): route scheduled direct messages by stable id
BenGuanRan Jul 18, 2026
47cb96d
fix(core): retain due one-shots across shared reloads
BenGuanRan Jul 18, 2026
0f97eaf
docs(channels): record scheduled delivery e2e
BenGuanRan Jul 18, 2026
fe48ff3
test(channels): retain direct delivery ids with chat labels
BenGuanRan Jul 18, 2026
2d299cb
docs(channels): narrow scheduled delivery design
BenGuanRan Jul 18, 2026
5a00255
docs(channels): plan typed scheduled delivery
BenGuanRan Jul 18, 2026
dc2d72f
refactor(scheduler): type channel delivery targets
BenGuanRan Jul 18, 2026
8376c64
refactor(daemon): accept explicit delivery targets
BenGuanRan Jul 18, 2026
db4ce6a
refactor(channels): type proactive delivery targets
BenGuanRan Jul 18, 2026
41d844f
feat(channels): map scheduled user and chat targets
BenGuanRan Jul 18, 2026
72ef37a
feat(daemon): dispatch scheduled channel results
BenGuanRan Jul 18, 2026
109f42a
refactor(daemon): keep scheduled delivery backend-only
BenGuanRan Jul 18, 2026
50bf7ea
fix(scheduler): harden workspace channel delivery
BenGuanRan Jul 18, 2026
998aa10
fix(scheduler): secure existing delivery outboxes
BenGuanRan Jul 18, 2026
d79eefd
docs(serve): document scheduled channel delivery capability
BenGuanRan Jul 18, 2026
4c9d8a0
fix(scheduler): reset delivered answer on retry
BenGuanRan Jul 19, 2026
106af09
docs(scheduler): define bounded delivery text
BenGuanRan Jul 19, 2026
f7829f1
fix(scheduler): bound oversized delivery text
BenGuanRan Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .qwen/e2e-tests/scheduled-channel-delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Daemon Scheduled Channel Delivery E2E

## Scope

This E2E covers the minimal daemon-owned contract:

```json
{
"kind": "channel",
"channelName": "e2e-dingtalk",
"target": { "type": "chat", "id": "<chat-id>" }
}
```

`target.type` is either `chat` or `user`. The target is explicit and is not
admitted through the observed-contact graph. Topic/thread targets, mentions,
the Web Shell picker, and standalone `qwen channel start` behavior are outside
this change.

## Real DingTalk result — 2026-07-19 (Asia/Shanghai)

An isolated `QWEN_HOME` and runtime directory were used. `qwen serve` started
one daemon-managed `e2e-dingtalk` worker for the repository workspace. The
daemon advertised `scheduled_task_channel_delivery`, the worker connected over
DingTalk Stream mode, and the temporary configuration was deleted after the
run.

### Chat target

- Task: `ngh4wqzr`
- Delivery: `ngh4wqzr:1784391780000`
- Marker: `QWEN-SCHED-E2E-20260719-0023-CHAT`
- Target type: `chat`
- Result: `delivered`, `attempts=1`

The one-shot task fired at its scheduled minute, disappeared from the task
list, produced only the requested final marker, persisted that marker in the
workspace outbox, and received a successful DingTalk group-send acknowledgement.

### User target

- Task: `dz1vu8i2`
- Delivery: `dz1vu8i2:1784391900000`
- Marker: `QWEN-SCHED-E2E-20260719-0025-USER`
- Target: `{ "type": "user", "id": "<redacted-user-id>" }`
- Result: `delivered`, `attempts=1`

The direct send used the stable DingTalk staff ID, not the inbound conversation
ID. The adapter accepted the platform response only after checking that the
recipient was absent from DingTalk's invalid and rate-limited user lists.

## Verified boundaries

- The daemon owns the timer, task store, final-answer capture, outbox, retries,
and Channel Worker dispatch.
- The task's immutable workspace owns both its outbox and its Channel Worker;
a later session `/cd` cannot move delivery to another workspace.
- Omitting `delivery` preserves the existing scheduled-task behavior.
- Only a clean, non-empty terminal model answer is enqueued. Thoughts, tool
output, interrupted turns, errors, and Todo Stop Guard drafts are excluded.
- Delivery retries reuse the persisted final answer and do not rerun the Agent.
- Outbox directories/files use owner-only POSIX permissions.
- Standalone loop target validation and Feishu direct proactive mapping remain
unchanged; daemon delivery uses dedicated validation/mapping hooks.

## Automated regression evidence

- Core scheduler/task/outbox: 195 tests passed.
- ChannelBase: 495 tests passed.
- DingTalk: 72 tests passed; Feishu: 76; WeCom: 135; Telegram: 15.
- Session final-answer capture: 368 tests passed.
- Focused CLI scheduled-delivery routes/IPC/worker/controller: 177 tests passed.
- CLI daemon/worker/server regression group: 1,105 tests passed; one transient
parallel socket case passed on isolated retry.
- CLI typecheck and serve fast-path bundle closure check passed.
1 change: 1 addition & 0 deletions docs/developers/qwen-serve-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ operator diagnostic snapshot documented below.
| `workspace_reload` | workspace reload support is available in the embedded route configuration. |
| `channel_reload` | a daemon-managed channel worker manager is enabled and can reload its current selection. |
| `channel_control` | daemon-managed channel worker runtime control is wired. |
| `scheduled_task_channel_delivery` | the daemon's post-run scheduled-task delivery pipeline is wired, so an optional typed `chat` or `user` target can be dispatched through the exact task workspace's Channel worker. |
| `multi_workspace_sessions` | more than one workspace runtime is registered, so session creation can select a trusted runtime by cwd. |
| `multi_workspace_session_rewind` | more than one workspace runtime is registered; singular live-session rewind routes resolve the owning runtime. |
| `multi_workspace_session_shell` | more than one workspace runtime is registered and session shell execution is explicitly enabled; singular REST shell resolves the owning runtime. |
Expand Down
Loading
Loading