Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

feat(openspec): quorum-declarative-migration — first ADR-031-aware spec#146

Merged
rubenvdlinde merged 1 commit into
developmentfrom
feature/quorum-declarative-migration
May 7, 2026
Merged

feat(openspec): quorum-declarative-migration — first ADR-031-aware spec#146
rubenvdlinde merged 1 commit into
developmentfrom
feature/quorum-declarative-migration

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

First ADR-031-aware OpenSpec change on decidesk. Specifies the migration of Meeting's quorum logic from lib/Service/QuorumService.php (168 LOC, 2 methods) into x-openregister-aggregations + x-openregister-calculations on the Meeting schema in lib/Settings/decidesk_register.json.

This is only the spec, not the implementation. Sanity-check first; once the shape reads right, the same template covers the four remaining service migrations (VotingService → lifecycle, ActionItemAnalyticsService → aggregations, DecisionNotificationService → notifications, OverdueActionItemsJob → processing).

Why this one is the canonical worked example

QuorumService is the smallest of the five planned migrations (168 LOC) and crucially exercises the full ADR-031 decision tree, not just the happy path:

  • The straightforward declarative case: percentage / met as schema calculations.
  • The cross-schema case: present-count + total-count as aggregations over related Participants — depends on engine support for @self.{relation} filters, which existing decidesk aggregations don't yet exercise.
  • The legitimate-PHP case: MeetingTransitionGuard stays in PHP per ADR-031 (lifecycle guards are explicitly preserved). It just gets dumber — reads a field instead of calling a service.
  • The exception case: if the engine does NOT support cross-schema filters, ADR-031 exception 1 applies — file an OR feature request, leave QuorumService in place, recheck when OR ships.

Artifacts

  • proposal.md — problem / proposed solution / capabilities / stakeholders / references.
  • design.mdDeclarative-vs-imperative decision table per ADR-031 + opsx-ff's new artifact rule. Engine-dependency call-out. Reuse / dedup analysis. Risks. Out of scope.
  • tasks.md — schema-register patches only; no new Service class authored. Task 1 is a spike that gates tasks 2-7 on engine capability. Three guard rails in the trailer (no escape-hatch service, don't migrate the guard, don't expand scope).

Sanity-check checklist

  • Reading design.md § Declarative-vs-imperative decision: does the table match what ADR-031 asks for? (Each behaviour has a path + rationale; legitimate PHP cases are explicit.)
  • Reading tasks.md: do the register-patch JSON snippets look syntactically right against ActionItem's existing aggregations + calculations? (Sample expressions: if/mul/div/eq/or/gte. Adjust operator names if engine uses different keys — flagged in task 3.)
  • Engine spike (task 1): is the cross-schema aggregation filter (schema: + @self.governanceBody) something the OR engine currently supports? If yes, the migration ships as written. If no, ADR-031 exception 1 + OR feature request.
  • Tone of the trailer guard rails — do they read as helpful template, or preachy?

Notes

Markdown only, no code paths affected. Worktree-built per the standing rule (decidesk's main checkout has WIP on feature/declarative-annotation-pilot). Draft because I want your eyes on the spec shape before we apply the same template to the other four migrations.

Migrates Meeting's quorum logic from `lib/Service/QuorumService.php`
(168 LOC, 2 methods) into `x-openregister-aggregations` +
`x-openregister-calculations` on the Meeting schema, per the new
ADR-031 (schema-declarative business logic over service classes)
that landed in hydra/development on 2026-05-06.

QuorumService is consumed exclusively by `MeetingTransitionGuard`
during the `scheduled → opened` transition. The guard itself stays
in PHP — ADR-031 explicitly preserves lifecycle guards as a
legitimate PHP seam — but it gets dumber: reads `meeting.quorumMet`
from the object instead of calling QuorumService.

Three artifacts:

- proposal.md — what / why / capabilities / stakeholders.
- design.md — declarative-vs-imperative decision table per ADR-031,
  engine-dependency call-out (the migration depends on
  cross-schema aggregation filters via `@self.{relation}`; if the
  OR engine doesn't yet support that, ADR-031 exception 1 applies
  and we file an OR feature request instead of a workaround
  service).
- tasks.md — schema-register patches first (no new Service class
  authored), spike-then-rest gate on task 1.

This is intentionally the smallest of the five planned decidesk
service migrations and the canonical worked example for the rest
(VotingService → lifecycle, ActionItemAnalyticsService →
aggregations, DecisionNotificationService → notifications,
OverdueActionItemsJob → processing). Sanity-check first; if the
shape reads right, Hydra picks up the bigger four with the same
template.
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/decidesk @ 5e59453

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-06 14:22 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde rubenvdlinde marked this pull request as ready for review May 7, 2026 05:20
@rubenvdlinde rubenvdlinde requested a review from Rem-Dam as a code owner May 7, 2026 05:20
@rubenvdlinde rubenvdlinde merged commit 988e63a into development May 7, 2026
30 of 39 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant