Skip to content

docs(runtime,automation): document the run-lifecycle doors, and turn two ledger notes into a decision - #17038

Merged
os-trump merged 3 commits into
mainfrom
claude/issue-16896-automation-run-lifecycle-doors-docs
Sep 9, 2026
Merged

docs(runtime,automation): document the run-lifecycle doors, and turn two ledger notes into a decision#17038
os-trump merged 3 commits into
mainfrom
claude/issue-16896-automation-run-lifecycle-doors-docs

Conversation

@os-trump

@os-trump os-trump commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

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 and packages/services/service-automation/README.md's REST API list both named resume / screen without the two operator run-lifecycle doors PR #16755 shipped. Each gains a row for POST /automation/:name/runs/:runId/cancel and .../restore-suspension, naming the gate (PLATFORM_ADMIN posture rung, isSystem bypass), the closed { reason? } body, and the 501 NOT_IMPLEMENTED-when-absent shape. No table was restructured — same two columns in flows.mdx, same comment-per-line shape in the README.

2. :name scoping 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 flow parts[0] — the same shape resume / screen / getRun already 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 / restoreSuspension not added; both ledger rows stay server-only. Both notes' prose ("adding one reclassifies the row to sdk") 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.mjs on the head lists neither flows.mdx nor the README as naming a route the tree does not document, and route-ledger.conformance.test.ts is 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.

  • Deleting the restore-suspension row from flows.mdx's table leaves node 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_ADMIN still appears via the surviving cancel row and the ledger note), not this specific route is listed in this specific table. It has no way to notice a row's absence.
  • Deleting the whole cancel ROUTE_LEDGER entry (both lines) leaves route-ledger.conformance.test.ts at 6/6 passing — its only assertions are domain-level (/automation still has plenty of other rows) and per-row hygiene (a present row's note is 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 -c before/after, git hash-object differing from the HEAD blob) and were restored under a trap, confirmed by blob equality and an empty git 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

  • No behaviour change: only prose (docs + route-ledger.ts note strings) changed. packages/services/service-automation/src/{engine,index,suspended-run-store,sys-automation-run.object}.ts and its two named test files were not touched.
  • No new exported symbol, published-payload key, or packages/spec/src/** path — Clause-②: no holds.
  • 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's note fields — 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/objectstack derived 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 as PREREQUISITE NOT MET-class (stale/missing dist/ 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 full pnpm build (73/73 tasks) resolved all four to green, re-measured. check:route-envelope was 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

…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
@os-trump os-trump added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 9, 2026 — with Claude
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/runtime, @objectstack/service-automation, touching 2 documentable anchor(s). ⚠️ 1 changed file(s) yielded no anchor (packages/services/service-automation/README.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/automation/flows.mdx (via PLATFORM_ADMIN (literal, a string literal in note))
  • content/docs/deployment/environment-variables.mdx (via PLATFORM_ADMIN (literal, a string literal in note))
  • content/docs/kernel/runtime-services/sharing-service.mdx (via platform_admin (literal, a string literal in note))
  • content/docs/permissions/authentication.mdx (via platform_admin (literal, a string literal in note))
  • content/docs/permissions/authorization.mdx (via PLATFORM_ADMIN (literal, a string literal in note), platform_admin (literal, a string literal in note))
  • content/docs/permissions/permission-metadata.mdx (via platform_admin (literal, a string literal in note))
  • content/docs/permissions/permission-sets.mdx (via PLATFORM_ADMIN (literal, a string literal in note))
  • content/docs/permissions/positions.mdx (via platform_admin (literal, a string literal in note))
  • content/docs/permissions/sharing-rules.mdx (via platform_admin (literal, a string literal in note))

4 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v14.mdx (via platform_admin (literal, a string literal in note))
  • content/docs/releases/v15.mdx (via PLATFORM_ADMIN (literal, a string literal in note))
  • content/docs/releases/v16.mdx (via PLATFORM_ADMIN (literal, a string literal in note))
  • content/docs/releases/v17.mdx (via PLATFORM_ADMIN (literal, a string literal in note))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/services/service-automation/README.md) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 27 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json de1a6114ad28e0493a0dd294fa68c4acee992c36packageMentionDocs.

Which tree this was computed on

This run read content/docs from 2eb07df2eb7d2a9ba001248d3c4cfdebf0216108 — the merge of head 98d70c65505fcf8750cbaa291fed32bb90fcf971 into base de1a6114ad28e0493a0dd294fa68c4acee992c36, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# 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

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs de1a6114ad28e0493a0dd294fa68c4acee992c36 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@os-trump
os-trump marked this pull request as ready for review September 9, 2026 04:42
@os-trump
os-trump enabled auto-merge September 9, 2026 04:42
@os-trump
os-trump added this pull request to the merge queue Sep 9, 2026
Merged via the queue into main with commit 6a7910a Sep 9, 2026
40 checks passed
@os-trump
os-trump deleted the claude/issue-16896-automation-run-lifecycle-doors-docs branch September 9, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

automation run-lifecycle doors (cancel, restore-suspension): docs route tables, :name scoping clause, and the SDK-method decision left open by PR #16755

2 participants