Repository navigation
train: land 32 ready PRs (11 Oct, b) - #3742
Merged
Merged
Conversation
…them without a grant Every curated read (deadline dashboard, lead times, KPIs, workload, available transitions, overdue complaints) now declares reach: 'user'. Without it a two-segment id resolves to external and needs an explicit grant. Needs openregister build/dep-dossiq-mcptool-reach on the instance first.
… and work its terms Curated write tools, each on the service its controller calls: transitionCase (StatusTransitionService, guards and status record intact), reassignCase (new CaseAssignmentService::reassign, coordinators only, the receiver is notified), completeTask (the engine's complete verb), extendDeadline/pauseDeadline/resumeDeadline (new TermTools: the term is read and its CASE must be changeable by the caller before the term services run). Refusals come back as envelopes with the service's own rule and sentence. WIP: AppointmentTools and BeschikkingTools are listed but not written yet.
…chikking AppointmentTools (scheduleAppointment, cancelAppointment; external reach: the resident is told) run AppointmentController's case checks and call AppointmentService. BeschikkingTools offers draftBeschikking only, through BeschikkingService::compose(); approving, signing and sending stay with the caseworker. A test holds the tool classes off ObjectService. hermiq-ai-tooling 3.1-3.3 ticked; the spec names the services as found.
# Conflicts: # lib/Settings/register.d/60-termijnbewaking.json # tests/schemas/schema-version-digests.json
… verdict woo-review-triage section 1: wooDocumentReview, wooTriageRule and wooReviewBatch schemas (87-woo-review.json, register 0.20.23); only an in-scope document needs a verdict and an unmarked one is always outstanding; POST relevance and GET summary on the Woo case; a repair step marks documents assessed before this change in scope so they do not block their case. (unit tests written, run pending a slot)
…h install has no assessments
# Conflicts: # lib/Settings/register.d/60-termijnbewaking.json # tests/schemas/schema-version-digests.json
…duleAppointment (phpmd finds nothing without it)
…1-4) Decision 179 (Ruben, 10 Oct 2026): a form submits into its destination object, with no in-between intake layer, and is valid against that object's schema when built. Cross-app change: hydra openspec/changes/form-submits-into-its-destination-object (ADR-117, hydra#748). Spec only.
# Conflicts: # appinfo/info.xml # tests/schemas/schema-version-digests.json
…rmed only when its term runs WooRequestIntake::receive() takes opencatalogi's answer keys (portal-form and opencatalogi origins, subjectRef optional for those two), writes the Woo case directly (decision 179: no intake object in between), counts the term from when the requester sent it, and reads the term back: armed only when a statutory instance with an engine timer ends on the case deadline; otherwise not-armed with an internal timeline entry, or unavailable with nothing written. PortalContributionProvider::receiveWooRequest() has opencatalogi's signature. Register 0.20.26 (wooRequest origin enum, phone and address).
…t, a due invoice and a published award Four x-openregister-notifications rules on the supplier schemas mail the supplier's contact address through supplierRef, using OpenRegister's new email recipient kind (portal-contribution T3).
…nd act as dossiq on the case layer The bridge called createPlan and getPlan with uid null, which OpenRegister refuses, so every case start created nothing. It now calls the system verbs from openregister#4544 and names an OpenRegister that lacks them. The drain (retire-cmmn-caseplanstate 2.1-2.3): occ dossiq:cmmn:migrate-case-plans and a post-migration repair step hand each blob to ensureItems with the recorded states and the event log as history, verify every state, then clear the blob. Unmappable cases keep their blob and are reported.
…chable
formerReferences (list of {application, reference}) on the case schema, an
exact search declaration, register 0.20.27.
OpenCatalogiWooCase maps every status to its stage (received, in_progress, awaiting_clarification, decided, withdrawn), carries start, requester, channel, old reference, extension count and end date, on opencatalogi's own request shape as fixture. First part of takes-over 4.2.
…s no approval floor Decision 176 (Q-dossiq-L6-2): REQ-MCP-206 now says hermiq decides which AI writes wait for a person. dossiq declares readOnlyHint: false and a scope on every write so hermiq can gate it, and ships no grant or waiver. CHANGELOG entry for the curated tools (task 4.3).
…who gets a task for it
POST /api/cases/{id}/woo/batches takes a list of documents or a filter on
the rule that marked them, refuses a document already in another open
batch (409, naming the batch), writes the batch on each review and hands
the reviewer an engine task. GET lists the batches with assessed of total.
Also: WooThroughputReport gets its row in the date-arithmetic audit that
development's EveryTermOnTheCalendarTest now requires.
…siq.fileCase dossiq.fileCase carries the citizenIntake mark with scope and action create, which is how hermiq now recognises an intake tool (decision 177). It writes through the create form's own path: one save on the case schema as the caller, so the schema, the intake requirements, the duplicate policy and RBAC all run, and a refusal is thrown so hermiq hands the resident to a person. No intermediate intake object (decision 179). The six curated reads carry outsideAgent for hermiq's outbound surface. ai-features-on-the-case-consume-hermiq 5.1, 5.2; screens.md added.
…throughput tally has its audit row
…d the viewer reports the pages seen
Review depth per document type (every page, or a sample drawn from a seed
recorded on the review). POST .../documents/{documentRef}/pages-seen
appends each displayed page with the reviewer and time; the first page
count a review hears sets its required pages from the recorded depth.
caseType.aiFeatures (register fragment 43) maps hermiq's feature slug to case, intake or none, and holds no provider, model or residency. Register 0.20.25, info.xml bumped, en/nl strings. Ticks ai-features 1.1, and 1.2/2.1 with the files that already carry them.
…tick them with their files
# Conflicts: # lib/AppInfo/Registrar/ObjectListenerRegistrar.php # lib/Settings/dossiq_register.json # tests/schemas/schema-version-digests.json
…ctor; list readers are instances FreezeDefinition, DecisionDocumentDefinition, RoleLinkDefinition, SessionDefinition and LinkMarkerRule take their configuration entry and validate it in the constructor, which replaces the static fromArray() and the long positional parameter lists. The list factories move to RoleLinkDefinitionReader, SessionDefinitionReader and LinkMarkerRuleReader, so the services no longer reach a class statically. No behaviour change.
…inks to generic collaborators WooRequestIntake (complexity 53, coupling 14) keeps start(), receive() and the case it composes. The system reads and the case write go to SystemCaseStore, the resident's own collection (owned, linked item by item, recorded once) to CollectionCaseLinks, and the unscoped read by id to UnscopedObjectReader. receive() takes its answers mapper injected instead of building it from the date reader. Complexity 27, coupling 12, no suppression. No behaviour change.
…outstanding read to collaborators WOODocumentAssessmentService (complexity 52, coupling 13) keeps bulkUpsert, the redaction proposal and the lookup. Validation against the classifications and the refusal-ground list moves to DisclosureAssessmentValidator, the documents still waiting for a verdict to OutstandingDocuments. The public validate() and getOutstanding() delegate. Complexity 21, coupling 12. No behaviour change.
…s through collaborators WOODecisionService (coupling 13) keeps assembleDecision and its guards. The case title and the assessment tally move to DecisionRecordComposer, the ready-to-publish mark on the case to PublicationReadiness. Coupling 12, complexity 12. No behaviour change.
…catalog through collaborators WooPublicationService (coupling 13) keeps publish, withdraw, the payload and the case and decision state. Loading the case, the decision and the disclosable documents, with the disclosure matrix, moves to PublicationSources; the delivered set around the send, the files, the depublish and their logs to CatalogTransport. The public collectDelivery() and selectDisclosableDocuments() delegate. Coupling 12, complexity 26. No behaviour change.
Development closed the register to everybody outside dossiq-medewerkers (#3753); the reviewer-access block on wooDocumentAssessment still granted read, create and update to every signed-in account. They go to the staff group and the background account; delete stays with the coordinators. Schema 1.2.1, digests regenerated.
…umes the run through collaborators DecisionConcludedListener (coupling 13) keeps handle() and the event projection. Finding the record and case of the decision, and mirroring an advice deviation, move to ConcludedDecisionRecord; waking the run suspended on the decision to WaitingRunResumer. Coupling 12, complexity 22. No behaviour change.
…RequestBody BeschikkingController (complexity 61) loses its own body reader and the two successor field helpers to the generic JsonRequestBody (read, only, textOrNull). Complexity 49, no suppression. No behaviour change.
# Conflicts: # tests/l10n/language-neutral-keys.json
The seventeen suppressions the train added are gone, and a train PR had already removed two of development's, so the baseline drops from 196. No number is raised.
This was referenced Oct 12, 2026
With a coverage driver, as in CI, 57 tests on the train were risky because they ran a class their coverage metadata did not list: the review, reviewer access, import and linked-case classes of the merged PRs, and the collaborators of this refactor. Each now carries its @uses. The 33 that development carries itself are left.
Development's own PHPUnit run counts 33 risky tests: LanguageMapText in 13 test classes, OnboardingListenerRegistrar in the registrar test and CaseDateNormaliser in the intake term start test. Each test class now lists the class in its @uses. No assertion changes.
phpmd: PublicationChecks builds its text reader instead of taking a tenth constructor argument; MigrateWorkflowDefinitions (complexity 58) hands the steps and transitions of a basis template to BackfilledTemplateShape and reads rows through the shared trait instead of its own copy (complexity 47). format: prettier on the seven files development left unformatted. No behaviour change.
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ❌ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-debt-ratchet | ❌ | ||||
| check-types-e2e | ✅ | ||||
| composer | ✅ | ✅ 109/109 | |||
| npm | ✅ | ✅ 659/659 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ 8174/8174 · 4 skipped | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-12 07:17 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-debt-ratchet | ❌ | ||||
| check-types-e2e | ✅ | ||||
| composer | ✅ | ✅ 109/109 | |||
| npm | ✅ | ✅ 659/659 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ 8174/8174 · 4 skipped | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-12 07:38 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge train 2. Each PR head below is merged with
--no-ff, so GitHub marks each PR merged when this lands. Do not squash. Train 1 (#3718) has already landed; this branch was built on development after that.Included heads (32)
#3608 df9f1cf, #3632 28dfe82, #3643 921a391, #3660 c3c9dc4, #3661 364cae0, #3667 5f4509b, #3670 8deab16, #3719 ba6f654, #3626 c6f1148, #3603 62f11a1, #3724 9a8dd6f, #3644 d614fb4, #3674 0174c67, #3654 e10eb2b, #3664 a042113, #3728 c0a7f9f, #3663 1ee9c17, #3628 77c23c4, #3627 fb3fd0c, #3622 2efe4ab, #3613 0670fcd, #3605 96cdc24, #3583 8609a83, #3607 e64c25b, #3625 86ea512, #3629 6e39327, #3648 1cb50dc, #3659 19f14db, #3624 144e37f, #3665 5e31133, #3668 13cb508, #3658 258f41e.
Left out
Conflict notes
info.version0.20.32 (highest seen 0.20.31, plus one); digests regenerated once. App version: the higher one. Repair steps from both sides kept, no duplicates.ReportCommunicationChannelValuesstep stays out of info.xml (feat(case): the channel is a slug mapped at the ZGW boundary; a declared outcome issues the held product #3628 replaces it withNormaliseCommunicationChannelValues).WOODocumentAssessmentService(feat(review): document review is a generic capability: relevance, batches, pages seen, stopping rule and recall #3663 + feat(access): case-scoped reviewer access, declared per case type #3660): bothreviewerAccessandreviewskept; the excluded documents of the corpus change are removed before the relevance count.WOODecisionService:draftsandpagesSeenboth kept. Tests now pass these as named arguments.AppHostRegistrar(feat: build open OpenSpec changes (dossiq L6, part 3): agent write tools with reach #3583): DashboardWidgetList kept, the old MCP provider registration dropped, as in train 1.IntakeListenerRegistrar: both listeners.info.version0.20.33 (both sides were at 0.20.32). The case schema is 1.43.0 (the train had 1.41.0, development 1.42.0).ObjectListenerRegistrarkeeps both the case-link and the onboarding registrar.language-neutral-keys.jsonkeeps both new keys. Digests regenerated.Fixes the merge needed (no PR branch carries them)
TermijnTimerFiredListenerno longer holds the settings service that refactor(dwangsom): the penalty is a stored OpenRegister calculation #3724 retired (phpstan).Refactor for phpmd
The seventeen
@SuppressWarningsthe train added are removed and the four phpmd findings are fixed by splitting classes. Nothing is suppressed and no baseline is raised. New classes are generic and named by what they do (decision 182). No behaviour changes. Each new class has its own unit test.WooRequestIntake(complexity 53, coupling 14, now 27 and 12)Service\Intake\SystemCaseStoreService\Intake\CollectionCaseLinksService\Support\UnscopedObjectReaderWOODocumentAssessmentService(complexity 52, coupling 13, now 21 and 12)Review\DisclosureAssessmentValidatorReview\OutstandingDocumentsWOODecisionService(coupling 13, now 12)Service\DecisionDocument\DecisionRecordComposerService\DecisionDocument\PublicationReadinessWooPublicationService(coupling 13 under a suppression, now 12)Service\Publication\PublicationSourcesService\Publication\CatalogTransportDecisionConcludedListener(coupling 13 under a suppression, now 12)Service\DecisionDocument\ConcludedDecisionRecordService\Flow\WaitingRunResumerBeschikkingController(complexity 61 under a suppression, now 49)Controller\Support\JsonRequestBodyRoleLinkDefinition,SessionDefinition,LinkMarkerRule(static factories, long parameter lists)RoleLinkDefinitionReader,SessionDefinitionReader,LinkMarkerRuleReaderFreezeDefinition,DecisionDocumentDefinition(11 and 13 constructor parameters, boolean flags)Three of the seventeen suppressions hid nothing and are simply gone: the one on
PackageSchemaReferences(FleetAppIdis already exempt in the ruleset) and the two boolean-flag ones onSessionDefinition::flag()andSessionRules::assertAttendance().One signature changed:
WooRequestIntaketakes?WooReceivedAnswers $receivedAnswerswhere it took?CaseDateNormaliser $dates. The container wires it the same way.Fixes found on the way
--no-coverageand could not see this. Each test now carries its@uses.wooDocumentAssessmentgranted read, create and update to every signed-in account. Development closed the register to everybody outsidedossiq-medewerkers(fix(access): a case is read by its case type's handling teams and its assignee, and the register is closed to everybody outside dossiq-medewerkers #3753), so the block now names the staff group and the background account. Schema 1.2.1.rateBands[].upToandrateBands[].ratehave a title and a description in both registers, with four catalogue keys in English and Dutch, in the words refactor(money): payouts go through the finance app, on generic names (C16 part 2) #3769 uses.Development's own reds, fixed here
Landing this train should leave development green, so these are fixed on the train although development brought them.
CaseEndingActsTest,DeadlineReportingControllerContractTest,MigrateWorkflowDefinitionsLabelsTest,VthCaseTypeChildSeederTestand nine more test classes)LanguageMapTextran without being listed@uses LanguageMapTexton each test class. No assertion changed.ObjectListenerRegistrarTest, 2 riskyOnboardingListenerRegistrarnot listed@useson the test classIntakeTermStartListenerTest, 1 riskyCaseDateNormalisernot listed@useson the test classStubApiDriftTest(McpTool)ManifestColumnBindingTestPublicationChecks, 10 constructor parametersMigrateWorkflowDefinitions, complexity 58Service\Workflow\BackfilledTemplateShape; rows are read through the shared trait. Complexity 47.Exit codes (full runs)
COMPOSER_PROCESS_TIMEOUT=0 composer check:strict: 0, ALL CHECKS PASSED, on 4127f39 (lint, refusal-grounds snapshot, phpcs, phpmd, psalm, phpstan, PHPUnit 8178 tests). The merge after it brought no PHP and no unit test.RefusalGroundsSnapshotTestrewrites a file in the tree. It passes on the host.php vendor/bin/phpunit --no-coverage0 (8178 tests).npx vitest run --maxWorkers=20 (295 files, 3341 tests).npm run lint0.format0.test:l10n,check:schema-l10n,check:l10n-js,check:manifest,check:types-e2e,check:dexie: 0.node scripts/debt-ratchet.js: 1.phpmd.suppressWarningsis 194 and the baseline is tightened from 196 to 194. The exit code comes only fromeslint.inlineDisables, 15 against 14, which is development's own.Still red, and why
check:debt-ratchet:eslint.inlineDisables15 against 14. Development counts the same fifteen at the same places. The one named for the difference isMyWorkWidget.vue:160, a prop declared on purpose and never read. I did not raise the baseline and did not remove the prop, because that changes the widget. This needs a reviewer: either the baseline goes to 15, or the widget changes.Live passes still open: opencatalogi#1897 (import stamp, #3608/#3632), hermiq#1147 and #1148 (#3607, #3629).