feat(wechat): add Intent Transaction Layer with unified task schema
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts so reminders and automations get explicit user confirmation before persisting. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -76,7 +76,7 @@ test('createTask returns existing active duplicate for same schedule', async ()
|
||||
let insertCount = 0;
|
||||
const service = createScheduledTaskService({
|
||||
async query(sql) {
|
||||
if (sql.includes('FROM h5_scheduled_tasks') && sql.includes('status = \'active\'')) {
|
||||
if (sql.includes('FROM h5_scheduled_tasks') && sql.includes("status IN ('active', 'locked')")) {
|
||||
return [[{
|
||||
id: 'task-existing',
|
||||
user_id: 'user-1',
|
||||
@@ -125,6 +125,59 @@ test('createTask returns existing active duplicate for same schedule', async ()
|
||||
assert.equal(insertCount, 0);
|
||||
});
|
||||
|
||||
test('createTask returns existing locked duplicate for same schedule', async () => {
|
||||
let insertCount = 0;
|
||||
const service = createScheduledTaskService({
|
||||
async query(sql) {
|
||||
if (sql.includes('FROM h5_scheduled_tasks') && sql.includes("status IN ('active', 'locked')")) {
|
||||
return [[{
|
||||
id: 'task-locked',
|
||||
user_id: 'user-1',
|
||||
title: '每日天气预报播报(上海+武穴)',
|
||||
task_spec: 'running spec',
|
||||
recurrence: 'daily',
|
||||
hour: 8,
|
||||
minute: 0,
|
||||
weekday: null,
|
||||
timezone: 'Asia/Shanghai',
|
||||
next_run_at: 1780000000000,
|
||||
last_run_at: null,
|
||||
notify_channel: 'both',
|
||||
status: 'locked',
|
||||
attempts: 1,
|
||||
last_error: null,
|
||||
last_result_json: null,
|
||||
source_channel: 'agent',
|
||||
source_session_id: null,
|
||||
source_message_id: null,
|
||||
source_text: null,
|
||||
created_at: 1780000000000,
|
||||
updated_at: 1780000000000,
|
||||
}]];
|
||||
}
|
||||
if (sql.includes('INSERT INTO h5_scheduled_tasks')) {
|
||||
insertCount += 1;
|
||||
return [{ affectedRows: 1 }];
|
||||
}
|
||||
return [[]];
|
||||
},
|
||||
}, {
|
||||
clock: { now: () => 1780000000000 },
|
||||
});
|
||||
|
||||
const task = await service.createTask({
|
||||
userId: 'user-1',
|
||||
title: '每日天气预报播报(上海+武穴)',
|
||||
taskSpec: 'new spec',
|
||||
recurrence: 'daily',
|
||||
hour: 8,
|
||||
minute: 0,
|
||||
});
|
||||
|
||||
assert.equal(task.id, 'task-locked');
|
||||
assert.equal(insertCount, 0);
|
||||
});
|
||||
|
||||
test('cancelTask updates status to cancelled', async () => {
|
||||
const service = createScheduledTaskService({
|
||||
async query(sql, params) {
|
||||
|
||||
Reference in New Issue
Block a user