Skip to main content

Implementation Plan: Collections

Feature ID: collections Spec: ./spec.md Status: Done (Retrospective) Last updated: 2026-05-01


1. Architecture

2. Tech Choices

ConcernChoiceRationale
StorageYAML in the data repoPrinciple III
Slug generationslugifyText() from shared utilsConsistent with categories/tags
Mutation atomicitySingle git commit per CRUD operationSimple recovery model
AI integrationStandard Pipeline categorization stepKeeps generation logic in the plugin
Toggle separationTwo independent flags (website / pipeline)Lets users curate manually with AI off

3. Data Model

No core schema changes. The data lives in collections.yml:

- id: editors-picks
name: Editor's Picks
description: Hand-picked favorites by the editorial team
priority: 1
- id: best-for-beginners
name: Best for Beginners

Items reference by slug id:

# data/<item-slug>/item.yml
collection: editors-picks

4. API Surface

MethodEndpointDescription
GET/api/works/:id/categories-tagsList taxonomy (3 dims)
POST/api/works/:id/collectionsCreate
PUT/api/works/:id/collections/:collectionIdUpdate
DELETE/api/works/:id/collections/:collectionIdDelete + cleanup

5. Plugin Surface

  • Standard Pipeline categorization step assigns collections during generation when generate_collections: true.
  • No new plugin capability — runs inside the existing pipeline.

6. Web / CLI

  • Web: Items → Collections tab with create/edit/delete UI.
  • Website-side rendering controlled by collections_enabled in website settings.
  • CLI: not directly exposed; piggybacks on work commands.

7. Background Jobs

None — collection mutations are inline.

8. Security & Permissions

  • Read: viewer role.
  • Write: editor role.
  • Both checked via WorkOwnershipService.

9. Observability

  • Activity log: collection_change entries with action (added / updated / removed) and collection name.
  • Surfaces in the Work Changelog.

10. Risks & Mitigations

RiskMitigation
Stale references after deleteService clears collection field on all affected items
AI assigns to non-existent collectionPipeline only assigns collections it has just defined
Name collision via concurrent createsValidation reads then writes within a single git session

11. Constitution Reconciliation

See spec.md §9.

12. References

  • Spec: ./spec.md
  • Implementation:
    • packages/agent/src/services/work-taxonomy.service.ts
    • packages/plugins/standard-pipeline/src/steps/categories-tags-processing.step.ts