You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(skill): stop routing template bodies through command substitution
Review of the previous commit found the safe-write flow it introduced carried the
same class of defect it exists to prevent. Three corrections:
Silent truncation. The flow moved channel bodies with `"$(cat …)"` / `"$(jq -r …)"`.
Bash command substitution strips every trailing newline, so a body that legitimately
ends in a blank line was written back shortened — and the verification step compared
only which fields were non-empty, so a truncated-but-still-non-empty channel reported
clean. Measured: a 15-byte body round-trips as 11. The write step now builds the whole
request with `jq --rawfile` (byte-exact) and posts it via `--data -`, and step 5 diffs
per-channel byte lengths instead of the non-empty field set, which catches truncation
and wipes alike. Rebuilding the body from the snapshot also removes the previous
"one flag per non-empty key" instruction, whose jq filter was unscoped and surfaced
template_id/status/created_at/updated_at — keys `update` has no flags for.
Miscount. `buildTemplateUpdates` writes 14 channel-content fields, not 16.
Category error. `status` was listed among the inputs that survive omission. It is not
a field of `update`'s request at all — it moves only through the separate
enable/disable endpoints, which the CLI does not expose. The survivors are exactly the
pointer-typed inputs: team_id, feishu_app_card_v2_table_enabled,
incident_card_hidden_fields.
Guard extended and mutation-verified.
-**`info`, `update`, `delete` take `<template-id>` as a positional first argument** — pass it bare, not as `--template-id`. `create`, `list`, `preview`, `validate`, `get-preset`, `functions`, `variables` take all inputs as flags.
204
209
-**`update` is a full-object replace — every channel field you omit is CLEARED.** The
205
-
server writes all 16 channel fields plus `description` on every call, and a field absent
206
-
from the request arrives as the empty string: omitting `--dingtalk-app` sets
207
-
`dingtalk_app` to `""`, and that channel silently stops rendering for every escalation
208
-
rule bound to the template. Only `team_id`, `feishu_app_card_v2_table_enabled`,
209
-
`incident_card_hidden_fields` and `status` survive omission (they are patch-semantics).
210
-
Always snapshot with `info --json` first and pass every non-empty channel back — see the
211
-
hot flow above. `--template-name` is required on every update even when unchanged.
210
+
server writes all 14 channel-content fields plus `description` on every call, and a
211
+
field absent from the request arrives as the empty string: omitting `--dingtalk-app`
212
+
sets `dingtalk_app` to `""`, and that channel silently stops rendering for every
213
+
escalation rule bound to the template. Only the pointer-typed inputs survive omission:
is not part of `update`'s request at all — it moves only through the separate
216
+
enable/disable endpoints, which the CLI does not expose — so `update` can never change
217
+
it.) Always snapshot with `info --json` first and rebuild the body from that snapshot —
218
+
see the hot flow above. `--template-name` is required on every update even when
219
+
unchanged.
220
+
-**Never move a template body through `"$(cat …)"` or `"$(jq -r …)"`.** Bash command
221
+
substitution strips *all* trailing newlines, so a body that legitimately ends in a blank
222
+
line is written back shortened — and a check that only asks which fields are non-empty
223
+
cannot see it, because the field is still non-empty. Carry bodies with `jq --rawfile`
224
+
and write with `--data -`, as the hot flow does.
212
225
-**`--feishu-app-card-v2-table-enabled` uses pointer semantics on `update`** — unlike the plain string channel-content flags, it patches the table-rendering setting only when the flag is explicitly passed; omit it to leave the existing setting untouched. It is a plain bool on `create` (no prior setting to preserve).
213
226
-**`list` returns every channel's full template source for every row** — a few dozen
214
227
templates blow past a tool-output cap in one call. Never render it directly: go to a
0 commit comments