Skip to main content

Implementation Plan: Work Changelog

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


1. Architecture

2. Tech Choices

ConcernChoiceRationale
Storagejsonb column changelog on existing history tableNo new tables; queryable + flexible
Activity typesPlain string enumEasy to extend
PaginationOffset-based via limit + offset paramsSufficient for typical history sizes
Filter groupingServer-side mapping from group → activity-type setUI doesn't need to know the full enum

3. Data Model

@Entity('work_generation_history')
export class WorkGenerationHistory {
// ... existing columns
@Column({ type: 'varchar', nullable: true }) activityType: string | null;
@Column({ type: 'jsonb', nullable: true }) changelog: WorkChangelog | null;
}

interface WorkChangelog {
summary?: string | null;
addedCount: number;
updatedCount: number;
removedCount: number;
entries: WorkChangelogEntry[];
}

interface WorkChangelogEntry {
entityType: 'item' | 'comparison' | 'category' | 'tag' | 'collection';
action: 'added' | 'updated' | 'removed';
name: string;
slug?: string;
fieldsChanged?: string[];
}

Migration: additive — new columns default to null for existing rows.

4. API Surface

MethodEndpointDescription
GET/api/works/:id/historyPaginated history with optional activityType filter

5. Plugin / Web / CLI

  • Plugins: pipeline plugins call the activity-log service when they finalise a generation; they don't own the changelog format.
  • Web: History tab with pagination + filter chips.
  • CLI: not exposed.

6. Background Jobs

None — changelog writes are inline.

7. Security & Permissions

  • Read: viewer.
  • Write: only platform internals — no public endpoint accepts user-supplied changelog payloads.

8. Observability

The changelog itself is the observability surface. No additional metrics.

9. Risks & Mitigations

RiskMitigation
Huge entry lists bloat history rowsCap entries per row at a configurable limit
Forgotten activity-type assignmentService requires activityType non-null on insert
Secret leak via changelog name fieldname is the entity name (item/category/etc.), not free text — no secret risk

10. Constitution Reconciliation

See spec.md §9.

11. References

  • Spec: ./spec.md
  • Implementation:
    • packages/agent/src/activity-log/activity-log.service.ts
    • packages/agent/src/entities/work-generation-history.entity.ts