Skip to content

feat: group ↔ campus assignment + deliberate group field coverage (#21) - #43

Merged
2000game merged 4 commits into
mainfrom
feat/group-campus-assignment-21
Jul 9, 2026
Merged

2000game merged 4 commits into
mainfrom
feat/group-campus-assignment-21

Conversation

@2000game

@2000game 2000game commented Jul 9, 2026

Copy link
Copy Markdown
Member

Implements #21 per the instance-readiness roadmap: campusId becomes a managed group field with a numeric escape hatch now; same-run campus references (a blueprint assigning a group to its own new campus) are explicitly deferred to #20's resolver and documented as such.

What's in

  • campusId in group managedFields, read via the information.* nested-with-fallback pattern and written top-level on PATCH — mirroring groupTypeId exactly. Unset campus normalizes to null (assign/change/clear all diff concretely; campus id 0 survives).
  • DSL guards: a logical campus: "key" reference is rejected with a pointer to feat: portable configs — logical references instead of numeric CT ids (shared resolver) #20; non-numeric campusId rejected — no silently un-diffed phantom fields.
  • No state migration needed for pre-existing snapshots (additive field: diff is desired-driven, drift is snapshot-driven, write body comes from fetched actuals per bug: apply reverts drifted fields — update body built from stale state snapshot, not actuals #27) — reasoning documented next to migrateState and locked by a no-phantom-drift test.
  • docs/group-field-decisions.md: the deliberate coverage table — managed (name, groupTypeId, groupStatusId, campusId), opt-in synthetic (parents, dynamic), out-of-scope with rationale (visibility, note, autoAccept, chat, sort key).
  • Runbook updated: campus row moved off "not yet implemented".

Known live-unverifiable assumption

PATCH acceptance of top-level campusId mirrors the already-working groupTypeId path but wasn't verified against a live instance — flagged for the #23 bootstrap smoke test.

Verification: 282 passed / 4 skipped, typecheck + lint clean.

Closes #21.

2000game added 4 commits July 9, 2026 08:31
Add campusId to the group's managedFields, read from information.campusId
(with top-level fallback) and normalised to null when unset, mirroring how
groupTypeId/groupStatusId are wired. The executor already writes it the
field-agnostic way (top-level campusId on PATCH). The DSL passes a numeric
campusId through as a plain field and now rejects a logical `campus: "key"`
reference (deferred to #20) and a non-numeric campusId. Document why an
additive managed field needs no state migration (unlike shortName->shorty).
…drift (#21)

- registry: managedFields snapshots campusId (nested/top-level), normalises
  unset to null, preserves campus id 0.
- context: numeric campusId passes through; logical campus + non-numeric rejected.
- plan: assign/change/clear campus as normal field updates; no-op when matching;
  no spurious diff for a pre-#21 snapshot lacking campusId.
- execute: campus assignment PATCHes a top-level { campusId }.
- adopt: a campus-assigned group captures campusId from information.
- New docs/group-field-decisions.md: managed/opt-in/out-of-scope triage of
  group fields with rationale, the information.campusId GET/PATCH shape, and
  the no-migration reasoning.
- runbook: move group<->campus assignment out of 'not yet implemented' (managed
  now); same-run campus link deferred to #20; decision-table row marked shipped;
  add campusId to the #20 hardcoded-ids list.
- README + blueprints.md + campus-blueprint example: show numeric campusId and
  note the same-run reference is #20's job.
Emitting campusId: null would actively manage 'no campus' — a later
UI-assigned campus would be planned back to null. Omission leaves the
field unmanaged, matching the adopt philosophy. Flagged by the PR #43
review.
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.

feat: group ↔ campus assignment + deliberate group field coverage

1 participant