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.
82 lines
4.1 KiB
Markdown
82 lines
4.1 KiB
Markdown
# 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}] }`.
|