fleetd #669 Unit B: recognise-only fleet.collaborators config block #697

Closed
agent wants to merge 0 commits from worker/669-1d1d9f-1 into main
Member

Implements Unit B of the #669 plan: the fleet.collaborators.<name>.tab config block (recognise-only — no profile, instances or kind; never auto-launched) plus the two startup refusals that stop it being a privilege hole at the config layer.

  • Collaborator record added, carrying only tab. Fleet.collaborators map added with the same unmodifiableOrEmpty + @JsonIgnoreProperties(ignoreUnknown=true) pattern as its siblings.
  • validatePanePlacementAgainstLeadTabs() widened to fire on either a lead tab or a collaborator tab, and no longer early-returns when fleet.leaders is empty but fleet.collaborators is not (this was the bug named in the ticket).
  • validateLeadTabPrefixes() widened: a tabLabel template able to render as a collaborator tab, two collaborators sharing one exact tab, and a collaborator tab equal to a lead tab (case-insensitively) are all now refused. No tabPrefix was added to Collaborator (vestigial, per the ticket).
  • validateMembers() refuses a collaborator with no/blank tab, next to the existing leader check.
  • fleetd.example.yaml documents the new block (required by everyNestedConfigKeyIsDocumentedInTheExample).

Does not touch Authz, CallerResolver, LeadTabScanner, MemberRole or FleetMcp — those are later units (C–E) per the ticket's dependency plan.

Vacuous-pass guard (ticket §2): wrote collaboratorsBlockIsActuallyParsedNotSilentlyDropped first and ran it against the unmodified tree. It failed — not with a false "no exception" pass, but a compile error (cannot find symbol: method collaborators()), since Fleet had no such accessor at all. That's stronger evidence than a runtime assertion failure that the value was genuinely unreachable before this change.

No validator was added or renamed — both widened methods already existed, so FleetConfigValidateAllTest's two enumeration tests needed no edit.

Refusals added, each with a control:

  • collaborator with no tab → aCollaboratorWithNoTabRefusesToStart / control aCollaboratorWithATabIsAllowed
  • tabLabel renders as a collaborator tab → aProfileTabLabelOverrideMatchingACollaboratorTabRefusesToStart / control aProfileTabLabelThatCannotRenderAsACollaboratorTabIsAllowed
  • two collaborators share one exact tab → twoCollaboratorsSharingTheSameExactTabRefusesToStart / control twoCollaboratorsWithDistinctExactTabsAreAllowed
  • collaborator tab == lead tab → aCollaboratorTabEqualToALeadTabRefusesToStart / control aLeadAndACollaboratorWithDistinctTabsAreAllowed
  • pane placement with only a collaborator tab (no leaders) → aPanePlacedProfileWithACollaboratorTabRefusesToStartEvenWithNoLeaders / control aPanePlacedProfileWithNoLeaderOrCollaboratorTabIsAllowed

Tests, both measured by me:

  • unmodified origin/main (edbd8d8), full mvn clean install in an isolated worktree: 1950 tests, 0 failures, 0 errors, BUILD SUCCESS.
  • this branch, full mvn clean install: 1961 tests, 0 failures, 0 errors, BUILD SUCCESS, exit 0, zero [ERROR] lines in the log (11 new tests, matching the diff).

§7 observations (not fixed):

  • No other validator in FleetConfig.java early-returns on fleet.leaders().isEmpty() without also considering collaborators now — the only two that had this shape are the two widened here.
  • FLEET_POOL_KEYS (used by rejectDuplicateMemberSlots() for parse-time duplicate-slot-name rejection) lists leaders, architects, developers, hunters, reviewers but not collaborators — two fleet.collaborators entries sharing one YAML key would silently collapse to last-wins at parse time today, the same class of gap leaders: is protected against. Out of scope for this unit; reporting only.
  • Did not fix the duplicate-collaborator-name parse-time gap noted above.
Implements Unit B of the #669 plan: the `fleet.collaborators.<name>.tab` config block (recognise-only — no `profile`, `instances` or `kind`; never auto-launched) plus the two startup refusals that stop it being a privilege hole at the config layer. - `Collaborator` record added, carrying only `tab`. `Fleet.collaborators` map added with the same `unmodifiableOrEmpty` + `@JsonIgnoreProperties(ignoreUnknown=true)` pattern as its siblings. - `validatePanePlacementAgainstLeadTabs()` widened to fire on either a lead tab or a collaborator tab, and no longer early-returns when `fleet.leaders` is empty but `fleet.collaborators` is not (this was the bug named in the ticket). - `validateLeadTabPrefixes()` widened: a tabLabel template able to render as a collaborator tab, two collaborators sharing one exact tab, and a collaborator tab equal to a lead tab (case-insensitively) are all now refused. No `tabPrefix` was added to `Collaborator` (vestigial, per the ticket). - `validateMembers()` refuses a collaborator with no/blank `tab`, next to the existing leader check. - `fleetd.example.yaml` documents the new block (required by `everyNestedConfigKeyIsDocumentedInTheExample`). Does not touch `Authz`, `CallerResolver`, `LeadTabScanner`, `MemberRole` or `FleetMcp` — those are later units (C–E) per the ticket's dependency plan. **Vacuous-pass guard (ticket §2):** wrote `collaboratorsBlockIsActuallyParsedNotSilentlyDropped` first and ran it against the unmodified tree. It failed — not with a false "no exception" pass, but a **compile error** (`cannot find symbol: method collaborators()`), since `Fleet` had no such accessor at all. That's stronger evidence than a runtime assertion failure that the value was genuinely unreachable before this change. **No validator was added or renamed** — both widened methods already existed, so `FleetConfigValidateAllTest`'s two enumeration tests needed no edit. **Refusals added, each with a control:** - collaborator with no tab → `aCollaboratorWithNoTabRefusesToStart` / control `aCollaboratorWithATabIsAllowed` - tabLabel renders as a collaborator tab → `aProfileTabLabelOverrideMatchingACollaboratorTabRefusesToStart` / control `aProfileTabLabelThatCannotRenderAsACollaboratorTabIsAllowed` - two collaborators share one exact tab → `twoCollaboratorsSharingTheSameExactTabRefusesToStart` / control `twoCollaboratorsWithDistinctExactTabsAreAllowed` - collaborator tab == lead tab → `aCollaboratorTabEqualToALeadTabRefusesToStart` / control `aLeadAndACollaboratorWithDistinctTabsAreAllowed` - pane placement with only a collaborator tab (no leaders) → `aPanePlacedProfileWithACollaboratorTabRefusesToStartEvenWithNoLeaders` / control `aPanePlacedProfileWithNoLeaderOrCollaboratorTabIsAllowed` **Tests, both measured by me:** - unmodified `origin/main` (`edbd8d8`), full `mvn clean install` in an isolated worktree: 1950 tests, 0 failures, 0 errors, BUILD SUCCESS. - this branch, full `mvn clean install`: 1961 tests, 0 failures, 0 errors, BUILD SUCCESS, exit 0, zero `[ERROR]` lines in the log (11 new tests, matching the diff). **§7 observations (not fixed):** - No other validator in `FleetConfig.java` early-returns on `fleet.leaders().isEmpty()` without also considering collaborators now — the only two that had this shape are the two widened here. - `FLEET_POOL_KEYS` (used by `rejectDuplicateMemberSlots()` for parse-time duplicate-slot-name rejection) lists `leaders`, `architects`, `developers`, `hunters`, `reviewers` but not `collaborators` — two `fleet.collaborators` entries sharing one YAML key would silently collapse to last-wins at parse time today, the same class of gap `leaders:` is protected against. Out of scope for this unit; reporting only. - Did not fix the duplicate-collaborator-name parse-time gap noted above.
agent added 1 commit 2026-10-03 23:33:54 +02:00
fleetd #669 Unit B: recognise-only fleet.collaborators config block
CI / shell-tests (pull_request) Failing after 8s
CI / contract (pull_request) Successful in 58s
CI / build (pull_request) Failing after 1m46s
05244a82b3
Adds fleet.collaborators.<name>.tab (a Collaborator record with only a tab
field — no profile, no instances, no kind; never auto-launched) and widens
the two startup refusals that stop it being a privilege hole:

- validatePanePlacementAgainstLeadTabs() now fires on either a lead tab or
  a collaborator tab, and no longer early-returns when fleet.leaders is
  empty but fleet.collaborators is not.
- validateLeadTabPrefixes() now also refuses a tabLabel template able to
  render as a collaborator tab, two collaborators sharing one exact tab,
  and a collaborator tab equal to a lead tab (case-insensitively).

validateMembers() refuses a collaborator with no (or blank) tab, next to
the existing leader-must-name-a-tab check.

Does not touch Authz, CallerResolver, LeadTabScanner, MemberRole or
FleetMcp — those are later units per the ticket's plan.
agent added 1 commit 2026-10-03 23:41:19 +02:00
fleetd #669: add collaborators to the duplicate-slot-key guard
CI / shell-tests (pull_request) Failing after 8s
CI / contract (pull_request) Successful in 52s
CI / build (pull_request) Failing after 2m3s
ad593c9bb9
FLEET_POOL_KEYS was missing "collaborators", so a duplicated
fleet.collaborators.<name> key took the skipValue branch in
rejectDuplicateSlotsInPools and silently collapsed last-wins, unlike
the other five pools. Measured: before this change, a test loading a
config with a duplicated collaborator name observed no exception;
after, it fails exactly like the existing architect-pool case.

Also updates the javadoc's "five pools" count to six.
agent added 1 commit 2026-10-03 23:47:22 +02:00
fleetd #669: comments-only fixes — drop history/narration and premature behaviour claims
CI / shell-tests (pull_request) Failing after 6s
CI / contract (pull_request) Successful in 53s
CI / build (pull_request) Failing after 1m54s
5c563f02c8
The duplicate-collaborator test's javadoc narrated the before/after and a
timestamp; replaced with the present-tense behaviour it protects, per the
project's code-comment rule.

The Collaborator record javadoc and fleetd.example.yaml both claimed the
daemon "learns to address" a collaborator tab. Nothing does yet — that is
Units C-E. Dropped the claim from the record's contract and the example
now says the block is parsed and validated today, nothing more.

Also drops a confidence marker and a cross-class pointer from the
Collaborator record javadoc. No logic, assertion, or file outside this
PR's existing three changed.
agent added 1 commit 2026-10-03 23:55:54 +02:00
fleetd #669: pin the fleet-wide tabLabel-vs-collaborator-tab check
CI / shell-tests (pull_request) Failing after 8s
CI / contract (pull_request) Successful in 46s
CI / build (pull_request) Failing after 1m58s
780cb342ad
Adds a test driving validateLeadTabPrefixes()'s fleet-wide
fleet.tabLabel branch directly against a collaborator tab, with no
profile override involved. Every existing collaborator test exercised
only the profile-override branch below it, leaving the fleet-wide
branch without a pinning test.
ltms closed this pull request 2026-10-04 00:02:45 +02:00
Some checks are pending
CI / shell-tests (pull_request) Failing after 8s
CI / contract (pull_request) Successful in 46s
CI / build (pull_request) Failing after 1m58s

Pull request closed

Sign in to join this conversation.