Files
website/docs/plant-tracker.md
Stan Runge e24ee7f95d
All checks were successful
Deploy production / deploy (push) Successful in 1m19s
plant: private Cargill Gouda tracker (/trackers/cargill)
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.
2026-10-26 13:42:37 +00:00

4.1 KiB

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.

{
	"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}] }.