@homericintelligence/athena-opencode 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +30 -17
  2. package/package.json +2 -2
  3. package/plugin.js +20 -5
  4. package/skills/TECHNICAL_ENGLISH.md +78 -0
  5. package/skills/_cli.py +26 -18
  6. package/skills/_support/docs/dependency-resolution.md +192 -0
  7. package/skills/_support/docs/policies/development.md +117 -0
  8. package/skills/_support/docs/policies/evidence-integrity.md +40 -0
  9. package/skills/_support/docs/principles/README.md +542 -0
  10. package/skills/_support/docs/principles/details/p001-kiss.md +114 -0
  11. package/skills/_support/docs/principles/details/p002-yagni.md +109 -0
  12. package/skills/_support/docs/principles/details/p003-dry.md +126 -0
  13. package/skills/_support/docs/principles/details/p004-solid.md +165 -0
  14. package/skills/_support/docs/principles/details/p005-modularity.md +123 -0
  15. package/skills/_support/docs/principles/details/p006-principle-of-least-astonishment.md +115 -0
  16. package/skills/_support/docs/principles/details/p007-subtraction-over-addition.md +113 -0
  17. package/skills/_support/docs/principles/details/p008-understand-before-subtracting.md +115 -0
  18. package/skills/_support/docs/principles/details/p009-general-mechanisms-over-special-cases.md +108 -0
  19. package/skills/_support/docs/principles/details/p010-scope-fidelity.md +117 -0
  20. package/skills/_support/docs/principles/details/p011-minimal-coherent-change.md +128 -0
  21. package/skills/_support/docs/principles/details/p012-evidence-before-modification.md +115 -0
  22. package/skills/_support/docs/principles/details/p013-avoid-hasty-abstractions.md +112 -0
  23. package/skills/_support/docs/principles/details/p014-preserve-unrequested-behavior.md +110 -0
  24. package/skills/_support/docs/principles/details/p015-architecture-conformance.md +124 -0
  25. package/skills/_support/docs/principles/details/p016-separation-of-concerns.md +125 -0
  26. package/skills/_support/docs/principles/details/p017-high-cohesion-low-coupling.md +130 -0
  27. package/skills/_support/docs/principles/details/p018-information-hiding.md +128 -0
  28. package/skills/_support/docs/principles/details/p019-explicit-contracts.md +134 -0
  29. package/skills/_support/docs/principles/details/p020-executable-architecture.md +130 -0
  30. package/skills/_support/docs/principles/details/p021-evolutionary-and-reversible-design.md +126 -0
  31. package/skills/_support/docs/principles/details/p022-test-behavior-not-implementation.md +129 -0
  32. package/skills/_support/docs/principles/details/p023-parameterized-table-driven-testing.md +129 -0
  33. package/skills/_support/docs/principles/details/p024-boundary-value-testing.md +128 -0
  34. package/skills/_support/docs/principles/details/p025-property-based-testing-for-invariants.md +133 -0
  35. package/skills/_support/docs/principles/details/p026-regression-before-repair.md +134 -0
  36. package/skills/_support/docs/principles/details/p027-deterministic-and-hermetic-tests.md +128 -0
  37. package/skills/_support/docs/principles/details/p028-test-failure-paths.md +133 -0
  38. package/skills/_support/docs/principles/details/p029-generalize-error-policy-preserve-specific-cause.md +131 -0
  39. package/skills/_support/docs/principles/details/p030-nearest-responsible-error-boundary.md +133 -0
  40. package/skills/_support/docs/principles/details/p031-propagate-rather-than-swallow.md +131 -0
  41. package/skills/_support/docs/principles/details/p032-handle-once-preserve-causality.md +137 -0
  42. package/skills/_support/docs/principles/details/p033-state-safe-failure-semantics.md +140 -0
  43. package/skills/_support/docs/principles/details/p034-fail-fast.md +132 -0
  44. package/skills/_support/docs/principles/details/p035-fail-secure-fail-closed.md +137 -0
  45. package/skills/_support/docs/principles/details/p036-graceful-degradation.md +137 -0
  46. package/skills/_support/docs/principles/details/p037-idempotency-before-retry.md +139 -0
  47. package/skills/_support/docs/principles/details/p038-bounded-retry.md +145 -0
  48. package/skills/_support/docs/principles/details/p039-bounded-waiting.md +151 -0
  49. package/skills/_support/docs/principles/details/p040-bounded-resources.md +138 -0
  50. package/skills/_support/docs/principles/details/p041-backpressure-and-load-shedding.md +141 -0
  51. package/skills/_support/docs/principles/details/p042-fault-isolation-bulkheads.md +140 -0
  52. package/skills/_support/docs/principles/details/p043-circuit-breakers.md +148 -0
  53. package/skills/_support/docs/principles/details/p044-atomicity-where-possible.md +141 -0
  54. package/skills/_support/docs/principles/details/p045-compensation-where-atomicity-is-impossible.md +163 -0
  55. package/skills/_support/docs/principles/details/p046-resumability.md +138 -0
  56. package/skills/_support/docs/principles/details/p047-observability-is-part-of-correctness.md +134 -0
  57. package/skills/_support/docs/principles/details/p048-secure-by-design.md +132 -0
  58. package/skills/_support/docs/principles/details/p049-secure-by-default.md +126 -0
  59. package/skills/_support/docs/principles/details/p050-least-privilege.md +123 -0
  60. package/skills/_support/docs/principles/details/p051-complete-mediation.md +124 -0
  61. package/skills/_support/docs/principles/details/p052-separation-of-duties.md +129 -0
  62. package/skills/_support/docs/principles/details/p053-validate-at-trust-boundaries.md +126 -0
  63. package/skills/_support/docs/principles/details/p054-defense-in-depth.md +135 -0
  64. package/skills/_support/docs/principles/details/p055-minimize-attack-surface.md +133 -0
  65. package/skills/_support/docs/principles/details/p056-secrets-stay-out-of-code-and-context.md +137 -0
  66. package/skills/_support/docs/principles/details/p057-supply-chain-integrity.md +135 -0
  67. package/skills/_support/docs/principles/details/p058-bounded-agent-authority.md +137 -0
  68. package/skills/_support/docs/principles/details/p059-data-is-not-instruction.md +130 -0
  69. package/skills/_support/docs/principles/details/p060-constrain-sub-agents.md +136 -0
  70. package/skills/_support/docs/principles/details/p061-separate-decision-from-high-impact-execution.md +131 -0
  71. package/skills/_support/docs/principles/details/p062-human-approval-for-irreversible-or-high-risk-actions.md +129 -0
  72. package/skills/_support/docs/principles/details/p063-requirement-to-code-traceability.md +116 -0
  73. package/skills/_support/docs/principles/details/p064-requirement-to-test-traceability.md +116 -0
  74. package/skills/_support/docs/principles/details/p065-verify-before-claiming-completion.md +129 -0
  75. package/skills/_support/docs/principles/details/p066-preserve-existing-work.md +114 -0
  76. package/skills/_support/docs/principles/details/p067-no-test-cheating.md +126 -0
  77. package/skills/_support/docs/principles/details/p068-no-validation-bypass.md +119 -0
  78. package/skills/_support/docs/principles/details/p069-independent-review-for-high-risk-changes.md +129 -0
  79. package/skills/_support/docs/principles/details/p070-code-health-must-not-regress.md +116 -0
  80. package/skills/_support/docs/principles/details/p071-consistency-over-personal-preference.md +117 -0
  81. package/skills/_support/docs/principles/details/p072-technical-evidence-over-preference.md +122 -0
  82. package/skills/_support/docs/principles/details/p073-optimize-only-with-evidence.md +123 -0
  83. package/skills/_support/docs/principles/details/p074-prefer-existing-mechanisms.md +121 -0
  84. package/skills/_support/docs/principles/details/p075-make-invalid-states-hard-to-represent.md +128 -0
  85. package/skills/_support/docs/principles/details/p076-parse-then-validate-then-operate.md +133 -0
  86. package/skills/_support/docs/principles/details/p077-separate-policy-from-mechanism.md +112 -0
  87. package/skills/_support/docs/principles/details/p078-single-source-of-truth.md +131 -0
  88. package/skills/_support/docs/principles/details/p079-explicit-ownership-and-lifetimes.md +124 -0
  89. package/skills/_support/docs/principles/details/p080-make-concurrency-deliberate.md +122 -0
  90. package/skills/_support/docs/principles/details/p081-forward-progress-with-safety.md +125 -0
  91. package/skills/_support/docs/principles/details/p082-design-for-cancellation.md +133 -0
  92. package/skills/_support/docs/principles/details/p083-irreversible-actions-last.md +124 -0
  93. package/skills/_support/docs/principles/details/p084-prefer-local-reasoning.md +131 -0
  94. package/skills/_support/docs/principles/details/p085-explicit-is-better-than-implicit.md +123 -0
  95. package/skills/_support/docs/principles/details/p086-readability-counts.md +113 -0
  96. package/skills/_support/docs/principles/details/p087-comments-explain-why-code-explains-what.md +120 -0
  97. package/skills/_support/docs/principles/details/p088-delete-dead-code.md +125 -0
  98. package/skills/_support/docs/principles/details/p089-delete-obsolete-configuration-and-dependencies.md +125 -0
  99. package/skills/_support/docs/principles/details/p090-prefer-negative-code.md +134 -0
  100. package/skills/_support/docs/principles/details/p091-test-driven-development.md +149 -0
  101. package/skills/_support/docs/review/README.md +59 -0
  102. package/skills/_support/docs/review/behavior-first-testing.md +73 -0
  103. package/skills/_support/docs/review/common.md +365 -0
  104. package/skills/_support/docs/review/design-docs.md +74 -0
  105. package/skills/_support/docs/review/issue-planning.md +220 -0
  106. package/skills/_support/docs/review/language-routing.md +141 -0
  107. package/skills/_support/docs/review/repository-scorecard.md +170 -0
  108. package/skills/advise/SKILL.md +93 -67
  109. package/skills/advise/scripts/list_retrievable_skills.py +3 -3
  110. package/skills/brainstorm/SKILL.md +160 -127
  111. package/skills/change-review/SKILL.md +91 -71
  112. package/skills/change-review/references/scope-resolution.md +69 -46
  113. package/skills/change-review/scripts/resolve_scope.py +119 -73
  114. package/skills/finalize-plan/SKILL.md +198 -139
  115. package/skills/git-worktrees/SKILL.md +100 -80
  116. package/skills/git-worktrees/scripts/prepare_worktree.py +16 -10
  117. package/skills/issue-review/SKILL.md +136 -79
  118. package/skills/learn/SKILL.md +276 -186
  119. package/skills/myrmidon-swarm/SKILL.md +126 -86
  120. package/skills/plan-issue/SKILL.md +122 -81
  121. package/skills/pr-review/SKILL.md +164 -114
  122. package/skills/pr-review/references/criteria.md +58 -37
  123. package/skills/pr-review/references/delivery.md +156 -98
  124. package/skills/pr-review/references/evidence.md +265 -148
  125. package/skills/pr-review/references/prevalidated.md +93 -61
  126. package/skills/pr-review/scripts/collect_evidence.py +211 -140
  127. package/skills/pr-review/scripts/diff_context.py +6 -4
  128. package/skills/pr-review/scripts/materialize_snapshot.py +112 -120
  129. package/skills/pr-review/scripts/pr_identity.py +27 -15
  130. package/skills/pr-review/scripts/resolve_pr.py +53 -31
  131. package/skills/repo-review/SKILL.md +202 -131
  132. package/skills/systematic-debugging/SKILL.md +210 -192
  133. package/skills/systematic-debugging/scripts/repository_evidence.py +9 -4
  134. package/skills/test-driven-development/SKILL.md +126 -96
  135. package/skills/tidy/SKILL.md +92 -59
  136. package/skills/tidy/scripts/run_tidy.py +3 -3
@@ -0,0 +1,128 @@
1
+ # P027 — Deterministic and Hermetic Tests
2
+
3
+ ## Definition
4
+
5
+ Use controlled inputs and isolation from undeclared external influences to make tests repeatable.
6
+ Such influences include time, random values, environment variables, file state, networks, locale,
7
+ concurrency, and shared services.
8
+
9
+ Tests must give the same result for each execution order.
10
+
11
+ **Aliases:** isolated tests, reproducible tests, hermetic testing.
12
+
13
+ ## Provenance
14
+
15
+ **Classification:** established principle.
16
+
17
+ Software test guidance includes determinism and isolation. Large build and test systems use the term
18
+ "hermetic." No one source gives this full formulation.
19
+
20
+ ## Decision rule
21
+
22
+ If an external input can change a result, the test must declare or control that input. The test must
23
+ not share mutable state between executions.
24
+
25
+ ## How to apply
26
+
27
+ - If a clock, random generator, environment, or external client can change a result, inject that input.
28
+ - Use temporary resources for each test and deterministic cleanup.
29
+ - Use controlled local substitutes, not live networks. Use live networks only in specified
30
+ integration or acceptance suites.
31
+ - Record seeds and schedules for generated or concurrent tests. Preserve each counterexample.
32
+ - Run tests individually and in different orders.
33
+ - If the test harness can run tests in parallel, use parallel execution.
34
+
35
+ ## Diagram
36
+
37
+ ```mermaid
38
+ flowchart LR
39
+ Test["Test case"] --> Inputs["Declare or control inputs"]
40
+ Inputs --> Isolate["Isolate mutable resources"]
41
+ Isolate --> Execute["Run many times"]
42
+ Execute --> Same{"Same result?"}
43
+ Same -->|Yes| Valid["Repeatable test"]
44
+ Same -->|No| Influence["Find undeclared influence"]
45
+ Influence --> Inputs
46
+ ```
47
+
48
+ ## Language examples
49
+
50
+ The two examples inject the same clock value and do not read the wall clock.
51
+
52
+ Python:
53
+
54
+ ```python
55
+ def expired(expires_at: int, now: int) -> bool:
56
+ return now >= expires_at
57
+
58
+ def test_expiry_with_controlled_time() -> None:
59
+ assert expired(100, 100)
60
+ assert not expired(101, 100)
61
+ ```
62
+
63
+ Rust:
64
+
65
+ ```rust
66
+ fn expired(expires_at: u64, now: u64) -> bool {
67
+ now >= expires_at
68
+ }
69
+
70
+ #[test]
71
+ fn expiry_with_controlled_time() {
72
+ assert!(expired(100, 100));
73
+ assert!(!expired(101, 100));
74
+ }
75
+ ```
76
+
77
+ ## Boundaries and tensions
78
+
79
+ Deterministic and hermetic are related but different. If a fixed external service gives the same
80
+ input, a nonhermetic test can be deterministic. A hermetic test can use uncontrolled random values.
81
+
82
+ Full isolation can hide integration failures. Keep specified nonhermetic suites in
83
+ controlled environments. Retries can diagnose flaky behavior, but they cannot make an unreliable
84
+ test reliable.
85
+
86
+ ## Examples
87
+
88
+ ### Positive application
89
+
90
+ A cache-expiry test receives a fake clock and a new temporary directory. The test controls clock
91
+ changes. Machine time zone and test order cannot change the result.
92
+
93
+ ### Misuse or counterexample
94
+
95
+ A test uses a public web service and retries until success. Availability, remote data, DNS, and
96
+ rate limits control the result.
97
+
98
+ ### Athena or agent workflow
99
+
100
+ A repository validator test creates an isolated fixture tree and supplies each environment value.
101
+ The helper does not use a user checkout or network credentials.
102
+
103
+ ## Related principles
104
+
105
+ - [P022 — Test Behavior, Not Implementation](p022-test-behavior-not-implementation.md)
106
+ - [P025 — Property-Based Testing for Invariants](p025-property-based-testing-for-invariants.md)
107
+ - [P028 — Test Failure Paths, Not Just Success Paths](p028-test-failure-paths.md)
108
+
109
+ ## References
110
+
111
+ ### Source information
112
+
113
+ - [Google Testing Blog, "Hermetic Servers" (2012)](https://testing.googleblog.com/2012/10/hermetic-servers.html)
114
+ gives information about isolation from live network dependencies in end-to-end tests.
115
+
116
+ ### Applicable information
117
+
118
+ - [Bazel, "Hermeticity"](https://bazel.build/basics/hermeticity)
119
+ gives declared inputs, fixed environment properties, and isolation for deterministic results.
120
+ - [Microsoft, ".NET unit testing best practices"](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices)
121
+ gives isolation and repeatability as core test characteristics.
122
+
123
+ ### More information
124
+
125
+ - [Google Testing Blog, "Flaky Tests at Google and How We Mitigate Them" (2016)](https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html)
126
+ gives causes and operational costs of nondeterministic test results.
127
+
128
+ [Back to the engineering principles catalog](../README.md#p027)
@@ -0,0 +1,133 @@
1
+ # P028 — Test Failure Paths, Not Just Success Paths
2
+
3
+ ## Definition
4
+
5
+ Verify system behavior for malformed inputs, failed dependencies, and failed operations. Include
6
+ cancellation, timeout, progress before failure, unavailability, retry, cleanup,
7
+ authorization, and resource exhaustion.
8
+
9
+ Verify success behavior with its own baseline.
10
+
11
+ **Aliases:** negative testing, robustness testing, error-path testing.
12
+
13
+ ## Provenance
14
+
15
+ **Classification:** established principle.
16
+
17
+ Sources for negative tests and robustness tests include reliability, security, and protocol work.
18
+ No one source gives all failure conditions in this principle.
19
+
20
+ ## Decision rule
21
+
22
+ Find failures that can occur for each material dependency or state transition. Verify the contract
23
+ result, preserved invariants, cleanup, and diagnostic evidence.
24
+
25
+ ## How to apply
26
+
27
+ - Use contracts and architecture to find failures. Do not use coverage percentages.
28
+ - Inject dependency errors, timeouts, and cancellations.
29
+ - After an operation makes progress, inject a stop.
30
+ - After failure, assert caller-visible error semantics and durable state.
31
+ - Verify resource release. Keep retries and compensation in their budgets.
32
+ - Include authorization denial and malformed untrusted input without live operations that are not safe.
33
+
34
+ ## Diagram
35
+
36
+ ```mermaid
37
+ flowchart LR
38
+ Boundary["Dependency or state transition"] --> Failures["Find possible failures"]
39
+ Failures --> Inject["Inject controlled fault"]
40
+ Inject --> Result["Assert error contract"]
41
+ Result --> State["Verify state and cleanup"]
42
+ State --> Budget["Verify retry or compensation budget"]
43
+ ```
44
+
45
+ ## Language examples
46
+
47
+ The two examples simulate a write failure, preserve the previous data, and return the cause.
48
+
49
+ Python:
50
+
51
+ ```python
52
+ from collections.abc import Callable
53
+ def replace(current: str, write: Callable[[], str]) -> tuple[str, Exception | None]:
54
+ try:
55
+ return write(), None
56
+ except OSError as cause:
57
+ return current, cause
58
+ def test_failure_preserves_current() -> None:
59
+ cause = OSError("disk full")
60
+ def fail() -> str:
61
+ raise cause
62
+ value, error = replace("old", fail)
63
+ assert value == "old" and error is cause
64
+ ```
65
+
66
+ Rust:
67
+
68
+ ```rust
69
+ fn replace<F>(current: &str, write: F) -> (String, Option<&'static str>)
70
+ where F: FnOnce() -> Result<String, &'static str> {
71
+ match write() {
72
+ Ok(value) => (value, None),
73
+ Err(cause) => (current.to_owned(), Some(cause)),
74
+ }
75
+ }
76
+ #[test]
77
+ fn failure_preserves_current() {
78
+ let result = replace("old", || Err("disk full"));
79
+ assert_eq!(result, ("old".to_owned(), Some("disk full")));
80
+ }
81
+ ```
82
+
83
+ ## Boundaries and tensions
84
+
85
+ Do not cause destructive production failures for test evidence. Use controlled substitutes,
86
+ sandboxes, fault injection, or staged environments that the approved risk policy specifies.
87
+
88
+ Mock failures can be different from dependency behavior in production. When mock behavior changes
89
+ the contract, add contract or integration evidence. Do not show sensitive internal details in caller-visible errors.
90
+
91
+ ## Examples
92
+
93
+ ### Positive application
94
+
95
+ A file replacement test injects a write failure after the write operation creates temporary output. It verifies that
96
+ the previous file is correct. It also verifies cleanup and cause preservation.
97
+
98
+ ### Misuse or counterexample
99
+
100
+ A client has many success-path tests but no test for a timeout after a committed write. An automatic
101
+ retry can duplicate the operation.
102
+
103
+ ### Athena or agent workflow
104
+
105
+ A skill test simulates a missing necessary capability. It verifies a clear, safe failure response.
106
+ The test verifies that the skill does not skip work or return success without evidence.
107
+
108
+ ## Related principles
109
+
110
+ - [P022 — Test Behavior, Not Implementation](p022-test-behavior-not-implementation.md)
111
+ - [P027 — Deterministic and Hermetic Tests](p027-deterministic-and-hermetic-tests.md)
112
+ - [P030 — Handle Errors at the Nearest Responsible Boundary](p030-nearest-responsible-error-boundary.md)
113
+
114
+ ## References
115
+
116
+ ### Source information
117
+
118
+ - [NIST, "An Approach for Analyzing the Robustness of Windows NT Software" (1998)](https://csrc.nist.gov/files/pubs/conference/1998/10/08/proceedings-of-the-21st-nissc-1998/final/docs/paperf8.pdf)
119
+ gives robustness tests with accepted inputs, rejected inputs, and exception conditions.
120
+
121
+ ### Applicable information
122
+
123
+ - [Google Engineering Practices, "What to look for in a code review"](https://google.github.io/eng-practices/review/reviewer/looking-for.html)
124
+ says tests must detect broken behavior.
125
+ - [OWASP Web Security Testing Guide, "Testing for Error Handling"](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/08-Testing_for_Error_Handling/README)
126
+ gives security tests for incorrect error responses and stack disclosure.
127
+
128
+ ### More information
129
+
130
+ - [OWASP, "Business Logic Security Cheat Sheet"](https://cheatsheetseries.owasp.org/cheatsheets/Business_Logic_Security_Cheat_Sheet.html)
131
+ adds adversarial cases for incorrect order, steps that occur again, concurrency, and rule bypass.
132
+
133
+ [Back to the engineering principles catalog](../README.md#p028)
@@ -0,0 +1,131 @@
1
+ # P029 — Generalize Error Policy; Preserve Specific Cause
2
+
3
+ ## Definition
4
+
5
+ Use a small taxonomy for stable errors at architectural boundaries. Preserve the initial cause,
6
+ stack, and safe structured context for diagnosis.
7
+
8
+ A general policy helps callers select a response. A specific cause helps operators diagnose the
9
+ failed event.
10
+
11
+ **Aliases:** error translation with cause preservation, layered error taxonomy.
12
+
13
+ ## Provenance
14
+
15
+ **Classification:** Athena synthesis.
16
+
17
+ Sources are different for exception chains, causal errors, and protocol problem taxonomies.
18
+ No historical source gives this full rule.
19
+
20
+ ## Decision rule
21
+
22
+ At a boundary that owns caller policy, translate a low-level failure. Map the failure to stable
23
+ caller policy. Attach the initial cause with non-sensitive diagnostic context.
24
+
25
+ ## How to apply
26
+
27
+ - Give a bounded error set that lets callers select responses, for example rejected input, unavailable,
28
+ or conflict.
29
+ - Translate vendor and transport failures at the boundary that owns the public contract.
30
+ - Preserve causal links and structured fields for operators.
31
+ - Keep retry status and user messages different from exception text that can change.
32
+ - Remove secrets and internal details from public results. Keep safe internal evidence.
33
+
34
+ ## Diagram
35
+
36
+ ```mermaid
37
+ flowchart LR
38
+ Failure["Low-level failure"] --> Boundary{"Boundary owns caller policy?"}
39
+ Boundary -->|No| Propagate["Preserve and propagate cause"]
40
+ Boundary -->|Yes| Policy["Map to stable error policy"]
41
+ Policy --> Public["Return safe public error"]
42
+ Policy --> Evidence["Keep specific internal cause"]
43
+ ```
44
+
45
+ ## Language examples
46
+
47
+ The two examples map a storage timeout to an unavailable error and preserve the specific cause.
48
+
49
+ Python:
50
+
51
+ ```python
52
+ class StorageTimeout(RuntimeError):
53
+ pass
54
+
55
+ class UnavailableError(RuntimeError):
56
+ pass
57
+
58
+ def load(fetch):
59
+ try:
60
+ return fetch()
61
+ except StorageTimeout as cause:
62
+ raise UnavailableError("storage unavailable") from cause
63
+ ```
64
+
65
+ Rust:
66
+
67
+ ```rust
68
+ #[derive(Debug)]
69
+ struct StorageTimeout;
70
+
71
+ #[derive(Debug)]
72
+ struct UnavailableError { message: &'static str, source: StorageTimeout }
73
+
74
+ fn load(result: Result<String, StorageTimeout>) -> Result<String, UnavailableError> {
75
+ result.map_err(|source| UnavailableError { message: "storage unavailable", source })
76
+ }
77
+ ```
78
+
79
+ ## Boundaries and tensions
80
+
81
+ One `operation failed` result is too general when callers must select different responses. Each
82
+ dependency exception is too specific and couples consumers to internal details.
83
+
84
+ Cause preservation does not authorize disclosure of stacks, paths, queries, credentials, or
85
+ personal data. Use approved decisions to change stable taxonomies. Do not add one type for
86
+ each event.
87
+
88
+ ## Examples
89
+
90
+ ### Positive application
91
+
92
+ A storage timeout becomes a public `temporarily-unavailable` problem. The response includes a
93
+ correlation ID and retry policy. The internal record preserves the driver error and operation context.
94
+
95
+ ### Misuse or counterexample
96
+
97
+ A handler converts each exception to a `null` response with success status. This conversion erases the
98
+ error policy and cause. A second handler sends the full database stack to the client.
99
+
100
+ ### Athena or agent workflow
101
+
102
+ A dependency helper returns one specified unavailable status. Its diagnostic record identifies
103
+ the checkout, command, exit status, and causal error. The record excludes secrets.
104
+
105
+ ## Related principles
106
+
107
+ - [P019 — Explicit Contracts](p019-explicit-contracts.md)
108
+ - [P028 — Test Failure Paths, Not Just Success Paths](p028-test-failure-paths.md)
109
+ - [P030 — Handle Errors at the Nearest Responsible Boundary](p030-nearest-responsible-error-boundary.md)
110
+
111
+ ## References
112
+
113
+ ### Source information
114
+
115
+ - [PEP 3134, "Exception Chaining and Embedded Tracebacks" (2005)](https://peps.python.org/pep-3134/)
116
+ records explicit causal links and context for a new exception after a second exception.
117
+
118
+ ### Applicable information
119
+
120
+ - [RFC 9457, "Problem Details for HTTP APIs" (2023)](https://www.rfc-editor.org/rfc/rfc9457.html)
121
+ gives stable problem types and event-specific details. The RFC gives a warning about exposure of
122
+ implementation details.
123
+ - [Python documentation, "Exception context"](https://docs.python.org/3/library/exceptions.html#exception-context)
124
+ gives implicit and explicit exception chain semantics.
125
+
126
+ ### More information
127
+
128
+ - [OWASP, "Error Handling Cheat Sheet"](https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html)
129
+ shows the difference between safe external errors and detailed internal diagnostics for investigation.
130
+
131
+ [Back to the engineering principles catalog](../README.md#p029)
@@ -0,0 +1,133 @@
1
+ # P030 — Handle Errors at the Nearest Responsible Boundary
2
+
3
+ ## Definition
4
+
5
+ Handle an error only where policy and context are sufficient for correct recovery, retry,
6
+ compensation, translation, or termination. A lower layer frequently detects a failure first.
7
+
8
+ When the lower layer cannot select the correct result, it must propagate the failure.
9
+
10
+ **Aliases:** catch where you can handle, responsible error boundary.
11
+
12
+ ## Provenance
13
+
14
+ **Classification:** practitioner heuristic.
15
+
16
+ Exception systems use stack-based handler selection. Language communities gave related rules
17
+ about error propagation. No one source first gave this formulation.
18
+
19
+ ## Decision rule
20
+
21
+ At the first boundary that can satisfy the caller's contract and preserve correct state, handle the
22
+ failure. If the boundary cannot satisfy the contract or preserve correct state, add applicable safe
23
+ context. After the boundary adds the context, propagate the failure.
24
+
25
+ ## How to apply
26
+
27
+ - Detection, cleanup, translation, recovery, and caller presentation are different operations.
28
+ - When a layer owns a recovery or contract decision, the layer can catch the error.
29
+ - Use deterministic cleanup constructs. Cleanup does not recover the operation.
30
+ - After translation, preserve the cause. Do not record the same failure at each layer.
31
+ - Put retries at the boundary that knows idempotency, deadlines, and dependency semantics.
32
+
33
+ ## Diagram
34
+
35
+ ```mermaid
36
+ flowchart LR
37
+ Detect["Layer detects failure"] --> Decide{"Boundary owns result policy?"}
38
+ Decide -->|No| Context["Add applicable safe context"]
39
+ Context --> Propagate["Propagate failure"]
40
+ Decide -->|Yes| Policy["Apply boundary policy"]
41
+ Policy --> Action["Recover, retry, translate, or terminate"]
42
+ Action --> State["Preserve correct state"]
43
+ ```
44
+
45
+ ## Language examples
46
+
47
+ The two examples put retry policy in the caller of a low-level read operation that propagates its
48
+ error.
49
+
50
+ Python:
51
+
52
+ ```python
53
+ def read_once(client):
54
+ return client.read()
55
+
56
+ def read_with_retry(client):
57
+ try:
58
+ return read_once(client)
59
+ except TimeoutError:
60
+ return read_once(client)
61
+ ```
62
+
63
+ Rust:
64
+
65
+ ```rust
66
+ trait Client { fn read(&mut self) -> Result<String, TimeoutError>; }
67
+ struct TimeoutError;
68
+ fn read_once(client: &mut impl Client) -> Result<String, TimeoutError> {
69
+ client.read()
70
+ }
71
+
72
+ fn read_with_retry(client: &mut impl Client) -> Result<String, TimeoutError> {
73
+ match read_once(client) {
74
+ Ok(value) => Ok(value),
75
+ Err(_) => read_once(client),
76
+ }
77
+ }
78
+ ```
79
+
80
+ ## Boundaries and tensions
81
+
82
+ The first `catch` site is not always the responsible boundary. A top-level boundary can convert an
83
+ unhandled error to a process exit, protocol response, or job status.
84
+
85
+ A lower-level operation can do cleanup and preserve the failure. Security policy can make a generic
86
+ public result and restricted internal diagnostics necessary.
87
+
88
+ ## Examples
89
+
90
+ ### Positive application
91
+
92
+ A repository propagates a database timeout. The service knows that the operation is read-only and
93
+ has a deadline. It makes one bounded retry.
94
+
95
+ The API boundary converts an exhausted retry budget to a public error with an unavailable status.
96
+
97
+ ### Misuse or counterexample
98
+
99
+ A low-level parser catches each exception, records it, and returns an empty object. Callers cannot
100
+ tell permitted empty input from corrupt input.
101
+
102
+ ### Athena or agent workflow
103
+
104
+ A helper returns a typed capability failure. The skill owns fallback policy. It selects the
105
+ specified degraded path or a safe stop and returns the result.
106
+
107
+ ## Related principles
108
+
109
+ - [P028 — Test Failure Paths, Not Just Success Paths](p028-test-failure-paths.md)
110
+ - [P029 — Generalize Error Policy; Preserve Specific Cause](p029-generalize-error-policy-preserve-specific-cause.md)
111
+ - [P019 — Explicit Contracts](p019-explicit-contracts.md)
112
+
113
+ ## References
114
+
115
+ ### Source information
116
+
117
+ - [Goodenough, "Exception Handling: Issues and a Proposed Notation" (1975)](https://doi.org/10.1145/361227.361230)
118
+ gives a full treatment from 1975 of exception detection, handler selection, and recovery.
119
+
120
+ ### Applicable information
121
+
122
+ - [Microsoft, ".NET best practices for exceptions"](https://learn.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions)
123
+ recommends a catch for recovery or cleanup. When code at the boundary cannot recover, the guidance
124
+ recommends propagation.
125
+ - [Microsoft, "Exceptions and Exception Handling"](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/exceptions/)
126
+ says that a handler rethrows if it cannot keep the application in a known state.
127
+
128
+ ### More information
129
+
130
+ - [Go Blog, "Error handling and Go"](https://go.dev/blog/error-handling-and-go)
131
+ shows explicit propagation and caller-related context without loss of the failure.
132
+
133
+ [Back to the engineering principles catalog](../README.md#p030)
@@ -0,0 +1,131 @@
1
+ # P031 — Propagate Rather Than Swallow
2
+
3
+ ## Definition
4
+
5
+ If a layer cannot satisfy all specified postconditions after recovery, it must propagate the
6
+ failure to a responsible boundary. The layer can use its specified interface to return, throw, or
7
+ signal the failure.
8
+
9
+ The layer must not give a success result, return an empty value, or continue work after a failure.
10
+ The contract must show the difference between success and a failure that the caller must handle.
11
+
12
+ **Aliases:** error propagation, no silent catch, surface unrecovered failures
13
+
14
+ ## Provenance
15
+
16
+ **Classification:** established principle.
17
+
18
+ Authors wrote about structured exception handling for many years. Athena cannot identify one source
19
+ for this phrase. Athena uses it as a language-neutral decision rule.
20
+
21
+ ## Decision rule
22
+
23
+ If this boundary can satisfy its specified postconditions or give a specified alternative
24
+ result, handle the failure. If the boundary cannot do this, propagate the failure and keep its cause.
25
+
26
+ ## How to apply
27
+
28
+ - Give failure behavior in return types, exceptions, result objects, exit statuses, or
29
+ protocol responses.
30
+ - When the layer has the necessary policy context, it can retry, compensate, translate, or stop
31
+ after a failure.
32
+ - Keep the initial cause during error translation. Add stable context that helps the caller.
33
+ - Give fallback values in the interface. When the contract includes an alternative outcome, give
34
+ its fallback as a success result.
35
+ - Make sure that dependency failures give a public failure outcome and keep correct state.
36
+
37
+ ## Diagram
38
+
39
+ ```mermaid
40
+ flowchart TD
41
+ A["An operation detects a failure"] --> B{"Can this boundary satisfy the contract?"}
42
+ B -- "Yes" --> C["Recover or return a specified alternative result"]
43
+ B -- "No" --> D["Add safe context and keep the cause"]
44
+ D --> E["Propagate the failure to a responsible boundary"]
45
+ ```
46
+
47
+ ## Language examples
48
+
49
+ Each example adds caller context and keeps a failure outcome.
50
+
51
+ ### Python
52
+
53
+ ```python
54
+ def load_record(store, key):
55
+ try:
56
+ return store.read(key)
57
+ except StorageError as error:
58
+ raise RecordLoadError(key) from error
59
+ ```
60
+
61
+ ### Rust
62
+
63
+ ```rust
64
+ fn load_record(store: &Store, key: &str) -> Result<Record, RecordLoadError> {
65
+ store
66
+ .read(key)
67
+ .map_err(|source| RecordLoadError::new(key, source))
68
+ }
69
+ ```
70
+
71
+ ## Boundaries and tensions
72
+
73
+ A boundary can translate an internal error into a stable taxonomy. It must keep the causal chain.
74
+ Use [P032](p032-handle-once-preserve-causality.md) for cause preservation.
75
+
76
+ [P036](p036-graceful-degradation.md) gives conditions for a safe reduced mode. The mode is
77
+ applicable only when the contract includes it as an alternative outcome.
78
+
79
+ Use [P035](p035-fail-secure-fail-closed.md) for security uncertainty. Do not show secrets or
80
+ credentials. If the caller contract does not include internal information, do not show it. Keep
81
+ necessary cause data in protected diagnostics.
82
+
83
+ ## Examples
84
+
85
+ ### Positive application
86
+
87
+ A repository adapter cannot read a necessary record. It attaches the record identifier to the
88
+ storage error and returns the error. The service boundary maps the failure to its specified API
89
+ error. Protected diagnostics keep the initial cause.
90
+
91
+ ### Misuse or counterexample
92
+
93
+ A configuration loader catches each parse error and returns an empty configuration. Startup gives
94
+ a success result. The service operates with invalid values. Engineers cannot find the initial
95
+ failure.
96
+
97
+ ### Athena or agent workflow
98
+
99
+ If a necessary validation command returns a nonzero status, an Athena workflow records the command
100
+ and its results. The workflow does not give a success result because other checks had correct results.
101
+
102
+ ## Related principles
103
+
104
+ - [P032 — Handle Once; Preserve Causality](p032-handle-once-preserve-causality.md)
105
+ - [P033 — State-Safe Failure Semantics](p033-state-safe-failure-semantics.md)
106
+ - [P034 — Fail Fast](p034-fail-fast.md)
107
+ - [P036 — Graceful Degradation](p036-graceful-degradation.md)
108
+
109
+ ## References
110
+
111
+ ### Source information
112
+
113
+ - [John B. Goodenough, “Structured Exception Handling” (1975)](https://doi.org/10.1145/512976.512997)
114
+ — a 1975 analysis of exception conditions and control transfer to a handler with the necessary
115
+ context. This source is not the source of Athena's phrase.
116
+
117
+ ### Applicable information
118
+
119
+ - [The Rust Programming Language: Propagating Errors](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#propagating-errors)
120
+ — official guidance for a callee that returns an error when its caller has the necessary decision
121
+ context.
122
+ - [C++ Core Guidelines, Error Handling](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-errors)
123
+ — guidance that recommends a specified error strategy. It recommends no handler in each
124
+ function.
125
+
126
+ ### More information
127
+
128
+ - [P029 — Generalize Error Policy; Preserve Specific Cause](../README.md#p029) — the catalog rule
129
+ for error translation that keeps diagnostic specificity.
130
+
131
+ [Back to the engineering principles catalog](../README.md#p031)