docs(runtime,automation): document the run-lifecycle doors, and turn two ledger notes into a decision - #17038
Conversation
…two ledger notes into a decision content/docs/automation/flows.mdx and packages/services/service-automation/README.md list the run family's REST doors without POST .../cancel and .../restore-suspension, which PR #16755 shipped behind the PLATFORM_ADMIN posture rung (isSystem bypass). Both tables gain a row: the gate, the closed { reason? } body, and the 501-when-absent shape. route-ledger.ts's two notes carried two loose ends the contract review (comment 5587229770 on #16755) carried forward as non-blocking findings: - Both arms dispatch the verb with parts[2] (the run id) alone and never check the run belongs to flow parts[0] -- the existing, deliberate convention resume / screen / getRun already use on this domain. One clause per note says so, so the flow-scoped URL shape is not read as a scoping guarantee this door enforces. - Both notes said "adding one reclassifies this row to `sdk`" as open scope prose. The seat ruled on #16896 (comment 5595099733): client.automation.cancelRun / restoreSuspension stay unadded -- no operator has asked, and an inert SDK method is worse than an absent one (ADR-0078) -- reopening only when an operator or app repo asks for programmatic cancel/restore. Both notes now cite that decision by URL instead of restating the open question. No behaviour change; no new exported symbol, published-payload key, or spec path. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zTkyNHJ7TkuN2oXtP5x37
…tomation-run-lifecycle-doors-docs
…tomation-run-lifecycle-doors-docs
📓 Docs Drift CheckThis PR changes 2 package(s): 9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 27 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 2eb07df2eb7d2a9ba001248d3c4cfdebf0216108 && git checkout 2eb07df2eb7d2a9ba001248d3c4cfdebf0216108
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin de1a6114ad28e0493a0dd294fa68c4acee992c36 98d70c65505fcf8750cbaa291fed32bb90fcf971 && git checkout -B drift-repro de1a6114ad28e0493a0dd294fa68c4acee992c36 && git merge --no-ff 98d70c65505fcf8750cbaa291fed32bb90fcf971
node scripts/docs-audit/affected-docs.mjs --json de1a6114ad28e0493a0dd294fa68c4acee992c36
|
Fixes #16896
Three non-blocking findings carried out of the contract review of PR #16755 (comment 5587229770 on #16755), executed per the ruling in claim comment issuecomment-5595099733 on this card.
1. Docs route tables (F7/N2)
content/docs/automation/flows.mdx's run-family table andpackages/services/service-automation/README.md's REST API list both namedresume/screenwithout the two operator run-lifecycle doors PR #16755 shipped. Each gains a row forPOST /automation/:name/runs/:runId/canceland.../restore-suspension, naming the gate (PLATFORM_ADMINposture rung,isSystembypass), the closed{ reason? }body, and the501 NOT_IMPLEMENTED-when-absent shape. No table was restructured — same two columns in flows.mdx, same comment-per-line shape in the README.2.
:namescoping clause (F5/N5)Both route-ledger.ts notes (cancel, restore-suspension) now carry one clause each stating the existing, deliberate convention: both arms dispatch the verb with
parts[2](the run id) alone and never check that the run belongs to flowparts[0]— the same shaperesume/screen/getRunalready use on this domain. Stated as convention, not as a defect or TODO, per the claim's binding wording constraint. I did not find the convention itself to be wrong; no separate card is filed.3. SDK method — decided, not filed (F4/N4)
The claim ruled
client.automation.cancelRun/restoreSuspensionnot added; both ledger rows stayserver-only. Both notes' prose ("adding one reclassifies the row tosdk") is replaced with a citation of issuecomment-5595099733 on #16896 and carry its reopening condition in spirit: an operator or app repo asking for programmatic cancel/restore. No SDK card filed, no methods added.H-check, and its positive control
Card's check:
node scripts/docs-audit/affected-docs.mjson the head lists neitherflows.mdxnor the README as naming a route the tree does not document, androute-ledger.conformance.test.tsis green with the amended notes. Both hold.The mandated control — reported, not smoothed over: removing one of the two new rows does not turn either half of the H-check red.
restore-suspensionrow fromflows.mdx's table leavesnode scripts/docs-audit/affected-docs.mjs's output byte-for-byte unchanged (same summary line, same anchor list) — the tool detects code touched, doc not updated via literal/symbol/route anchors it can already see elsewhere in the same diff (PLATFORM_ADMINstill appears via the survivingcancelrow and the ledger note), not this specific route is listed in this specific table. It has no way to notice a row's absence.cancelROUTE_LEDGERentry (both lines) leavesroute-ledger.conformance.test.tsat 6/6 passing — its only assertions are domain-level (/automationstill has plenty of other rows) and per-row hygiene (a present row'snoteis non-empty); it was never designed to assert every documented route still has a ledger row.Both mutations were proven to land on disk (
grep -cbefore/after,git hash-objectdiffering from the HEAD blob) and were restored under a trap, confirmed by blob equality and an emptygit diff HEAD. Positive control did not fire on either half — this class of change (one of two new rows quietly dropped) is invisible to the named H-check, in both directions it names. Filed as an observation for the PM rather than a card of its own, since fixing the gate is outside this docs card's scope.Scope discipline
route-ledger.tsnote strings) changed.packages/services/service-automation/src/{engine,index,suspended-run-store,sys-automation-run.object}.tsand its two named test files were not touched.packages/spec/src/**path —Clause-②: noholds.content/docs/releases/**untouched.Changeset
None —
skip-changeset. This diff changes only hand-written docs (content/docs/automation/flows.mdx), a package README, and prose inside a non-exported, runtime-internal module (route-ledger.ts'snotefields — that file's own docblock states it is "not exported from the package index... the guard's data, not public API"). Nothing publishes from any released package. Same precedent as prior docs-only route-ledger note commits in this history (e.g. #10600, #16955), both landed with no changeset.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 73 commands on the fully merged tree. All 73 run; reconciliation:73 derived, 73 run, 0 NOT-MEASURED, 0 UNRUN. Four of the 73 initially failed asPREREQUISITE NOT MET-class (stale/missingdist/in this worktree, unrelated to this diff's content —check:skill-examples,check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure); a fullpnpm build(73/73 tasks) resolved all four to green, re-measured.check:route-envelopewas run explicitly (it sits in the deriver's Silent bucket, #16828) — green, unaffected since no route registration changed.🤖 Generated with Claude Code
https://claude.ai/code/session_012zTkyNHJ7TkuN2oXtP5x37
Generated by Claude Code