Tracking (epic): codeplug-tool#93 · in-scope: #91, #53, #52, #54
Epic plan: .cursor/plans/vendor-neutral_data_model_epic_941d5a01.plan.md
Review doc: vendor-agnostic-review.md
Outstanding: pristine-model-refactor-outstanding.md
Doc audit: vendor-boundary-doc-audit.md — documentation violations of the vendor-boundary / format-agnostic rules, scheduled by phase below
Status: In progress (Phase 4 complete on branch 93/paddy/fk-by-uuid, PR pending)
The model refactor is delivered as a phased epic. Each phase is a self-contained subplan, executed by a separate agent session, on its own branch + PR, merged to main sequentially before the next phase branches.
- One phase at a time. Do not start a phase until the previous phase's PR is merged to
main. - Each phase branches
{ticket}/paddy/{slug}fromorigin/main(latest). - Generate the phase's subplan first (use make-a-plan in plan mode), then execute it.
- Commit atomically as you go (per git-workflow); never batch into one end-of-phase commit.
- Update this file and the outstanding file at every checkpoint and before opening each PR. This is the primary handoff channel between agent sessions.
- Keep the OpenGD77/1701 import → edit → export → re-import round-trip green every phase.
The next agent relies on these values. Keep them accurate.
- Current
CODEPLUG_SCHEMA_VERSION: 7 - Last merged phase: Phase 3 (provenance meta + opengd77Extras rename) — Phase 4 ready on branch
93/paddy/fk-by-uuid mainis at: after Phase 3 merge — Phase 4 PR pending- Epic ticket: #93. No per-phase child tickets — FK-by-UUID and provenance/rename are folded under #93.
- New tickets created in Phase 0:
- OpenGD77 export issues (tracking): #95
- Shared test builders:
src/test/builders/(Phase 2) - Provenance
metashape:EntityMeta.imported: { formatId, sourceFile, importedAt, memberWireNames?, contactWireName?, rxGroupListWireName? }— accessors insrc/lib/entityProvenance.ts vendorExtrasrenamed toopengd77Extras? Yes (Phase 3)
- Epic with per-phase subplans/PRs, sequential to
main. - Dual-kind FK = discriminated ref
{ kind: 'talkGroup' | 'contact'; id };TalkGroupandContactstay separate entities. vendorExtras→opengd77Extras; recurring extras may be promoted to first-class fields.scanSkipis first-class;zoneSkipstays an OpenGD77 extra.- Field types per section 2 of the review doc: frequencies as integer Hz;
power/squelchas percent withnull= master; tones as a CTCSS/DCS string enum;colourCode/timeslot/dmrId/transmitTimeoutnullable numbers/enums;rxOnlyboolean. Channel.numberremoved from the model; assigned at OpenGD77 export.aprsConfigNamestays a string FK until APRS is modelled.- Vendor limits (e.g. zone member cap) belong at export only — never in model/mutations/validation/CRUD.
Status: Complete (merged)
Branch: 91/paddy/data-model-vendor-agnostic-review
PR: #94 (Closes #91)
Delivered
- vendor-agnostic-review.md (
74c4293) + refined field types (05f9142). - These tracking docs created (
62b39fe). - OpenGD77 export-issues tracker created: #95.
- Fixed stale schema version in persistence README (v1 → 3).
Verify
- Docs-only; no code changed.
- Tracking docs linked from docs/features/README.md and the epic plan.
Status: Complete (merged)
Branch: 53/paddy/drop-channel-number
PR: #96 (Closes #53)
Delivered
- Export assigns
Channel Numbersequentially (0bdcf8c). - Import discards wire column; merge equality updated (
0f95e08). - Channel edit/detail UI no longer shows channel number (
de1f117). Channel.numberremoved; schema v4 migration discards persisted values (fb6ee6d).- Docs: data-model README, persistence schema v4, OpenGD77 reference, map channels.
- Doc-compliance pass on touched files (data-model README, AGENTS.md, persistence, map README/channels/zones): name FKs reframed as transitional → UUID, OpenGD77/CSV defaults generalised. Remaining violations catalogued in vendor-boundary-doc-audit.md and scheduled under the phases below.
Verify
npm run lint && npm run test && npm run buildgreen.- v3→v4 migration fixture passes; round-trip test green.
- Original import channel numbers are not preserved (by design).
Status: Complete (merged)
Branch: 52/paddy/typed-channel-fields
PR: #98 (Closes #52)
Delivered
- Schema v5 typed
Channelfields (Hz frequencies, percent power/squelch, tone enum, DMR scalars,rxOnlyboolean). - Neutral helpers in
src/lib/channelFields/; OpenGD77 wire mapping insrc/lib/import|export/opengd77/channelWire.ts. - v4→v5 migration on load; shared test builders at
src/test/builders/. - Channel CRUD and map UI updated for typed controls.
- Doc audit #3: OpenGD77 import/export columns removed from generic
channel-modes.md; wire rules indocs/reference/opengd77/.
Verify
npm run lint && npm run test && npm run buildgreen.- v4→v5 migration fixture passes; OpenGD77 round-trip test green.
Status: Complete (merged)
Branch: 93/paddy/import-provenance-meta
Delivered
- Per-entity
EntityMeta.importedprovenance; zone/RGL member wire names inmeta.imported.memberWireNames. vendorExtras→opengd77Extras; schema v6 migration (v5→v6 fixture).- Accessors in
src/lib/entityProvenance.ts; import stamps provenance on OpenGD77 parse. - Neutral unresolved member reason string in map layer (
unresolved member).
Doc debt cleared: vendor-boundary doc audit #4 (map zones + channels.ts reason string).
Verify
npm run lint && npm run test && npm run buildgreen.- v5→v6 migration fixture passes; OpenGD77 round-trip test green.
Status: Complete (PR pending)
Branch: 93/paddy/fk-by-uuid
Prerequisite: Phase 3 provenance meta shape merged.
Delivered
EntityReftype and resolution/export helpers (src/lib/entityRefs.ts).Channel.contactRefreplacescontactName;Channel.rxGroupListIdreplacesrxGroupListName.RxGroupList.memberRefsreplaces internal name membership; wire names in provenance only.- Schema v7 migration (v6→v7 fixture); import merge resolves refs after entity merge.
- CRUD, validation, mutations, report lookups, and map popups use id-based FKs.
aprsConfigNameunchanged (string FK until APRS modelled).
Doc debt cleared: vendor-boundary doc audit #1, #2, #5 (data-model README, crud README, RxGroupListMemberPicker sidecar).
Verify
npm run lint && npm run test && npm run buildgreen.- v6→v7 migration fixture passes (channels + RGL memberRefs); OpenGD77 round-trip test green.
Status: Complete — PR pending
Branch: 54/paddy/first-class-callsign-naming
Log: channel-naming-progress.md
Delivered: callsign + name + exportNameMode, channelNaming.ts, import split + export compose, schema v12, CRUD/map UI.
- Open PR for Phase 5 (#54); merge when reviewed.
From the doc audit #6–#8 — pure doc/anchor fixes, clearable in any small docs PR (not tied to a model change):
.cursor/rules/codeplug-tool.mdc"Channel map" section points at non-existentChannelMap.tsx/Map.tsx/csv.ts; update toCodeplugMap, real routes, andsrc/lib/import/.README.md(repo root) L53 — soften "import an OpenGD77 CPS export" to keep OpenGD77 as an example, not the definition.- Confirm no other stale
ChannelMapanchors remain (seeCodeplugMap.md).