Skip to content

Commit 59441b6

Browse files
docs(qa): automation recipes score the second packaged caller and the 503 store arm (#26802)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8DcJexQ1vAppgxsiiNUjjkf)_ Fixes #26622 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:`areas/automation.json` 新增区级配方 `qa-second-packaged-caller`(N1),并给已有配方 `qa-flow-status-doors` 加第 5 步故障臂(A4 的 503);两个条目 revision 各升一级(9 → 10、6 → 7)。 - 为什么改:两条子句在 18.2.0 两轮里都只能记 blocked(fixture):N1 要第二个「打包」调用方,A4 的 503 STORE_UNAVAILABLE 没有现成触发办法。 - 风险与回滚:只改 QA 台账一个 JSON 文件,不动产品代码;回滚即 revert 本 PR。 - 先看:`docs/qa/platform-checklist/areas/automation.json` 顶部 `fixtures` 块的新配方与 step 5,再看两个条目 history 的最新一行(含裁决)。 - 两分钟验证:`node scripts/check-platform-checklist.mjs`,预期 OK,且显示 7 个区级配方、7/7 被引用。 - 需要你做的:无,席位落地。 ## What changes - `docs/qa/platform-checklist/areas/automation.json` gains the area-level recipe `qa-second-packaged-caller`, in the README's "Area-level `fixtures`" shape: one `POST /api/v1/marketplace/install-local` call carrying an inline manifest whose one flow, `qasub_second_notify_caller`, calls `showcase_notify_owner` as a subflow, a read-back step, and a mandatory teardown. - The existing recipe `qa-flow-status-doors` gains step 5, the fault arm for the resume door's 503 `STORE_UNAVAILABLE` row: with a live paused `showcase_reassign_wizard` run, `sys_automation_run` is renamed away in the boot's telemetry database (`node:sqlite`, a second process) for one resume, then renamed back. Its title, `why`, `provenance`, `requires` and `teardown` say so. - `automation.packaged-flow-subflow-disable-refusal` (revision 9 → 10) opts in with `fixtures.provisioning.use` + `why`; `negative[1]` names the recipe instead of `blocked(fixture)`; `steps[8]` drives the several-callers leg; `knownGaps` gains its CLOSED-by-recipe line (the engine-pin fallback kept); `source` cites the install-local door and `packagedArtifactOwner`; `history` records the re-drive and its verdict. - `automation.trigger-status-contract` (revision 6 → 7): `fixtures.provisioning.why`, `steps[5]` and `acceptance[4].verify` name step 5 in place of "record it blocked(fixture)"; `source` cites `run-resume.ts#loadSuspendedRunStrict`; `history` records the re-drive and its verdict. No clause sentence changed in either item. ## Why Both clauses scored `blocked(fixture)` in both 18.2.0 waves. Read on main d31329f: - N1: a flow counts as packaged only when the package loader registered it (`packagedArtifactOwner` reads the loader's set, never the body's stamps), so a `?package=`-authored flow, a `POST /api/v1/automation` flow and anything under a `POST /api/v1/packages` (authored) package are deployment-authored. The install-local door's inline-manifest branch registers through the kernel's `manifest` service as marketplace code and announces `metadata:reloaded`, from which the automation engine re-syncs its flows. It is mounted on a stock showcase boot unless `OS_CLOUD_URL=off`, and the inline branch fetches nothing from the cloud. - A4: the resume door answers 503 only when the durable suspended-run store throws on the strict load (`loadSuspendedRunStrict` inside `resumeInternal`). No request makes it throw, but the store reads `sys_automation_run` through the data engine, which rethrows a missing table, so taking the table away for one resume is a live arm. The table lives in the telemetry file beside the primary database (`resolveTelemetryDbPath`), not in the primary. No door is missing, so no product card is filed. ## Tests No code changed, so no test was added. Both clauses were re-driven once, REST only, on a fresh showcase boot built from d31329f (`OS_PORT=38917 pnpm dev -- --fresh -p 38917`, a stock boot with no env posture). <details><summary>N1 on qa-second-packaged-caller</summary> ```text POST /api/v1/marketplace/install-local -> 200 hotLoaded true, manifestId com.objectstack.qa.qasub GET /api/v1/automation/qasub_second_notify_caller -> 200 status active, _provenance package, _packageId com.objectstack.qa.qasub POST /api/v1/automation/showcase_notify_owner/toggle {"enabled": false} -> 409 {"code":"DELETE_RESTRICTED","message":"Flow 'showcase_notify_owner' cannot be disabled while 2 packaged flows still call it as a subflow: 'showcase_task_done_notify_owner', 'qasub_second_notify_caller'. Disabling it would break those callers mid-run at their subflow node with a late, inexplicable failure (ADR-0126 §7.3). Disable the calling flows 'showcase_task_done_notify_owner', 'qasub_second_notify_caller' first — or leave this one armed.","httpStatus":409} GET /api/v1/data/sys_metadata_activation -> 200 records [] DELETE /api/v1/marketplace/install-local/com.objectstack.qa.qasub -> 200 cleanups [security.package-permissions ok] POST /api/v1/automation/showcase_notify_owner/toggle {"enabled": false} -> 409 names showcase_task_done_notify_owner alone ``` Verdict for negative[1]: pass. `examples/app-showcase/.objectstack/installed-packages/` was empty after the teardown. </details> <details><summary>A4 (503 arm) on qa-flow-status-doors step 5</summary> ```text POST /api/v1/automation/showcase_reassign_wizard/trigger {"params":{"recordId":TASK,"objectName":"showcase_task"}} -> 200 paused, runId run_59bec4ba-… node:sqlite on PRIMARY.telemetry.db: sys_automation_run row count for the run = 1 ALTER TABLE sys_automation_run RENAME TO sys_automation_run__qa_off POST /api/v1/automation/showcase_reassign_wizard/runs/RUNID/resume {"inputs":{"new_assignee":ADMIN}} -> 503 {"code":"STORE_UNAVAILABLE","message":"Durable suspended-run store unreachable for run 'run_59bec4ba-…' — retry once the store is available: The database refused to run this query for object 'sys_automation_run'. …","httpStatus":503} ALTER TABLE sys_automation_run__qa_off RENAME TO sys_automation_run (row count still 1) GET /api/v1/automation/showcase_reassign_wizard/runs/RUNID -> 200 status paused POST /api/v1/automation/showcase_reassign_wizard/runs/RUNID/resume (same body) -> 200 apply node acted 1 ``` Verdict for the 503 arm of acceptance[4]: pass, the suspension intact. A first attempt aimed the rename at the primary file and answered `no such table` there, which is why step 5 names the telemetry file. </details> ## Acceptance notes - Done-when line 1 asks for a keyed recipe each item references. An item carries one `fixtures.provisioning.use` (the validator reads a single string), and `automation.trigger-status-contract` already uses `qa-flow-status-doors`, so the 503 arm is that recipe's step 5 rather than a third key. A separate key would have no consumer and fail the gate's unreferenced-recipe check. - The card names "the boot or config that makes the run store unavailable". There is none: the arm is an out-of-process edit of the run's own telemetry file on a stock boot. It needs a file database and Node 22.5+; the recipe's `requires` says so, and a run without them records the arm `blocked(fixture)` with the in-process pin beside it. - The install-local ledger lands in the project tree (`examples/app-showcase/.objectstack/installed-packages/`, gitignored), not in the `--fresh` tempdir, so the teardown DELETE is mandatory; the recipe's `requires` and `teardown` say so. - The packaged self-caller arm of `knownGaps[0]` needs the same kind of install; it was not measured and stays as it was (the recipe's `knownGaps[1]`). - The branch merged origin/main f7c95cd after the re-drive; of the paths this PR reads, the incoming commits touch only `areas/api-backend.json`, `areas/approvals.json` and `ObjectQL.validateData` in `packages/objectql/src/engine.ts` — not `automation.json`, the engine's `find`, or any door cited. ## Verification Gates at head 185f67d: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 16 commands; all 16 exit 0, and `--ran` reconciles 16 derived, 16 run, 0 NOT-MEASURED. `node scripts/check-platform-checklist.mjs`: OK, 7 area recipes, 12 item references resolved, 7/7 recipes referenced, symbol anchors 1006/1016 resolved (10 on the named residual). No changeset: the diff touches only `docs/qa/**`, which no package publishes (`skip-changeset`). ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (not touched) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes. (CI runs it) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (publishes nothing) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (not touched) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01JQwxbYrT5jXrc7zvLFLnyA)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 63e3873 commit 59441b6

1 file changed

Lines changed: 130 additions & 13 deletions

File tree

0 commit comments

Comments
 (0)