Repository navigation
Commit 7a09eee
docs(skills): objectstack-automation routes an outbound credential to a connector credentialRef and drops the Slack webhook-url example (#20778)
Fixes #20657
Clause-②: no
The skills half of the #20590 family (the parent is completed; the spec,
runtime and guide faces landed in #20654 / #20655 / #20672).
`skills/objectstack-automation` now tells an author what a flow
definition serves and where an outbound credential goes, and its long
example no longer teaches a secret-bearing Slack webhook url.
## What changed
**`skills/objectstack-automation/SKILL.md`**
- The `http` row of the node table now says: `url` and `headers` are
served as written with the definition to every member who can read flows
— only `signingSecret` and a start node's `secret` are withheld — so
never a credential there; routed by shape — a header credential → a
declarative connector (`bearer` / `basic` / `api-key`) with
`auth.credentialRef`; a query-string key → `api-key` with `paramName`; a
path-secret webhook url → a token-authenticated connector such as
`slack` — called via `connector_action`. The same row carries the
`timeoutMs` lesson that used to live only in the example's `http` node
(the executor arms a timer only when `timeoutMs` is set —
`packages/services/service-automation/src/builtin/http-nodes.ts:281`).
- The `script` note's dispatch sentence routes Slack to
`connector_action` on the `slack` connector instead of "or `http`
webhook".
- The CRM Blueprint's lead sentence carries the metadata-first rule —
"Default approach for metadata apps — model the business lifecycle in
Flow/Approval metadata first, reserve custom code for edge-case
integrations — in this CRM-style structure:" — because that rule had no
other home in the skill.
- Removed as token payment (content with a home elsewhere or redundant
in place, never a re-wrap): the `http_request` alias clause on the
`http` row — the clause was accurate: the ADR-0087 conversion
`flow-node-http-callout-rename`
(`packages/spec/src/conversions/registry.ts:58`) still rewrites
`http_request` / `http_call` / `webhook` to `http` on build/validate
even though the node-type enum
(`packages/spec/src/automation/flow.zod.ts:41`) names only `http`; the
skill teaches the canonical `http` and the alias needs no author action,
so the deletion stands; the `FlowNodeAction` seed-set aside; the
engine-internal `resolveTriggerBinding` name; the trigger-intro clause
that duplicated the Trigger Types table's ObjectQL-hook column; the "It
is not a way past a guardrail" one-liner that duplicated the paragraph
under the routing table; the three-line `previous` / `record` blockquote
reduced to a one-line pointer at objectstack-formula §5
(`skills/objectstack-formula/SKILL.md:283-296` carries it); the word
"verbatim" in the three moved-to pointers; and word trims in four
sentences.
**`skills/objectstack-automation/references/examples-flows.md`**
- The `notify_manager` node is a `connector_action` on the `slack`
connector (`chat.postMessage`, `input: { channel, text }`) — the shape
`examples/app-showcase/src/automation/flows/index.ts:329-339` dispatches
and `packages/connectors/connector-slack/src/slack-connector.ts:100-114`
declares. A three-line comment says why it is not an `http` node with a
webhook url. The block keeps its `os:check` marker and type-checks
(readings below).
- Removed as token payment: the four-line schedule comment is two lines
of the same facts, and the `filter` comment that duplicated the
blockquote at the top of the file.
Wording matches the landed sources: the `HttpConfigSchema.headers`
describe (`packages/spec/src/automation/io-node-config.zod.ts:363-370`,
the #20654 describe the dispatch could not locate; its sibling for
`connectorConfig.input` is `flow.zod.ts:628-634`), the `http` node
descriptor describes
(`packages/services/service-automation/src/builtin/http-nodes.ts:111-133`)
and the flows guide callout (`content/docs/automation/flows.mdx:274`,
whose "Only `signingSecret` (and a start node's `secret`) is withheld"
and "`bearer`, `basic` or `api-key`" the row now matches; the redaction
paths are `packages/metadata-protocol/src/metadata-redaction.ts:427` /
`:477` / `:521`). Per the wording guard on the card, no sentence routes
a path-secret webhook url to `auth.credentialRef`.
Not touched, by the card's serial constraint: SKILL.md's `api` trigger
row and the inbound-webhook `secret` row are #20569's; #20569 remains
open.
## `skills/**` readings
Tokens are `scripts/check-skills-token-ratchet.mjs` readings (ceil of
utf8 bytes / 4); lines are `wc -l`. Before = `c9c182ed`, after =
`6b3450a0` (the `skills/**` bytes are identical at `7d4fcc50`).
| File | Lines before → after | Tokens before → after (ceiling) |
|---|---|---|
| `skills/objectstack-automation/SKILL.md` | 448 → 439 | 5785 → 5777
(5785, headroom 8) |
| `skills/objectstack-automation/references/examples-flows.md` | 136 →
135 | 1436 → 1426 (1436, headroom 10) |
| Whole package — every `skills/**/SKILL.md` | 4404 → 4395 | ratcheted
authored total 143347 → 143329 |
| Whole package — every `SKILL.md` plus the touched reference file |
4540 → 4530 (net −10 against the PM's +4 budget) | bundle total 153900 →
153882 |
No ceiling row moved. `evals/flows-triggers-approvals.json` is untouched
(1255 / 1255).
## Verification (all on head `6b3450a0`; exit codes captured before any
pipe)
Head `6b3450a0` is `7d4fcc50` (the review-round commit) merged with
`origin/main` `91e8fa19`; the merge touched nothing under `skills/**`,
recorded no regen deferral, and the diff against `origin/main` is
exactly the two files above. The merge is the derivation tool's own
prescription: at `7d4fcc50` it reported a STALE TREE (`origin/main` had
moved to `eead9dcf` with `.github/workflows/release.yml` and
`scripts/release-pending-publish.mjs` changed, both inputs of derived
families).
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` (no paths) derived the same 25 commands at `b6041881`,
`7d4fcc50` and `6b3450a0`; all 25 ran on `6b3450a0` with exit 0,
recorded as `cmd :: exit N`, and `dispatch-gates --ran` answers "25
derived families accounted for — 25 run, 0 NOT-MEASURED" with no
stale-tree warning: `check-ci-filter-parity`,
`check-closing-keyword-parity` (+ `--self-test`),
`check-comment-mask-corpus`, `check-doc-route-spelling --advisory` (+
`--self-test`), `check-skills-token-ratchet` (+ `--self-test`), lint
`check:doc-formula-expressions`, spec `check:skill-docs`, spec
`check:skill-refs`, root `check:agent-test-spelling`,
`check:corpus-claim-drift`, `check:cross-package-test-inputs`,
`check:doc-authoring`, `check:driver-memory-census`,
`check:gitlink-declared`, `check:nul-bytes`, `check:pm-governed-merges`,
`check:refd-timer-probe`, `check:role-word`,
`check:skill-compatibility`, `check:skill-frame-sync`,
`check:skill-identifier-liveness`, `check:watch-hint-literal`. The same
25 also ran on `7d4fcc50`, all exit 0.
- Implicated beyond the derived list: spec `check:skill-examples` (the
edited example carries an `os:check` marker): exit 0 on `6b3450a0` —
"259 prose examples type-check across 3 surface(s) — every marked block
parsed, so tsc ran the SEMANTIC pass on all of them" (skills + docs
surface: 225 blocks), after `turbo run build --filter=@objectstack/spec
--filter=@objectstack/formula --filter=@objectstack/lint
--filter=@objectstack/client --filter=@objectstack/client-react` under
the verify lock.
- Ablation of the edited block, both legs through
`scripts/ablation-replace.mjs`, run at `b6041881` on the
`examples-flows.md` blob `6e725a55` — the same blob at `6b3450a0`, so
the reading stands (anchor hit 1 → 0 on disk, blob hash changed,
restored to the `HEAD` blob with `git diff HEAD` empty; no build step
involved because the checker reads the markdown itself):
- `actionId:` → `actionIdX:` inside `connectorConfig`: exit 1 —
`examples-flows.md:56:9 error TS2561: Object literal may only specify
known properties, but 'actionIdX' does not exist in type '{ connectorId:
string; actionId: string; input?: ... }'` (the `input` type is a Record
of string to unknown, spelled in words here because the platform eats
angle-bracket fragments). The block's `connectorConfig` shape is
measured.
- `type: 'connector_action'` → `type: 'connector_actionX'`: exit 0,
still 259 green. The node `type` string is not constrained by the
type-check (plugin-registered node types such as `approval` mean it
admits any string), so that half of the example rests on the showcase
app and the spec enum, not on this gate. Reported as observed.
- A control-character grep (the C0 range and DEL) over both touched
files: no match. No HTML comment and no angle-bracket fragment is added
by this diff.
- `check:skill-docs` / `check:skill-refs` are green without
regeneration: the frontmatter is unchanged, so no generated artifact
moved.
## Changeset
`skip-changeset`, measured: `git grep -n -w skills -- '*/package.json'`
→ 0 hits at `6b3450a0` (positive control: `git grep -n '"files"' --
'packages/*/package.json'` hits `packages/adapters/hono`,
`packages/apps/account`, `packages/apps/setup`), so nothing under
`skills/**` ships in any released package's `files[]`. Precedent: the
last skills-only PR that touched these files (#19738) carried the same
label.
## Acceptance notes
- `SKILL.md` `:216` (a reference outside a filter — message body, `http`
url, write payload — renders an empty string) is a
template-interpolation statement, not a credential statement; left as
is, the `http` row carries the steer.
- The eval `evals/flows-triggers-approvals.json:47` expects an `http`
node to set `timeoutMs`; that lesson now lives on the `http` row (it
left the example when the node became a `connector_action`).
- `content/docs/automation/flows.mdx:274`, which the services seat's
wording guard said carried an over-reach, already routes by shape on
`main` at `c9c182ed`; nothing to correct, and this PR does not touch it.
- Noted, not filed: `check:doc-formula-expressions` and
`check:skill-examples` each refuse (exit 3) on a fresh worktree until
their producer packages are built; both say so loudly and name the
build. Working as designed.
## 维护者速读(草稿)
**改了什么**:`objectstack-automation` 技能的 `http` 节点行现在说明:flow 定义(含 `http`
节点的 `url` 与 `headers`)会原样提供给所有能读 flow 的成员——只有 `signingSecret` 与 start
节点的 `secret` 会被隐去——因此凭据不能写在那里;并按凭据所在位置给出去向:请求头凭据 → 声明式 connector 的
`auth.credentialRef`(`bearer` / `basic` / `api-key`),查询串密钥 → `api-key` 的
`paramName`,路径即密钥的 webhook → 带 token 的 connector(如 `slack`),再用
`connector_action` 调用。长示例里的 Slack incoming-webhook url 换成了 `slack`
connector 的 `chat.postMessage`,与 showcase
示例应用的写法一致。「元数据优先、自定义代码只留给边缘集成」这条规则并入了 CRM 蓝图的首句(它在技能里没有别的落脚点)。为守住 token
上限,删掉的都是别处已有归属或原地重复的内容(如 `previous` / `record` 的说明缩成指向
objectstack-formula §5 的一行)。
**为什么改**:这是 #20590 家族的技能面。AI 作者直接从这份技能复制,原示例教的是把秘密写进 url;spec
描述、运行时描述与文档已在别的 PR 落地同一措辞,技能面是最后一块。
**风险与代价(含回滚)**:纯文档改动,不动运行时、不发布任何包(`skip-changeset` 已实测)。示例块经
`check:skill-examples` 类型检查通过,并用消融证明 `connectorConfig` 的形状确实在检。SKILL.md
剩余 token 余量为 8,下一张改此文件的卡(#20569)仍需自付 token。回滚即 revert 本 PR,无迁移。
**席位意见**:(留空)
**你要做的**:`skills/**` 是 Tier H 受管面——需要维护者的 APPROVED review 后由席位落地;本 PR 保持
draft,不进队列、不开 auto-merge。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg)_
---------
Co-authored-by: os-warren <warren@objectstack.ai>
Co-authored-by: Claude <noreply@anthropic.com>1 parent 4b4ee88 commit 7a09eee
2 files changed
Lines changed: 30 additions & 40 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
42 | | - | |
| 41 | + | |
43 | 42 | | |
44 | 43 | | |
45 | 44 | | |
| |||
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
56 | | - | |
57 | | - | |
| 55 | + | |
| 56 | + | |
58 | 57 | | |
59 | 58 | | |
60 | 59 | | |
| |||
85 | 84 | | |
86 | 85 | | |
87 | 86 | | |
88 | | - | |
| 87 | + | |
89 | 88 | | |
90 | 89 | | |
91 | 90 | | |
| |||
140 | 139 | | |
141 | 140 | | |
142 | 141 | | |
143 | | - | |
| 142 | + | |
144 | 143 | | |
145 | 144 | | |
146 | 145 | | |
| |||
154 | 153 | | |
155 | 154 | | |
156 | 155 | | |
157 | | - | |
158 | | - | |
159 | 156 | | |
160 | 157 | | |
161 | 158 | | |
| |||
221 | 218 | | |
222 | 219 | | |
223 | 220 | | |
224 | | - | |
225 | | - | |
226 | | - | |
| 221 | + | |
| 222 | + | |
227 | 223 | | |
228 | 224 | | |
229 | 225 | | |
| |||
256 | 252 | | |
257 | 253 | | |
258 | 254 | | |
259 | | - | |
| 255 | + | |
260 | 256 | | |
261 | 257 | | |
262 | 258 | | |
| |||
309 | 305 | | |
310 | 306 | | |
311 | 307 | | |
312 | | - | |
| 308 | + | |
313 | 309 | | |
314 | 310 | | |
315 | 311 | | |
316 | 312 | | |
317 | 313 | | |
318 | 314 | | |
319 | 315 | | |
320 | | - | |
321 | | - | |
322 | | - | |
| 316 | + | |
323 | 317 | | |
324 | 318 | | |
325 | 319 | | |
| |||
396 | 390 | | |
397 | 391 | | |
398 | 392 | | |
399 | | - | |
400 | | - | |
401 | | - | |
| 393 | + | |
| 394 | + | |
402 | 395 | | |
403 | | - | |
| 396 | + | |
404 | 397 | | |
405 | 398 | | |
406 | 399 | | |
407 | 400 | | |
408 | 401 | | |
409 | | - | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
410 | 405 | | |
411 | 406 | | |
412 | 407 | | |
413 | 408 | | |
414 | 409 | | |
415 | 410 | | |
416 | 411 | | |
417 | | - | |
418 | | - | |
419 | | - | |
420 | 412 | | |
421 | 413 | | |
422 | 414 | | |
| |||
432 | 424 | | |
433 | 425 | | |
434 | 426 | | |
435 | | - | |
| 427 | + | |
436 | 428 | | |
437 | 429 | | |
438 | 430 | | |
| |||
441 | 433 | | |
442 | 434 | | |
443 | 435 | | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
448 | 439 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
| 29 | + | |
| 30 | + | |
33 | 31 | | |
34 | 32 | | |
35 | 33 | | |
| |||
38 | 36 | | |
39 | 37 | | |
40 | 38 | | |
41 | | - | |
42 | 39 | | |
43 | 40 | | |
44 | 41 | | |
| |||
49 | 46 | | |
50 | 47 | | |
51 | 48 | | |
52 | | - | |
| 49 | + | |
53 | 50 | | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
59 | 58 | | |
60 | 59 | | |
61 | 60 | | |
| |||
0 commit comments