Skip to content

spec: approval onEmptyApprovers gains 'fallback' with a sibling fallbackApprovers at the node level — the empty { type: 'manager' } rung becomes survivable (from #16678 Phase 2 §8.2, ruled) #17931

Description

@os-tesla

Filed by the director seat out of #16678's Phase 2 ruling (decision batch #127 item 1, maintainer ruling 2026-09-13; recorded on #16678). ⛔ Not claimed, ⛔ not dispatched. domain:spec because the landing point is packages/spec/src/automation/approval.zod.ts; Clause-②: yes is expected — this widens an authorable enum and adds a sibling key — and the domain:spec seat declares it at claim time.

What is ruled (verbatim scope from the #16678 Phase 2 design §8.2, adopted)

Extend the approval node's empty-slate policy so it can name people: onEmptyApprovers gains a 'fallback' member, with a sibling fallbackApprovers reusing the existing approver-entry shape (ApproverEntrySchema, ⛔ not a new shape). This belongs on the node, ⛔ not on the manager rung: the #3807 warning already shows all five graph approver types (manager / team / department / position / org_membership_level) share the dead end, and the node is where the platform already decided emptiness is handled (admin_rescue | fail | auto_approve). Take the capability the measured platforms bind to the manager rung (Entra "Add fallback"; Odoo "If empty, the approval is done by an Administrator or Approver") at the node level.

Measured facts the implementer inherits (#16678 design §8.1, verified by the services seat on origin/main)

Scope

  1. packages/spec: onEmptyApprovers enum + fallbackApprovers (required iff 'fallback', refined with a remedy naming both keys); .describe() text and the generated reference page; authorable-surface gains the entries; minor changeset.
  2. packages/plugins/plugin-approvals (openNodeRequest empty-slate block): the 'fallback' branch resolves fallbackApprovers through the same resolver as ordinary approver entries and opens the request on them; ⛔ never the manager:undefined literal.
  3. packages/lint validate-approval-approvers.ts: the MANAGER_ONLY_REMEDY / MANAGER_ONLY_ROUTES text gains "or declare onEmptyApprovers: 'fallback'"; the finding keeps firing on shape (a static check cannot read the column); stackWiresManagerChain stays the silencer. ⛔ Do not delete the rule. The docs callout content/docs/automation/approvals.mdx:66-87 follows.
  4. Pins: fallback resolves when the manager is empty; fail / auto_approve / admin_rescue unchanged (negative controls); the new manager row in the approvals: a department approver never resolves when the business unit has organization_id = null (every seeded BU) #3807 table.

Cross-domain declaration: packages/spec (designated lane) + plugin-approvals + packages/lint faces declared in the claim comment, per the cross-domain exception path.

Relations

Parent ruling: #16678 (Phase 2 design adopted as the Phase 3 baseline, minus §4). This card is independent of the manager write surface (design §8.2: "a fallback does not make manager resolve; it makes the failure survivable. The two are independent and both are wanted") ⇒ ⛔ no Blocked-by:. #17579 (the generated reference page's manager line) is closed in substance by #17640 and is re-verified here.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions