#540: collaborative tags #620

Merged
Cordy merged 8 commits from fix-540 into main 2026-09-18 16:37:09 +00:00
Owner

Per the design note on #540 (build on approval-by-silence).

  • New internal/tags package: path → tags map beside recents/favorites (tags.json, statestore pattern). Normalization mirrored client-side (pure:tag-norm): lowercase, trimmed, single-spaced, letters/digits/dash/space, ≤40 chars. Caps: 20 tags/item, 5000 tagged items.
  • GET/PUT /api/v1/tags?path= and GET /api/v1/tags/find?tag= — Stat gate through the caller's scoped store on every path, including each find result (recents pattern: invisible/vanished paths drop off silently).
  • Rename/move re-keys (exact + directory-prefix carry, applied beside the #539 activity rekey); copy carries tags (destination tags win).
  • Details pane overview: Tags section between the kv grid and the drill rows — chips with ×-remove, pill input with Enter-to-add, gated on menuGates(...).mutate; hidden entirely on read-only items without tags.
  • tag:foo in the search box lists everything carrying that tag (feat.tags boot probe, curly-quoted view title, noTagResults empty state). i18n ×4.

Deliberate v1 edges (documented on the issue): tags survive the trash round-trip by staying path-keyed; a purge leaves a stale entry that the Stat gate hides and the path cap bounds.

Red witnessed on both sides, then green: go vet, go test ./..., extract fence, full web suite.

Per the design note on #540 (build on approval-by-silence). - New `internal/tags` package: path → tags map beside recents/favorites (`tags.json`, statestore pattern). Normalization mirrored client-side (`pure:tag-norm`): lowercase, trimmed, single-spaced, letters/digits/dash/space, ≤40 chars. Caps: 20 tags/item, 5000 tagged items. - `GET/PUT /api/v1/tags?path=` and `GET /api/v1/tags/find?tag=` — Stat gate through the caller's scoped store on every path, including each find result (recents pattern: invisible/vanished paths drop off silently). - Rename/move re-keys (exact + directory-prefix carry, applied beside the #539 activity rekey); copy carries tags (destination tags win). - Details pane overview: Tags section between the kv grid and the drill rows — chips with ×-remove, pill input with Enter-to-add, gated on `menuGates(...).mutate`; hidden entirely on read-only items without tags. - `tag:foo` in the search box lists everything carrying that tag (`feat.tags` boot probe, curly-quoted view title, `noTagResults` empty state). i18n ×4. Deliberate v1 edges (documented on the issue): tags survive the trash round-trip by staying path-keyed; a purge leaves a stale entry that the Stat gate hides and the path cap bounds. Red witnessed on both sides, then green: go vet, go test ./..., extract fence, full web suite.
Cordy merged commit e7d7cd1dbc into main 2026-09-18 16:37:09 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#620
No description provided.