Commit Graph

6 Commits

Author SHA1 Message Date
Émile Ré
46fc755b6e Fix enrichment re-arm and migration backfill gaps
Three crash- and migration-recovery gaps in the unified enrichment
model left rows stuck or misclassified:

- Upsert re-armed a blank, newly-linked tracker pattern without
  clearing its prior enrichment payload. A crash between the worker's
  claim and persist then left the row with a stale payload, so the
  stale-recovery sweep (which only catches rows with a null payload)
  skipped it forever. Clear enrichment on re-arm so the row reads as
  not-yet-completed again, and pin the behavior with a test.

- The migration added last_enrichment_attempt_at to
  common_third_parties without seeding it. Rows with prior attempts
  kept a NULL clock and could never satisfy the stale-reset predicate.
  Backfill from updated_at, the historical claim-time proxy.

- The migration switched the tracker-pattern enriched-state source to
  the enrichment payload without backfilling rows previously marked by
  enriched_at, making already-enriched rows read as unenriched.
  Seed a provenance sentinel for rows that carried the old done-flag.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-16 17:44:57 +02:00
Émile Ré
ef6cead482 Unify enrichment tracking and outcome-based status
Make common_tracker_patterns and common_third_parties share one
enrichment-tracking model and fix the misleading proboctl status.

Both tables now carry the enrichment JSONB provenance payload, an
enrichment_attempts counter, and a last_enrichment_attempt_at clock.
On common_tracker_patterns the enriched_at done-flag is renamed to
last_enrichment_attempt_at and stamped at claim time, so it is truthful
to "attempt" rather than "success". A row is considered to have been
through the workflow when it carries an enrichment payload, not when a
timestamp is set, which lets stale recovery key off the payload being
absent with budget remaining, exactly like common_third_parties.

The claim path reads the attempt counter and timestamp back via
RETURNING so the in-memory receiver matches the database clock instead
of a separate app-side time.Now.

The enricher builds a per-field provenance payload (description and
third-party outcomes plus the mapping attribution) and persists it via
UpdateEnrichment, named to mirror the common-third-party sibling. The
common pattern enrichment worker gains a max-attempts ceiling so a
permanently failing row stops looping.

proboctl now shows "enriched" only when every field the last run
recorded an outcome for resolved a value, otherwise "partial (X/Y)",
replacing the misleading "enriched (no description)" label.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-16 17:44:57 +02:00
Sacha Al Himdani
9ac71f948f Update contact email to hello@probo.com
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 16:45:23 +02:00
Bryan Frimin
a8d4da3916 Centralize Postgres test fixture in internal/test
Each package that exercises the database against a real Postgres
carried its own copy of the connection bootstrap and schema setup.
Those copies had already drifted: some keyed off PROBO_TEST_PG_ADDR
with hardcoded defaults, others off PROBO_TEST_PG_URL, and the
agentrun/coredata suites hand-applied individual agent_runs
migrations to ensure the table existed.

Introduce a single test.PGClient helper that parses PROBO_TEST_PG_URL
(falling back to the local compose database), runs the full coredata
migration set once per process, and skips when no database is
reachable so make test stays a pure unit-test run. Migrate the
agentrun, coredata, cookiebanner, iam, and thirdparty suites onto it
and delete the duplicated helpers so the bootstrap can no longer
diverge.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-08 15:27:54 +02:00
Émile Ré
c8b7615046 Fix lint issues
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-01 13:17:17 +02:00
Émile Ré
9b03d199da Reuse mapping agent to attribute trackers in enricher
The enrichment worker no longer invents a description when a tracker's
purpose cannot be substantiated; it records an empty description and
marks the row enriched so the stale-recovery loop does not retry it.

Vendor identification is the mapping pipeline's job, so the enricher
reuses the existing tracker-mapping agent to attribute a third party
for an unlinked common pattern before describing it. A confident
catalog match seeds the enrichment prompt and links the pattern, but
the enricher never creates or overrides an attribution.

When a blank, unlinked catalog row later gains a third party through
the mapping pipeline's upsert, enrichment is re-armed so the now-known
vendor gets a second, better-informed description attempt.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-01 13:17:17 +02:00