Skip to content

fix(fleet): planninq is live and swept; zaakafhandelapp is the deprecated one - #644

Merged
rubenvdlinde merged 3 commits into
mainfrom
fix/planninq-is-not-deprecated
Aug 30, 2026
Merged

fix(fleet): planninq is live and swept; zaakafhandelapp is the deprecated one#644
rubenvdlinde merged 3 commits into
mainfrom
fix/planninq-is-not-deprecated

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Three sources disagreed about which apps are live, and each disagreement hides work.

CLAUDE.md fleet-apps.json app-health.md
planninq core app deprecated Deprecated table
zaakafhandelapp core app swept Deprecated table

planninq is live

It meets the mechanical membership test exactly, and the reason recorded for deprecating it has been resolved:

app id           <id>planninq</id>      <- the recorded blocker was 'app id pending'
code-quality.yml on development         present
last 4 dev runs  success x4 (2026-08-29)
commits (30d)    71
latest release   v0.1.4  2026-08-30     <- released while listed as not-taken-forward
archived         false

Being deprecated meant no drift sweep and no unattended merge ever named it — the exact failure this file's own comment warns about ("humaniq sat red on development for six days because no sweep named it").

zaakafhandelapp is the deprecated one

Confirmed with @rubenvdlinde: superseded by dossiq, which occupies the same Application / Case management slot. Moved out of swept so sweeps and unattended merge stop claiming it, and its rationale is now written down.

And the reason is now recorded

planninq sat in the Deprecated table on the strength of a stale one-line reason. A row with no live rationale is indistinguishable from an app someone forgot, so the section now carries a Why table — deprecation is a decision, and the decision should be visible rather than inferred.

swept goes 21 → 21 (planninq in, zaakafhandelapp out); deprecated [planninq][zaakafhandelapp]. JSON validated, list sorted.

planninq ships <id>planninq</id>, runs code-quality.yml on development,
and its last four Code Quality runs on development are green (most
recent 2026-08-29). It is not archived. It meets the mechanical
membership test exactly.

Marked deprecated, it was excluded from every sweep -- the drift sweep
never named it and the Friday merge never touched its PRs. That is the
failure this file's own comment warns about: humaniq sat red on
development for six days because no sweep named it.
rubenvdlinde pushed a commit that referenced this pull request Aug 30, 2026
My change added planninq to `swept` without removing it from
`deprecated`, leaving it in BOTH lists. #644 makes the same call with the
research behind it — planninq ships <id>planninq</id> and released while
still marked not-taken-forward — and pairs it with the correction that
zaakafhandelapp is the deprecated one, superseded by dossiq.

This PR keeps to the dependabot allowlist and the back-merge workflow.
@rubenvdlinde
rubenvdlinde merged commit a2e3bd9 into main Aug 30, 2026
39 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/planninq-is-not-deprecated branch August 30, 2026 08:46
rubenvdlinde added a commit that referenced this pull request Aug 30, 2026
…642)

* feat(fleet): admit dependabot, and carry what lands back downstream

Dependabot reads its config from the repository's DEFAULT branch only. Ten
fleet apps default to main, whose .github/dependabot.yml carries no
target-branch, so every bump is opened against main -- where
branch-protection refused it. Measured 2026-08-30: 41 open pull requests
that could never merge, across zaakafhandelapp (12), filinq (11),
openregister (5), opencatalogi (3), integriq (3), dossiq (2), planninq (2)
and one each on thematiq, launchpad and stackiq. Dependabot reopens them,
so the backlog only grew.

Three changes:

* branch-protection.yml admits dependabot/* into main and beta, alongside
  the existing beta, hotfix/* and release/v* allowances. Exercised across
  12 source/target pairs: the six that should pass do, and feature/* is
  still refused into both main and beta, so the allowance is narrow.

* fleet-back-merge.yml carries whatever reaches main down into beta, and
  whatever reaches beta down into development. It does not try to identify
  the source of each commit -- squash merges, direct pushes and
  force-pushes all defeat that. It asks the equivalent question the refs
  can answer exactly: does the upstream branch hold anything the
  downstream one does not?

* fleet-apps.json gains planninq. It listed 21 names but planninq was not
  among them, so the app was invisible to every fleet sweep -- the exact
  failure the file's own comment warns about.

A dry run of the real logic against the fleet reports 42 outstanding
back-merges and 2 correct skips (humaniq has neither main nor beta). Every
app has main ahead of beta and beta ahead of development, which is why
promotions have been conflicting on version files and lockfiles.

Merging is held to the same rule as fleet-friday-merge: every check
reported and none failed. Pending, cancelled, unreadable and ZERO checks
are each a refusal -- a conflicted pull request runs no CI at all, and
"no failures" is exactly what that looks like.

Verified: YAML parses; bash -n on each run block extracted from the parsed
YAML; and the hop logic exercised against a mocked gh across 9 cases,
including the two that matter most -- an empty comparison and a literal
"null" are both refused rather than read as "in sync".

* revert(fleet-apps): leave the planninq decision to #644

My change added planninq to `swept` without removing it from
`deprecated`, leaving it in BOTH lists. #644 makes the same call with the
research behind it — planninq ships <id>planninq</id> and released while
still marked not-taken-forward — and pairs it with the correction that
zaakafhandelapp is the deprecated one, superseded by dossiq.

This PR keeps to the dependabot allowlist and the back-merge workflow.

* fix(back-merge): --admin, and keep the refusal text

Both `Beta Branch Protection` and `Development Branch Protection` set
required_approving_review_count: 1 with OrganizationAdmin as the only
bypass actor. A plain `gh pr merge` from this token is refused with "the
base branch policy prohibits the merge", so this workflow would have
opened 42 back-merge pull requests and then merged none of them.

That is not hypothetical: fleet-friday-merge.yml shipped with the same
omission and merged almost nothing for weeks while reporting success. 20
of its 23 real attempts on 2026-08-28 died exactly here, 18 of them
release version bumps that were then superseded and closed unmerged.

It also stops discarding the error. The old shape sent stderr to
/dev/null, so a refusal named no reason and read as an ordinary conflict
-- which is why the friday-merge cause went undiagnosed for so long.

This does not weaken the gate: those same rulesets require ZERO status
checks, so GitHub would merge a red pull request here. The green rule
enforced above is strictly stronger than the policy being bypassed.

Verified: YAML parses; bash -n on each run block extracted from the
parsed YAML; and the hop logic re-exercised against a mocked gh, now
asserting the merge is invoked with BOTH --merge and --admin, and that a
refusal is reported with its reason rather than swallowed.

* fix(back-merge): a branch-to-branch PR cannot converge anything

The first shape of this workflow opened `gh pr create --head main --base
beta`. That cannot work, and testing it on the real fleet is what showed
why: such a pull request has no way to resolve the version conflict, so it
opens CONFLICTING, gets no CI at all (a conflicted PR runs none), and sits
forever. Measured on portaliq -- the direct beta->development pull request
opened CONFLICTING while the sync branch below merged clean and took the
gap from 5 commits to 0.

It now does what release.yml already does for its own
`sync/*-to-development` pull requests: branch off the DOWNSTREAM ref, merge
the upstream one, and resolve ONLY the version files to the downstream
side -- whose unstable line is ahead of the released one, so a version
never moves backwards. Anything else that conflicts is a real disagreement
and stops for a human, because resolving those automatically is how a sync
silently drops work.

A 0-file merge is the POINT, not a no-op. A squash merge of beta into main
creates a commit beta does not contain even though the trees are identical;
recording the ancestry is the payload. That also decides when merging
unattended is safe:

  0 files changed  -> nothing to test; merge. Requiring CI would block
                      ancestry repair forever on branches already red for
                      unrelated reasons, which is most of beta and main.
  any file changed -> real content moves; every check must be green.

Proven end to end on portaliq and thematiq before this was written: both
hops carried, both apps now report 0 commits outstanding in both
directions, and each app's stalled `development -> beta` promotion went
from CONFLICTING to MERGEABLE as a direct result.

Verified: YAML parses; bash -n on each run block extracted from the parsed
YAML.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant