docs: fix docker service name in refactor plan (db → postgres)
Plan used 'db' service name but docker-compose.yml uses 'postgres'. Correcting pre-flight to avoid tripping every implementer. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
## Context for the Implementer
|
## Context for the Implementer
|
||||||
|
|
||||||
**The codebase has no automated test suite.** There is no `tests/` directory, no `conftest.py`, no pytest fixtures. The existing convention (see migrations `h26041901`, `i26041901` and every feature commit on the branch) is manual verification: run the server in `docker compose`, exercise the feature in the browser, poke at the database via `docker compose exec web flask shell` or `docker compose exec db psql -U imagerepo imagerepo`.
|
**The codebase has no automated test suite.** There is no `tests/` directory, no `conftest.py`, no pytest fixtures. The existing convention (see migrations `h26041901`, `i26041901` and every feature commit on the branch) is manual verification: run the server in `docker compose`, exercise the feature in the browser, poke at the database via `docker compose exec web flask shell` or `docker compose exec postgres psql -U imagerepo imagerepo`.
|
||||||
|
|
||||||
**Do not invent a test suite.** Each task below ships with explicit manual verification: a shell command, a SQL query, or a UI interaction with an expected result. These are the project's conventions — honor them.
|
**Do not invent a test suite.** Each task below ships with explicit manual verification: a shell command, a SQL query, or a UI interaction with an expected result. These are the project's conventions — honor them.
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ docker compose exec web flask db downgrade # revert
|
|||||||
docker compose exec web flask db history # list revisions
|
docker compose exec web flask db history # list revisions
|
||||||
|
|
||||||
# Postgres shell (inside the db container)
|
# Postgres shell (inside the db container)
|
||||||
docker compose exec db psql -U imagerepo imagerepo
|
docker compose exec postgres psql -U imagerepo imagerepo
|
||||||
```
|
```
|
||||||
|
|
||||||
**Commit cadence:** one commit per task. The `app/main.py` file is large; commit per logical route or helper change so git blame stays useful.
|
**Commit cadence:** one commit per task. The `app/main.py` file is large; commit per logical route or helper change so git blame stays useful.
|
||||||
@@ -94,7 +94,7 @@ None. `app/tasks/maintenance.py` stays (empty body, retains git history); the Ce
|
|||||||
Run in shell:
|
Run in shell:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT
|
SELECT
|
||||||
COALESCE(kind, '(null)') AS kind,
|
COALESCE(kind, '(null)') AS kind,
|
||||||
COUNT(*) AS total,
|
COUNT(*) AS total,
|
||||||
@@ -112,7 +112,7 @@ Expected: a table with rows per kind. Record these numbers in your scratchpad
|
|||||||
- [ ] **Step 2: Export full tag list for diff-comparison after migration**
|
- [ ] **Step 2: Export full tag list for diff-comparison after migration**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
COPY (SELECT id, name, kind, fandom_id FROM tag ORDER BY id) TO STDOUT WITH CSV HEADER
|
COPY (SELECT id, name, kind, fandom_id FROM tag ORDER BY id) TO STDOUT WITH CSV HEADER
|
||||||
" > /tmp/tag_snapshot_pre.csv
|
" > /tmp/tag_snapshot_pre.csv
|
||||||
wc -l /tmp/tag_snapshot_pre.csv
|
wc -l /tmp/tag_snapshot_pre.csv
|
||||||
@@ -123,7 +123,7 @@ Expected: CSV file of every tag row, one row per line plus header. Keep it — t
|
|||||||
- [ ] **Step 3: Snapshot image_tags counts (will verify zero lost after migration)**
|
- [ ] **Step 3: Snapshot image_tags counts (will verify zero lost after migration)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT COUNT(*) AS total_image_tag_rows FROM image_tags;
|
SELECT COUNT(*) AS total_image_tag_rows FROM image_tags;
|
||||||
"
|
"
|
||||||
```
|
```
|
||||||
@@ -133,7 +133,7 @@ Record this number. The migration must never reduce it (except intentionally via
|
|||||||
- [ ] **Step 4: Verify database is backed up (user-facing reminder)**
|
- [ ] **Step 4: Verify database is backed up (user-facing reminder)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db pg_dump -U imagerepo imagerepo > /tmp/imagerepo_pre_refactor_backup.sql
|
docker compose exec -T postgres pg_dump -U imagerepo imagerepo > /tmp/imagerepo_pre_refactor_backup.sql
|
||||||
ls -lh /tmp/imagerepo_pre_refactor_backup.sql
|
ls -lh /tmp/imagerepo_pre_refactor_backup.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -617,7 +617,7 @@ Expected: output ends with the report block. Note the four counts (Phase 1 renam
|
|||||||
- [ ] **Step 4: Verify no colons remain in non-post/non-archive tag names**
|
- [ ] **Step 4: Verify no colons remain in non-post/non-archive tag names**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT kind, COUNT(*) AS n
|
SELECT kind, COUNT(*) AS n
|
||||||
FROM tag
|
FROM tag
|
||||||
WHERE name LIKE '%:%' AND kind NOT IN ('post', 'archive')
|
WHERE name LIKE '%:%' AND kind NOT IN ('post', 'archive')
|
||||||
@@ -630,7 +630,7 @@ Expected: zero rows returned. (Post/archive tags legitimately retain inner `:` i
|
|||||||
- [ ] **Step 5: Verify no character tag name contains a fandom suffix**
|
- [ ] **Step 5: Verify no character tag name contains a fandom suffix**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT id, name FROM tag
|
SELECT id, name FROM tag
|
||||||
WHERE kind = 'character'
|
WHERE kind = 'character'
|
||||||
AND name ~ '^.+ \(.+\)$'
|
AND name ~ '^.+ \(.+\)$'
|
||||||
@@ -643,7 +643,7 @@ Expected: zero rows. If any remain, they're malformed orphans that the migration
|
|||||||
- [ ] **Step 6: Verify the four partial indices exist**
|
- [ ] **Step 6: Verify the four partial indices exist**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT indexname, indexdef FROM pg_indexes
|
SELECT indexname, indexdef FROM pg_indexes
|
||||||
WHERE tablename = 'tag'
|
WHERE tablename = 'tag'
|
||||||
AND indexname IN (
|
AND indexname IN (
|
||||||
@@ -660,7 +660,7 @@ Expected: four rows, each with the partial-WHERE clause visible in `indexdef`.
|
|||||||
- [ ] **Step 7: Verify image_tags count unchanged (no data loss)**
|
- [ ] **Step 7: Verify image_tags count unchanged (no data loss)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "SELECT COUNT(*) FROM image_tags;"
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "SELECT COUNT(*) FROM image_tags;"
|
||||||
```
|
```
|
||||||
|
|
||||||
Compare against the baseline from Task 0 Step 3. Acceptable outcomes:
|
Compare against the baseline from Task 0 Step 3. Acceptable outcomes:
|
||||||
@@ -966,7 +966,7 @@ def add_tag(image_id):
|
|||||||
- [ ] **Step 2: Exercise the endpoint against an existing image**
|
- [ ] **Step 2: Exercise the endpoint against an existing image**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 1;"
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 1;"
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy the returned id (call it `$IMG`). Then:
|
Copy the returned id (call it `$IMG`). Then:
|
||||||
@@ -990,7 +990,7 @@ Expected for the second: `ok=true`, `tag.name="Test Char Ephemeral"`, `tag.kind=
|
|||||||
- [ ] **Step 3: Clean up the ephemeral test tags**
|
- [ ] **Step 3: Clean up the ephemeral test tags**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
DELETE FROM image_tags WHERE tag_id IN (
|
DELETE FROM image_tags WHERE tag_id IN (
|
||||||
SELECT id FROM tag WHERE name IN (
|
SELECT id FROM tag WHERE name IN (
|
||||||
'test general ephemeral', 'Test Char Ephemeral', 'Test Fandom Ephemeral'
|
'test general ephemeral', 'Test Char Ephemeral', 'Test Fandom Ephemeral'
|
||||||
@@ -1128,7 +1128,7 @@ def bulk_add_tag():
|
|||||||
- [ ] **Step 3: Verify with two dummy images**
|
- [ ] **Step 3: Verify with two dummy images**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 2;"
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 2;"
|
||||||
```
|
```
|
||||||
|
|
||||||
Take the two ids (call them IMG1, IMG2):
|
Take the two ids (call them IMG1, IMG2):
|
||||||
@@ -1148,7 +1148,7 @@ Expected: `ok=true`, `added_count=2` (or less if the images already had that tag
|
|||||||
Clean up:
|
Clean up:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name = 'bulk test ephemeral');
|
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name = 'bulk test ephemeral');
|
||||||
DELETE FROM tag WHERE name = 'bulk test ephemeral';
|
DELETE FROM tag WHERE name = 'bulk test ephemeral';
|
||||||
"
|
"
|
||||||
@@ -1279,7 +1279,7 @@ def accept_image_suggestion(image_id):
|
|||||||
- [ ] **Step 3: Smoke-test the 0-candidate branch**
|
- [ ] **Step 3: Smoke-test the 0-candidate branch**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 1;"
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "SELECT id FROM image_record LIMIT 1;"
|
||||||
IMG=<paste_id>
|
IMG=<paste_id>
|
||||||
|
|
||||||
curl -sX POST "http://localhost:5000/image/$IMG/suggestions/accept" \
|
curl -sX POST "http://localhost:5000/image/$IMG/suggestions/accept" \
|
||||||
@@ -1324,7 +1324,7 @@ Expected: HTTP 409, JSON body with `error="ambiguous"` and a `candidates` array
|
|||||||
Clean up:
|
Clean up:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name LIKE '%Ambig%' OR name = 'Nonexistent Test Character');
|
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name LIKE '%Ambig%' OR name = 'Nonexistent Test Character');
|
||||||
DELETE FROM tag WHERE name LIKE '%Ambig%' OR name = 'Nonexistent Test Character';
|
DELETE FROM tag WHERE name LIKE '%Ambig%' OR name = 'Nonexistent Test Character';
|
||||||
"
|
"
|
||||||
@@ -1547,7 +1547,7 @@ Remove any further downstream code that used the old `tag_name` variable; replac
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Pick any existing tag
|
# Pick any existing tag
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "SELECT id, name, kind FROM tag WHERE kind = 'character' LIMIT 1;"
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "SELECT id, name, kind FROM tag WHERE kind = 'character' LIMIT 1;"
|
||||||
TAG_ID=<paste_id>
|
TAG_ID=<paste_id>
|
||||||
|
|
||||||
curl -s -o /dev/null -w "%{http_code}" "http://localhost:5000/?tag_id=$TAG_ID"
|
curl -s -o /dev/null -w "%{http_code}" "http://localhost:5000/?tag_id=$TAG_ID"
|
||||||
@@ -1653,7 +1653,7 @@ def set_tag_fandom(tag_id):
|
|||||||
- [ ] **Step 2: Verify via curl**
|
- [ ] **Step 2: Verify via curl**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT t.id, t.name, t.fandom_id
|
SELECT t.id, t.name, t.fandom_id
|
||||||
FROM tag t
|
FROM tag t
|
||||||
WHERE t.kind = 'character'
|
WHERE t.kind = 'character'
|
||||||
@@ -1679,7 +1679,7 @@ curl -sX POST "http://localhost:5000/api/tag/$TAG_ID/set-fandom" \
|
|||||||
Expected: `ok=true`, `fandom_id: null`, `display_name` matches `name` (no suffix). Then clean up the ephemeral fandom:
|
Expected: `ok=true`, `fandom_id: null`, `display_name` matches `name` (no suffix). Then clean up the ephemeral fandom:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
DELETE FROM tag WHERE kind='fandom' AND name='Test Fandom For Set';
|
DELETE FROM tag WHERE kind='fandom' AND name='Test Fandom For Set';
|
||||||
"
|
"
|
||||||
```
|
```
|
||||||
@@ -1873,7 +1873,7 @@ def update_tag(tag_id):
|
|||||||
- [ ] **Step 5: Verify via curl**
|
- [ ] **Step 5: Verify via curl**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT id, name, kind FROM tag WHERE kind = 'user' LIMIT 1;
|
SELECT id, name, kind FROM tag WHERE kind = 'user' LIMIT 1;
|
||||||
"
|
"
|
||||||
TAG_ID=<paste_id>
|
TAG_ID=<paste_id>
|
||||||
@@ -2251,7 +2251,7 @@ If `re.` is not called anywhere in the file after removing `_FANDOM_SUFFIX_RE`,
|
|||||||
- [ ] **Step 5: Smoke-test suggestions for any image**
|
- [ ] **Step 5: Smoke-test suggestions for any image**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT image_id, COUNT(*)
|
SELECT image_id, COUNT(*)
|
||||||
FROM image_tag_prediction
|
FROM image_tag_prediction
|
||||||
GROUP BY image_id
|
GROUP BY image_id
|
||||||
@@ -2473,7 +2473,7 @@ Replace each:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Pick a series tag
|
# Pick a series tag
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT id, name FROM tag WHERE kind = 'series' LIMIT 1;
|
SELECT id, name FROM tag WHERE kind = 'series' LIMIT 1;
|
||||||
"
|
"
|
||||||
SERIES_ID=<paste_id>
|
SERIES_ID=<paste_id>
|
||||||
@@ -2920,7 +2920,7 @@ In the modal, type `character:Test Char A` in tag input. Type `Test Fandom A` in
|
|||||||
Check DB:
|
Check DB:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
SELECT t.id, t.name, t.kind, t.fandom_id, f.name AS fandom_name
|
SELECT t.id, t.name, t.kind, t.fandom_id, f.name AS fandom_name
|
||||||
FROM tag t LEFT JOIN tag f ON t.fandom_id = f.id
|
FROM tag t LEFT JOIN tag f ON t.fandom_id = f.id
|
||||||
WHERE t.name = 'Test Char A';
|
WHERE t.name = 'Test Char A';
|
||||||
@@ -2932,7 +2932,7 @@ Expected: one row. `kind='character'`, `name='Test Char A'`, `fandom_name='Test
|
|||||||
Clean up:
|
Clean up:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose exec -T db psql -U imagerepo imagerepo -c "
|
docker compose exec -T postgres psql -U imagerepo imagerepo -c "
|
||||||
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name IN ('Test Char A', 'Test Fandom A'));
|
DELETE FROM image_tags WHERE tag_id IN (SELECT id FROM tag WHERE name IN ('Test Char A', 'Test Fandom A'));
|
||||||
DELETE FROM tag WHERE name IN ('Test Char A', 'Test Fandom A');
|
DELETE FROM tag WHERE name IN ('Test Char A', 'Test Fandom A');
|
||||||
"
|
"
|
||||||
|
|||||||
Reference in New Issue
Block a user