plant: private Cargill Gouda tracker (/trackers/cargill)
All checks were successful
Deploy production / deploy (push) Successful in 1m19s
All checks were successful
Deploy production / deploy (push) Successful in 1m19s
Owner-only tracker for learning the Cargill Bioindustrial plant in Gouda: schema plant (entries, links with confidence, pending refs), plant.apply_entries bulk import, overview with clusters and flow diagram, kind tabs, glossary, questions, detail pages and owner inline editing. Docs in docs/plant-tracker.md.
This commit is contained in:
81
docs/plant-tracker.md
Normal file
81
docs/plant-tracker.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Plant tracker (`/trackers/cargill`)
|
||||
|
||||
A private (owner-only) knowledge base about the Cargill Bioindustrial plant in Gouda:
|
||||
departments, products, process steps, equipment, glossary terms, questions, notes and roles
|
||||
(never colleague names). Logged-out visitors get a 404 on the page, its data and its actions
|
||||
(`ownerOnlyPrefixes` in `src/lib/server/owner.ts`).
|
||||
|
||||
## Schema `plant` (migration `drizzle/20261026133106_plant`)
|
||||
|
||||
- `plant.entries`: `kind`, `slug` (unique per kind), `title`, `summary`, `body` (markdown),
|
||||
`parent_id` (any kind, e.g. a note under a note), `tags`, `sort_order`, `source`,
|
||||
`confidence` (`confirmed` | `assumed` | `open`), `answered_at` (questions), timestamps.
|
||||
- `plant.links`: `from_id`, `to_id`, `relation` (`feeds_into`, `made_in`, `uses`, `part_of`,
|
||||
`related`), optional `label`, `dashed`, `confidence` (default `confirmed`; `assumed` or
|
||||
`open` links show dashed in the flow and with a "?" badge on entry pages).
|
||||
- `plant.pending`: parents and links whose target doesn't exist yet. Every `apply_entries` run
|
||||
retries them, so a later batch that adds the target resolves them. Entry pages list them as
|
||||
"pending".
|
||||
|
||||
Kinds: `department`, `product`, `process_step`, `equipment`, `glossary`, `question`, `note`,
|
||||
`person_role`.
|
||||
|
||||
How tags drive the UI:
|
||||
|
||||
- `cluster` (departments): a section in the departments tab and a card in the overview, with
|
||||
every unit below it (units with `parent: "cluster-ea"`, and their own units, like MP1's).
|
||||
- `inactive`: dimmed everywhere; the "hide inactive" switch hides them (off by default).
|
||||
- `overview` (notes): shown at the top of the overview.
|
||||
|
||||
## Bulk import: `plant.apply_entries(jsonb)`
|
||||
|
||||
Upserts by `(kind, slug)`, then sets parents and links by slug. Run it as the app user or the
|
||||
owner; for big files pipe SQL through stdin, e.g.
|
||||
`select plant.apply_entries($doc$ { ... } $doc$::jsonb);`
|
||||
|
||||
The argument is either an object `{ "source": ..., "entries": [...], "links": [...],
|
||||
"delete": [...] }` or a bare array of entries.
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "Walter White, batch 5 (2026-10-26)",
|
||||
"entries": [
|
||||
{
|
||||
"kind": "department",
|
||||
"slug": "414-kolom-1",
|
||||
"title": "414 Kolom 1",
|
||||
"summary": "Fat splitting column, continuous",
|
||||
"body": "In and out:\n- In: feed, water and high-pressure steam.\n- Out: fatty acid and glycerine water.",
|
||||
"parent": "cluster-dim",
|
||||
"tags": ["splitting", "continuous"],
|
||||
"confidence": "confirmed",
|
||||
"links": [{ "to": "splitting", "relation": "uses", "label": "optional" }]
|
||||
},
|
||||
{ "kind": "question", "slug": "rndm", "title": "What is RNDM?", "tags": ["answered"] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- Required: `kind`, plus `slug` or a `title` to slugify; new entries need a `title`.
|
||||
- Optional: `summary`, `body`, `parent` (alias `parent_slug`; `null` clears it), `tags`,
|
||||
`confidence` (default `assumed`, `open` for questions), `sort_order`, `source`, `answered`,
|
||||
`replace_links`, `replace_tags`, `body_mode` (`"append"`), `links` (`to`, `relation`,
|
||||
`label`, `dashed`, `confidence`, `remove`).
|
||||
- Updating an existing entry:
|
||||
- Keys that are left out keep their current value. An empty `summary` or `body` also keeps
|
||||
the current text. With `"body_mode": "append"` the new body is added below the current
|
||||
one (skipped when it is already there) instead of replacing it.
|
||||
- `tags` are merged into the existing tags, unless the entry sets
|
||||
`"confidence": "confirmed"` or `"replace_tags": true`, which replace them.
|
||||
- The top-level `source` is only the default for new entries; pass `source` on an entry to
|
||||
overwrite it.
|
||||
- A question tagged `answered` (or with `"answered": true`) is marked answered; the tag is
|
||||
dropped.
|
||||
- References (`parent`, `to`, `from`) are a slug or `kind:slug`. A bare slug used by several
|
||||
kinds resolves in this order: process_step, product, department, equipment, note,
|
||||
question, person_role, glossary (so `splitting` is the process step).
|
||||
- Unknown references never abort the import: they are listed in `unresolved` and kept in
|
||||
`plant.pending` until their target exists.
|
||||
|
||||
Returns `{ inserted, updated, linked, unlinked, deleted, unresolved: [{from, field, to}],
|
||||
resolved_pending, pending, entries: [{id, kind, slug, action}] }`.
|
||||
Reference in New Issue
Block a user