Repository navigation
[finding] requires: ['triggers'] without automation validates, but at boot the record-change trigger is not installed and every flow "will never run" #20332
Description
Activity
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsPath: approvals and automation | 缺项 (no item validates a stack declaring
triggerswithoutautomation) | P2Triage: first grade —
bug·priority:p2·domain:spec·area:workflow·pm:queue. Direction: validation requires bothTriage: lands in
packages/spec/src/stack.zod.ts(validateTriggerCapabilityand its docblock) ⇒domain:spec. Rationale: a stack declaringrequires: ['triggers']with arecord_changeflow passesos validate, and then boots with 「they will never run」 and 「record-change trigger NOT installed」. The runtime needsautomationtoo (CAPABILITY_PROVIDERS.automation). On the road, this is a flow that silently never fires ⇒ p2.Triage seat (objectstack-wide, seat post #6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-28T00:19Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments) and PR #20329 (open; it declaresrequires: ['automation', 'triggers']in theos inittemplates).The contract choice, decided here: refuse, do not imply. The charter prefers contract tightening to consumer-side tolerance: a loud refusal at publish with a prescription, never a silent fallback.
validateTriggerCapabilityrefusestriggerswithoutautomation, with the prescription 「addautomationtorequires」, and its docblock says the trigger is installed by the pair. Havingtriggersimplyautomationwould silently switch on a service the author did not name. It is a narrowing of the accept set, not a new capability, so it needs no maintainer word.Execution notes.
- Refuse at
os validate/ the stack parse with the prescription. Theos inittemplates already declare both after PR fix(cli): generated scaffolds reach the stack, or os g says they do not (#20215) #20329. - Pin
['triggers']alone refused,['automation', 'triggers']accepted (the control), and a stack with norecord_changeflow unaffected. Clause-②: yes (narrowing), BREAKINGminor. Census the examples and hotcrm fortriggerswithoutautomation, and name any producer.
- Refuse at
- addedarea:workflowApprovals and automation — the work that runs without a person driving itApprovals and automation — the work that runs without a person driving itbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 · 2026-09-28T00:34Z
Session:session_01Rjy9MeetSfq34PKn81CRiN
Account:os-zhuang
Branch:claude/issue-20332-triggers-require-automation
Worktree:objectstack-issue-20332
Domain:domain:spec
Seat:domain:spec#1
File surface:packages/spec/src/stack.zod.ts(validateTriggerCapability, its docblock and theStackTriggerCapabilityRequiredErrordocblock);packages/spec/src/automation/flow-trigger-kind.ts(docblock only, if it repeats the one-token sentence); tests; an ADR-0087 D3 entry if one is owed, plus the generated regions ofregistry.ts; regenerated docs;.changeset/. ⛔ Notpackages/cli/src/commands/{init,generate}.tsorutils/scaffold-wiring.ts(PR #20329); ⛔serve.ts,packages/triggers/**,platform-capabilities.tsandpackages/lintread only. (stop on breach; explain in the report)
Container & model:S,mode:subagent,model: default judgment tier(dispatch-gates --tieratd3958bac: no path-derived mandate; Clause ② SUSPECT onpackages/spec/src/**). A published accept set narrows, so it is reviewed atCONTRACT_REVIEW_TIERbefore enqueue.
Clause-②: yes
Thread-read: 5861188312
Serial constraints cleared:Read at {{NOW}} on origin/main d3958bac. No open PR touches stack.zod.ts (18 read). Of the pm:dispatched claims, only #20289 (seat 2; PR #20341, os test requires-skip) and #20215 (cli; PR #20329, the os init/generate templates) name requires or stack. Neither edits stack.zod.ts. PR #20329's templates declare requires ['automation', 'triggers'], which this refusal accepts. The area:workflow in-flight card #15429 (decision-node conditions) is on a disjoint surface.- added a commit that references this issue
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 20332,
"status": "blocked",
"branch": "claude/issue-20332-triggers-require-automation",
"pr": "#20365",
"session": "session_01Rjy9MeetSfq34PKn81CRiN — mode:subagent, the dispatching PM's session; identity is the branch",
"premise_still_valid": true,
"summary": "Draft PR #20365 (head 94e3202, merged with origin/main 6704717 through os-regen-merge.sh) implements triage's direction 5861188312.validateTriggerCapabilitynow refusestriggerswithoutautomationfor all four auto-launched kinds, on the same STACK_TRIGGER_CAPABILITY_REQUIRED code, with the prescription to add 'automation'. A stack that declares neither token is told to add both, so following the message once is enough.['automation']keeps its old message byte for byte. The one-token sentence is restated at every site (spec docblocks, ledger comment, flows.mdx, capabilities.mdx). The two unfenced test stacks that declaredtriggersalone now declare the pair. Theos gpin landed by #20329 ('triggers-only → cannot run, exit 0') is flipped to a refusal (exit 1, tree byte-identical), with cli.mdx and the pending 20215 changeset corrected to match. BLOCKED on two things only the PM or a person can clear. (1) FENCE:packages/lint/src/authoring-rule-input-tier.test.ts:93declaresrequires: ['triggers']on a schedule flow and now fails (1 failed of 4304 in @objectstack/lint).packages/lintis fenced read-only ('stop on breach'), so it is untouched. The fix is one line: ['automation', 'triggers'] plus its comment, the same conversion the refusal's first landing (948dd6b) made to the same fixture. (2)check-empty-changesetis red by design: this PR corrects two sentences of the pending, unreleased.changeset/20215-generate-scaffolds-reach-stack.mdthat it made false ('without automation the server loads the flow and never runs it', and the 'cannot run' os g state). The gate asks for a person's confirmation; restoring the file would republish false text. Zone 2 held: neither runtime's resolver hastriggerspullautomation(framework serve.ts, cloud 96eb092 resolveCapabilityDependencies). All four trigger kinds need the automation service: a real boot at the pre-fix dist printed all four 'automation service not available — … trigger NOT installed' warns. Producer census found 0 producers.",
"tests": "Spec at 94e3202: vitest --project local 554 files / 16439 passed / 1 todo; typecheck exit 0; check:generated all up to date after a rebuild. Targeted at 94e3202: stack-requires + stack-refusal-envelopes + flow-trigger-kind + error-code-ledger, 87 passed. New pins (stack-requires.test.ts, table-driven over requires × kind × status, each an envelope: code + status 422 + issues + prescription): 30 in the file. ABLATION, committed first (0fedfef), via scripts/ablation-replace.mjs: leg A put back the old early exitif (hasTriggers) return errors;(anchor 1→0, blob 4c0bfced0f02→ad3f88aa67c5) → 7 failed | 23 passed; leg B gave the neither case the old triggers-only message (blob→5a9e026581f7) → 3 failed | 27 passed; restored blob == HEAD 4c0bfced0f02, git diff HEAD empty → 30 passed. Direction: turns red, as predicted. DOOR ablation through dist: the leg-A mutation was built into packages/spec/dist (ablation-dist-preflight exit 0, marker present);os validate(tsx bin/run-dev.js) on a probe with requires ['triggers'] + a record_change flow exited 0;os serve --devon the same probe reached 'Server is ready' and printed '⚠ Flows: 1 flow(s) declared but the automation engine is not enabled — they will never run' and 4 × 'automation service not available — {record-change,schedule,time-relative,api} trigger NOT installed'. The restore leg rebuilt with the marker absent from all 222 dist files and a clean tree; the same probe then exited 1 with the new message. At head, the door gives: ['triggers'] exit 1; [] exit 1 (pair named); ['automation','triggers'] exit 0. Consumer suites at 45cfbaa: cli unit (generate-object-namespace-prefix + generate-scaffold-wiring) 52 passed; cli integration generate-stack-reach 7 passed; lint full 1 failed | 4303 passed (the fenced fixture; re-read at 94e3202: still 1 failed | 34 passed in that file, refused by the new automation arm, as expected); dogfood fixture module loads with requires [automation, triggers] (the boot pin is left to CI's Dogfood gate);os validateexits 0 on examples app-todo, app-showcase and app-crm. Gates: dispatch-gates --commands at 94e3202 derives 112; all 112 ran with exit codes recorded;--rangives '112 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero)'; 111 exit 0; check-empty-changeset exit 1 (deliberate correction, above).",
"mcp_calls": "0",
"api_writes": "3 relay (fleet-write) dispatches plus git pushes. (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (PR #20365, draft; body read back byte-equal, 14082 bytes); (2) label-write --assign os-zhuang → POST /repos//issues/20365/assignees (read back: assignees os-zhuang, labels untouched); (3) this os-dev-report via post-stamped → POST /repos//issues/20332/comments. Git pushes (not REST, paced by write-pace): 5 — the empty probe, 0fedfef, 89a4ac7, 45cfbaa, 94e3202. No label added: the dispatch names none, and skip-changeset does not apply because a changeset ships.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 94e3202: 112 families. Ran with exit codes: light set (85, unlocked) + package set (27, under os-verify-lock) = 112;--ranreconciliation: 112 run / 0 NOT-MEASURED / 0 UNRUN. Non-zero:node scripts/check-empty-changeset.mjs --base origin/mainexit 1 (DELIBERATE CORRECTION of .changeset/20215-generate-scaffolds-reach-stack.md; needs a person's confirmation). check-adr-0087-registration: '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition'. check-changeset-no-major: 'no major bump'. check:nul-bytes OK (9820 files). check:error-code-casing OK. check:dual-build-cjs-loads and check:skill-examples measured (exit 0) after their prerequisite builds; the first attempts were exit 3 (PREREQUISITE NOT MET), re-run and not counted as failures. Relative to the dispatch lead (derived at d3958ba over expected paths): the actual paths drop check:generated, migration-registry, spec-changes, upgrade-guide, future-spec-major and quick-reference-counts from the list (check:generated ran anyway, exit 0), and add check:error-code-provenance, check:cli-test-child-env, check:error-code-casing and check:cli-examples-parity (all run, exit 0). Declared to CI: the 6 path-scheduled jobs, the 4 type-check lanes and the Dogfood Regression Gate.",
"files_changed": ".changeset/20332-triggers-require-automation.md (+51); .changeset/20215-generate-scaffolds-reach-stack.md (+3/-3, deliberate correction); packages/spec/src/stack.zod.ts (+71/-24); packages/spec/src/stack-requires.test.ts (+182/-1); packages/spec/src/stack-refusal-envelopes.test.ts (+1/-1, comment); packages/spec/src/automation/flow-trigger-kind.ts (+5/-3, docblock); packages/spec/src/api/error-code-ledger.zod.ts (+1/-1, comment); packages/cli/test/generate-object-namespace-prefix.test.ts (+6/-5); packages/cli/test/generate-stack-reach.test.ts (+24/-11); packages/qa/dogfood/test/fixtures/override-composite-fixture.ts (+6/-2); content/docs/automation/flows.mdx (+13/-9); content/docs/deployment/cli.mdx (+5/-6); content/docs/permissions/capabilities.mdx (+1/-1). 13 files, +369/-67 vs merge base 6704717.",
"line_budget": "n/a — no skills/** and no governed surface (.claude/, AGENTS.md, docs/adr/) touched. 436 changed lines vs the 5000 human-merge threshold.",
"deviations": [
"Clause-② line: the claim 5861303325 carriesClause-②: yes. The per-card order says to measure the value. Measured: the PR adds no export, no error code and no accepted shape, so the PR body and the changeset sayClause-②: no (narrowing), BREAKING minor. The standing os-dev rule to copy the claim's line verbatim was overridden by the per-card order.",
"Zone 3 suggestedrequires: []→ today's message. I chose to name BOTH tokens for the neither case, on the four axes. Measured need: every real producer declares the pair, and the CLI banner prescribes it. AI-error: today's message, followed literally, lands on['triggers'], which the new arm refuses a second time. No scope growth: no code, export or new path, only the text of one arm. It is pinned: 'each prescription, applied literally once, is ACCEPTED'.",
"Touched two files outside the claim's named surface, both forced by the pin sweep. (a) packages/cli/test/generate-stack-reach.test.ts, which landed with #20329 after the claim: its 'cannot run' case asserted exit 0 for a triggers-only stack, and that becomes a refusal. (b) .changeset/20215-generate-scaffolds-reach-stack.md and content/docs/deployment/cli.mdx, which stated the old behaviour. None of the fenced src files (init.ts, generate.ts, scaffold-wiring.ts, serve.ts, packages/triggers, platform-capabilities.ts, packages/lint) was edited.",
"The worktree is kept after the report instead of being removed, because the card is blocked on a one-line follow-up (see open_questions). The probe projects and serve process are gone; the tree is clean."
],
"open_questions": [
{
"question": "FENCE: maypackages/lint/src/authoring-rule-input-tier.test.ts:93(requires: ['triggers']→['automation', 'triggers'], plus its 3-line comment) be converted in PR #20365? Until it is, @objectstack/lint's suite is red on that one test.",
"options": [
"A: lift the fence for this one fixture line; this branch adds it as a follow-up commit (the #20295-style patch round). It is textually disjoint from the #19886-2f branch, which touches validate-rls-predicate-enforceability* only.",
"B: route the line to the lint lane's (#19886 2f) PR and hold #20365 out of the queue until it lands.",
"C: land #20365 red on lint — not acceptable (a required context)."
],
"recommendation": "A. Long-term: the refusal's own first landing (948dd6b) converted this same fixture in the same PR, so the conversion belongs with the contract change. AI-error: it is a fixture that exists only to satisfy this contract. No scope growth: one line, no new surface. Business: no producer depends on it."
},
{
"question": "Confirm the deliberate correction of the pending, unreleased.changeset/20215-generate-scaffolds-reach-stack.md(check-empty-changesetstays red until a person confirms).",
"options": [
"A: confirm the corrected text (three sentences: 'If either one is missing, defineStack refuses…'; the 'cannot run' clause removed; 'withouttriggersor withoutautomation')",
"B: restore the base text — it would publish two sentences this PR makes false"
],
"recommendation": "A: the corrected note describes the behaviour on main once #20365 lands."
},
{
"question": "Fenced emitted text now false:packages/cli/src/commands/init.ts:649-652(the config comment os init writes) andpackages/cli/src/commands/generate.ts:366-369(the flow file header os g writes), plus their docblocks (init.ts:606-611, generate.ts:349-356), say that without 'automation' 'the server loads the flow and never runs it'. After #20365 the config stops loading. Who fixes the text?",
"options": [
"A: lift the fence for those comment lines in #20365 (text only)",
"B: a cli-lane follow-up card with Blocked-by: #20332 in objectstack"
],
"recommendation": "A if the fence is lifted for the lint line anyway (the same kind of fence, text only). Otherwise B, filed by the seat."
},
{
"question": "Zone 2 §1 cloud cell, for the record: the hosted hosts (apps/objectos HOSTED_FORCED_REQUIRES; objectos-ee defaultRequires) force-mount automation AND triggers on every tenant env whatever the artifact declares, so a ['triggers'] stack does run there. I read this as NOT the fork: the resolver never implies automation from triggers, and the published first arm has always refused a no-requiresstack that runs there too. Does the PM agree?",
"options": [
"A: agree — the refusal judges the portable declaration, not a host's floor",
"B: treat as a fork"
],
"recommendation": "A: same reading as the arm already on main."
}
],
"out_of_scope_findings": [
"class: b · reach: public dooros validatemeasured at 94e3202. A config thatexport defaults a plain object (no defineStack() call) with requires ['triggers'] and a record_change flow exits 0 ('Validation passed'). The same stack wrapped in defineStack() exits 1 with STACK_TRIGGER_CAPABILITY_REQUIRED. validate.ts runs only ObjectStackDefinitionSchema.safeParse at step 2, so every defineStack cross-field refusal (capability, namespace prefix, single app, hierarchy scope, trigger capability) runs only when the author called defineStack. The ledger comment in error-code-ledger.zod.ts says these codes are 'Raised byos validate/os build'. Seam: spec:defineStack refusal family → runtime:packages/cli/src/commands/validate.ts step 2 (and, unmeasured, compile.ts). The whole refusal family's door, not this arm's. Dedupe words:os validate plain object config skips defineStack refusal·defineStack cross-field refusals only when defineStack called·validate without defineStack capability refusal",
"carrier: the next PR to touch packages/cli/src/commands/generate.ts · noted, not filed:reportStackReach's 'cannot run' branch has no scaffold that reaches it after #20332 (the flow scaffold's only tokens are the pair, and a stack missing either one is refused). Dead for today's generators; in PR #20365's Acceptance notes."
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsReview: ACCEPT · PR #20365 at head
cf623471· 2026-09-28T03:50Zdomain:specseat 1 (session_01Rjy9MeetSfq34PKn81CRiN), reviewer of record, on claim5861303325and triage's direction5861188312(refuse, do not imply). Checked against GitHub and the dev report5862603596, ⛔ not against the report alone.Checklist
- Shape. Draft, base
main,Fixes #20332,Clause-②: no (narrowing), BREAKINGminor. Not governed; 472 changed lines in 16 files. - The refusal.
validateTriggerCapabilityrefusestriggerswithoutautomationfor all four auto-launched kinds (record_change,schedule,time_relative,api), on the sameSTACK_TRIGGER_CAPABILITY_REQUIREDcode, prescribing 「addautomation」.- A stack declaring neither token is told to add both, so following the message once is accepted.
['automation']keeps its old message byte for byte.- A stack with no auto-launched flow, or only
obsolete/invalidones, is unaffected. - The one-token sentence is restated at every site.
- Premises (Zone 2).
- Neither runtime's resolver makes
triggerspull inautomation: frameworkserve.ts, and cloudresolveCapabilityDependenciesat96eb092. - All four trigger kinds need the automation service. A real boot before the fix printed four 「trigger NOT installed」 warnings.
- Producer census: 0.
- Neither runtime's resolver makes
- Measured (report fields).
- spec local 16439 passed; typecheck 0;
check:generatedcurrent. - New pins: 30 table-driven envelope pins.
- Ablation: two legs, 7 and 3 red; restore proven.
- A dist-level door ablation through the real
os validate/os serve --dev. - Follow-up at
cf623471: lint full 112 files / 4640 passed / 0 failed; cli unit 266; cli integrationgenerate-stack-reach7. - Gates: 112 derived, 112 run.
check-empty-changesetis red by design (below).
- spec local 16439 passed; typecheck 0;
- CI at
cf623471: running.
The seat's answers to the report's four questions
- The lint fence is lifted for exactly
packages/lint/src/authoring-rule-input-tier.test.ts. Its fixture now declares the pair, the same conversion the refusal's first landing made (948dd6baf8). The [finding]$newith an array comparand splits across backends: driver-sql and driver-memory refuse (400), driver-mongodb answers, formula matches every row — and both shared faces pass it #19886 2g branch does not touch it. - The deliberate correction of
.changeset/20215-generate-scaffolds-reach-stack.mdis confirmed on PR fix(spec): refuse an auto-launched flow whose stack declares triggers without automation (#20332) #20365 in this act. - The cli fence is lifted for text only. PR fix(cli): generated scaffolds reach the stack, or os g says they do not (#20215) #20329 has landed as
c5dcb3ba, and no open PR touchesinit.ts/generate.ts. The changed text is the emitted config comment and flow header plus their docblocks; no code moved. - Cloud's hosted forced floor is not a fork. The refusal judges the portable declaration, as the first arm on
mainalready does.
The neither-case naming both tokens (a Zone 3 deviation) is accepted: it is measured, and pinned as 「each prescription, applied literally once, is ACCEPTED」.
Contract review. Owed: a published accept set narrows. An isolated at-tier reviewer is dispatched on this head, and
needs:contract-reviewis added to PR #20365 in this act.Findings, one line each
os validateruns only the schema parse, so a config that exports a plain object skips everydefineStackcross-field refusal and passes → filed [finding]os validateruns only the stack schema parse, so a config that exports a plain object (nodefineStack()call) skips every defineStack cross-field refusal and passes #20367.reportStackReach's 「cannot run」 branch ingenerate.ts(about :1591) is dead for today's generators → carried to the next PR that touchesgenerate.ts; Acceptance notes.
- Shape. Draft, base
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsLanded: PR #20365 →
main2d91c9aa21c571bb7d900f8a8c275ac2798e531d(Fixes #20332) · 2026-09-28T05:47Zdomain:specseat 1 (session_01Rjy9MeetSfq34PKn81CRiN), on claim5861303325and triage's direction5861188312.How it got here
- Seat ACCEPT
5863004037, then at-tier review PASS5863370769at headcf623471, which is the head that landed. The PASS measured:- the refusal grid through
defineStackand the realos validate; - each prescription applied literally once, and accepted;
- the runtime premise (no resolver pulls in
automation; each trigger plugin needs it at install); - a census of 0 configs;
- an ablation.
- the refusal grid through
- The deliberate correction of
.changeset/20215-generate-scaffolds-reach-stack.mdwas confirmed on the PR (5863010118).Check Changesetstays red by design: it is not a required context and does not run onmerge_group. Test Core (6/6)timed out in plugin-dev atcf623471(5863096877, tracked as [finding] plugin-devdev-plugin-tenancy-mount-refusal.test.tstimed out at 5000ms in its first test (the positive control) on a required Test Core shard, on a PR that touches no plugin-dev file #20376). After the maintainer's one re-run it went green.- CI at
cf623471: 34 success, 7 expected skips, andCheck Changesetred by design. Not governed; 472 changed lines. - Queue: enqueued at 05:22Z, merged at 05:45Z.
Verified on
main, two readings2d91c9aa's first parent isab946560, and no queue branch for fix(spec): refuse an auto-launched flow whose stack declares triggers without automation (#20332) #20365 remains.- Diff against the first parent: 16 files, +388/−84, the same file list and counts as the PR's three-dot. The increment's added and removed lines hash identically to
29720975...cf623471, both overall and per file. - Content control: in
packages/spec/src/stack.zod.ts, the parent carries the early exitif (requires.includes('triggers')) return errors;and2d91c9aareplaces it withconst hasTriggers = requires.includes('triggers');..changeset/20332-triggers-require-automation.mdis present at2d91c9aaand absent at its parent. - This card closed through
Fixes.
Carried elsewhere
- [finding]
os validateruns only the stack schema parse, so a config that exports a plain object (nodefineStack()call) skips every defineStack cross-field refusal and passes #20367:os validateon a config that exports a plain object skips everydefineStackcross-field refusal. - [finding] plugin-dev
dev-plugin-tenancy-mount-refusal.test.tstimed out at 5000ms in its first test (the positive control) on a required Test Core shard, on a PR that touches no plugin-dev file #20376: the plugin-dev cold-start timeout inTest Core (6/6). - Not filed (Acceptance notes): the 「cannot run」 branch of
reportStackReachinpackages/cli/src/commands/generate.tsis dead for today's generators. It rides the next PR that touches that file.
- Seat ACCEPT
- added a commit that references this issue
on Oct 9, 2026
Filing gate: ① a defect with a named landing site,
packages/spec/src/stack.zod.tsvalidateTriggerCapability(its contract text) against the runtime's install path. Finding class (b): a declared contract the runtime does not honour, withreach:measured at a public door.Found by the
os-devround on #20215 (PR #20329, whoseos inittemplates now declarerequires: ['automation', 'triggers']). Filed by thedomain:cliexecution seat (#6024,session_01UYBdGBzWSrAMzpW8ah3GbP). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happens (measured by the dev at
origin/main6a6a17b6, relayed)A stack declaring
requires: ['triggers']and onerecord_changeflow:os validateexits 0;os serve --devboots, and prints:The contract it contradicts
validateTriggerCapability's own docblock (packages/spec/src/stack.zod.ts): 「the trigger that fires a record_change … flow … is installed by ONE token, requires: [triggers]」. The runtime also needsautomation(packages/cli/src/commands/serve.tsCAPABILITY_PROVIDERS.automation,AutomationServicePlugin;packages/triggers/trigger-record-changeRecordChangeTriggerPlugin). So the declared single token does not install a working trigger, and nothing at author time says so.Seam
spec:validateTriggerCapability→runtime:packages/cli/src/commands/serve.ts CAPABILITY_PROVIDERS.automationandpackages/triggers/trigger-record-change RecordChangeTriggerPlugin. Eithertriggersimpliesautomation, or validation requires both. Which one is triage's call, and the maintainer's if it is a contract choice.Dedupe
MCP issue search in this repository, run 2026-09-27: 「requires triggers without automation, record_change flow validates but automation engine is not enabled, flows never run」 → 18 hits.
description/outputSchemareach the flow designer (7 keys) #20287 (open, connector triggers, unrelated), andtrigger.recordIdis never populated on record_change runs, and the persistedsys_automation_runrow carries no trigger block at all — runs cannot be correlated to their triggering record, and trigger kinds are lost across restart #7533,POST /api/v1/automation/:name/toggleanswers 500 INTERNAL_ERROR instead of 404 NOT_FOUND for an unknown flow #7535, examples/app-todotask_completiondeclarestype: 'record_change'with notriggerType— the flow is dead, and its trigger condition is written to a key nothing reads #6882, flow record trigger: array-formtriggerTypeis silently dead at every layer (no lint, no audit, no runtime warn) #3481, finding: aflow-type action's AutomationContext gets the same stampedrecordstub when the caller cannot read the row — and the flow face has norecordLoadDenied#14244, bug(service-automation):execute()never carries the flow author'ssuccessMessage/errorMessage— onlyresume()does, so a triggered run's friendly text is silently dropped #9414 and finding: the whole /automation read domain is gated only by "authenticated" — run-detail returns the triggering record's fields without that record's own FLS #7900 (all closed, runtime flow defects).None of them is this defect.
Dedupe words:
requires triggers without automation flow never runs·validateTriggerCapability automation·automation engine is not enabled validate passesGenerated by Claude Code