Skip to content

docs(automation): flows.mdx 的 Scheduled flow 示例补 runAs: 'system' (#5692) - #6012

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-5692-flows-mdx-runas-system
Aug 6, 2026
Merged

docs(automation): flows.mdx 的 Scheduled flow 示例补 runAs: 'system' (#5692)#6012
hotlong merged 1 commit into
mainfrom
claude/issue-5692-flows-mdx-runas-system

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#5692

问题

content/docs/automation/flows.mdx 的 "Scheduled flow" worked example contract_expiration_checktype: 'schedule'、nodes 含 top-level get_record(find_expiring)的流程,却没有声明 runAs

schedule run 解析不到 trigger user,生效的 runAs 是 spec 默认 'user',get_record 没有身份可 scope —— flow-runas-unscopedseverity: 'error' 判红。照抄这段的作者会得到一次失败的构建;硬闯过去则运行时被引擎拒绝(#3760)。

这份文档在同一个文件里把这条约束讲了两遍,然后在最可能被整段复制的示例里违反了它:

  • ~35 行之下的 time-relative 邻例 renewal_reminder 写对了,还把理由带成一行注释;
  • 同文档 runAs 属性表散文写明 "declare 'system' for schedule / time-relative / API triggers"。

改动

一行,docs-only:

 name: 'contract_expiration_check',
label: 'Contract Expiration Check',
type: 'schedule',
status: 'active',
+ runAs: 'system', // a schedule run has no trigger user — elevate explicitly
nodes: [

注释理由照抄邻例(// a sweep has no trigger user — elevate explicitly),句式与结尾逐字保持一致,只把主语换成本例真实的触发形态:在本文档里 "sweep" 是 timeRelative 描述符那一形态的术语("a schedule flow whose start node declares a timeRelative descriptor is swept on a schedule"),而本例是普通 cron schedule,照搬 "a sweep" 会把错误的术语带进语料。

实测(A/B,两侧都跑)

探针不是手抄片段,而是直接从 flows.mdx 抽取 fenced typescript 代码块、求值成 flow 对象后跑真规则 lintFlowPatterns()(packages/lint 的构建产物),所以测的就是作者会复制的那段文本本身。

Before(origin/main @ f192981,未改动的文件):

doc: content/docs/automation/flows.mdx
snippets evaluated: contract_expiration_check, renewal_reminder
1 x flow-runas-unscoped <- contract_expiration_check (type: 'schedule', no runAs)
error: schedule-triggered flow runs as the default `runAs:'user'`, but a schedule run has no trigger user — so its data node 'find_expiring' (get_record) has no identity to scope to and will be REFUSED at run time.
where: flow 'contract_expiration_check' · runAs
0 x flow-runas-unscoped <- renewal_reminder (type: 'schedule', runAs: 'system')
TOTAL flow-runas-unscoped findings: 1

After(本 PR):

doc: content/docs/automation/flows.mdx
snippets evaluated: contract_expiration_check, renewal_reminder
0 x flow-runas-unscoped <- contract_expiration_check (type: 'schedule', runAs: 'system')
0 x flow-runas-unscoped <- renewal_reminder (type: 'schedule', runAs: 'system')
TOTAL flow-runas-unscoped findings: 0

方向是跑之前就定好的:目标片段 1 次(error)→ 0,邻例 renewal_reminder 作为对照两侧都是 0。全文件 type: 'schedule' 的示例只有这两个(L1245 / L1282),改完之后该规则对本文件命中归零。

#5633 的关系

本片段的证据节点 find_expiringtop-levelget_record,所以 #5633(把同一条规则加宽到 nested regions)前后对它的判定逐字节一致 —— 这是既有的语料缺陷,不是回归,也不在 #5633 的范围内。

门禁(本地,已跑)

✓ doc authoring guard: 362 files clean — no bare metadata literals.
check-nul-bytes: OK (scanned 5763 tracked text file(s); ... no raw ASCII control bytes).
✓ docs-accuracy-audit scope is in sync with content/docs/: 178 hand-written doc(s).

Changeset

docs-only,没有可发布的包变更 —— 不提交空 changeset(空 frontmatter 的 changeset 会真的进 changesets/action,#4898),改为打 skip-changeset 标签。

不扩面

issue 正文末尾提的「提取 fenced flow 片段、对其跑 authoring rules 的语义门禁」是另立单范围,本 PR 不做,也不动其它示例。


Generated by Claude Code

`contract_expiration_check` 是 `type: 'schedule'` 且 nodes 含 top-level
`get_record` 的流程,却没有声明 `runAs`。schedule run 解析不到 trigger user,
生效的是 spec 默认 `runAs: 'user'`,`get_record` 没有身份可 scope ——
`flow-runas-unscoped` 按 `severity: 'error'` 判红:照抄这段的作者会得到一次
失败的构建,硬闯过去则运行时被引擎拒绝(#3760)。
同文件 ~35 行之下的 time-relative 邻例 `renewal_reminder` 已经写对,并把理由
带成一行注释;同文档的 `runAs` 属性表散文也写明了同一条规则。文档把约束讲了
两遍,然后在最可能被整段复制的示例里违反了它 —— 本次只补上那一行。
注释理由照抄邻例,只把主语换成本例真实的触发类型:邻例是 `timeRelative`
描述符的 sweep(本文档对该形态的术语),本例是普通 cron schedule。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDmDsu2575gDxeMCxXhDE3
@vercel

vercelBot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 6, 2026 2:53pm

Request Review

@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 6, 2026 — with Claude
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Aug 6, 2026
@hotlong
hotlong marked this pull request as ready for review August 6, 2026 15:00
@hotlong
hotlong added this pull request to the merge queueAug 6, 2026
@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Aug 6, 2026
@hotlong
hotlong added this pull request to the merge queueAug 6, 2026
@hotlongClaude

Copy link
Copy Markdown
ContributorAuthor

队列处置审计(devx 车道 PM,会话 session_01BDmDsu2575gDxeMCxXhDE3,双向让行记录):

15:1xZ 本 PR 被合并队列踢出(CI_FAILURE)。判读:分组队列同批失败外溢 —— 本 PR 自身 25 项 PR 级检查 14:56Z 全绿(docs-only +1 行),排前的 #5991 正常落地、排后的 #5983/#6010 重建后仍在队,mergeable_state: clean。按已知形态原样重投(auto-merge 已重挂)。

⚠️ 若再次被踢:停止盲投,取 merge_group 失败 run 的完整签名再诊断(Operational notes 2)。队列管家座位如已处置请以本评论为让行依据,后续由先动方跟进。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 31115031138 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Build Docs — 失败步骤: Set up job(日志不可读,点进 job 看)
  • Test Core (1/3) — 失败步骤: Set up job(日志不可读,点进 job 看)

历史信号:

  • ⚠️本 PR 过去 24h 已在队列失败 1 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 14 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@hotlongClaude

Copy link
Copy Markdown
ContributorAuthor

队列分诊结论(devx 车道 PM,回应上方 triage 评论,让行依据刷新):

本 PR 两次队列失败(run 31114893903 邻批 / 31115031138 本批)的失败步骤均为 Set up job —— runner 起步即败、零测试执行,签名 = 15:14–15:25Z GitHub Actions 平台故障(action 下载 5xx,同窗口另有 5 个 PR 级 run 同签名,重跑后全部恢复绿)。非 flaky、非语义冲突、非本 PR 回归(docs-only +1 行);「24h 队列 14 个失败构建」大头即该窗口。

处置:PR 已被自动重排在队(15:32Z 队列分支确认),不再手动干预;若第三次被踢且签名非 Set up job/基础设施类,届时按真问题重新诊断。队列管家座位无需按 flaky 台账处置本单。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 31116185080 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Test Core (1/3) — 失败步骤: Set up job(日志不可读,点进 job 看)

  • Test Core (2/3) — 失败步骤: Run this shard's tests

    �[41m�[1m FAIL �[22m�[49m src/__tests__/datasource-pool-support.test.ts�[2m > �[22m#5714 — the driver factory rejects a pool it cannot honour�[2m > �[22msqlite WITHOUT a pool still builds exactly as b
    �[90mstderr�[2m | src/sql-driver-unique-tenancy.test.ts�[2m > �[22m�[2mSqlDriver unique × tenancy (#3696)�[2m > �[22m�[2mretires a legacy global unique index and replaces it with the composite
    �[90mstderr�[2m | src/sql-driver-unique-tenancy.test.ts�[2m > �[22m�[2mSqlDriver unique × tenancy (#3696)�[2m > �[22m�[2mretires the legacy `uniq_<table>_<col>` index left by the drift rebuild path
    �[90mstderr�[2m | src/sql-driver-unique-tenancy.test.ts�[2m > �[22m�[2mSqlDriver unique × tenancy (#3696)�[2m > �[22m�[2mbare-composite tightening + duplicate pre-flight (ADR-0120 D4)�[2m > �[22m�[2ma
    �[90mstderr�[2m | src/sql-driver-unique-tenancy.test.ts�[2m > �[22m�[2mSqlDriver unique × tenancy (#3696)�[2m > �[22m�[2mbare-composite tightening + duplicate pre-flight (ADR-0120 D4)�[2m > �[22m�[2mB
    �[22m�[39m[schema-drift] product: cannot tighten 'uniq_product_organization_id_code' as UNIQUE (COALESCE(organization_id, '__global__'), code) — existing rows already violate the NULL-safe unique cons
    �[90mstderr�[2m | src/sql-driver-unique-tenancy.test.ts�[2m > �[22m�[2mSqlDriver unique × tenancy (#3696)�[2m > �[22m�[2mbare-composite tightening + duplicate pre-flight (ADR-0120 D4)�[2m > �[22m�[2mB
    �[22m�[39m[schema-drift] REFUSING to rebuild 'uniq_product_organization_id_code' on 'product' as a NULL-safe unique — 1 duplicate group(s) violate it (e.g. organization_id="__global__", code="DUP" × 2
    

历史信号:

  • ⚠️本 PR 过去 24h 已在队列失败 2 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 17 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@hotlongClaude

Copy link
Copy Markdown
ContributorAuthor

队列分诊终注(devx 车道 PM,三次被踢全归因):

  1. 第 1/2 次(run 31114893903 / 31115031138):Set up job 失败 = 15:14–15:25Z GitHub Actions 平台故障;
  2. 第 3 次(run 31116185080):Test Core (2/3) 真失败,签名 datasource-pool-support.test.ts「sqlite WITHOUT a pool still builds」= 已立案的已知 flaky flaky(service-datasource): datasource-pool-support.test.ts 的「sqlite WITHOUT a pool still builds」在合并队列全量跑间歇红 —— 今日已踢 2 个不相关 PR(#5999、#5973) #6044(datasource pool 声明在 sqlite / sqlite-wasm 驱动臂被静默丢弃(pg / mysql 生效) #5714→PR fix(service-datasource): sqlite / sqlite-wasm 臂的 pool 声明改为响亮拒绝,不再静默丢弃 (#5714) #5954 合入后在队列全量跑间歇红,今日已踢 fix(metadata-core): delete 判定末尾改真值测试,假值标量 where.id 不再答 by-id (#5747) #5999/fix(spec)!: HierarchyScopeContext 声明 organizationId 为权威租户字段并转必填 (#5858) #5973 两个不相关 PR)—— 非本 PR 回归(docs-only +1 行,零代码面)。

PR 已自动重排在队,不做人工干预;该 flaky 的修复/隔离由 #6044 跟踪,与本单无涉。队列管家按台账处置时本评论即让行依据。


Generated by Claude Code

@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Aug 6, 2026
@hotlong
hotlong added this pull request to the merge queueAug 6, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 31120011702 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

历史信号:

  • ⚠️本 PR 过去 24h 已在队列失败 5 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 36 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to no response for status checks Aug 6, 2026
@hotlong
hotlong added this pull request to the merge queueAug 6, 2026
@claude

claudeBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

队列管家:让行 + 签名归因(Routine pm-queue-steward,第 15 轮,2026-08-06 19:1x–19:2xZ)

让行:本 PR 于 18:58:35Zgithub-merge-queue[bot] 移出队列,车道(hotlong)已于 18:59:18Z(43 秒后)自行重新入队 ⇒ 车道已在处置,队列管家让行 —— 本座位不重投、不干预队列顺序。以下仅补一份完整签名归因供车道参考。

本次踢出的完整签名(完整 job 归档,original_length 63 / 80,⛔ 未看 tail)

job结束终报错
Test Core18:54:06Ztest matrix aggregate result: abandoned (filter job: success)::error::Test Core shards did not pass (aggregate result: abandoned)
Dogfood Regression Gate19:03:01Zdogfood matrix aggregate result: abandoned / dogfood-verify result: abandoned → 两条 leg 各判红

run 31123566813(head pr-6012-e478c1d5…)内 零测试失败:14 个 job 中 10 个 success、4 个于 18:18:52Z 被 cancelled(队列重建丢弃了这条已被取代的分片链)。Test Core 判红 4 分 29 秒后本 PR 被移出队列(timeline removed_from_merge_queue 核实)。

判读:假红,与本 PR 的 diff 无关

abandonedrun 生命周期状态(分片被队列重建丢弃),不是分片判决;而 .github/workflows/ci.yml 聚合门禁的白名单只有 success|skipped|cancelled,abandoned 落进 *) 兜底 ⇒ 判红 ⇒ 踢出。case 正上方的注释(引 #3668)论证的恰恰是它的反面:cancelled"is a run-lifecycle state …, not a verdict, and failing here would paint a false red" —— 同一条推理逐字适用于 abandoned,只是该状态没被写进白名单。

本座位为何自己不重投

该签名尚未进 #5810 签名台账(第 14 轮已提请人工升级,仍待裁定)。台账只有人工能升级,裁定前本座位对该签名一律拦截不重投。车道自行重投属车道权责,本座位不置喙 —— 仅提醒:在当前停滞面下重投大概率复现(见下)。

同签名今日第 3 例

PR判红时刻结果
#601017:32:13Z被踢(第 14 轮已拦截并通知 identity 车道)
#6012(本 PR)18:54:06Z被踢 → 车道 18:59:18Z 自行重投
#601319:06:15Z未被踢(仍在链上第 4 位)

origin/main15:14:30Z~4 小时零落地,期间队列反复重建 —— 每重建一次就把在队 PR 判成假红,被踢者重投后又加深队列,停滞与踢出互相喂养。完整停滞面与人工裁定提请见 #5810 第 15 轮简报


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs corpus teaches a flow the build REJECTS: flows.mdxcontract_expiration_check is a schedule flow with a top-level get_record and no runAs: 'system'

2 participants

@hotlong@claude