From d86b63a4529e1f7a3cc1d7495c2dd745b33c1f78 Mon Sep 17 00:00:00 2001
From: artiehinz <133814822+artiehinz@users.noreply.github.com>
Date: Tue, 28 Jul 2026 20:29:50 -0600
Subject: [PATCH] feat: add ambiguous external write recovery skill
---
docs/README.skills.md | 1 +
.../SKILL.md | 190 ++++++++++++++++++
2 files changed, 191 insertions(+)
create mode 100644 skills/recover-ambiguous-external-writes/SKILL.md
diff --git a/docs/README.skills.md b/docs/README.skills.md
index 46d2bb38bf..0afb8a88df 100644
--- a/docs/README.skills.md
+++ b/docs/README.skills.md
@@ -343,6 +343,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [react19-source-patterns](../skills/react19-source-patterns/SKILL.md)
`gh skills install github/awesome-copilot react19-source-patterns` | Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates. | `references/api-migrations.md` |
| [react19-test-patterns](../skills/react19-test-patterns/SKILL.md)
`gh skills install github/awesome-copilot react19-test-patterns` | Provides before/after patterns for migrating test files to React 19 compatibility, including act() imports, Simulate removal, and StrictMode call count changes. | None |
| [readme-blueprint-generator](../skills/readme-blueprint-generator/SKILL.md)
`gh skills install github/awesome-copilot readme-blueprint-generator` | Intelligent README.md generation prompt that analyzes project documentation structure and creates comprehensive repository documentation. Scans .github/copilot directory files and copilot-instructions.md to extract project information, technology stack, architecture, development workflow, coding standards, and testing approaches while generating well-structured markdown documentation with proper formatting, cross-references, and developer-focused content. | None |
+| [recover-ambiguous-external-writes](../skills/recover-ambiguous-external-writes/SKILL.md)
`gh skills install github/awesome-copilot recover-ambiguous-external-writes` | Recover external writes whose result was lost or timed out without blindly repeating duplicate-sensitive mutations. Use when a tool may have committed a create, send, update, delete, payment, deployment, or other side effect but the agent did not receive a trustworthy result. | None |
| [refactor](../skills/refactor/SKILL.md)
`gh skills install github/awesome-copilot refactor` | Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements. | None |
| [refactor-method-complexity-reduce](../skills/refactor-method-complexity-reduce/SKILL.md)
`gh skills install github/awesome-copilot refactor-method-complexity-reduce` | Refactor given method `${input:methodName}` to reduce its cognitive complexity to `${input:complexityThreshold}` or below, by extracting helper methods. | None |
| [refactor-plan](../skills/refactor-plan/SKILL.md)
`gh skills install github/awesome-copilot refactor-plan` | Create a concrete plan before starting a multi-file refactor. Use when the user asks to plan, sequence, scope, or safely execute a refactor across multiple files; always investigate first, output the plan, and wait for confirmation before making code changes. | None |
diff --git a/skills/recover-ambiguous-external-writes/SKILL.md b/skills/recover-ambiguous-external-writes/SKILL.md
new file mode 100644
index 0000000000..ab0cef6c73
--- /dev/null
+++ b/skills/recover-ambiguous-external-writes/SKILL.md
@@ -0,0 +1,190 @@
+---
+name: recover-ambiguous-external-writes
+description: 'Recover external writes whose result was lost or timed out without blindly repeating duplicate-sensitive mutations. Use when a tool may have committed a create, send, update, delete, payment, deployment, or other side effect but the agent did not receive a trustworthy result.'
+---
+
+# Recover Ambiguous External Writes
+
+Treat a lost response as an unknown outcome, not a failed operation. Reconcile the
+destination before deciding whether to retry.
+
+## Non-negotiable rules
+
+- Persist the logical operation identity before starting the external write.
+- Reuse one provider idempotency key for every attempt at that logical operation.
+- Never classify a timeout, disconnect, or malformed response as proof of failure.
+- Never retry a duplicate-sensitive write until absence is proven or the provider
+ guarantees idempotency for the reused key.
+- Prefer destination state over client logs when the two disagree.
+- Keep credentials, personal data, and destination payloads out of shared
+ checkpoints. Store only opaque identifiers and evidence fingerprints.
+- Do not claim exactly-once execution unless the destination provides that
+ guarantee.
+
+## Recovery workflow
+
+### 1. Classify the operation
+
+Record:
+
+- operation type: create, send, update, delete, payment, deployment, or batch;
+- duplicate harm: harmless, reversible, costly, destructive, or unknown;
+- provider idempotency contract, including key lifetime and request matching rules;
+- stable destination marker or lookup key;
+- read-after-write, status, audit-log, or webhook evidence available;
+- compensation action and whether it requires approval.
+
+Use the ordinary path for a one-time, low-risk operation when recovery machinery
+would add no useful protection. State that decision explicitly.
+
+### 2. Establish a stable identity
+
+Create one opaque `operation_id` for the intended logical effect. Before the first
+write, durably record:
+
+```text
+operation_id
+provider_idempotency_key
+destination_marker
+expected_invariant
+stage = planned
+```
+
+Do not generate a new identity merely because a process restarted or a response
+was lost.
+
+### 3. Preflight the destination
+
+Search by the stable marker or query the provider status API. If the intended
+effect already exists and matches the expected invariant, record it as verified
+and do not write again.
+
+If multiple workers may act on the same operation, acquire a lease or compare-and-
+swap claim before proceeding. A lease prevents concurrent attempts; it does not
+prove what happened at the destination.
+
+### 4. Record intent before the write
+
+Transition the durable checkpoint to:
+
+```text
+stage = external_attempt_started
+attempt = N
+started_at =
+```
+
+Persist this transition before invoking the mutating tool. Then make at most one
+unprotected attempt.
+
+### 5. Handle the response
+
+- **Trusted success:** verify the destination, then record `caller_verified`.
+- **Trusted rejection before execution:** record `failed`; retry only if the
+ operation remains authorized and the error is retryable.
+- **Timeout, disconnect, cancellation, or invalid response:** record
+ `external_result_uncertain`; do not immediately retry.
+
+The checkpoint records the caller's knowledge. It is not external proof by itself.
+
+### 6. Reconcile an uncertain result
+
+Use the strongest available evidence in this order:
+
+1. provider operation-status lookup using the original idempotency or request key;
+2. destination read-back using the stable marker;
+3. destination audit log, event, receipt, or webhook;
+4. a domain invariant that uniquely establishes the intended effect.
+
+Classify the result:
+
+| Finding | Next action |
+| --- | --- |
+| Matching effect found | Record `caller_verified`; do not retry |
+| Conclusive proof of absence | Retry only if still authorized |
+| Conflicting or partial evidence | Keep `external_result_uncertain`; stop for review |
+| No trustworthy evidence | Keep `external_result_uncertain`; stop for review |
+
+When retrying after proven absence, reuse the original provider idempotency key.
+When the provider rejects expired keys, treat the retry as a new risk decision and
+obtain approval if duplicate harm is material.
+
+### 7. Verify completion
+
+Verification must identify the destination result and check the expected invariant.
+Store an opaque result identifier, evidence type, observation timestamp, and
+optional keyed fingerprint. Do not store sensitive response bodies merely to make
+the checkpoint look complete.
+
+### 8. Report the honest guarantee
+
+Use one of these labels:
+
+- `provider-idempotent`: the provider contract deduplicates the stable key;
+- `duplicate-resistant`: read-back or fencing reduces duplicate risk;
+- `concurrency-safe`: one valid worker can attempt the operation at a time;
+- `best-effort`: the outcome cannot be conclusively reconciled.
+
+Report the operation identity strategy, attempts made, evidence observed, final
+stage, guarantee label, remaining uncertainty, and any human follow-up.
+
+## Reference state machine
+
+```text
+planned
+ -> external_attempt_started
+ -> caller_verified
+ -> failed
+ -> external_result_uncertain
+ -> caller_verified
+ -> failed # only with conclusive proof of absence/rejection
+ -> compensated # only after an authorized compensation
+```
+
+Never transition `external_result_uncertain` directly back to
+`external_attempt_started` solely because time passed.
+
+## Pseudocode
+
+```text
+checkpoint = load_or_create(operation_id)
+
+if checkpoint.stage == caller_verified:
+ return checkpoint.verified_result
+
+evidence = reconcile(destination_marker, provider_idempotency_key)
+if evidence.matches_expected_effect:
+ save(caller_verified, evidence)
+ return evidence.result
+
+if checkpoint.stage == external_result_uncertain and not evidence.proves_absence:
+ stop_for_review(evidence)
+
+claim(operation_id)
+save(external_attempt_started)
+
+try:
+ response = write_once(idempotency_key=provider_idempotency_key)
+except LostResponse:
+ save(external_result_uncertain)
+ evidence = reconcile(destination_marker, provider_idempotency_key)
+ if evidence.matches_expected_effect:
+ save(caller_verified, evidence)
+ return evidence.result
+ stop_for_review(evidence)
+
+evidence = verify(response, destination_marker)
+save(caller_verified, evidence)
+return evidence.result
+```
+
+## Stop conditions
+
+Stop and request human review when:
+
+- the operation could be destructive and the destination cannot prove presence or
+ absence;
+- the stable marker is not unique;
+- the provider's idempotency behavior is undocumented or the key expired;
+- observed state conflicts across provider status, read-back, and audit evidence;
+- compensation would create another irreversible effect;
+- required authorization has expired or changed.