docs: align tracked files to single coherent SoT

Contradictions resolved:

- AGENTS.md: add 'Known stale PRD lines' section (FR17, FR19, FR40, NFR, FR42)
  so PRD's cross-reference resolves
- AGENTS §6: remove 'tag sets' from Call 1 body description (Call 1 only uses
  species and attribute lists)
- PROMPTS.md: shipped defaults path corrected to backend/app/prompts/ (matches
  DEPLOYMENT repo layout)
- PROMPTS.md: Call 1 notes removed feat-* and fig-* from taxonomy list (Call 1
  returns free-text observations mapped to feat-* tags by server, not fig-*)
- PROMPTS.md: Call 2 template field names aligned with CONTENT-WOO defaults
  (width_avg_in, width_min_in, width_max_in, length_in_remainder)
- UX.md §112: remove 'tag lists' from Call 1 body description
- DATA-MODEL: prompt files location corrected from /data/prompts/ to
  backend/app/prompts/ (bind-mounted read-only to /app/prompts/)
- DEPLOYMENT: backup script updated (prompts are version-controlled in repo,
  no separate backup needed)
- docker-compose.yml: prompts mount corrected to ../backend/app/prompts
This commit is contained in:
2026-09-07 02:17:22 +00:00
parent 68185d8bd7
commit 80af35721f
6 changed files with 28 additions and 18 deletions
+7 -1
View File
@@ -53,6 +53,12 @@ Phase map: **Phase 0 = Gates A+B.** **Gate C = early Phase 1** claimable publish
Docs refactor is on `main` (cut 2026-09-06). Product locks above are unchanged. Docs refactor is on `main` (cut 2026-09-06). Product locks above are unchanged.
### Known stale PRD lines
`docs/archive/PRD-2026-08.txt` is frozen history. These PRD lines are superseded by live docs:
FR17 (fig-* 1+, feat-* 0+), FR19 (species $/bdft only), FR40 (client-side, not server-side
processing), NFR server normalization timing, FR42 (env-agnostic DEPLOYMENT + deploy/INVENTORY.md).
--- ---
## 1. Topology (locked — hybrid) ## 1. Topology (locked — hybrid)
@@ -149,7 +155,7 @@ Payload and publish sequence depth: `docs/CONTENT-WOO.md`. Key only: DATA-MODEL
- **Gate C** claimable path: inference **OFF**; manual taxonomy + deterministic numbers + Woo draft path. - **Gate C** claimable path: inference **OFF**; manual taxonomy + deterministic numbers + Woo draft path.
- **Call 1 (vision) / Call 2 (text) only after Gate C is green**, still inside overall POC before "done." - **Call 1 (vision) / Call 2 (text) only after Gate C is green**, still inside overall POC before "done."
- Call 1 auto only if `inference_enabled`; Call 2 never auto-fires (user taps Generate text). - Call 1 auto only if `inference_enabled`; Call 2 never auto-fires (user taps Generate text).
- Call 1 body: all inventory photos @1024. Taxonomy lists sent to Call 1 are **exactly the Woo-synced species / attribute / tag sets**. - Call 1 body: all inventory photos @1024. Taxonomy lists sent to Call 1 are **exactly the Woo-synced species / attribute sets**.
- **Confidence 0.7 (default):** ≥ 0.7 → pre-populate species, wood categories, edge, figure, grade, and feat-* from Call 1 (**mutable**). < 0.7 → those fields stay **empty**. Ready still requires the full named set in §7. Presentation: `docs/UX.md`. - **Confidence 0.7 (default):** ≥ 0.7 → pre-populate species, wood categories, edge, figure, grade, and feat-* from Call 1 (**mutable**). < 0.7 → those fields stay **empty**. Ready still requires the full named set in §7. Presentation: `docs/UX.md`.
- **Taxonomy cache:** `taxonomy_last_sync_at` vs `taxonomy_anchor` (bump only on stored-subset hash change, including deletions). Client re-pulls iff the anchor advanced. `test-woo` always syncs; publish if last_sync >1h. No per-nav sync. No Woo taxonomy timestamp. - **Taxonomy cache:** `taxonomy_last_sync_at` vs `taxonomy_anchor` (bump only on stored-subset hash change, including deletions). Client re-pulls iff the anchor advanced. `test-woo` always syncs; publish if last_sync >1h. No per-nav sync. No Woo taxonomy timestamp.
- Call 2 portable context: default full resend; never require `previous_response_id`. `test-inference` two-turn probe `stateful|stateless|fail`. Fail blocks **Call 2 enablement only**. - Call 2 portable context: default full resend; never require `previous_response_id`. `test-inference` two-turn probe `stateful|stateless|fail`. Fail blocks **Call 2 enablement only**.
+1 -1
View File
@@ -31,7 +31,7 @@ services:
volumes: volumes:
- slab_db:/data - slab_db:/data
- slab_images:/images - slab_images:/images
- ../prompts:/app/prompts:ro - ../backend/app/prompts:/app/prompts:ro
ports: ["127.0.0.1:${FASTAPI_PORT:-18081}:8000"] ports: ["127.0.0.1:${FASTAPI_PORT:-18081}:8000"]
mem_limit: 2g mem_limit: 2g
restart: unless-stopped restart: unless-stopped
+5 -4
View File
@@ -194,10 +194,11 @@ Sheet/slider prefs (`sheet_mode`, sensitivity, edge offset, feather) are **not**
settings keys in POC. Client localStorage is source of truth (AGENTS §4 / ARCHITECTURE §5). settings keys in POC. Client localStorage is source of truth (AGENTS §4 / ARCHITECTURE §5).
Optional server sync of those prefs is out of scope for POC. Optional server sync of those prefs is out of scope for POC.
**Prompt files** — not in the settings table. Stored as text files in **Prompt files** — not in the settings table. Shipped as text files in
`/data/prompts/` (server volume). Read fresh on each invocation. Default `backend/app/prompts/` (repo), bind-mounted read-only to `/app/prompts/` in the
prompts shipped with the app; owner edits directly. A reset-to-default script FastAPI container. Read fresh on each invocation. Default prompts shipped with the
restores originals. app; owner edits on the host; no restart needed. A reset-to-default script
restores originals from the app bundle.
This table is the ciphertext **key inventory** and schema only. The never-browser / This table is the ciphertext **key inventory** and schema only. The never-browser /
AES-GCM / `SLAB_AES_KEY` env policy lives in AGENTS.md §4; flow lives in ARCHITECTURE §5. AES-GCM / `SLAB_AES_KEY` env policy lives in AGENTS.md §4; flow lives in ARCHITECTURE §5.
+6 -3
View File
@@ -147,11 +147,14 @@ provide `python -m app.security.rekey NEW_KEY` (reads old key from env
``` ```
1. sqlite3 /data/slab.db ".backup /backups/slab-YYYYMMDD.db" # WAL-safe 1. sqlite3 /data/slab.db ".backup /backups/slab-YYYYMMDD.db" # WAL-safe
2. tar czf /backups/slab-images-YYYYMMDD.tgz -C /images . 2. tar czf /backups/slab-images-YYYYMMDD.tgz -C /images .
3. cp -r /backups/prompts-YYYYMMDD.tar.gz prompts/ # prompt files 3. retain: 7 daily + 4 weekly; prune older
4. retain: 7 daily + 4 weekly; prune older 4. log result to /var/log/slab-backup.log; alert (Hermes) on failure
5. log result to /var/log/slab-backup.log; alert (Hermes) on failure
``` ```
Prompt files live in the git repo (`backend/app/prompts/`) and are version-controlled;
they do not need a separate backup. The `reset-to-default` script restores shipped
defaults from the app bundle.
- Backup target: local dir first; mirror to an off-box share for safety (same pattern - Backup target: local dir first; mirror to an off-box share for safety (same pattern
as other stacks on the host). as other stacks on the host).
- **Restore**: stop compose → restore DB file + untar images → start compose. - **Restore**: stop compose → restore DB file + untar images → start compose.
+8 -8
View File
@@ -2,17 +2,17 @@
Status: SPEC · 2026-08-27 · SlabUploader Status: SPEC · 2026-08-27 · SlabUploader
Prompts are server-side text files, not settings values. Read fresh on each Prompts are server-side text files, not settings values. Read fresh on each
invocation. Shipped defaults live in `backend/prompts/`. invocation. Shipped defaults live in `backend/app/prompts/`.
## Management ## Management
- **Location:** `/app/prompts/` inside the FastAPI container, mounted read-only - **Location:** `/app/prompts/` inside the FastAPI container, mounted read-only
from host `prompts/`. from host `backend/app/prompts/`.
- **Editing:** Edit the text files on the host. No server restart needed. - **Editing:** Edit the text files on the host. No server restart needed.
- **Versioning:** The inference_log stores the prompt content (or hash) with each - **Versioning:** The inference_log stores the prompt content (or hash) with each
inference call, so you can trace which prompt version produced which result. inference call, so you can trace which prompt version produced which result.
- **Reset-to-default:** `python -m app.prompts.reset` restores shipped defaults - **Reset-to-default:** `python -m app.prompts.reset` restores shipped defaults
from the app bundle. from `backend/app/prompts/`.
## Call 1 — Vision (species/character classification) ## Call 1 — Vision (species/character classification)
@@ -85,7 +85,7 @@ Return valid JSON matching this schema:
``` ```
### Notes ### Notes
- The taxonomy list (species, wood categories, edge type, figure, grade, feat-*) is - The taxonomy list (species, wood categories, edge type, figure, grade) is
pulled from the **synced Woo cache only**. No hardcoded mill species list. A term pulled from the **synced Woo cache only**. No hardcoded mill species list. A term
not in the cache cannot be suggested or selected. not in the cache cannot be suggested or selected.
- Brief definitions help the model distinguish ambiguous cases - Brief definitions help the model distinguish ambiguous cases
@@ -95,8 +95,8 @@ Return valid JSON matching this schema:
is the authoritative source for feat-* tag definitions; the design does not is the authoritative source for feat-* tag definitions; the design does not
duplicate them. duplicate them.
- **Pre-population (when `inference_enabled`):** Call 1 results are the primary - **Pre-population (when `inference_enabled`):** Call 1 results are the primary
source that fills the review screen for species, character, wood categories, source that fills the review screen for species, wood categories, edge type,
figure/edge/grade attributes, and mapped `fig-*`/`feat-*` tags. figure, grade, and mapped `feat-*` tags from free-text observations.
- **Confidence gate (default threshold 0.7):** - **Confidence gate (default threshold 0.7):**
- Field confidence **≥ threshold** → pre-populate that field (mutable; - Field confidence **≥ threshold** → pre-populate that field (mutable;
user may clear or change it). user may clear or change it).
@@ -171,9 +171,9 @@ Return JSON: { "prose": "..." }
The server assembles the final title and description from templates with The server assembles the final title and description from templates with
deterministic measurements, inserting the LLM prose where appropriate. deterministic measurements, inserting the LLM prose where appropriate.
Example title: `{species} {length_ft}ft × {width_avg}in Slab — {figure}` Example title: `{species} {length_ft}ft {length_in_remainder}in × {width_avg_in}in Wood Slab — {figure}`
Example description: `{llm_prose}. Each slab is naturally shaped — width varies Example description: `{llm_prose}. Each slab is naturally shaped — width varies
along the length at {width_min}in to {width_max}in. Sold by the slab; along the length at {width_min_in}in to {width_max_in}in. Sold by the slab;
dimensions as measured. {geo_sentence}` dimensions as measured. {geo_sentence}`
### Notes ### Notes
+1 -1
View File
@@ -109,7 +109,7 @@ values always win and every value stays editable.
### What vision fills, and when ### What vision fills, and when
When inference is on, Call 1 runs after the calibrated draft uploads. It sends all inventory photos When inference is on, Call 1 runs after the calibrated draft uploads. It sends all inventory photos
downscaled to 1024 plus the store's synced species, attribute, and tag lists, and returns a guess downscaled to 1024 plus the store's synced species and attribute lists, and returns a guess
with a confidence per field. The threshold is 0.7 by default: with a confidence per field. The threshold is 0.7 by default:
- A field at or above 0.7 pre-fills on review. It stays editable; the owner can change or clear it. - A field at or above 0.7 pre-fills on review. It stays editable; the owner can change or clear it.