dodil/erp-brick-lead

AGENTS.md

Instructions for agents working on brick-lead

This brick is built on erp-platform. Read its BRICKS.md before changing anything here — it holds the rules (ownership, use cases, data, identity, tests) and why each one exists.

Where a change goes

You are changing…It goes in
a rule about leads, scoring, qualification, conversion or lookalike profilessrc/brick_lead/domain/lead.py — and a test in tests/test_rules.py named for the story
who may do something, or which leads they seesrc/brick_lead/application/use_cases.py — the permission, or _scope() / _load(write=True)
how a neighbour (business-partner, activity, pipeline) is asked, or what its answer meanssrc/brick_lead/application/neighbours.py — the anti-corruption layer; nowhere else calls a seam
a new action for people and agentsa new @LEAD.use_case in application/ — it becomes a route AND a tool
a column or tablesrc/brick_lead/schema.sql (append; never drop or rename) and infrastructure/tables.py
the default scoring weightsDEFAULT_POLICY in the domain — but a customer's weights are rows (PUT /scoring-policy)

Never add an HTTP route or an MCP tool by hand. Never import SQLAlchemy, FastAPI or MCP in domain/. Use the words in the glossary at the top of domain/lead.py (lead, signal, score, scoring policy, qualification, conversion, lookalike) in code, docstrings and the history.

Before you commit

pytest -q --tb=short        # rules, both doors, and tier 1 with the real bp/activity/pipeline bricks
BUCKET=<scratch> DODIL_ORG=<org> python scripts/live_check.py   # after touching SQL, the vector, or scoring

Add a test to tests/test_doors.py for any new use case: the outcome through the API and through MCP, and the 404 for another person's lead. A change to conversion needs a case in tests/test_suite.py.

Don't

  • Don't open the deal through the pipeline's person route: conversion uses POST /opportunities/from-source with the lead's source_ref and the converting person as owner (C2).

  • Don't let a half-converted lead's domain change (its partner was made from it), and don't save a lead without its loaded version — an import claims every lead's next version in bulk (save_many).

  • Don't write to another brick's tables — call it through application/neighbours.py.

  • Don't type a score: it is derived by score() from the lead, its signals and the policy.

  • Don't mint a lead id: it is derived from the email or domain (LeadKey), so a re-import is idempotent.

  • Don't write an upsert or DELETE by hand — use the repository (DataK3's ON CONFLICT differs from Postgres).

  • Don't commit credentials or .env.