feat(lint): widen flow-trigger-unroutable to the omission shape (#7215) - #7273
Conversation
`flow-trigger-unroutable` (#6637) fired only on the contradiction shape: `config.triggerType` present but the engine routes it nowhere. Per #7215 (maintainer-ruled, disposition 1), it now also fires on the omission shape: `type: 'record_change'` with no `triggerType` key at all. Both shapes fall through `resolveTriggerBinding` the same way and are equally dead at runtime, so they share the id and severity rather than getting a new one. Corpus-verified before landing: the only two real `type: 'record_change'` flows in the tree (examples/app-todo's TaskCompletionFlow, repaired by #7039, and examples/app-showcase's UrgentTaskAlertFlow) both already declare an explicit triggerType — zero omission instances, so the widening ships green with no baseline churn. Deletes the scope-boundary pin test in validate-flow-trigger-readiness.test.ts per its own instruction that widening "is a deliberate edit that has to delete this test, not a side effect" — replaced with tests for the omission shape firing, staying silent on non-record_change flow types, and staying silent when a routed sibling key is present. Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn Co-authored-by: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also reference the affected code. These are read-only:
|
|
PM 验收:ACCEPT。 门禁按名点名复读(head
合入后本单收卡、#7215 清 Generated by Claude Code |
Fixes #7215
What changed
flow-trigger-unroutable(#6637) previously fired only on the contradiction shape:config.triggerTypepresent but the engine routes it to no trigger (triggerType: 'onCreate').Per #7215's maintainer-delegated ruling (disposition 1, "take it now" — see the RULED comment on
that issue), this PR widens the same rule to also fire on the omission shape:
type: 'record_change'with notriggerTypekey at all. Both shapes fall throughAutomationEngine.resolveTriggerBinding's same branch chain toundefined, and both are equallyinvisible to
getTriggerBindingAudit(which skips a flow with no resolved binding as "manual —nothing to bind"). They are two spellings of one defect, so they share the same rule id and the
same
errorseverity rather than getting a new id.The rule's other exclusion is unchanged: a
record_changeflow that declares something the enginedoes route (
config.schedule,triggerType: 'api', aconfig.timeRelativeobject) still bindsand fires — on the wrong trigger's terms — and is a different defect this rule does not speak to.
Corpus count (measured before landing, per the dispatch's stop condition)
Ran the widened criterion over every
type: 'record_change'flow definition found by contentsearch across
examples/,apps/, andpackages/(excluding test fixtures and the CLI'sscaffold-string template, which produces a different, non-
record_changeshape). The tree hasexactly two real
record_changeflows:examples/app-todo/src/flows/task.flow.ts—TaskCompletionFlow, repaired by fix(example-todo): armtask_completion— it bound to nothing and gated on a key nothing reads (#6882) #7039 to declaretriggerType: 'record-after-update'.examples/app-showcase/src/automation/flows/index.ts—UrgentTaskAlertFlow, declarestriggerType: 'record-after-write'.Both already declare an explicit, valid
triggerType. Verified programmatically (not just bygrep) by importing both flow modules and running
validateFlowTriggerReadinessagainst themdirectly:
Omission instances found: 0. The widening ships green on the whole tree — no baseline entry,
no example-app churn, no new vocabulary.
Test changes
validate-flow-trigger-readiness.test.tscontained a scope-boundary pin(
an ABSENT triggerType — dead too, deliberately deferred (#6637 corpus)) whose own comment saidwidening "is a deliberate edit that has to delete this test, not a side effect." That test is
deleted, per #7215, and replaced with:
FLOW_TRIGGER_UNROUTABLE,error, same path shape asthe contradiction case),
config.schedule/config.timeRelative)still stays silent — the "mis-bound, not un-bound" exclusion applies to the omission shape too,
record_changeflow types (autolaunched,screen,schedule,api, notypeat all) stay silent even withtriggerTypeabsent — enumerated from the code's exactflow.type === 'record_change'guard, not guessed.All of the contradiction shape's pre-existing tests are untouched and still pass.
Provenance comments were updated in both files (the rule's own scope-boundary comment above the
1f block, and the exported
FLOW_TRIGGER_UNROUTABLEJSDoc) to record the widening's history —kept in historical form per the PR #7172 discipline, with the forward-pointer to "the still-open
widening question" now resolved to #7215 rather than deleted outright.
Reverse verification
Temporarily restored the pre-widening rule file (
git show origin/main:… >, nogit stash) andre-ran the new tests against it: all 4 new omission-shape tests went red, while the other 61
pre-existing tests (contradiction shape, severity map, etc.) stayed green — confirming the new
tests are non-vacuous and the existing scope is untouched. Restored the widened file and re-ran;
back to 65/65 green.
Verification
Changeset
Added
.changeset/lint-flow-trigger-unroutable-omission.md(@objectstack/lint: minor) — afunctional widening of a published lint rule's gating criterion, precedent PR #7214.
Generated by Claude Code