Repository navigation
feat(spec): a flow step log declares the warnings and droppedFields the run history already serves - #33368
Conversation
The run-history routes serve each step the engine wrote, and the engine writes both members on a step that ran; the published step-log schema now names them (optional; strings, and the data engine's own drop event). The engine copies them onto the step only in that declared shape, so a host executor's malformed value is no longer persisted and served as-is. Claude-Session: https://claude.ai/code/session_01FEkQ5ps2JcdASVedaYorBN Co-Authored-By: Claude <noreply@anthropic.com>
…l index, add changeset The new import edge from automation/execution.zod.ts to the data engine's event would have dragged five pointers into the objectstack-automation skill index; an allowlist row holds it at the pointers it already published. Claude-Session: https://claude.ai/code/session_01FEkQ5ps2JcdASVedaYorBN Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift Check3 anchor(s) derived from 2 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 172 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 34a2d175ba1993d7fc4401cd6cac67f17d6a2304 && git checkout 34a2d175ba1993d7fc4401cd6cac67f17d6a2304
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d3f3f4abf9f392a49fecf77f2175424fe1680bef e84915df95f561a7a9b57598ff75d4bd1a119d0c && git checkout -B drift-repro d3f3f4abf9f392a49fecf77f2175424fe1680bef && git merge --no-ff e84915df95f561a7a9b57598ff75d4bd1a119d0c
node scripts/docs-audit/affected-docs.mjs --json d3f3f4abf9f392a49fecf77f2175424fe1680bef |
|
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag Contract reviewServed-tier: Inputs read: card #33020 (body and all 5 comments: triage 6844423823, added nit 6846941860, claim 6880781482, amendment 6880933599, os-dev-report 6881607020), PR #33368 (body, 8-file list, net diff against merge-base ① Derived judgments
② Semver levelClause-②: yes (widening), on the PR body and on the changeset body;
③ Boundary flags
④ Design judgment
Findings:
No must-fix, no should-fix. Nits alone end the round. Implemented-by: VERDICT: PASS |
|
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag ACCEPT · PR #33368 (#33020) · head
|
Requested by Leehom · project thread
Fixes #33020
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: none — the step log is a run record the engine writes and the run-history routes serve, not a key a metadata author writes; no published skill or docs page lists step-log members (grep of
skills/andcontent/docs/automation/flows.mdx: 0 member listings), so nothing teaches it维护者速读
ExecutionStepLogSchema) 新增两个可选字段:warnings(字符串数组)和droppedFields(数据引擎自己的「字段被丢弃」事件数组,复用已有的DroppedFieldsEventSchema)。引擎写步骤日志时只按这个声明的形状写:宿主注册的执行器返回的畸形值不再原样落进运行记录。GET /api/v1/automation/:name/runs/:runId与运行列表) 原样返回,但发布的 schema 一个都没声明;按 schema 解析的读者会把它们剥掉,分不清「部分字段没写进去」的步骤和干净成功的步骤。席位裁定走「声明」而非「从接口里剔除」。@objectstack/specminor,@objectstack/service-automationpatch。内置写节点产出的值本来就合规,步骤内容不变;只有宿主执行器的畸形元素被跳过。回滚即 revert。packages/spec/src/automation/execution.zod.ts新增两个成员;②packages/services/service-automation/src/dag-traversal.ts的stepAdvisoriesOf及两处调用;③packages/spec/scripts/lib/skill-map-guards.ts新增的objectstack-automation白名单行(防止新的 import 边把 5 个无关指针拖进技能索引)。pnpm --filter @objectstack/service-automation exec vitest run src/run-dropped-fields.test.ts,预期 22 个测试全绿,其中新 describe「the step log carries the advisory members only in the declared shape」4 条。What changes
ExecutionStepLogSchema(packages/spec/src/automation/execution.zod.ts): two optional members,warnings: string[]anddroppedFields: DroppedFieldsEvent[](the exportedDroppedFieldsEventSchemafromdata/data-engine.zod.ts, imported, no second copy). Measured: the producer writeswarningsasstring[](NodeExecutionResult.warnings,StepLogEntry.warningsinengine.ts), so it is declared as strings.ExecutionLogSchema.stepsembeds the step log, andGetRunResponseSchema(GET /api/v1/automation/:name/runs/:runId,data: ExecutionLogSchema) andListRunsResponseSchema(data.runs: ExecutionLogSchema[]) embed that. No other spec schema referencesExecutionStepLogSchemaorExecutionLogSchema.automation-api.zod.tsandexport.zod.tsimportDroppedFieldsEventSchemafor their own members and are unchanged.packages/services/service-automation/src/dag-traversal.ts, the card's added nit): both step pushes (the failure step and the success step) used to copyresult.droppedFieldsandresult.warningswhenever they had a truthylength. They now go through one module-localstepAdvisoriesOf(result):droppedFieldskeeps each element that is a well-typedDroppedFieldsEventSchemaevent (the same per-element filterfoldDropEventsapplies to the run's terminal answer),warningskeeps its string entries, and a member with nothing well-typed left is omitted, never[]. Total: it never throws inside the step'stry. This is the member's first producer-side guard (D5), in@objectstack/service-automation.warningshalf is taken under os-dev rule 3's bounded in-place exemption: same defect class as the nit (a host value served as-is on a member the spec now declares), mechanical, same file, same gate family. The seat amended the claim to include it (comment 6880933599).packages/spec/authorable-surface/automation.json(+ExecutionStepLog:droppedFields, +ExecutionStepLog:warnings) andcontent/docs/references/automation/execution.mdx, both frompnpm --filter @objectstack/spec check:generated --fix.packages/spec/scripts/lib/skill-map-guards.ts): the new import edgeautomation/execution.zod.ts→data/data-engine.zod.tsmadegen:skill-refsadd five transitive pointers (data-engine,filter,query,execution-context,explain) toskills/objectstack-automation/references/_index.md, which the objectstack-automation SKILL.md does not teach. ATRANSITIVE_ALLOWLISTrow forobjectstack-automationholds the index at the 17 transitive pointers it already published (the same recipe as theobjectstack-apirow), soskills/**is byte-identical and this PR touches no governed surface..changeset/33020-step-log-advisory-members.md:@objectstack/specminor,@objectstack/service-automationpatch.Declaration lines (deviation from the original claim, amended by the seat)
The claim first carried
Metadata-protocol: none. The two members move theauthorable-surface/automation.jsonshard (the step log is in the authorable census), andcheck-changeset-no-majorrefusesnoneover a moved shard (verdictnone-baseline-moved). So the body and changeset declareadded, specminor, per AGENTS.md Post-Task Checklist step 3. The seat amended the claim (comment 6880933599).Tests
packages/spec/src/automation/execution.test.ts, newdescribe('warnings / droppedFields')(5 pins): a step carrying both members parses and keeps them; a step without either still parses and neither is invented;ExecutionLogSchema.steps(what the run-history routes serve) keeps both; adroppedFieldselement off the event's shape is refused at['droppedFields', 0, 'reason']; a non-string warning is refused at['warnings', 0].packages/services/service-automation/src/run-dropped-fields.test.ts, newdescribe('the step log carries the advisory members only in the declared shape')(4 pins, read throughengine.listRuns): a host executor's malformeddroppedFieldselements and non-string warnings are not copied onto its success step while the well-typed ones are, and the step parses underExecutionStepLogSchema; the failure step applies the same filter; an array-like value (truthylength, not a list) leaves neither member; control: the in-treeupdate_recordstep's well-typed members reach it unchanged.Ablations (each leg via scripts/ablation-replace.mjs, mutation proven on disk, restored to the HEAD blob)
lengthcopy:× a host executor's malformed elements are not copied onto its success step …,× a value that is not a list at all …— Tests 2 failed, 20 passed. Restored: blob == HEAD93aab66eda92,git diff HEADempty.× a failure step applies the same filter— Tests 1 failed, 21 passed. Restored likewise.droppedFieldsmember renamed away:× a step carrying both members parses and keeps them,× the run log a run-history route serves keeps both members on its steps,× droppedFields is the data engine's own event …— Tests 3 failed, 51 passed. Restored: blob == HEADeeb6fde232c0.The service-automation suite imports
dag-traversal.tsfromsrc/(relative), and the spec suite imports./execution.zod, so nodist/sits between the mutation and the test.Acceptance notes
packages/services/service-automation/src/builtin/region-index-keys.test.tsholds the engine'sStepLogEntryand the spec'sExecutionStepLogin step for the region keys only; its comment nameswarningsas an engine-local field the contract does not carry, which this PR makes stale. Extending that type-level pin towarnings/droppedFieldsis outside the claim's file surface; noted for the seat (carrier: none).content/docs/automation/flows.mdxdescribessteps[]without listing members, so no docs page changes.Verification
Local gates on head
e84915df(base24f2f401;origin/mainhas since moved tod3f3f4ab, and none of its new commits touch a file this PR changes): 115 derived bydispatch-gates --commands(8 paths, 266 changed lines), each run with its exit code captured before any pipe; 114 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads, exit 3 PREREQUISITE NOT MET: it needs every package'sdist, which CI builds).check:skill-examplesfirst exited 3 (the client SDKdistwas not built), then 0 after building@objectstack/clientand@objectstack/client-react(344 prose examples type-check).--ranreconciles 115 accounted, 114 run, 1 NOT-MEASURED, 0 UNRUN.Package suites and replayed changeset gates
pnpm --filter @objectstack/spec test: Test Files 840 passed (840), Tests 26837 passed, 1 todo.pnpm --filter @objectstack/spec typecheck: exit 0.pnpm --filter @objectstack/service-automation test: Test Files 281 passed (281), Tests 3893 passed.pnpm --filter @objectstack/service-automation typecheck: exit 0 (it compilessrc/**/*.test.ts, including the type-level pin inregion-index-keys.test.ts).pnpm --filter @objectstack/spec check:generated: after--fix, all 14 artifacts up to date; the skills index is unchanged.check-changeset-no-major,check-empty-changesetandcheck-adr-0087-registrationreplayed withGITHUB_EVENT_NAME=pull_requestand this body: exit 0 each (Clause-②: yes (widening),Metadata-protocol: added, specminor).Full list: the card's
os-dev-report. CI runs the full set.Generated by Claude Code