Repository navigation
feat(condition): CreateOutcomeUnknown, its own Ready reason for a create the runtime refuses to repeat (#93) - #94
Merged
Conversation
…ate the runtime refuses to repeat (#93) When a create was started (krateo.io/external-create-pending set) and the existence check that would decide its outcome fails, the worker refuses to act rather than risk creating the resource twice. That refusal is right: azuredevops-provider-kog ran 10 forced status-write races against a real vendor and got 0 duplicates, one through this exact branch. But it set a bare Ready=False/Creating, which reads like a healthy create in progress. A consumer could not tell "converging" from "needs a human unless the next check succeeds", and the cause reached only Synced. Decision (Diego, 2026-11-15): a distinct reason, resolved by a human. Not provider-runtime's bounded recovery (a grace, then remove the marker and retry), which on a backend that cannot find what a lost create made would create a duplicate real resource. condition.ReasonCreateOutcomeUnknown = "CreateOutcomeUnknown" and condition.CreateOutcomeUnknown(message) (Ready, False). The worker writes it with the existence check's error and the remediation, beside the existing ReconcileError on Synced. It clears when a later existence check succeeds (retried on every resync, so a transient cause clears by itself) or when a human, having verified the external state, removes the marker. Announced to installer (their gate refuses an unclassified reason by design) and to oasgen-provider (who adds it to their condition fallback) before merge. rest-dynamic-controller's createHasBeenAttempted returns early on the annotation, so no coordinated release there (oasgen's retraction on the issue). Test: TestCreateIncomplete_ConditionCarriesTheReason (which drives the branch, with calibrations) now also asserts Ready itself is False/CreateOutcomeUnknown, carrying the cause and the remediation. Mutant (back to a bare Creating) killed. Unit (18 packages) and vet under every tag pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N8HNbBzRpE6rUjMRzosAjG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a create was started (krateo.io/external-create-pending set) and the
existence check that would decide its outcome fails, the worker refuses
to act rather than risk creating the resource twice. That refusal is
right: azuredevops-provider-kog ran 10 forced status-write races against
a real vendor and got 0 duplicates, one through this exact branch. But it
set a bare Ready=False/Creating, which reads like a healthy create in
progress. A consumer could not tell "converging" from "needs a human
unless the next check succeeds", and the cause reached only Synced.
Decision (Diego, 2026-11-15): a distinct reason, resolved by a human. Not
provider-runtime's bounded recovery (a grace, then remove the marker and
retry), which on a backend that cannot find what a lost create made would
create a duplicate real resource.
condition.ReasonCreateOutcomeUnknown = "CreateOutcomeUnknown" and
condition.CreateOutcomeUnknown(message) (Ready, False). The worker writes
it with the existence check's error and the remediation, beside the
existing ReconcileError on Synced. It clears when a later existence check
succeeds (retried on every resync, so a transient cause clears by itself)
or when a human, having verified the external state, removes the marker.
Announced to installer (their gate refuses an unclassified reason by
design) and to oasgen-provider (who adds it to their condition fallback)
before merge. rest-dynamic-controller's createHasBeenAttempted returns
early on the annotation, so no coordinated release there (oasgen's
retraction on the issue).
Test: TestCreateIncomplete_ConditionCarriesTheReason (which drives the
branch, with calibrations) now also asserts Ready itself is
False/CreateOutcomeUnknown, carrying the cause and the remediation.
Mutant (back to a bare Creating) killed. Unit (18 packages) and vet
under every tag pass.
Closes #93. Hold merge until installer and oasgen have confirmed the literal.
🤖 Generated with Claude Code
https://claude.ai/code/session_01N8HNbBzRpE6rUjMRzosAjG