vibe-coding-master 0.4.42 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,813 +0,0 @@
1
- # VCM Gateway Design
2
-
3
- Last updated: 2026-06-24
4
-
5
- This document defines VCM gateway product behavior and implementation plan. The
6
- first channel was based on the local Tencent iLink smoke test at:
7
-
8
- ```text
9
- /Users/sheldon/Documents/New project 3/weixin-ilink-gateway-test
10
- ```
11
-
12
- Supported gateway channels:
13
-
14
- - Tencent iLink Bot API / Weixin DM
15
- - Lark QR setup plus bot WebSocket event delivery
16
-
17
- ## Product Definition
18
-
19
- VCM Gateway is a mobile conversation bridge between chat clients and one
20
- desktop VCM instance. It is not a remote terminal.
21
-
22
- Product rules:
23
-
24
- - Weixin supports DM only.
25
- - Lark accepts direct messages and group messages only when the bot is
26
- mentioned.
27
- - Weixin binds one mobile chat identity to one desktop VCM instance.
28
- - Lark does not require pairing. Any chat that can DM the bot or @mention it can
29
- control Gateway; the most recent active Lark chat becomes the PM reply target.
30
- - The active chat is not project-specific and not task-specific.
31
- - The active chat can manage every project and task available to that desktop
32
- VCM instance.
33
- - Gateway user messages talk only to the `project-manager` role.
34
- - Gateway never sends directly to `architect`, `coder`, or `reviewer`.
35
- - When the desktop UI has a current task selected, Gateway should adopt that
36
- project/task context automatically instead of requiring `/tasks` and
37
- `/use-task` first.
38
- - After channel setup succeeds, VCM keeps a channel connection even when Gateway is
39
- disabled. Disabled Gateway accepts only `/help`, `/start`, `/status`,
40
- `/projects`, and `/tasks`.
41
- - VCM stores the latest PM reply for each task in local Gateway state. When
42
- `/start` enables Gateway and the current task has a cached PM reply, Gateway
43
- returns that reply immediately so the phone user sees the current task state.
44
- - Gateway does not change the desktop `Pause alert sound` preference. The
45
- desktop pause dialog remains a fixed local UI signal, and Gateway is the
46
- mobile notification path.
47
- - Gateway may push PM replies to the active mobile chat whenever it is enabled,
48
- even when the PM turn was started from the desktop UI rather than from the
49
- mobile chat.
50
- - When translation is enabled, Chinese input is translated to English before it
51
- is sent to PM.
52
- - The prompt sent to PM does not include the original Chinese text.
53
- - There is no allowed-user list. Weixin is a bound identity model; Lark is a
54
- trusted-chat bot model.
55
-
56
- The short product sentence is:
57
-
58
- ```text
59
- One active mobile chat controls one desktop VCM; the chat can select project/task context,
60
- pull the connected base repository, create and initialize a task through the
61
- saved launch template, send ordinary messages to the current task's PM, receive
62
- translated PM replies, and close completed tasks while gateway is enabled; when
63
- gateway is disabled, the active chat can still run `/start` and read-only status
64
- commands.
65
- ```
66
-
67
- ## Binding Model
68
-
69
- The control target is the desktop VCM instance.
70
-
71
- ```text
72
- Weixin DM or Lark chat
73
- <-> desktop VCM instance
74
- ```
75
-
76
- The gateway stores channel credentials and active chat metadata in app-local
77
- state. Weixin stores the iLink bot account token from QR login. Lark QR setup
78
- creates/configures the bot app and stores App ID/App Secret locally. VCM does
79
- not support manual Lark App ID/App Secret configuration.
80
-
81
- Weixin accepts messages from the bound identity. Lark accepts messages from any
82
- chat that can reach the bot, and each accepted message updates the active Lark
83
- chat used for PM reply push.
84
-
85
- Changing Weixin phones or accounts is a rebind operation. Lark active chat
86
- changes automatically whenever another reachable Lark chat messages the bot:
87
-
88
- ```text
89
- desktop settings -> disable gateway or reset binding -> QR login again
90
- ```
91
-
92
- ## Mobile Context
93
-
94
- Because Gateway controls a desktop VCM instance, it needs a current mobile
95
- context:
96
-
97
- ```text
98
- current project
99
- current task
100
- current role = project-manager
101
- translation enabled/disabled
102
- saved launch template
103
- ```
104
-
105
- Plain text messages are sent to the PM session of the current task only when
106
- Gateway is enabled. If no project or task is selected, gateway replies with a
107
- short setup hint.
108
-
109
- VCM normally runs one project and one task at a time. When Gateway is enabled,
110
- or when `/status` is called, VCM should refresh Gateway context from the
111
- desktop-selected project/task when available.
112
-
113
- The desktop UI remains the source of truth. Gateway changes mobile context or
114
- task lifecycle state only through explicit commands.
115
-
116
- ## Command Surface
117
-
118
- MVP commands:
119
-
120
- ```text
121
- /help
122
- /start
123
- /retry
124
- /status
125
- /projects
126
- /use-project <index-or-path>
127
- /pull-current
128
- /tasks
129
- /use-task <index-or-task-slug>
130
- /create-task <task-slug> [title]
131
- /close-task
132
- /close-task confirm <task-slug>
133
- /translate on
134
- /translate off
135
- ```
136
-
137
- Plain text that does not start with `/` is treated as a PM message for the
138
- current task only when Gateway is enabled.
139
-
140
- When Gateway is disabled but the channel is still connected, only this subset is accepted:
141
-
142
- ```text
143
- /help
144
- /start
145
- /status
146
- /projects
147
- /tasks
148
- ```
149
-
150
- `/start` enables Gateway from the active mobile chat. If there is a current task
151
- and VCM has cached a latest PM reply for that task, `/start` includes that reply
152
- in the command response. All plain text, task-changing commands,
153
- project-changing commands, translation toggles, and repository pull commands
154
- require Gateway to be enabled.
155
-
156
- When Gateway output translation is enabled, PM replies are translated before
157
- being sent to Weixin. If translation fails or times out, Gateway sends a
158
- translation failure notice instead of the English source. The latest failed
159
- output translation is kept in memory only, and `/retry` retries that source
160
- content. Successful retry clears the memory item; failed retry keeps it for a
161
- later `/retry`.
162
-
163
- Task lifecycle commands:
164
-
165
- - `/pull-current` calls `POST /api/projects/current/pull` for the selected
166
- desktop VCM project. It runs the same connected-repository fast-forward-only
167
- pull as the desktop button. It must fail if the base repo has uncommitted
168
- changes or if the branch has no upstream.
169
- - `/create-task <task-slug> [title]` creates a task worktree,
170
- selects it as the mobile current task, applies the saved launch template, and
171
- starts the four role sessions (`project-manager`, `architect`, `coder`,
172
- `reviewer`) using the saved desktop launch-template values. The saved template
173
- controls permission mode, model, effort, and auto orchestration.
174
- If no template has been saved, VCM uses the default launch template.
175
- - `/close-task` starts a destructive confirmation flow for the current task.
176
- Gateway replies with the exact confirmation command.
177
- - `/close-task confirm <task-slug>` calls VCM Close Task cleanup for that task:
178
- stop VCM-managed role sessions, remove the task worktree and task branch when
179
- the task owns them, and remove VCM task/runtime metadata.
180
-
181
- Commands intentionally not in MVP:
182
-
183
- ```text
184
- /approve
185
- /reject
186
- /pause
187
- /resume
188
- /stop-session
189
- ```
190
-
191
- The first version should not expose arbitrary terminal controls, role-specific
192
- start/stop controls, approve/reject gates, or shell execution. The state-changing
193
- commands are limited to the VCM task lifecycle primitives needed to run a task
194
- end to end from mobile.
195
-
196
- ## Inbound Message Flow
197
-
198
- ```text
199
- Tencent iLink getupdates
200
- -> weixin-ilink channel
201
- -> verify bound DM identity for Weixin, or update active chat for Lark
202
- -> dedupe message id
203
- -> parse text / command
204
- -> if command: execute gateway command and reply
205
- -> if plain text:
206
- -> require current project + current task
207
- -> require current task PM session running and hook-idle
208
- -> translate Chinese to English when enabled
209
- -> submit English prompt to PM
210
- -> reply with accepted / busy / error status
211
- ```
212
-
213
- PM prompt shape when translation is enabled:
214
-
215
- ```text
216
- [VCM Gateway]
217
- <translated English instruction>
218
- ```
219
-
220
- The original Chinese is not included in the PM prompt.
221
-
222
- If translation is disabled, the plain user text is submitted as-is with the same
223
- `[VCM Gateway]` marker.
224
-
225
- Gateway should use the same bracketed-paste terminal submission path as the VCM
226
- desktop input path. A terminal write only proves the text was written to the PTY;
227
- Claude Code `UserPromptSubmit` remains the acceptance signal.
228
-
229
- ## Task Lifecycle Command Flows
230
-
231
- ### Pull Current Base Repository
232
-
233
- ```text
234
- /pull-current
235
- -> require current project
236
- -> call POST /api/projects/current/pull
237
- -> backend runs git pull --ff-only on connected base repo
238
- -> refresh current project status
239
- -> reply with branch, upstream, ahead/behind, and short commit
240
- ```
241
-
242
- Rules:
243
-
244
- - Pull only the connected base repository, never a task worktree.
245
- - Use the same backend guard as desktop Connected Repository Pull.
246
- - Do not stash, merge, or continue after divergence.
247
- - If pull fails, reply with the VCM error message and hint.
248
-
249
- ### Create And Initialize Task
250
-
251
- ```text
252
- /create-task <task-slug> [title]
253
- -> require current project
254
- -> create a task branch and worktree through existing task service/API
255
- -> select it as gateway current task
256
- -> load saved launch template from app preferences
257
- -> set orchestration from template
258
- -> start four role sessions with template permission/model/effort
259
- -> switch mobile current role to project-manager
260
- -> reply with task slug, branch, worktree, template summary, and session status
261
- ```
262
-
263
- Rules:
264
-
265
- - Use the same task creation validation as desktop VCM.
266
- - Use the same one-click-start semantics as desktop VCM: only start from a newly
267
- created task with no existing role sessions.
268
- - If one role session fails to start, reply with the role that failed and leave
269
- the partially created task visible in desktop VCM for manual recovery.
270
- - Do not send the task request as a PM prompt. Task creation is a VCM control
271
- command, not natural-language work for Claude.
272
-
273
- ### Close Task
274
-
275
- ```text
276
- /close-task
277
- -> require current task
278
- -> reply with destructive confirmation text
279
-
280
- /close-task confirm <task-slug>
281
- -> require current task slug matches confirmation slug
282
- -> call VCM Close Task cleanup
283
- -> clear mobile current task if cleanup succeeds
284
- -> reply with removed worktree, deleted branch, and cleaned state paths
285
- ```
286
-
287
- Rules:
288
-
289
- - Close Task is destructive, so mobile requires explicit confirmation with the
290
- task slug.
291
- - Use the same cleanup path as desktop Close Task.
292
- - Do not preflight or preserve uncommitted work beyond the existing desktop
293
- Close Task behavior.
294
- - After cleanup, gateway should ask the user to run `/tasks` or
295
- `/create-task <task-slug>` for the next task.
296
-
297
- ## PM Reply Push Flow
298
-
299
- Gateway push is not limited to gateway-originated turns. If gateway is enabled,
300
- VCM should push PM replies to Weixin after PM completes a turn.
301
-
302
- ```text
303
- PM Claude Code Stop hook
304
- -> load PM session transcript
305
- -> extract new assistant text since last pushed transcript cursor
306
- -> ignore tool logs, raw terminal output, and non-PM roles
307
- -> translate English reply to Chinese when enabled
308
- -> send Weixin DM through iLink sendmessage
309
- -> persist last pushed transcript cursor
310
- ```
311
-
312
- Rules:
313
-
314
- - Push only PM assistant replies.
315
- - Do not push token-by-token terminal output.
316
- - Do not push raw tool logs.
317
- - Do not push architect/coder/reviewer replies directly.
318
- - Deduplicate by PM session id and transcript event id or timestamp.
319
- - If translation fails, send the PM original text with a short translation
320
- failure note.
321
-
322
- This keeps the mobile side readable and avoids exposing the embedded terminal as
323
- a chat stream.
324
-
325
- ## Busy And Error Behavior
326
-
327
- The MVP should be conservative.
328
-
329
- If the PM session is busy, do not queue arbitrary mobile prompts. Reply:
330
-
331
- ```text
332
- PM is still working on the current turn. Please wait and send again later.
333
- ```
334
-
335
- If PM is not running:
336
-
337
- ```text
338
- The current task's PM session is not running. Start it from desktop VCM first.
339
- ```
340
-
341
- If no task is selected:
342
-
343
- ```text
344
- No task is selected. Use /tasks and /use-task first.
345
- ```
346
-
347
- If `/pull-current` cannot run because the base repo is dirty or has no upstream,
348
- reply with the same VCM reason shown in the desktop Connected Repository section.
349
-
350
- If `/create-task` fails task validation, reply with the VCM error and hint.
351
- Common examples are invalid task slug, dirty base repo, existing task branch, or
352
- missing harness ignore rules for `.ai/vcm/` / `.claude/worktrees/`.
353
-
354
- If `/create-task` creates the task but one of the four role sessions fails to
355
- start, do not hide the partial state. Reply with:
356
-
357
- ```text
358
- Task was created, but <role> failed to start. Open desktop VCM to recover or retry.
359
- ```
360
-
361
- If `/close-task confirm <task-slug>` does not match the current task, do not
362
- clean up anything. Reply with the current task slug and the exact confirmation
363
- command.
364
-
365
- If gateway translation fails before sending to PM, do not send the original
366
- Chinese. Reply with a translation failure message and ask the user to retry.
367
-
368
- ## Tencent iLink Feasibility
369
-
370
- The local smoke test proves the required channel primitives:
371
-
372
- - QR login with `ilink/bot/get_bot_qrcode`.
373
- - QR status polling with `ilink/bot/get_qrcode_status`.
374
- - Long-poll DM receive with `ilink/bot/getupdates`.
375
- - Text reply with `ilink/bot/sendmessage`.
376
- - Token and cursor persistence outside a repository.
377
- - Handling session expiration through iLink error code `-14`.
378
-
379
- Observed request details from the smoke test:
380
-
381
- ```text
382
- base URL: https://ilinkai.weixin.qq.com
383
- default bot_type: 3
384
- default channel_version: 2.4.3
385
- ```
386
-
387
- Common headers:
388
-
389
- ```text
390
- Content-Type: application/json
391
- AuthorizationType: ilink_bot_token
392
- Authorization: Bearer <token>
393
- X-WECHAT-UIN: <random base64 uin>
394
- iLink-App-Id: bot
395
- iLink-App-ClientVersion: <encoded client version>
396
- SKRouteTag: <optional route tag>
397
- ```
398
-
399
- QR login:
400
-
401
- ```text
402
- POST ilink/bot/get_bot_qrcode?bot_type=<bot_type>
403
- body:
404
- {
405
- "local_token_list": ["<saved token>"]
406
- }
407
-
408
- GET ilink/bot/get_qrcode_status?qrcode=<qrcode>
409
- GET ilink/bot/get_qrcode_status?qrcode=<qrcode>&verify_code=<code>
410
- ```
411
-
412
- QR statuses handled by the smoke test:
413
-
414
- ```text
415
- wait
416
- scaned
417
- need_verifycode
418
- verify_code_blocked
419
- expired
420
- scaned_but_redirect
421
- binded_redirect
422
- confirmed
423
- ```
424
-
425
- Long poll receive:
426
-
427
- ```text
428
- POST ilink/bot/getupdates
429
- body:
430
- {
431
- "get_updates_buf": "<cursor>",
432
- "base_info": {
433
- "channel_version": "2.4.3",
434
- "bot_agent": "vcm-gateway/<version>"
435
- }
436
- }
437
- ```
438
-
439
- The response may include:
440
-
441
- ```text
442
- ret / errcode
443
- errmsg
444
- longpolling_timeout_ms
445
- get_updates_buf
446
- msgs[]
447
- ```
448
-
449
- Send text DM:
450
-
451
- ```text
452
- POST ilink/bot/sendmessage
453
- body:
454
- {
455
- "msg": {
456
- "from_user_id": "",
457
- "to_user_id": "<bound user id>",
458
- "client_id": "<unique client id>",
459
- "message_type": 2,
460
- "message_state": 2,
461
- "item_list": [
462
- {
463
- "type": 1,
464
- "text_item": {
465
- "text": "<reply text>"
466
- }
467
- }
468
- ],
469
- "context_token": "<optional latest context token>"
470
- },
471
- "base_info": {
472
- "channel_version": "2.4.3",
473
- "bot_agent": "vcm-gateway/<version>"
474
- }
475
- }
476
- ```
477
-
478
- Inbound message handling:
479
-
480
- - Ignore bot messages where `message_type` is bot.
481
- - Accept user messages where `message_type` is user or absent.
482
- - Extract text from `item_list[].text_item.text`.
483
- - Voice text can be read from `item_list[].voice_item.text` if iLink supplies
484
- it, but MVP should treat non-text input as unsupported unless text is present.
485
- - Use `message_id`, then `client_id`, then sender/time fallback for dedupe.
486
- - Persist `get_updates_buf` after each successful poll response.
487
- - Persist latest `context_token` per active user/chat and reuse it for replies.
488
-
489
- ## Local State
490
-
491
- Gateway state must live outside connected repositories.
492
-
493
- Recommended files:
494
-
495
- ```text
496
- <vcmDataDir>/gateway/settings.json
497
- <vcmDataDir>/gateway/audit.jsonl
498
- ```
499
-
500
- VCM resolves `vcmDataDir` from `VCM_DATA_DIR`; when it is unset or empty, VCM
501
- uses `~/.vcm`.
502
-
503
- Settings shape:
504
-
505
- ```json
506
- {
507
- "version": 1,
508
- "enabled": false,
509
- "channel": "weixin-ilink",
510
- "translationEnabled": true,
511
- "currentProjectId": null,
512
- "currentTaskSlug": null,
513
- "binding": {
514
- "accountId": null,
515
- "baseUrl": "https://ilinkai.weixin.qq.com",
516
- "boundUserId": null,
517
- "loginUserId": null,
518
- "token": null,
519
- "getUpdatesBuf": "",
520
- "contextTokens": {}
521
- },
522
- "dedupe": {
523
- "recentInboundMessageIds": []
524
- },
525
- "pendingConfirmations": {
526
- "closeTask": {
527
- "taskSlug": null,
528
- "createdAt": null,
529
- "expiresAt": null
530
- }
531
- },
532
- "pushCursors": {
533
- "<taskSlug>:project-manager:<claudeSessionId>": {
534
- "lastTranscriptEventId": null,
535
- "lastTranscriptTimestamp": null
536
- }
537
- },
538
- "updatedAt": "..."
539
- }
540
- ```
541
-
542
- The token is sensitive. The settings file should be written with user-only file
543
- permissions where the platform supports it.
544
-
545
- Audit log rules:
546
-
547
- - Record state transitions, command names, message ids, result codes, and error
548
- classes.
549
- - Redact token, Authorization header, QR URL, and full message bodies by default.
550
- - Store short message previews only when needed for debugging.
551
- - Never write gateway credentials to connected repositories, terminal logs,
552
- `.ai/vcm/**`, PR descriptions, or generated harness files.
553
-
554
- ## Backend Architecture
555
-
556
- Implemented files:
557
-
558
- ```text
559
- src/shared/types/gateway.ts
560
-
561
- src/backend/gateway/
562
- gateway-channel.ts
563
- gateway-service.ts
564
- gateway-settings-service.ts
565
- gateway-command-parser.ts
566
- gateway-audit-log.ts
567
- channels/
568
- lark-channel.ts
569
- lark-registration.ts
570
- weixin-ilink-channel.ts
571
-
572
- src/backend/api/gateway-routes.ts
573
- ```
574
-
575
- Responsibilities:
576
-
577
- - `gateway-settings-service`: load/save app-local gateway settings and secrets.
578
- - `gateway-channel`: define the generic channel adapter contract and registry.
579
- - `weixin-ilink-channel`: implement the generic adapter with Weixin iLink QR
580
- login, long polling, send text, and token expiration detection.
581
- - `lark-channel`: implement the generic adapter with Lark WebSocket event
582
- delivery, text send, chat id routing, and mention filtering for groups.
583
- - `lark-registration`: implement QR setup (`init`, `begin`, `poll`) against
584
- Lark account registration, then save the returned App ID/App Secret locally.
585
- - `gateway-command-parser`: parse `/help`, `/status`, `/projects`,
586
- `/use-project`, `/pull-current`, `/tasks`, `/use-task`, `/create-task`,
587
- `/close-task`, and `/translate`.
588
- - `gateway-audit-log`: append redacted JSONL audit entries.
589
- - `gateway-service`: lifecycle, poll loop, command dispatch, PM terminal
590
- submission, PM Stop reply push, and error backoff. It must depend on the
591
- channel registry and generic adapter types, not Weixin/iLink-specific types.
592
- - `gateway-routes`: desktop UI settings, QR login start/status, Lark QR setup,
593
- enable/disable, rebind, and gateway status.
594
-
595
- Service dependencies:
596
-
597
- - `ProjectService`: current project, recent project paths, connected-repo
598
- status, and fast-forward-only pull.
599
- - `TaskService`: task list, task creation, selected task validation, and Close
600
- Task cleanup.
601
- - `SessionService`: PM session state, Claude session metadata, and role session
602
- start for launch-template initialization.
603
- - `AppSettingsService`: saved launch template with permission mode, model,
604
- effort, auto orchestration, plus the global Gateway translation preference.
605
- - `MessageService` / orchestration state service: set the newly created task to
606
- template auto/manual orchestration mode.
607
- - `TerminalRuntime`: controlled PM terminal submission.
608
- - `ClaudeTranscriptService`: PM assistant output extraction.
609
- - `TranslationService` / Translator: inbound Chinese-to-English and
610
- outbound target-language translation.
611
- - `ClaudeHookService` or hook event integration: trigger PM reply push after PM
612
- `Stop`.
613
-
614
- ## Desktop UI
615
-
616
- Add a Gateway section to the sidebar settings area or a dedicated modal:
617
-
618
- ```text
619
- Gateway: off / on
620
- Channel: Weixin iLink / Lark
621
- Active chat: none / active
622
- Translation: off / on
623
- Current project
624
- Current task
625
- QR login / Lark QR setup / Rebind
626
- Last poll status
627
- Last message status
628
- ```
629
-
630
- The user should be able to:
631
-
632
- - enable or disable gateway
633
- - select the gateway channel
634
- - start Weixin QR login
635
- - start Lark QR setup
636
- - see whether the phone or Lark chat is active
637
- - reset binding or channel setup
638
- - inspect the current gateway project/task context
639
- - toggle gateway translation
640
- - inspect recent gateway errors
641
-
642
- ## Implementation Plan
643
-
644
- ### Phase 1: Types, Settings, And UI Skeleton
645
-
646
- - Add `src/shared/types/gateway.ts`.
647
- - Add app-local gateway settings service under `src/backend/gateway`.
648
- - Add `src/backend/api/gateway-routes.ts`.
649
- - Add desktop UI controls for enable/disable, translation, binding status, and
650
- current project/task.
651
- - Store settings under `<vcmDataDir>/gateway/settings.json`.
652
-
653
- Validation:
654
-
655
- - Unit tests for settings normalization and secret redaction.
656
- - API route tests for enable/disable and settings update.
657
-
658
- ### Phase 2: iLink Channel Adapter
659
-
660
- - Port the proven smoke-test behavior into `weixin-ilink-channel.ts`.
661
- - Support QR login and status polling.
662
- - Support token reuse from saved settings.
663
- - Support `getupdates` long polling.
664
- - Support `sendmessage` text DM.
665
- - Persist `get_updates_buf` and context tokens.
666
- - Handle `ret` / `errcode` `-14` as expired login.
667
-
668
- Validation:
669
-
670
- - Unit tests with mocked fetch for QR statuses, getupdates, sendmessage,
671
- expiration, redirect host, and retry backoff.
672
- - Manual smoke test with a real Weixin DM before wiring PM submission.
673
-
674
- ### Phase 3: Inbound Context Commands
675
-
676
- - Implement `/help`, `/start`, `/retry`, `/status`, `/projects`,
677
- `/use-project`, `/tasks`, `/use-task`, `/translate on`, and `/translate off`.
678
- - Implement Weixin bound identity check and Lark latest-active-chat updates.
679
- - Implement persistent inbound message dedupe.
680
- - Reply with short command results through iLink.
681
-
682
- Validation:
683
-
684
- - Parser tests for known commands and invalid commands.
685
- - Gateway service tests for ignored unbound Weixin users, Lark active chat
686
- updates, and deduped messages.
687
-
688
- ### Phase 4: Task Lifecycle Commands
689
-
690
- - Implement `/pull-current` by calling the connected repository pull path:
691
- `POST /api/projects/current/pull` or the equivalent project service method.
692
- - Implement `/create-task <task-slug> [title]` by creating a task worktree
693
- task, selecting it as mobile current task, applying the saved launch template,
694
- setting orchestration mode, applying the global Gateway translation state, and
695
- starting the four core role sessions.
696
- - Implement `/close-task` and `/close-task confirm <task-slug>` as a two-step
697
- destructive confirmation around the same Close Task cleanup path as desktop
698
- VCM.
699
- - Persist close-task pending confirmation outside the repository.
700
-
701
- Validation:
702
-
703
- - Parser tests for `/pull-current`, `/create-task`, `/close-task`, and
704
- confirmation mismatch.
705
- - Service tests for pull success and pull-blocked reasons.
706
- - Service tests that task creation creates a task worktree and uses launch
707
- template role settings.
708
- - Service tests for partial role-session start failure reporting.
709
- - Service tests that Close Task calls the existing cleanup path only after exact
710
- slug confirmation.
711
-
712
- ### Phase 5: PM Message Submission
713
-
714
- - Treat plain DM text as PM input for the current task.
715
- - Require current project, current task, running PM session, and idle PM
716
- activity.
717
- - If gateway translation is enabled, translate Chinese to English before
718
- submission.
719
- - Submit only the translated English text to PM with `[VCM Gateway]`.
720
- - Do not include the original Chinese text in the PM prompt.
721
- - Use bracketed paste plus Enter through `submitTerminalInput`.
722
-
723
- Validation:
724
-
725
- - Tests for no project/task/session/busy/translation failure paths.
726
- - Tests that translated prompts do not include original Chinese.
727
- - Tests that successful submit records a gateway turn audit entry.
728
-
729
- ### Phase 6: PM Reply Push
730
-
731
- - Hook PM `Stop` handling into `gateway-service`.
732
- - Load PM transcript and extract new assistant text since the last push cursor.
733
- - Push PM replies whenever gateway is enabled, regardless of whether the user
734
- turn started from gateway or desktop.
735
- - Translate PM reply to Chinese when gateway translation is enabled.
736
- - Persist push cursors so restart does not duplicate old PM replies.
737
-
738
- Validation:
739
-
740
- - Transcript extraction tests with multiple assistant events.
741
- - Deduplication tests across repeated Stop hooks and app restart.
742
- - Translation failure fallback test.
743
-
744
- ### Phase 7: Audit, Recovery, And Packaging
745
-
746
- - Add redacted audit JSONL writer.
747
- - Add gateway lifecycle shutdown on VCM server stop.
748
- - Add status reporting for poll errors, expired login, disabled gateway, and
749
- last successful message.
750
- - Document manual smoke test steps.
751
-
752
- Validation:
753
-
754
- - Full unit test pass.
755
- - Build pass.
756
- - Manual iLink smoke test:
757
- - QR bind
758
- - `/status`
759
- - `/pull-current`
760
- - `/create-task mobile-demo`
761
- - `/tasks`
762
- - `/use-task`
763
- - Chinese plain text to PM
764
- - PM reply pushed back to Weixin
765
- - `/close-task` + `/close-task confirm mobile-demo`
766
- - restart without replaying old messages
767
-
768
- ## Key Risks And Decisions
769
-
770
- PM reply extraction is the main implementation risk. VCM should use Claude
771
- transcript events, not raw PTY output, because terminal output contains tool
772
- logs, redraws, and partial text. The notifier must persist a per-PM-session
773
- cursor.
774
-
775
- The second risk is accidental command scope growth. Gateway should support the
776
- small task lifecycle needed to run work end to end from mobile: pull base repo,
777
- create and initialize a task, talk to PM, receive PM replies, and close the
778
- task. It should still avoid arbitrary terminal control, approve/reject gates,
779
- role-specific start/stop controls, shell commands, and direct non-PM prompts.
780
-
781
- The third risk is token and message leakage. Gateway credentials and audit logs
782
- must stay under `<vcmDataDir>/gateway`, with secrets redacted from logs and never
783
- written into connected repositories.
784
-
785
- The fourth risk is queueing. MVP should not queue multiple arbitrary user
786
- prompts while PM is running. It should return a busy message and let the user
787
- retry after PM stops.
788
-
789
- ## Acceptance Criteria
790
-
791
- Gateway MVP is complete when:
792
-
793
- - Desktop VCM can enable/disable Weixin iLink gateway.
794
- - Desktop VCM can QR-bind one Weixin DM identity.
795
- - Desktop VCM can use the most recent active Lark DM or group @mention as the
796
- Gateway reply target.
797
- - Bound phone can send `/status` and receive current VCM status.
798
- - Bound phone can list and select current project/task context.
799
- - Bound phone can run `/pull-current` to update the connected base repository
800
- through VCM's fast-forward-only pull path.
801
- - Bound phone can run `/create-task <task-slug> [title]` to create a task
802
- worktree, select it, apply the saved launch template, and start
803
- the four core role sessions.
804
- - Bound phone can send Chinese plain text to current task PM.
805
- - PM receives only the translated English prompt, without original Chinese.
806
- - Gateway can push PM assistant replies to Weixin whenever enabled.
807
- - PM replies are translated to Chinese when gateway translation is enabled.
808
- - Bound phone can close a completed task through `/close-task` plus exact slug
809
- confirmation, using the same cleanup path as desktop Close Task.
810
- - Duplicate iLink messages and duplicate PM Stop hooks do not produce duplicate
811
- sends.
812
- - Expired iLink token is reported clearly and requires rebind.
813
- - Gateway credentials and audit logs stay outside connected repositories.