Skip to content

fix(catalog): preserve recurring outcomes as latest - #541

Merged
kstonekuan merged 3 commits into
Hebbian-Robotics:mainfrom
Kaileshwar16:fix/catalog-recurring-outcomes
Sep 15, 2026
Merged

kstonekuan merged 3 commits into
Hebbian-Robotics:mainfrom
Kaileshwar16:fix/catalog-recurring-outcomes

Conversation

@Kaileshwar16

Copy link
Copy Markdown
Contributor

Fixes a catalog state bug where an outcome that occurred earlier could be deduplicated incorrectly when it happened again later.

For example:

error → success → error

The final error was previously treated as an old duplicate, so the catalog stayed ok and the episode remained in the dataset.

The same problem happened in reverse when a successful result followed an earlier failure.

This change keeps consecutive identical retries idempotent, while recording a recurring outcome as a new catalog occurrence. It also adds an optional execution_id for retries that may arrive after other executions have already completed.

The Parquet format and canonical episode identities remain unchanged.

Tests

Added coverage for:

  • recurring outcomes
  • consecutive retries
  • selective-stage runs
  • explicit execution IDs
  • local and bucket-backed catalogs
  • concurrent appends
  • crash recovery and dependent-table repair
  • historical timestamp preservation

Validation:

2032 passed, 9 skipped
ruff check --fix
ruff format
ty check
git diff --check

Closes #540.

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One gap: removing the execution_id must be non-empty when supplied check passes all 150 tests.

Everything else is held well. Reverting the scoping fails 21, and ignoring execution_id fails its own case.

I checked the property the new fingerprint could have broken, since it now depends on catalog state at append time: CATALOG.md:114 promises concurrent duplicate appends converge. Two workers appending the same outcome at once still produce one row, and so does a sequential repeat. Your design holds it.

@Kaileshwar16

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I removed the execution_id validation as suggested and reran the tests. The 150 catalog, dataset, and bucket tests passed, along with ruff, ty, and git diff --check.
I have pushed the follow up commit.

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant add a test, not delete the guard. My wording was ambiguous.

Without it, empty and whitespace ids become distinct scopes rather than an error:

None  -> out
""    -> out.a8de770a92e6a396
"  "  -> out.c758dd61b918da88

So execution_id="" silently buys a unique execution identity, and "" and " " are different ones. Restore the check and give it a case.

@Kaileshwar16

Copy link
Copy Markdown
Contributor Author

@kstonekuan Sorry, I misunderstood the first comment. Restored the guard and added tests for empty and whitespace-only IDs.

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, merging.

Guard restored and held, including whitespace-only: dropping .strip() fails its case on its own.

No apology needed, my first comment was ambiguous.

Full suite on the rebased result: 2054 passed / 8 skipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Repeated critical-check failures leave an episode marked ok after an intervening success

2 participants