Skip to content
S SocialSelling
main green · 150+ tests v0.17. x Local PoC · database-less feedback learning · ADR-007

More efficient customer search and automatic with AI.

SocialSelling answers a single question — "Who should I approach First?" — producing a Explainable ranking of prospects that learn from feedback The operator. This document is the project overview and, at the same time, a template good practice development and implementation adopted so far.

8
ADRs (decisions)
150+
deterministic tests
57
lessons recorded
0
Infra cost (tokens only)
Who's it for?
Who wants to understand the product and who wants to reproduce the development method.
Format
Project documentation
Depth
Technical reference · ~2 min for central idea · ~17 min complete

You prefer the essentials first? Read synthesis (~1 min)

1 & scope view

The product makes prospecting efficient and automatic: given a PCI (Ideal Customer Profile), the system discovers candidates, infers structured data, scores the fit/intent/trust, delivery Lead Cards ranked with justification (XAI) and learn from the operator's votes .

In scope

  • Explicable prospect ranking (fit · intent · confidence)
  • Discovery + incremental enrichment of leads
  • Structured justification (drivers +/− and missing signals)
  • Learned by feedback like/dislike (ADR-007)
  • Cockpit local web (view, weight editing, votes)

Out of scope (guardrails)

  • CRM, outreach/messengery automation, cadences
  • Database, Redis, Celery, Docker, AWS/Terraform
  • Instagram/LinkedIn Scraping
  • Automatic generation of outreach messages

2 PoC Architecture

A single Python 3.11+ process, without mandatory server, No bank, no line. Persistence in Atomic JSON (write-temp + os.replace). The only variable cost is the tokens of two cognition/search APIs.

Pipeline deterministic (modules, non-runtime agents)

M1 · Search
Tavily + Apollo
→
M2 · Extraction
Gemini (lot)
→
M3 · Score
linear · pure
→
M4 · Ranking
tie-break stable
→
M5 · XAI
explanation

M3 and M4 are functions pure: same input → byte-identical output. The orchestrator injects customers, cache, clock and config.

Support modules

Learning/ Logistic regression (pure Python) that readjusts w_fit/w_intent from votes ADR-007).
corpus/ Cumulative lead persistence between runs (upsert idempotent by entity_id) (ADR-006).
apollo/ Incremental enrichment ladder B2B: discovery → firmography → contact reveal (ADR-004).
web/ Cockpit FastAPI local with lead table, drawr details and feedback buttons.

External sensors

Tavily

Open search (M1). Social snippets and signs of intention.

Gemini (gemini-2.5-flash / flash-lite)

Cognition (M2). Extract structured entities + persona/intention in batches.

Apollo. io ADR-004

B2B Firmography. Incremental ladder; API master requires paid plan (Free blocks p/ entitlement).

3 Semantic layers & inviolable rules

The correction of the system rests on four invariants. They for all New code — including sensors, volume layer and module learning.

Observed Evidence
layer 1 · what was seen
≠
Inferences
layer 2 · which has been deducted
≠
Evaluated Hypotheses
layer 3 · score & XAI

1 Layer insulation

An inference is never treated as evidence. No Shared changeable references. Apollo flips ObservedEvidence, never inference. The feedback (ADR-007) operates only on the presentation layer — never plays Evidence or Inferences.

2 Byte-identical Determinism

Same memory → same output. Clock and RNG injection; IDs per stable hash; tie-break stable. O feedback model uses full-batch gradient without randomness — same log bit by bit.

3 Open-World

Absence of signal = uncertainty (↑u), never false. Missing Evidence is explicit; failures degrade, not They break. Dislike is a sign of training — the lead remains visible with a seal.

4 Atomic persistence

All writing is write-temp + os.replace. Never a half-written file — goes for cache, corpus, ledgers and the feedback store.

4 Architectural decisions (ADRs)

Each conscious decision becomes a versioned and referenced ADR. The source of truth is the ADR-000; the rest are amendments explicit.

5 Development specifications (SDDs)

Each non-trivial ADR is accompanied by an SDD (Spec-Driven Development: contracts, scenarios, testing plan and WUs. Spec-first — the document precedes the code.

6 Good development practices

This is where the project intends to be template: complexity lives in the construction process, Not in the system. PoC remains dry; discipline is total.

SDD-to-Code Loop (mandatory per module)

  1. 1Pydantic Contract
  2. 2BDD + fixtures
  3. 3Minimum implementation
  4. 4Green Gate
  5. 5PR + auto-merge

Operating mode: Day vs. Night (L-057)

☀️ Sessão de dia (interativa)

Specifies and generates cards — no develops the product. Author of ADRs, SDDs, docs, tooling and curation of board. Card only goes to All with 100% DoR (Gherkin, fixtures, without ambiguity).

🌙 Run noturno (autônomo)

Consumes column All via skill github-sdd-sync. Revalida DoR, implements, requires DoD (green gate, PR CI-green, PROGRESS and updated lessons).

Quality Gate non-negotiable

ruff + mypy --strict + pytest 100% green and deterministic. Flakiness = failure.

Git: branch → PR → auto-merge

Never commit Right on the main. Compulsory CI; merges only with green gate. Squash + delete-branch.

Tags = restore points

Each green WU receives an annotated tag. Public Rollback via git revertNever reset/force.

Always Mocked APIs

Tests never play network: recorded fixtures + fakes. Numeric tolerance 1e-9. Surfed API Errors to user (never silent — L-057).

Opt-in = parity

Every new feature enters offline by default → the baseline remains byte-identical (smoke E2E). [learning].enabled, [apollo].enabled, [corpus].enabled.

FinOps by atomic ledger

Credit (monthly) and requisition (daily) budgets persisted; try_spend/refund/reconciliation. Billing errors (429) propagate the raw message to the frontend.

Gate command (Windows)

.venv\Scripts\python.exe -m ruff check .   # lint
.venv\Scripts\python.exe -m mypy           # tipos (strict)
.venv\Scripts\python.exe -m pytest -q       # 150+ testes determinísticos
# Ou: .\scripts\gate.ps1  (roda os três em sequência)

7 Volume strategy (local rotation)

Objective: to seek much more leads without leaving local/database-less. It applied Constraint Theory funnel — Enlarge Discovery Without raise the cognitive ceiling only Makes it hit the wall faster. Hence the four pillars.

Pillar What do you do? Status
A · Cognitive ceiling Batch extraction + RPD budget + waves resumables (ADR-005) ✅ core
B · Cumulative corpus Runs accumulate; upsert idempotent; wave advances only result (ADR-006) ✅ core
Apollo · Discovery People Search + org-enrich + reveal (ADR-004) — API master requires paid plan ✅ implementado
C · Scalable state JSON monolithic → NDJSON/shards (no seat) ⏸ diferido
D · Entity resolution Canon domain + exclusion of vendors + dedup cross-provider ⏸ diferido

All opt-in ([apollo].enabled · [corpus].enabled · [gemini].rpd_enabled). Deferred with documented reason — no Risky refining for completeness.

8 Self-learning process

At the end of each task, learning is distilled into Docs/lices-learned. md (format L-NNN | Categoria | Lição | Como aplicar) and in memory persistent. Today they are. 57 lessons that backfeed future decisions — the project It gets smarter every cycle.

L-012 · Determinism

Inject clock and drift IDs by stable hash — never Random UUID or datetime.now() Internal. Ensures Byte-identical re-execution. It also applies to the feedback model (full-batch without random).

L-026 · Async resiliente

Fan-out with asyncio.gather(return_exceptions=True) + treat exception raw: a provider does not drop the lot.

L-051 · CSS point-events

Container fixed inset-0 z-50 closed needs to pointer-events:none; without it an invisible layer swallows all clicks without visible error.

L-052 · ML deterministic

Logistic regression with full-batch gradient, init in zeros, samples sorted by company_id and without random → same feedback. json

L-056 · Wave + resilience

Forward the wave only when the cycle produces leads. Forward To some "burn" curly queries and hid that the root cause was the billing of the Gemini (corrected on L-057).

L-057 · Billing vs. quota

Gemini's 429 was prepayment credits depleted, No free-tier quota. GeminiClient now surfs the error.message raw; the endpoint returns 502 with message actionable (billing link).

See at 57 full lessons →

9 Version map (restoring points)

v0.1.1

CI-green Foundation: toolchain, contracts, planning.

v0.7.0

Functional PoC: pipeline M1→M5 + smoke E2E byte-identical.

v0.8–0.12

Intent motor (hypothesis), actionable Lead Card, IU of operator, persona accuracy.

v0.13–0.14

Volume foundation: Apollo schemas, credit ledgers/RPD, corpus; discovery End-to-end Apollo.

v0.15.4

Full volume specs: Apollo ladder (1/2/3), batch+RPD, cumulative corpus. 120 green tests.

v0.16. x

Cockpit v2 (dense table + draker), billing degradation with actionable message (L-057), incremental search for waves.

v0.17. x

Learned by feedback (ADR-007): regression deterministic logistics, store of atomic votes, auto-apply weights with 4 locks. 150+ Green tests. Modules: learning/ (model, tuner, feedback store, schemas).

How to turn on volume + learning (real run)

# 1) runtime.toml
[apollo].enabled = true   [corpus].enabled = true
[gemini].rpd_enabled = true   [learning].enabled = true
# 2) gravar fixtures (supervisionado — Apollo master exige plano pago)
.venv\Scripts\python.exe scripts\record_apollo_fixtures.py
# 3) rodar o pipeline
.venv\Scripts\python.exe -m socialselling.orchestrator --icp config\icp_criteria.talita.json
# 4) cockpit web (marcar likes/dislikes → reajusta pesos automaticamente)
.venv\Scripts\python.exe -m socialselling.web  # → http://127.0.0.1:8000

10 Planning & development operation

The project adopts a governance model that separates author specification (interactive, made by day) implementation (autonomous, made at night). This optimizes Claude Code Pro's quota and maintains repository integrity — the owner uses the day to think and evolve the system; development runs on the scheduled run.

Board Flow (GitHub) Project #1

Backlog
card draft
DoR 100% → only human moves
All
approved p/ night
night run →
In Progress
skill runs
DoD 100% →
Done
Merged PR

Card blocked (Incomplete DoR or red gate after 2 attempts) → BLOCKED: in PROGRESS.md and return it to Backlog. Never guess — for and report.

☀️

Day Session — Authorship

  • 1.Understand what the owner whether to evolve (and why).
  • 2.Draft cards using o DoR/DoD template.
  • 3.Charge the DoR — ask the owner for each missing item (Gherkin, fixtures, contract, scope). Never push card incomplete.
  • 4.Card with DoR 100% → move to All (only human does that).
  • 5.Large developments → break into several small cards (1 WU each).
I do it on the day: specs, ADRs, contracts, docs, tooling (scripts/CI/skills), board governance and curatorship.
🌙

Night Run — Autonomous Execution

  • S1.Read .ai/state/PROGRESS.md + card in All major priority.
  • S2.If blocking → Stop and report (don't guess).
  • S3.Revalidate the DoR — if some item is open, mark BLOCKED: and returns Backlog.
  • S4.Run 1–2 steps of WU (pacing). Rotate ./scripts/gate.ps1.
  • S5.Green Gate → commit in feature branch; if WU closed: PR auto-merge + tag.
  • S6.Update PROGRESS.md + lessons. Stop at a secure checkpoint.
Vira card: implementation src/socialselling/, tests/, fixtures — everything that changes the behavior of product.

Definition of Ready (DoR)

Card can go from Backlog → All?

  • 1 Objective observable in 1 sentence (why + verifiable result)
  • 2 Sliced in 1 WU — fits in an execution window
  • 3 Pydantic Contract defined; ADR linked if module crosses
  • 4 Gherkin: happy path + degraded mode + Open-World
  • 5 Identifyed Fixtures; no pay/entitlement network lock
  • 6 No open border decision
  • 7 Within the canonical scope (§3/§5/ADR-000)
  • 8 Viable Determinism (Mocked IPAs, tolerance 1e-9)
  • 9 Specific DoD declared in card body

Definition of Done (DoD)

Card can go from In Progress → Done?

  • 1 Green and byte-identical BDD scenarios (zero flakiness)
  • 2 Committed Fixtures; Tests Do Not Play Network
  • 3 Full Gate: ruff + mypy --strict + pytest ✅
  • 4 Respected semantic invariants; atomic persistence
  • 5 Preserved Scope — Minimum Slice Implemented
  • 6 PR with green IC (gh pr merge --squash --auto)
  • 7 PROGRESS.md + lessons updated in the same PR
  • 8 Card in Done + tag vX.Y.Z if you've closed a milestone
  • 9 Fail-closed: red gate after 2 attempts → BLOCKED:

⛔ Guardrails de autonomia (inegociáveis)

  • Never commit/push directly to main — only via PR with CI green
  • Never --force; rollback only via git revert in PR
  • Never invent specification — ambiguity → BLOCKED: and for
  • No fixtures recorded → does not implement modules that play network (M1/M2)
  • Always stop at a secure checkpoint; never end in destructive step

Exceptions to night mode

  • Explicit request the owner: "do it now," "Implement this" — the override always wins.
  • Critical Hotfix: main broken or critical bug — fix on time via PR + green gate, register later.

Out of these two cases, product implementation = card/night.

State anchor & cadence

📌 .ai/state/PROGRESS.md

Source of truth from where we left off. The run read in start and update at end. Contains: current milestone, green tag, WU in progress, step (S1–S6), branch, next action, blocks and run history.

State never lives in session — lives in git + PROGRESS. md. Any new run rebuilds the context by reading these two.

Recommended cadence

Window Early BRT (~02:00) — no containment with interactive use
Frequency 1 run/night at start; adjust for weekly consumption
Scope/run 1–2 steps from a WU (cable in window; ends in checkpoint)
Supervision WUs with network (M1/M2): record fixtures with the present owner; Pure WUs: more safe to run alone
Review Owner reviews morning merges/tags; CI is the safety net

Technical reference

11 Contracts & data model

All pipeline operates on contracts Pydantic v2 declared ed src/socialselling/contracts.py — the only point of truth data models. Each M1–M5 module produces and consumes well-defined types; never share changeable references between layers.

Flow of contracts by pipeline

IN
ICPcriteria — universal pipeline entry

Firmographics geographies, business models) · Technographics (tech mandate/preferred/excluded) · PersonaMatrix (target rolls, minimum seniority) · intent triggers (signs of hypothesis)

M1
ObservedEvidence — layer 1 · what has been seen

evidence_id (hash SHA-256 stable) · query, source_url, snippet, source_trust · missing_evidence: bool (Open-World explicit)

M2
Inference — layer 2 · which has been deducted

CompanyEntity (name, domain, industry, technologies, contacts, social networks) · PersonEntity (name, position, seniority) · derived_from: list[evidence_id] (traceability) compulsory) · intent_signals, disqualifiers, persona · confidence

M3
ProspectScore — layer 3 · evaluation

fit, intent, confidence, persona_fit, p_score, hard_filter_passed

M5
XAIPayload — structured justification

positive_signals, negative_signals (list of Driver with impact and text) · missing_signals (Explicit Missing Evidence) · degraded_mode

OUT
LeadCard — actionable pipeline output

display_name, company, role, sector, location · links (Instagram first, LinkedIn, website) · contact (email, phone) · score (ProspectScore complete) · why_now[] (immediate reasons) · gaps[] (signs absent) · sources[]

Score Formula (M3)

P = (w fit · Fit + w intent · Intent)

    × Trustexp × persona fit

w_fit = weight of structural fit0.60
w_intent = weight of intention0.40
confidence_exponent0.5
persona_fit (founder)1.0
persona_fit (founder)0.0

M3 and M4 are pure functions: same input → output byte-identic (1e-9). Hard filter (disqualifier detected) zeros the lead. Configurable weights ed runtime.toml and readjustable by feedback

Hypothesis Catalogue (Intent)

Intent = intent_signals detected by M2. Config config/hypotheses_catalog.json.

H 01prior 0.30

Founding woman stuck in the operation — stopped growth

H 02prior 0.20

Recent Senior Hire / Team Training

H 03prior 0.18

Announced expansion — new unit or service

H 04prior 0.17

Intention to adopt AI without organized process

H 05prior 0.10

Recent completion of course/management mentoring

12 Source structure

Each subdirectory of src/socialselling/ You have a strict responsibility. delimited. No module imports from a level module above the pipeline.

Contracts. py point only contracts

All pipeline Pydantic models (4 layers): ICPCriteria → ObservedEvidence → Inference (+ CompanyEntity, PersonEntity) → ProspectScore / XAIPayload / RankedProspect → LeadCard. Rule: no business logic here.

modules/

m1_busca.py — Tavily/Apollo, atomic cache 24 hours, ObservedEvidence[]
m2_extracao.py — lots Gemini, parsing Pydantic, Inference[]
m3_score.py — pure linear formula, hard filter, ProspectScore[]
m4_ranking.py — sort stable by p score, tie-break by company id
m5_xai.py — generates XAIPayload by rules, without AI

Skills/ — external customers

tavily_client.py — HTTP + cache + degradation (429/timeout)
gemini_client.py — JSON generation, backoff exponential, surfacia error.message raw
apollo_client.py — REST Apollo, 3 endpoints, ledger integrated

Core/ — internal infrastructure

atomic.py — write-temp + os.replace (imprimitive atomic writing)
cache.py — cold cache in JSON, key = hash SHA-256 Content
credit_ledger.py — monthly budget Apollo (try_spend/refund)
request_ledger.py — daily budget DPR Gemini

apollo/ · corpus/ · learning/

apollo/schemas.py — REST contracts Apollo; normalize.py → ObservedEvidence
corpus/store.py — upsert idempotent by entity_id; waves.py — generation of queries per wave
learning/model.py — pure logistic regression; tuner.py — shrinkage + clamp; feedback_store.py — atomic votes

orchestrator. py

Synchronous unified pipeline M1→M5. Injects customers, cache and clock; returns list[LeadCard]. Export run_pipeline() (CLI and web) and accumulate_and_rank() (corpus+wave).

web/

app.py — routes FastAPI (run, feedback, weights, status) · services.py — UI business logic · static/ — HTML cockpit + JS · schemas.py — Web API contracts

config/

runtime.toml — all adjustable parameters (weights, TTLs, limits, opt-ins)
hypotheses_catalog.json — hypotheses priors and surface signals
icp_criteria.*.json — concrete PCIs (talita, example)

scripts/

gate.ps1 / gate.sh — ruff + mypy + pytest in sequence
bootstrap.ps1 / bootstrap.sh — zero setup (venv + deps + .env)
record_*_fixtures.py — record actual Tavily/Gemini/Apollo
new_card.ps1 — creates card in GitHub Project with DoR template
setup_github_project.ps1 — syncs PROGRESS. md → board

13 Tests, BDD & observability

The test suite is the guarantee that the system is deterministic, byte-identical and Never touch network. Every external call is mocked with supervised recorded fixtures.

Gherkin Features

tests/features/

m1_busca.feature · M2 · M3 · M4 · M5
pipeline_smoke.feature — E2E byte-identical
objetivo_ranking.feature — business objective

Each module requires 3 scenarios: Happy (normal path) + degraded (429/timeout → degrades, does not break) + Open-World (sign missing → uncertainty ↑, never false).

🗂️ Fixtures gravadas

tests/fixtures/

Real API responses captured once, with supervision, via dedicated scripts:

record_tavily_fixtures.py
record_gemini_fixtures.py
record_apollo_fixtures.py (requires paid plan)

Once recorded, the tests use them via FakeTavilyClient / FakeGeminiClient — network is never touched in IC.

Test guarantees

  • Byte-identical execution (smoke executes 2×)
  • Numeric tolerance abs(a-b) ≤ 1e-9
  • IDs per stable hash SHA-256 (never random UUID)
  • Clock injected as parameter (now: datetime)
  • Flakiness = failure (zero tolerance)
  • mypy --strict no errors
  • StrEnum (no str, Enum) for Python 3.11+

PoC & SLO observability

📊 logs/cognitive_trace.jsonl

Log append-only with an event by relevant decision of Pipeline. Each line: {ts, module, action, lead_id, inputs_hash, outputs_hash, tokens, degraded}. Allows auditing cost, reproducing decisions and, in the future, measuring latency without extra instrumentation. Traceability: Evidence → Inference → Score → Decision guaranteed via derived_from.

PoC SLOs

SLI Target (SLO)
Green tests on the main 100% (blocking)
Pipeline Determinism 100% byte-identical (blocker)
Type coverage mypy --strict without errors
Cost per execution ≤ budget runtime. Toml
Latency (N≤50 leads) p95 calibrating via trace

Error zero budget for determinism and testing. Latency/cost: target calibrating — does not block merge in PoC.

14 Central Configuration (runtime.toml)

config/runtime.toml It's the PoC control panel. None secret here ( API keys stay in .env). All features opt-in are turned off by default to preserve the parity of the smoke E2E.

[coring] — score formula

w_fit = structural fit weight0.60
w_intent = weight of intention0.40
confidence_exponent0.5
w_fit_tech / w_fit_industry0.60 / 0.40
intent_evidence_norm5

[persona] — multipliers per type

fundadora1.0 ← target
indefinido0.5
empresa0.35
fundador0.0 ← hard filter

[finops] — cost control

tau_finops — pruning threshold0.60
kappa_degraded — penalty in degraded mode0.80

[gemini] — cognition

modelgemini-2.5-flash-lite
batch_size50
timeout_seconds120
rpd_enabledfalse ← opt-in
rpd_cap req/day1000

[cache] · [tavily] · [runtime]

cache.ttl_hours24 h
tavily.max_queries3
tavily.persona_term"founder"
runtime.max_leads_per_cycle50

[apollus] — Firmographic sensor (opt-in)

enabledfalse ← opt-in
reveal_top_n20
org_enrich_ttl_hours720h (30d)
reveal_ttl_hours2160h (90d)
caps.data_credits_cap100/month

[corpus] & [learning] — opt-ins active

corpus.enabledtrue ← connected
corpus.pathdate/corpus/leads corpus.json
corpus.waves_pathdate/corpus/waves. json
learning.enabledtrue ← connected
learning.min_likes / min_dislikes3 / 3
learning.l20.1
learning.epochs500
learning.shrinkage_max0.5
Parity rule: any feature with enabled = false Leaves the pipeline byte-identical to the baseline. Connect a feature = change the hot path; disconnect = zero impact. The E2E smoke validates this every PR.

In short

What SocialSelling is

O SocialSelling makes customer search more efficient and automatic with AI, built with real engineering: decisions recorded in ADRs/SDDs, one SDD-to-Code Loop with deterministic gates and continuous feedback learning.

  • Automatic AI prospecting — find and qualify customers with less manual effort.
  • ADRs/SDDs — architecture and behaviour documented as a source of truth.
  • SDD-to-Code Loop + gates — determinism and Open-World on the critical path.
  • Learning by feedback — the system improves with the real result.

Frequently Asked Questions

Frequently Asked Questions

What is the SocialSelling project?

It is a system that makes the search and qualification of customers more efficient and automatic with AI. It was built with disciplined engineering: decisions in ADRs/SDDs, an SDD-to-Code loop with deterministic gates and feedback learning.

How do determinism and Open-World appear here?

The critical path solves what can be solved with rules (deterministic-first) and treats absence of data as explicit uncertainty (Open-World), not as "falso". This prevents AI from inventing qualifications and keeping the result auditable.

What is SDD-to-Code Loop?

It is the cycle in which the specification directs the implementation and the gates validate each step before advancing: the intention is written, the AI implements against it and the tests/gates prove compliance. The feedback learning feeds the spec.