Life Business Logic Registry — agent instructions

Read this first, every session. It is the short version; the documents it points at are the authority, and where they disagree with this file, they win.

This is a documentation-only repository. It describes how Life Interiors' systems behave. It does not run them, and nothing written here changes them.


1. Hard rules

These are not negotiable and not situational.

  1. This is the only writable repository. Every other Life Interiors repository is read-only — clone and read freely, never create, edit, delete, commit, push, or open a pull request against one. (ACCESS_POLICY.md)
  2. Never copy source code in. Point at it with code_refs — repo, path, commit. Pseudocode is hand-written, language-neutral and short; if a block would nearly run in the source language, it is too close. (CONVENTIONS.md §3)
  3. Never invent a field label, a meaning, or a term. Leave it blank and set confirmed: false. It renders as needs confirming, which is honest and actionable. A plausible guess is neither, because nobody re-checks the ones that look finished. (WORKING_AGREEMENT.md §4)
  4. Never change a rule ID. IDs land in Asana tickets and conversations. Retire or supersede a rule; never renumber or reuse one. (CONVENTIONS.md §4)
  5. Production wins. If an entry and production disagree, the entry is wrong. Correct it, or raise a defect — never document the system you wish existed.
  6. Ask before building anything new. Documenting, reviewing or diagramming a system is never permission to build one. If the conversation drifts from "explain this" to "so we'd need a service that…", stop and ask. (WORKING_AGREEMENT.md §1)

2. Before you finish

npm run build     # renders public/ and regenerates registry-index.json
npm run check     # front-matter, rule IDs, anchors, glossary terms, review drift

npm run check distinguishes errors (which fail CI) from warnings (which do not). A warning about an unconfirmed field or term is working as intended — it must never block an entry that is correct about behaviour. Do not silence one by inventing the missing value.

Read the warnings before you publish, not after. They are the generated list of everything the entry cannot answer for itself, which is exactly what §4 says to ask for in one batch. Publishing first and asking second is the thing that leaves needs confirming on the page for months.

CI also fails if the committed public/ or registry-index.json does not match a fresh build, so commit the build output in the same commit as the source change.


3. Where things are

Need Read
Read/write boundary across repositories ACCESS_POLICY.md
Asking before building; who is recorded on an entry WORKING_AGREEMENT.md
How an entry is identified, written and kept honest CONVENTIONS.md
Rule IDs, domain codes, allocating a number CONVENTIONS.md §4
The three readings and what belongs in each CONVENTIONS.md §8
What a business term means GLOSSARY.md
Starting a new entry integrations/_TEMPLATE.md
What is broken, and what nobody has answered DEFECTS.md · OPEN-QUESTIONS.md
What proves a rule still works TEST-CASES.md
Recording a defect, an open question or a test case CONVENTIONS.md §13, §14
The developer reading's section order, and writing a decision tree CONVENTIONS.md §15, §16
Hosting and deployment DEPLOYMENT.md

4. Writing or updating an entry

Before you write anything, ask four questions. None of them is in the code, and a plausible guess at any of them is worse than a blank (WORKING_AGREEMENT.md §2):

  1. Project owner — propose Kim Hoang Nguyen and have it confirmed. Kim is the default here, but a default is not an answer.
  2. Developers — ask who built it and who maintains it now. Corroborate from GitHub or Celigo authorship, then put the names to a person.
  3. For department — ask which team feels it when it breaks, and offer suggestions rather than an open question. The suggested list is in CONVENTIONS.md §6.
  4. Journey stage — propose where in the order journey it runs, from the six-rung ladder in CONVENTIONS.md §11. It groups the Organisation Map.

Then ask for everything else that would render as needs confirming, in the same message. Field meanings, glossary meanings, saved-search names, a depends_on you inferred — all of it, one batch, before the entry is published, so nobody reads a finished-looking page and has to open a second round of questions against it. Run npm run build && npm run check first: the warnings are a generated list of exactly what is still unconfirmed. Propose an answer for each rather than sending a list of blanks. It is still never blocking — if no answer comes back, the field stays blank and the entry publishes anyway. Full procedure: WORKING_AGREEMENT.md §5.

Then copy integrations/_TEMPLATE.md. The shape is not decorative:

  • Three h2 headings — ## Business logic, ## Developer logic, ## Diagram — are load-bearing. build.mjs splits the entry on them, in that order, and renders each as a tab. Do not rename, reorder, or nest them.
  • The developer reading has a fixed skeleton of fourteen ### sections, in one order (CONVENTIONS.md §15): Inputs · Processing · Decision tree · Outputs & side effects · Worked examples · Test cases · UAT · Edge cases · Failure modes · Known limitations · Known defects · Open questions · Source references · Change history. Proof before problems. npm run check warns when they run out of order. Sections of your own go between Processing and Decision tree. Never write a description line under a skeleton heading — the site generates it from SKELETON in build.mjs, so it reads the same on every entry.
  • A decision tree is the logic as a path, in the order it runs (§16) — every branch naming its rule, saying what must happen before what and why, and showing deployed behaviour, defects included. Do not write one for logic that has not been read.
  • The business reading must work with zero system access, and must answer, in this order: what it does · why it exists · who it affects · when it runs · how it decides · outcomes. How it decides is the whole logic at a high level, in five or six bullets. No field IDs, no script names, no Lambda names — if the reading needs one to make sense, the rule is under-explained or is really two rules.
  • The developer reading must be enough to rebuild the behaviour and to prove it still works — inputs, processing, outputs and side effects, worked examples, test cases, UAT, edge cases with a handled ✅/❌ column, failure modes, known limitations and known defects. A limitation is a decision; a defect is a mistake. Keeping them apart stops known scope being re-reported as a bug.
  • Test cases are a front-matter register too — test_cases:, in the shape a test pack uses: Case ID · Layer · Preconditions · Input · Expected output · Rule ref. Ids are <defect_prefix>-TC-<case>. No result columns — pass/fail belongs to a run, not to the registry (CONVENTIONS.md §14).
  • Defects and open questions are front-matter registers, not body tables — defects: and open_questions:, each ref namespaced by the entry's defect_prefix and each carrying a status. The build renders them under their headings and gathers them onto DEFECTS.md and OPEN-QUESTIONS.md. Refs are as immutable as rule IDs. A defect's breaks: link to the rule it breaks is left blank unless you actually know it — never inferred (CONVENTIONS.md §13).
  • Every field carries an io of read, written or read-written. The build splits the field registry into Inputs and Outputs on it, in both readings.
  • An entry touching NetSuite or Celigo carries its saved searches and flows in links:, so they are one click away. The build makes the URL from the id; never hand-write the table.
  • Every rule gets an explicit anchor immediately above its heading: <a id="LI-BL-FUL-003"></a>. Generated heading slugs change when a title is edited and silently break every link; the explicit anchor never does.
  • Rule headings are ### <ID> — <Name>. The build reads the name from the heading and renders it ahead of the id everywhere, with the id as a small chip. Keep the shape, write a name a person would say out loud, and never add a per-project rule number (CONVENTIONS.md §8).
  • Every diagram node carries data-kicker, data-title and data-detail. They feed the helper that appears beside the box on hover. A diagram whose nodes have no notes is not finished.
  • journey_stage places the entry on the Organisation Map, and depends_on records what must have run first. depends_on is a precondition; runs_after is a trigger — only use runs_after when one automation genuinely starts the other. Both are in CONVENTIONS.md §11.
  • Add a change-history row and bump documented_updated on every content change. There is no version field — it was removed because nobody kept it accurate. Bump last_reviewed only after re-verifying against production; skimming and bumping the date launders an unverified entry as verified. script_created / script_updated are read from GitHub or Celigo, never estimated.

5. Vocabulary

Business terms live in GLOSSARY.md, each with a stable LI-TERM-… ID. When an entry leans on a term, list its ID in the entry's terms: front-matter — the build renders it as a link and npm run check verifies it resolves.

  • Using a term that is not yet in the glossary? Add it, with confirmed: false and no invented meaning, and reference it. Do not leave the word floating.
  • Term IDs are immutable in the same way rule IDs are, even if the business renames the term.

6. Answering questions from this registry

The registry is the source of truth for how decisions are made — not for what is true right now. Live order status, current stock and delivery state come from the systems themselves, never from here.

  • Cite the rule ID. Never paraphrase a rule without one.
  • Check status before answering. A draft entry has not been verified against production. Say so in the answer rather than presenting it as settled.
  • Check last_reviewed against review_cycle. If it is past its cycle, say that too.
  • Respect the gaps. A field or term marked needs confirming is unknown, not implied. Do not fill it in from context.
  • If no rule covers it, say "not documented". Do not reason from adjacent rules to a confident answer. Four of the nine domain codes have entries; the rest are silence, and silence here means nobody has written it down — not that there is no rule.

7. Working with the code

build.mjs and scripts/check-registry.mjs are the only executable files here, and they exist to serve the entries. Before changing either:

  • Keep changes additive where possible. The rendering path, the three-section split and the field registry are relied on by every entry.
  • If you add a front-matter field the index should expose, update build.mjs — the generated registry-index.json is what makes the registry queryable. Its shape is documented in CONVENTIONS.md §4: entries, a flat rules list carrying each rule's name and anchor, and a flat terms list. Never add a timestamp to it — CI compares the committed output against a fresh build, so a generated-on field fails every build.
  • The sidebar search reads that index at runtime, from public/registry-index.json. A new searchable axis is a change there, not a new file.
  • Run npm run build && npm run check and commit the regenerated output.

8. Git

  • Work on a feature branch; never push directly to main.
  • Do not open a pull request unless asked.
  • Never touch another repository, on any branch, for any reason.