Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
446 changes: 74 additions & 372 deletions .claude/agent-memory/product-architect/MEMORY.md

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions .claude/agent-memory/product-architect/epic04-household-items.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# EPIC-04: Household Items Architecture

## ADR-016: Separate Entity with Parallel Structure

Decision: Household items are a separate `household_items` table (not STI on work_items, not EAV).

### Rationale

- Work items have scheduling/dependencies; household items have purchase status/delivery tracking
- Scheduling engine unaffected
- No nullable column confusion
- Budget overview aggregates both via UNION queries

## Schema (Migration 0010)

6 new tables:

1. **household_items**: Main entity
- TEXT PK (UUID), name, description, category (CHECK 8 values), status (CHECK 4 values)
- vendor_id FK->vendors ON DELETE SET NULL
- url, room (free text), quantity (>=1), order_date, expected_delivery_date, actual_delivery_date
- created_by FK->users ON DELETE SET NULL, created_at, updated_at
- Indexes: category, status, room, vendor_id, created_at

2. **household_item_tags**: M:N junction (composite PK)
3. **household_item_notes**: Per-item notes (TEXT PK, content, created_by FK)
4. **household_item_budgets**: Mirrors work_item_budgets exactly (no invoice linkage)
5. **household_item_work_items**: Simple M:N junction (no dep types like FS/SS/FF/SF)
6. **household_item_subsidies**: M:N with subsidy_programs (composite PK)

### Category Values

furniture, appliances, fixtures, decor, electronics, outdoor, storage, other

### Status Values

not_ordered, ordered, in_transit, delivered

### Shared Tables Reused

- tags (global resource)
- vendors (contractors + suppliers)
- budget_categories, budget_sources
- subsidy_programs
- document_links (already supports household_item entity_type)

## API Contract (20 Endpoints)

- Household Items: GET list (paginated/filterable/sortable), POST create, GET detail, PATCH update, DELETE
- Notes: GET list, POST create, PATCH update, DELETE (author/admin check)
- Budget Lines: GET list, POST create, PATCH update, DELETE (mirrors work item budget line endpoints)
- Work Item Links: GET list, POST link, DELETE unlink (simple M:N, 409 on duplicate)
- Subsidy Links: GET list, POST link, DELETE unlink (simple M:N, 409 on duplicate)
- Subsidy Payback: GET (same calculation as work item payback)

### List Query Params

- Filters: category, status, vendorId, room, tagId, q (full-text search on name/description/room)
- Sort: name, category, status, room, order_date, expected_delivery_date, created_at, updated_at

### Response Shapes

- HouseholdItemSummary: includes tagIds[], budgetLineCount, totalPlannedAmount
- HouseholdItemDetail: extends Summary with tags[], workItems[], subsidies[]
- Budget lines include actualCost/actualCostPaid/invoiceCount (always 0 for household items, shape consistency)

### Budget Overview Update

- GET /api/budget/overview must aggregate across BOTH work_item_budgets and household_item_budgets
- Response shape unchanged; backend uses UNION queries

## No New Error Codes Needed

- Existing codes cover all cases (NOT_FOUND, VALIDATION_ERROR, CONFLICT, UNAUTHORIZED, FORBIDDEN)

## Wiki Pages Updated

- Schema.md: EPIC-04 section with all 6 tables + migration SQL
- API-Contract.md: 20 endpoints (~1050 lines)
- ADR-016-Household-Items-Architecture.md: New ADR
- ADR-Index.md: Added ADR-016 entry
- PR #395: docs(epic-04) targeting beta
20 changes: 12 additions & 8 deletions .claude/agent-memory/product-owner/MEMORY.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Product Owner Agent Memory

## Backlog State (as of 2026-03-01)
## Backlog State (as of 2026-03-02)

- 12 epics, 60+ user stories across all epics
- 12 epics, 75+ user stories across all epics
- Sprint 1 COMPLETE: EPIC-01, EPIC-02, EPIC-11
- Sprint 2 COMPLETE: EPIC-03, EPIC-12
- Sprint 3 COMPLETE: EPIC-05 (v1.9.0), EPIC-06 (v1.10.0)
- Sprint 4 PLANNING: EPIC-08 stories created (#354-#360), EPIC-04 not yet decomposed
- Sprint 4 IN PROGRESS: EPIC-08 COMPLETE (v1.11.0), EPIC-04 stories created (#387-#394)
- Security hygiene backlog: Issue #315 (rate limiting, headers, lockout, etc.)
- GitHub Projects board: "Cornerstone Backlog" (project #4, owner steilerDev)

Expand All @@ -19,6 +19,7 @@
- EPIC-12 (#115): Design System Bootstrap -- CLOSED 2026-02-18, promoted with EPIC-03 via PR #110
- EPIC-05 (#5): Budget Management -- CLOSED (v1.9.0), all 12 stories
- EPIC-06 (#6): Timeline & Gantt -- CLOSED (v1.10.0), all 9 stories
- EPIC-08 (#8): Paperless-ngx Document Integration -- CLOSED (v1.11.0), all 6 stories

## Epic Quick Reference

Expand Down Expand Up @@ -50,13 +51,16 @@ All 8 stories merged to beta. Promotion PR #110 (beta -> main) merged. See [epic

All 9 stories + refinement + E2E tests + UAT fixes merged and promoted to main.

## EPIC-08 Stories (Paperless-ngx Document Integration) — IN PROGRESS
## EPIC-08 — COMPLETE (v1.11.0, promoted 2026-03-02)

7 stories created (#354-#360). See [epic-08-planning.md](epic-08-planning.md) for full details.
Story 8.1 (#354): ACCEPTED (PR #362, round 2 review). All 12 ACs passed.
All 6 stories merged and promoted to main. Story 8.6 (#359) remains open, blocked by EPIC-04. See [epic-08-planning.md](epic-08-planning.md).

- Acceptance criteria text corrected post-review: PAPERLESS_TOKEN -> PAPERLESS_API_TOKEN, removed version from status, /thumbnail -> /thumb
Remaining stories in Backlog. Story 8.6 blocked by EPIC-04.
## EPIC-04 Stories (Household Items & Furniture) — PLANNING COMPLETE

8 stories created (#387-#394). See [epic-04-planning.md](epic-04-planning.md) for full details.
Stories 4.1 (#387) and 4.2 (#388) set to Todo. Remaining stories in Backlog.
Story 8.6 (#359, EPIC-08) linked as sub-issue, blocked by #391 (detail page).
Total: 85 ACs, 103 UAT scenarios across 8 stories.

## EPIC-05 — COMPLETE (v1.9.0, promoted)

Expand Down
67 changes: 67 additions & 0 deletions .claude/agent-memory/product-owner/epic-04-planning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# EPIC-04: Household Items & Furniture Management -- Planning Notes

## Stories

| # | Issue | Title | Priority | Status | Depends On |
| --- | ----- | ----------------------------------------------- | ----------- | ------- | ---------------- |
| 4.1 | #387 | Household Items Schema & Migration | Must Have | Todo | (none) |
| 4.2 | #388 | Household Items CRUD API | Must Have | Todo | #387 |
| 4.3 | #389 | Household Items List Page | Must Have | Backlog | #388 |
| 4.4 | #390 | Household Item Create & Edit Form | Must Have | Backlog | #388 |
| 4.5 | #391 | Household Item Detail Page | Must Have | Backlog | #388 |
| 4.6 | #392 | Household Items Budget Integration | Must Have | Backlog | #387, #388 |
| 4.7 | #393 | Work Item Linking for Installation Coordination | Must Have | Backlog | #387, #388, #391 |
| 4.8 | #394 | Responsive & Accessibility Polish | Should Have | Backlog | #389, #390, #391 |

Story 8.6 (#359, EPIC-08) is also a sub-issue of EPIC-04, blocked by #391 (detail page).

## Dependency Chain

```
4.1 (schema) ─── > 4.2 (CRUD API) ──┬─> 4.3 (list page) ───────┬─> 4.8 (polish)
├─> 4.4 (create/edit form) ─┤
├─> 4.5 (detail page) ──────┤
│ └─> 8.6 (doc linking)*
├─> 4.6 (budget integration)
└─> 4.7 (work item linking, also needs 4.5)
```

## Key Design Decisions

1. **Distinct entity**: Household items are NOT work items (Section 5, Key Decisions). Separate table, separate routes, separate pages.
2. **Shared resources**: Reuses existing `tags` table (new junction `household_item_tags`), existing `vendors` table, existing budget categories/sources/subsidies.
3. **Budget pattern**: `household_item_budgets` mirrors `work_item_budgets` exactly (same columns, same confidence enum, same FK pattern).
4. **Work item linking**: M:N junction table `household_item_work_items` for coordination. Informational relationship, NOT a scheduling dependency in the Gantt engine.
5. **Purchase status workflow**: not_ordered -> ordered -> in_transit -> delivered (4 states, no backward transitions enforced at DB level).
6. **Category enum**: furniture, appliances, fixtures, decor, other.
7. **Room**: Free-text field (no predefined enum). Dynamic filter populated from distinct values.
8. **Document linking**: Already supported via EPIC-08's `document_links` table with `entity_type='household_item'`. Story 8.6 handles the UI.
9. **Budget overview integration**: Story 4.6 ensures household item budget lines contribute to project-wide totals (category sums, source usage, overall budget).

## Requirements Coverage

| Requirement Section | Covered By |
| ---------------------------------------- | -------------------------- |
| 2.3 Item Management | 4.1, 4.2, 4.3, 4.4, 4.5 |
| 2.3 Budget Integration | 4.6 |
| 2.3 Timeline Integration (data model) | 4.7 |
| 2.3 Timeline Integration (visualization) | EPIC-06 (future extension) |
| 2.3 Document Links | 8.6 (#359, EPIC-08) |
| 4 User Stories - track purchases | 4.2, 4.3, 4.4, 4.5 |
| 4 User Stories - delivery dates | 4.2, 4.4, 4.5 |
| 4 User Stories - link to work items | 4.7 |
| 4 User Stories - link documents | 8.6 |
| 4 User Stories - timeline delivery dates | EPIC-06 extension |
| 5 Key Decisions - NOT work items | All (separate entity) |

## Acceptance Criteria Counts

- Story 4.1: 8 ACs, 9 UAT scenarios
- Story 4.2: 10 ACs, 17 UAT scenarios
- Story 4.3: 11 ACs, 13 UAT scenarios
- Story 4.4: 12 ACs, 13 UAT scenarios
- Story 4.5: 12 ACs, 15 UAT scenarios
- Story 4.6: 10 ACs, 12 UAT scenarios
- Story 4.7: 10 ACs, 11 UAT scenarios
- Story 4.8: 12 ACs, 13 UAT scenarios
- **Total**: 85 ACs, 103 UAT scenarios
5 changes: 5 additions & 0 deletions .claude/agent-memory/qa-integration-tester/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Worktrees have no `node_modules`. To run tests from a worktree:

1. Create symlinks: `ln -sf /main/node_modules /worktree/node_modules` and `ln -sf /main/server/node_modules /worktree/server/node_modules`
2. Run from the WORKTREE directory: `node --experimental-vm-modules /main/node_modules/.bin/jest "path/to/test.ts" --no-coverage`
3. **This worktree already has node_modules** — node_modules are present in the worktree directly. Run jest directly without symlink step.

## Schema Quirk: tags table has NO updated_at

The `tags` table (migration 0002) only has: `id, name, color, created_at` — NO `updated_at`. `TagResponse` also has no `updatedAt`. Do not include this field in test inserts or type assertions.

- Do NOT cast `mockGet.mock.calls[0] as [string]` — TypeScript strict mode rejects empty arrays cast to tuple. Use `expect(mockGet).not.toHaveBeenCalledWith(expect.stringContaining(...))` pattern instead.

Expand Down
113 changes: 113 additions & 0 deletions server/src/db/migrations/0010_household_items.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
-- Migration 0010: Create household items tables
--
-- EPIC-04: Household Items & Furniture Management
--
-- Creates the household_items entity and all supporting tables:
-- - household_item_tags (M:N with shared tags table)
-- - household_item_notes (comments/notes)
-- - household_item_budgets (budget lines, mirrors work_item_budgets)
-- - household_item_work_items (M:N link to work items for coordination)
-- - household_item_subsidies (M:N with subsidy programs)
--
-- See ADR-016 for design rationale.
--
-- ROLLBACK:
-- DROP TABLE IF EXISTS household_item_subsidies;
-- DROP TABLE IF EXISTS household_item_work_items;
-- DROP TABLE IF EXISTS household_item_budgets;
-- DROP TABLE IF EXISTS household_item_notes;
-- DROP TABLE IF EXISTS household_item_tags;
-- DROP TABLE IF EXISTS household_items;

-- ── household_items ─────────────────────────────────────────────────────────

CREATE TABLE household_items (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
category TEXT NOT NULL DEFAULT 'other'
CHECK(category IN ('furniture', 'appliances', 'fixtures', 'decor', 'electronics', 'outdoor', 'storage', 'other')),
status TEXT NOT NULL DEFAULT 'not_ordered'
CHECK(status IN ('not_ordered', 'ordered', 'in_transit', 'delivered')),
vendor_id TEXT REFERENCES vendors(id) ON DELETE SET NULL,
url TEXT,
room TEXT,
quantity INTEGER NOT NULL DEFAULT 1 CHECK(quantity >= 1),
order_date TEXT,
expected_delivery_date TEXT,
actual_delivery_date TEXT,
created_by TEXT REFERENCES users(id) ON DELETE SET NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX idx_household_items_category ON household_items(category);
CREATE INDEX idx_household_items_status ON household_items(status);
CREATE INDEX idx_household_items_room ON household_items(room);
CREATE INDEX idx_household_items_vendor_id ON household_items(vendor_id);
CREATE INDEX idx_household_items_created_at ON household_items(created_at);

-- ── household_item_tags ─────────────────────────────────────────────────────

CREATE TABLE household_item_tags (
household_item_id TEXT NOT NULL REFERENCES household_items(id) ON DELETE CASCADE,
tag_id TEXT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (household_item_id, tag_id)
);

CREATE INDEX idx_household_item_tags_tag_id ON household_item_tags(tag_id);

-- ── household_item_notes ────────────────────────────────────────────────────

CREATE TABLE household_item_notes (
id TEXT PRIMARY KEY,
household_item_id TEXT NOT NULL REFERENCES household_items(id) ON DELETE CASCADE,
content TEXT NOT NULL,
created_by TEXT REFERENCES users(id) ON DELETE SET NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX idx_household_item_notes_household_item_id ON household_item_notes(household_item_id);

-- ── household_item_budgets ──────────────────────────────────────────────────

CREATE TABLE household_item_budgets (
id TEXT PRIMARY KEY,
household_item_id TEXT NOT NULL REFERENCES household_items(id) ON DELETE CASCADE,
description TEXT,
planned_amount REAL NOT NULL DEFAULT 0 CHECK(planned_amount >= 0),
confidence TEXT NOT NULL DEFAULT 'own_estimate'
CHECK(confidence IN ('own_estimate', 'professional_estimate', 'quote', 'invoice')),
budget_category_id TEXT REFERENCES budget_categories(id) ON DELETE SET NULL,
budget_source_id TEXT REFERENCES budget_sources(id) ON DELETE SET NULL,
vendor_id TEXT REFERENCES vendors(id) ON DELETE SET NULL,
created_by TEXT REFERENCES users(id) ON DELETE SET NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX idx_household_item_budgets_household_item_id ON household_item_budgets(household_item_id);
CREATE INDEX idx_household_item_budgets_vendor_id ON household_item_budgets(vendor_id);
CREATE INDEX idx_household_item_budgets_budget_category_id ON household_item_budgets(budget_category_id);
CREATE INDEX idx_household_item_budgets_budget_source_id ON household_item_budgets(budget_source_id);

-- ── household_item_work_items ───────────────────────────────────────────────

CREATE TABLE household_item_work_items (
household_item_id TEXT NOT NULL REFERENCES household_items(id) ON DELETE CASCADE,
work_item_id TEXT NOT NULL REFERENCES work_items(id) ON DELETE CASCADE,
PRIMARY KEY (household_item_id, work_item_id)
);

CREATE INDEX idx_household_item_work_items_work_item_id ON household_item_work_items(work_item_id);

-- ── household_item_subsidies ────────────────────────────────────────────────

CREATE TABLE household_item_subsidies (
household_item_id TEXT NOT NULL REFERENCES household_items(id) ON DELETE CASCADE,
subsidy_program_id TEXT NOT NULL REFERENCES subsidy_programs(id) ON DELETE CASCADE,
PRIMARY KEY (household_item_id, subsidy_program_id)
);

CREATE INDEX idx_household_item_subsidies_subsidy_program_id ON household_item_subsidies(subsidy_program_id);
Loading
Loading