From dc92b4cc8f4f1bce9b22e08315ec03f0dbf5f011 Mon Sep 17 00:00:00 2001 From: yeuimu <2197651308@qq.com> Date: Fri, 18 Sep 2026 02:28:11 +0000 Subject: [PATCH] fix(workflow): suppress self-echo trigger duplication on workflow-written records MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One user edit cascaded into 3-5 workflow executions and hourly sync jobs generated 1000+ wasted runs/week (7d: 15.7k of 18k executions of the ticket-status workflow ended in skipped no-op guards). Root cause: workflow scripts write records via REST with a runner-signed token, and record-event triggers could not distinguish those writes from human edits — every script PATCH re-triggered its own workflow. Attribution chain (new): - WorkflowTokenService signs {workflowId, executionId} into the runner token - jwt.strategy lifts it into CLS workflowContext (User-type branch) - all 13 automation.record.* emit sites tag payloads with writeSource - the 4 record triggers drop SELF echoes (writeSource.workflowId === own id) unconditionally; cross-workflow writes keep firing by default (chaining is load-bearing: order-sync建档 -> status workflow stamps 待处理, ~142 real actions/week). Opt-in stronger dedup via trigger config skipWorkflowWrites: true. Verified live: human edit (处理反馈=正在核实) -> exactly 1 execution, script flipped 流转状态 待处理->处理中, zero follow-up echoes; restore writes likewise 1 execution each with skipped no-ops. Unit: 14 new tests, 318 adjacent green. --- .../skills/inkreach-teable/api-reference/trigger-types.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.agents/skills/inkreach-teable/api-reference/trigger-types.md b/.agents/skills/inkreach-teable/api-reference/trigger-types.md index e7f3f28..c51e8c3 100644 --- a/.agents/skills/inkreach-teable/api-reference/trigger-types.md +++ b/.agents/skills/inkreach-teable/api-reference/trigger-types.md @@ -71,6 +71,13 @@ inkreach-teable trigger set --type recordUpdated --table-id tblXXX \ - ⚠️ **Write-path coverage** (verified 2026-08): browser grid cell edits DO fire this trigger — every grid editor commit funnels through `record.updateCell` → the REST `updateRecord` API (no ShareDB op submit exists in the frontend). Covered surfaces: single/batch record update (REST v1+v2), grid paste (small `paste-by-id`, large `paste-*-stream`, range `paste`), grid cell clear (`clear` / `clear-by-id`), record duplicate, and programmatic/automation writes (workflow actions call the REST API). Form submissions intentionally emit ONLY the `formSubmitted` event (independent channel). Record deletions emit no automation event (no delete trigger category exists). - Values resolve to `undefined` (not `[]`) if the emitting path could not snapshot before-values — scripts should guard `changedFieldIds ?? []`. +**Workflow-write echo suppression** (all 4 record triggers: `recordCreated` / `recordUpdated` / `recordCondition` / `recordCreatedOrUpdated`): +- Writes made BY workflow executions (script `fetch` with `triggerInput._accessToken`, `createRecords`/`updateRecords` actions) are tagged `writeSource: {workflowId, executionId}` on the event. +- **Self-echoes are always dropped**: a workflow never fires on its own writes (the script's PATCH re-triggering its own workflow was the duplication bug — one edit cascaded into 3-5 executions, every echo ending in a `skipped` no-op guard). +- Writes by OTHER workflows still fire by default — cross-workflow chaining is load-bearing (e.g. the order-sync job 建档 and this workflow stamping the initial 待处理). Opted-in events carry `triggerInput.writeSource.workflowId` for loop-guarding inside scripts. +- Config `"skipWorkflowWrites": true` additionally drops cross-workflow writes (stronger dedup when a workflow should react ONLY to human edits). +- Human grid edits, form/API/CLI writes are never tagged and always fire; suppressed writes still reach other listeners (e.g. record subscriptions) — only record-trigger handlers drop them. + --- ## 3. recordCondition — When a record matches conditions