@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.
- package/README.md +30 -17
- package/package.json +2 -2
- package/plugin.js +20 -5
- package/skills/TECHNICAL_ENGLISH.md +78 -0
- package/skills/_cli.py +26 -18
- package/skills/_support/docs/dependency-resolution.md +192 -0
- package/skills/_support/docs/policies/development.md +117 -0
- package/skills/_support/docs/policies/evidence-integrity.md +40 -0
- package/skills/_support/docs/principles/README.md +542 -0
- package/skills/_support/docs/principles/details/p001-kiss.md +114 -0
- package/skills/_support/docs/principles/details/p002-yagni.md +109 -0
- package/skills/_support/docs/principles/details/p003-dry.md +126 -0
- package/skills/_support/docs/principles/details/p004-solid.md +165 -0
- package/skills/_support/docs/principles/details/p005-modularity.md +123 -0
- package/skills/_support/docs/principles/details/p006-principle-of-least-astonishment.md +115 -0
- package/skills/_support/docs/principles/details/p007-subtraction-over-addition.md +113 -0
- package/skills/_support/docs/principles/details/p008-understand-before-subtracting.md +115 -0
- package/skills/_support/docs/principles/details/p009-general-mechanisms-over-special-cases.md +108 -0
- package/skills/_support/docs/principles/details/p010-scope-fidelity.md +117 -0
- package/skills/_support/docs/principles/details/p011-minimal-coherent-change.md +128 -0
- package/skills/_support/docs/principles/details/p012-evidence-before-modification.md +115 -0
- package/skills/_support/docs/principles/details/p013-avoid-hasty-abstractions.md +112 -0
- package/skills/_support/docs/principles/details/p014-preserve-unrequested-behavior.md +110 -0
- package/skills/_support/docs/principles/details/p015-architecture-conformance.md +124 -0
- package/skills/_support/docs/principles/details/p016-separation-of-concerns.md +125 -0
- package/skills/_support/docs/principles/details/p017-high-cohesion-low-coupling.md +130 -0
- package/skills/_support/docs/principles/details/p018-information-hiding.md +128 -0
- package/skills/_support/docs/principles/details/p019-explicit-contracts.md +134 -0
- package/skills/_support/docs/principles/details/p020-executable-architecture.md +130 -0
- package/skills/_support/docs/principles/details/p021-evolutionary-and-reversible-design.md +126 -0
- package/skills/_support/docs/principles/details/p022-test-behavior-not-implementation.md +129 -0
- package/skills/_support/docs/principles/details/p023-parameterized-table-driven-testing.md +129 -0
- package/skills/_support/docs/principles/details/p024-boundary-value-testing.md +128 -0
- package/skills/_support/docs/principles/details/p025-property-based-testing-for-invariants.md +133 -0
- package/skills/_support/docs/principles/details/p026-regression-before-repair.md +134 -0
- package/skills/_support/docs/principles/details/p027-deterministic-and-hermetic-tests.md +128 -0
- package/skills/_support/docs/principles/details/p028-test-failure-paths.md +133 -0
- package/skills/_support/docs/principles/details/p029-generalize-error-policy-preserve-specific-cause.md +131 -0
- package/skills/_support/docs/principles/details/p030-nearest-responsible-error-boundary.md +133 -0
- package/skills/_support/docs/principles/details/p031-propagate-rather-than-swallow.md +131 -0
- package/skills/_support/docs/principles/details/p032-handle-once-preserve-causality.md +137 -0
- package/skills/_support/docs/principles/details/p033-state-safe-failure-semantics.md +140 -0
- package/skills/_support/docs/principles/details/p034-fail-fast.md +132 -0
- package/skills/_support/docs/principles/details/p035-fail-secure-fail-closed.md +137 -0
- package/skills/_support/docs/principles/details/p036-graceful-degradation.md +137 -0
- package/skills/_support/docs/principles/details/p037-idempotency-before-retry.md +139 -0
- package/skills/_support/docs/principles/details/p038-bounded-retry.md +145 -0
- package/skills/_support/docs/principles/details/p039-bounded-waiting.md +151 -0
- package/skills/_support/docs/principles/details/p040-bounded-resources.md +138 -0
- package/skills/_support/docs/principles/details/p041-backpressure-and-load-shedding.md +141 -0
- package/skills/_support/docs/principles/details/p042-fault-isolation-bulkheads.md +140 -0
- package/skills/_support/docs/principles/details/p043-circuit-breakers.md +148 -0
- package/skills/_support/docs/principles/details/p044-atomicity-where-possible.md +141 -0
- package/skills/_support/docs/principles/details/p045-compensation-where-atomicity-is-impossible.md +163 -0
- package/skills/_support/docs/principles/details/p046-resumability.md +138 -0
- package/skills/_support/docs/principles/details/p047-observability-is-part-of-correctness.md +134 -0
- package/skills/_support/docs/principles/details/p048-secure-by-design.md +132 -0
- package/skills/_support/docs/principles/details/p049-secure-by-default.md +126 -0
- package/skills/_support/docs/principles/details/p050-least-privilege.md +123 -0
- package/skills/_support/docs/principles/details/p051-complete-mediation.md +124 -0
- package/skills/_support/docs/principles/details/p052-separation-of-duties.md +129 -0
- package/skills/_support/docs/principles/details/p053-validate-at-trust-boundaries.md +126 -0
- package/skills/_support/docs/principles/details/p054-defense-in-depth.md +135 -0
- package/skills/_support/docs/principles/details/p055-minimize-attack-surface.md +133 -0
- package/skills/_support/docs/principles/details/p056-secrets-stay-out-of-code-and-context.md +137 -0
- package/skills/_support/docs/principles/details/p057-supply-chain-integrity.md +135 -0
- package/skills/_support/docs/principles/details/p058-bounded-agent-authority.md +137 -0
- package/skills/_support/docs/principles/details/p059-data-is-not-instruction.md +130 -0
- package/skills/_support/docs/principles/details/p060-constrain-sub-agents.md +136 -0
- package/skills/_support/docs/principles/details/p061-separate-decision-from-high-impact-execution.md +131 -0
- package/skills/_support/docs/principles/details/p062-human-approval-for-irreversible-or-high-risk-actions.md +129 -0
- package/skills/_support/docs/principles/details/p063-requirement-to-code-traceability.md +116 -0
- package/skills/_support/docs/principles/details/p064-requirement-to-test-traceability.md +116 -0
- package/skills/_support/docs/principles/details/p065-verify-before-claiming-completion.md +129 -0
- package/skills/_support/docs/principles/details/p066-preserve-existing-work.md +114 -0
- package/skills/_support/docs/principles/details/p067-no-test-cheating.md +126 -0
- package/skills/_support/docs/principles/details/p068-no-validation-bypass.md +119 -0
- package/skills/_support/docs/principles/details/p069-independent-review-for-high-risk-changes.md +129 -0
- package/skills/_support/docs/principles/details/p070-code-health-must-not-regress.md +116 -0
- package/skills/_support/docs/principles/details/p071-consistency-over-personal-preference.md +117 -0
- package/skills/_support/docs/principles/details/p072-technical-evidence-over-preference.md +122 -0
- package/skills/_support/docs/principles/details/p073-optimize-only-with-evidence.md +123 -0
- package/skills/_support/docs/principles/details/p074-prefer-existing-mechanisms.md +121 -0
- package/skills/_support/docs/principles/details/p075-make-invalid-states-hard-to-represent.md +128 -0
- package/skills/_support/docs/principles/details/p076-parse-then-validate-then-operate.md +133 -0
- package/skills/_support/docs/principles/details/p077-separate-policy-from-mechanism.md +112 -0
- package/skills/_support/docs/principles/details/p078-single-source-of-truth.md +131 -0
- package/skills/_support/docs/principles/details/p079-explicit-ownership-and-lifetimes.md +124 -0
- package/skills/_support/docs/principles/details/p080-make-concurrency-deliberate.md +122 -0
- package/skills/_support/docs/principles/details/p081-forward-progress-with-safety.md +125 -0
- package/skills/_support/docs/principles/details/p082-design-for-cancellation.md +133 -0
- package/skills/_support/docs/principles/details/p083-irreversible-actions-last.md +124 -0
- package/skills/_support/docs/principles/details/p084-prefer-local-reasoning.md +131 -0
- package/skills/_support/docs/principles/details/p085-explicit-is-better-than-implicit.md +123 -0
- package/skills/_support/docs/principles/details/p086-readability-counts.md +113 -0
- package/skills/_support/docs/principles/details/p087-comments-explain-why-code-explains-what.md +120 -0
- package/skills/_support/docs/principles/details/p088-delete-dead-code.md +125 -0
- package/skills/_support/docs/principles/details/p089-delete-obsolete-configuration-and-dependencies.md +125 -0
- package/skills/_support/docs/principles/details/p090-prefer-negative-code.md +134 -0
- package/skills/_support/docs/principles/details/p091-test-driven-development.md +149 -0
- package/skills/_support/docs/review/README.md +59 -0
- package/skills/_support/docs/review/behavior-first-testing.md +73 -0
- package/skills/_support/docs/review/common.md +365 -0
- package/skills/_support/docs/review/design-docs.md +74 -0
- package/skills/_support/docs/review/issue-planning.md +220 -0
- package/skills/_support/docs/review/language-routing.md +141 -0
- package/skills/_support/docs/review/repository-scorecard.md +170 -0
- package/skills/advise/SKILL.md +93 -67
- package/skills/advise/scripts/list_retrievable_skills.py +3 -3
- package/skills/brainstorm/SKILL.md +160 -127
- package/skills/change-review/SKILL.md +91 -71
- package/skills/change-review/references/scope-resolution.md +69 -46
- package/skills/change-review/scripts/resolve_scope.py +119 -73
- package/skills/finalize-plan/SKILL.md +198 -139
- package/skills/git-worktrees/SKILL.md +100 -80
- package/skills/git-worktrees/scripts/prepare_worktree.py +16 -10
- package/skills/issue-review/SKILL.md +136 -79
- package/skills/learn/SKILL.md +276 -186
- package/skills/myrmidon-swarm/SKILL.md +126 -86
- package/skills/plan-issue/SKILL.md +122 -81
- package/skills/pr-review/SKILL.md +164 -114
- package/skills/pr-review/references/criteria.md +58 -37
- package/skills/pr-review/references/delivery.md +156 -98
- package/skills/pr-review/references/evidence.md +265 -148
- package/skills/pr-review/references/prevalidated.md +93 -61
- package/skills/pr-review/scripts/collect_evidence.py +211 -140
- package/skills/pr-review/scripts/diff_context.py +6 -4
- package/skills/pr-review/scripts/materialize_snapshot.py +112 -120
- package/skills/pr-review/scripts/pr_identity.py +27 -15
- package/skills/pr-review/scripts/resolve_pr.py +53 -31
- package/skills/repo-review/SKILL.md +202 -131
- package/skills/systematic-debugging/SKILL.md +210 -192
- package/skills/systematic-debugging/scripts/repository_evidence.py +9 -4
- package/skills/test-driven-development/SKILL.md +126 -96
- package/skills/tidy/SKILL.md +92 -59
- package/skills/tidy/scripts/run_tidy.py +3 -3
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# P080 — Make Concurrency Deliberate
|
|
2
|
+
|
|
3
|
+
## Definition
|
|
4
|
+
|
|
5
|
+
Measurements must first give proof of a benefit. **Make Concurrency Deliberate** then lets a design
|
|
6
|
+
use parallel or asynchronous execution. The design gives the full coordination model. The model includes shared state,
|
|
7
|
+
synchronization, order, cancellation, deadlines, error collection, and capacity limits.
|
|
8
|
+
|
|
9
|
+
**Aliases:** none.
|
|
10
|
+
|
|
11
|
+
## Provenance
|
|
12
|
+
|
|
13
|
+
**Classification:** principle with source evidence.
|
|
14
|
+
|
|
15
|
+
No source gives this text. The rule uses research on processes, synchronization, messages,
|
|
16
|
+
structured concurrency, and language memory models. This research gives evidence that concurrency
|
|
17
|
+
changes the correctness model. The design must include explicit analysis.
|
|
18
|
+
|
|
19
|
+
## Decision rule
|
|
20
|
+
|
|
21
|
+
As the default, use sequential execution. Use concurrency only for a measured latency, throughput,
|
|
22
|
+
response, or isolation benefit. Select a model with testable safety and termination properties.
|
|
23
|
+
|
|
24
|
+
## How to apply
|
|
25
|
+
|
|
26
|
+
- Record the specified benefit. Measure the latency, throughput, response, or isolation change.
|
|
27
|
+
- Use the minimum shared mutable state. Use immutable messages or ownership transfer.
|
|
28
|
+
- Give order guarantees, synchronization, and permitted interleavings.
|
|
29
|
+
- Set limits for workers, queues, fan-out, and active work.
|
|
30
|
+
- Propagate deadlines and cancellation to all tasks in the tree.
|
|
31
|
+
- Give one result for failures and concurrent errors.
|
|
32
|
+
- Where applicable, use race detection, stress tests, and deterministic model tests.
|
|
33
|
+
|
|
34
|
+
## Diagram
|
|
35
|
+
|
|
36
|
+
After measurements give proof of a benefit, the design adds concurrency.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
flowchart LR
|
|
40
|
+
A["Sequential design"] --> B{"Measured benefit?"}
|
|
41
|
+
B -->|No| C["Keep sequential flow"]
|
|
42
|
+
B -->|Yes| D["Owners and limits"]
|
|
43
|
+
D --> E["Order and cancellation"]
|
|
44
|
+
E --> F["Do bounded concurrent work"]
|
|
45
|
+
F --> G["Collect all results"]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Language examples
|
|
49
|
+
|
|
50
|
+
The two examples await two ordered operations, return each result, and cancel child operations when the caller stops.
|
|
51
|
+
|
|
52
|
+
### Python
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
FetchResult = bytes | BaseException
|
|
56
|
+
|
|
57
|
+
async def fetch_pair(urls: tuple[str, str]) -> tuple[FetchResult, FetchResult]:
|
|
58
|
+
results = await asyncio.gather(
|
|
59
|
+
fetch(urls[0]), fetch(urls[1]), return_exceptions=True
|
|
60
|
+
)
|
|
61
|
+
return results[0], results[1]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Rust
|
|
65
|
+
|
|
66
|
+
```rust
|
|
67
|
+
type FetchResult = Result<Body, Error>;
|
|
68
|
+
|
|
69
|
+
async fn fetch_pair(urls: [&str; 2]) -> (FetchResult, FetchResult) {
|
|
70
|
+
let results = tokio::join!(fetch(urls[0]), fetch(urls[1]));
|
|
71
|
+
results
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Boundaries and tensions
|
|
76
|
+
|
|
77
|
+
When concurrent callers or external systems use sequential code, the code can have races. Concurrency is
|
|
78
|
+
necessary in some domains. The principle gives a specified model and lets a design use concurrency.
|
|
79
|
+
If measured speed benefits increase correctness risk or operation cost, reject the benefits. An asynchronous
|
|
80
|
+
interface must not cause concurrency in other layers.
|
|
81
|
+
|
|
82
|
+
## Examples
|
|
83
|
+
|
|
84
|
+
**Positive:** A bounded operation starts two reads that operate independently with a shared deadline. The
|
|
85
|
+
reads have no shared mutable state. The result order is deterministic.
|
|
86
|
+
|
|
87
|
+
**Misuse:** A loop starts one worker for each input without a limit. The loop discards failures, and
|
|
88
|
+
the caller cannot cancel the work.
|
|
89
|
+
|
|
90
|
+
**Athena/agent workflow:** A coordinator delegates only subtasks that can operate independently. The
|
|
91
|
+
coordinator gives each worker bounded scope. Before the coordinator accepts shared conclusions, the
|
|
92
|
+
coordinator collects and compares all results.
|
|
93
|
+
|
|
94
|
+
## Related principles
|
|
95
|
+
|
|
96
|
+
- [P039 Bounded Waiting](p039-bounded-waiting.md)
|
|
97
|
+
- [P040 Bounded Resources](p040-bounded-resources.md)
|
|
98
|
+
- [P042 Fault Isolation / Bulkheads](p042-fault-isolation-bulkheads.md)
|
|
99
|
+
- [P079 Explicit Ownership and Lifetimes](p079-explicit-ownership-and-lifetimes.md)
|
|
100
|
+
- [P082 Design for Cancellation](p082-design-for-cancellation.md)
|
|
101
|
+
|
|
102
|
+
## References
|
|
103
|
+
|
|
104
|
+
### Source information
|
|
105
|
+
|
|
106
|
+
- [Communicating Sequential Processes](https://doi.org/10.1145/359576.359585) is C. A. R. Hoare's
|
|
107
|
+
1978 primary paper that gives a process-and-message model without implicit shared-state
|
|
108
|
+
coordination.
|
|
109
|
+
|
|
110
|
+
### Applicable information
|
|
111
|
+
|
|
112
|
+
- [Google Engineering Practices: What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html)
|
|
113
|
+
includes concurrency as a complexity and correctness area for careful inspection.
|
|
114
|
+
- [The Rust Programming Language: Fearless Concurrency](https://doc.rust-lang.org/book/ch16-00-concurrency.html)
|
|
115
|
+
gives examples of ownership and types that prevent many concurrency errors.
|
|
116
|
+
|
|
117
|
+
### More information
|
|
118
|
+
|
|
119
|
+
- [Go Concurrency Patterns: Context](https://go.dev/blog/context) gives information about explicit
|
|
120
|
+
propagation of deadlines and cancellation to all concurrent request work.
|
|
121
|
+
|
|
122
|
+
[Back to the engineering principles catalog](../README.md#p080)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# P081 — Forward Progress With Safety
|
|
2
|
+
|
|
3
|
+
## Definition
|
|
4
|
+
|
|
5
|
+
With **Forward Progress With Safety**, an operation must have bounded and clear progress to a
|
|
6
|
+
correct result. If progress stops, the operation terminates in a clear recoverable state. The rule
|
|
7
|
+
includes safety and liveness properties.
|
|
8
|
+
|
|
9
|
+
**Aliases:** none.
|
|
10
|
+
|
|
11
|
+
## Provenance
|
|
12
|
+
|
|
13
|
+
**Classification:** Athena synthesis.
|
|
14
|
+
|
|
15
|
+
Athena gives this rule for operations. The rule is not a theorem with a specified name. Leslie Lamport's 1977
|
|
16
|
+
research gives the difference between safety and liveness properties. Reliability practice includes deadlines, retry
|
|
17
|
+
budgets, cancellation, and recovery states for production workflows.
|
|
18
|
+
|
|
19
|
+
## Decision rule
|
|
20
|
+
|
|
21
|
+
For each loop, wait, retry, queue, and multistep workflow, give a progress measure and a bound.
|
|
22
|
+
Record the necessary invariants. Give a recoverable result for stopped progress.
|
|
23
|
+
|
|
24
|
+
## How to apply
|
|
25
|
+
|
|
26
|
+
- Use different results for terminal success, failure, cancellation, and paused states.
|
|
27
|
+
- Set limits for retries, waits, queues, and internal iteration.
|
|
28
|
+
- Monitor progress and record each stagnation event. Do not reset a watchdog without measured progress.
|
|
29
|
+
- Keep invariants at all checkpoints and failure exits.
|
|
30
|
+
- When necessary, record sufficient state to resume long work safely.
|
|
31
|
+
- Do tests of deadlock, timeout, starvation, cancellation, and dependency-loss scenarios.
|
|
32
|
+
|
|
33
|
+
## Diagram
|
|
34
|
+
|
|
35
|
+
The workflow makes measured progress or has a recoverable terminal state.
|
|
36
|
+
|
|
37
|
+
```mermaid
|
|
38
|
+
flowchart LR
|
|
39
|
+
A["Start bounded work"] --> H["Do next bounded work unit"]
|
|
40
|
+
H --> B{"Progress?"}
|
|
41
|
+
B -->|Yes| C{"Work completed?"}
|
|
42
|
+
C -->|No| H
|
|
43
|
+
C -->|Yes| D["Correct result"]
|
|
44
|
+
B -->|No| E{"Retry budget has capacity?"}
|
|
45
|
+
E -->|Yes| F["Do recovery step"]
|
|
46
|
+
F --> H
|
|
47
|
+
E -->|No| G["Recoverable failure"]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Language examples
|
|
51
|
+
|
|
52
|
+
The two examples stop after a fixed number of attempts and return a clear failure.
|
|
53
|
+
|
|
54
|
+
### Python
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
def complete(job: Job) -> Result:
|
|
58
|
+
for _ in range(3):
|
|
59
|
+
result = job.try_once()
|
|
60
|
+
if result.done:
|
|
61
|
+
return result
|
|
62
|
+
raise ProgressError("retry budget exhausted")
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Rust
|
|
66
|
+
|
|
67
|
+
```rust
|
|
68
|
+
fn complete(job: &mut Job) -> Result<Outcome, ProgressError> {
|
|
69
|
+
for _ in 0..3 {
|
|
70
|
+
let result = job.try_once()?;
|
|
71
|
+
if result.done {
|
|
72
|
+
return Ok(result);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
Err(ProgressError::BudgetExhausted)
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Boundaries and tensions
|
|
80
|
+
|
|
81
|
+
A wait-free algorithm and a short duration are not necessary. Some safe work is slow or
|
|
82
|
+
waits for external events. Clear state, cancellation, or an explicit resume state is necessary.
|
|
83
|
+
Safety can make the operation stop. A timeout is a failure result. The timeout does not give proof
|
|
84
|
+
that a side effect did not occur.
|
|
85
|
+
|
|
86
|
+
## Examples
|
|
87
|
+
|
|
88
|
+
**Positive:** A migration records each completed batch and sets a time budget. The migration keeps schema
|
|
89
|
+
invariants and stops with a `paused` status and resume token.
|
|
90
|
+
|
|
91
|
+
**Misuse:** A worker catches each error and retries without a limit. The worker keeps a queue slot. Callers
|
|
92
|
+
see no completion or failure.
|
|
93
|
+
|
|
94
|
+
**Athena/agent workflow:** A delegated task has a bounded iteration budget. The task gives success,
|
|
95
|
+
blocked, or failure status with evidence. The task does not stay active without a limit.
|
|
96
|
+
|
|
97
|
+
## Related principles
|
|
98
|
+
|
|
99
|
+
- [P039 Bounded Waiting](p039-bounded-waiting.md)
|
|
100
|
+
- [P040 Bounded Resources](p040-bounded-resources.md)
|
|
101
|
+
- [P046 Resumability](p046-resumability.md)
|
|
102
|
+
- [P047 Observability Is Part of Correctness](p047-observability-is-part-of-correctness.md)
|
|
103
|
+
- [P082 Design for Cancellation](p082-design-for-cancellation.md)
|
|
104
|
+
|
|
105
|
+
## References
|
|
106
|
+
|
|
107
|
+
### Source information
|
|
108
|
+
|
|
109
|
+
- [Proving the Correctness of Multiprocess Programs](https://doi.org/10.1109/TSE.1977.229904)
|
|
110
|
+
is Lamport's 1977 primary paper that gives safety and liveness as different correctness concerns.
|
|
111
|
+
|
|
112
|
+
### Applicable information
|
|
113
|
+
|
|
114
|
+
- [gRPC Deadlines](https://grpc.io/docs/guides/deadlines/) gives information about call deadlines.
|
|
115
|
+
Call deadlines must agree with the specified duration. Servers must stop work after cancellation.
|
|
116
|
+
- [AWS Well-Architected: Control and limit retry calls](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_limit_retries.html)
|
|
117
|
+
gives retry limits, backoff, and tested stop conditions.
|
|
118
|
+
|
|
119
|
+
### More information
|
|
120
|
+
|
|
121
|
+
- [Exponential Backoff and Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)
|
|
122
|
+
gives a bounded randomized retry method. The method decreases synchronized contention and helps
|
|
123
|
+
progress.
|
|
124
|
+
|
|
125
|
+
[Back to the engineering principles catalog](../README.md#p081)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# P082 — Design for Cancellation
|
|
2
|
+
|
|
3
|
+
## Definition
|
|
4
|
+
|
|
5
|
+
With **Design for Cancellation**, an interface includes a caller's loss of interest as a terminal
|
|
6
|
+
signal. The designer gives the cancellation request, propagation path, cleanup, and
|
|
7
|
+
terminal result for long or asynchronous work. Cancellation must keep state correct and must not
|
|
8
|
+
cause a resource leak.
|
|
9
|
+
|
|
10
|
+
**Aliases:** none. Cooperative cancellation is one implementation method.
|
|
11
|
+
|
|
12
|
+
## Provenance
|
|
13
|
+
|
|
14
|
+
**Classification:** practitioner heuristic.
|
|
15
|
+
|
|
16
|
+
No source records an initial author. Operating systems, concurrent programs, and distributed request
|
|
17
|
+
interfaces use cooperative cancellation. Structured concurrency and context interfaces
|
|
18
|
+
make the lifetime relation between callers and child work explicit.
|
|
19
|
+
|
|
20
|
+
## Decision rule
|
|
21
|
+
|
|
22
|
+
If work can continue after the caller request stops, give the work a cancellation contract. Tell the
|
|
23
|
+
cancellation point. Tell the cleanup guarantee and the terminal result.
|
|
24
|
+
|
|
25
|
+
## How to apply
|
|
26
|
+
|
|
27
|
+
- Accept and propagate the host's cancellation or context capability.
|
|
28
|
+
- Monitor cancellation at bounded, state-safe checkpoints.
|
|
29
|
+
- After the cancellation signal, do not start more work.
|
|
30
|
+
- Release resources and join child work or record each child result. Then return.
|
|
31
|
+
- Use different results for cancellation, timeout, dependency failure, and completion without error.
|
|
32
|
+
- When signals can occur again and again, make cleanup, compensation, and retries idempotent.
|
|
33
|
+
- Do tests of races between cancellation, completion, and side effects that stop before completion.
|
|
34
|
+
|
|
35
|
+
## Diagram
|
|
36
|
+
|
|
37
|
+
The worker releases the worker resources after cancellation or completion.
|
|
38
|
+
|
|
39
|
+
```mermaid
|
|
40
|
+
flowchart LR
|
|
41
|
+
A["Work in progress"] --> B{"Cancellation signal?"}
|
|
42
|
+
B -->|Yes| D["Complete safe checkpoint"]
|
|
43
|
+
D --> E["Release resources"]
|
|
44
|
+
E --> F["Cancellation result"]
|
|
45
|
+
B -->|No| C{"Work completed?"}
|
|
46
|
+
C -->|No| G["Do next bounded unit"]
|
|
47
|
+
G --> A
|
|
48
|
+
C -->|Yes| H["Release resources"]
|
|
49
|
+
H --> I["Success result"]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Language examples
|
|
53
|
+
|
|
54
|
+
The two examples monitor one cancellation signal, keep operation failures distinct, and release
|
|
55
|
+
resources on cancellation and completion.
|
|
56
|
+
|
|
57
|
+
### Python
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
async def import_rows(cancel: asyncio.Event) -> None:
|
|
61
|
+
try:
|
|
62
|
+
for batch in batches:
|
|
63
|
+
if cancel.is_set():
|
|
64
|
+
raise asyncio.CancelledError
|
|
65
|
+
await import_batch(batch)
|
|
66
|
+
finally:
|
|
67
|
+
await close_input()
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Rust
|
|
71
|
+
|
|
72
|
+
```rust
|
|
73
|
+
enum ImportError { Cancelled, Operation(Error) }
|
|
74
|
+
|
|
75
|
+
fn import_rows(cancel: &AtomicBool) -> Result<(), ImportError> {
|
|
76
|
+
let _input = InputGuard::open().map_err(ImportError::Operation)?;
|
|
77
|
+
for batch in batches() {
|
|
78
|
+
if cancel.load(Ordering::Acquire) {
|
|
79
|
+
return Err(ImportError::Cancelled);
|
|
80
|
+
}
|
|
81
|
+
import_batch(batch).map_err(ImportError::Operation)?;
|
|
82
|
+
}
|
|
83
|
+
Ok(())
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Boundaries and tensions
|
|
88
|
+
|
|
89
|
+
A cancellation request does not give proof of rollback. Before cancellation occurs, an atomic or
|
|
90
|
+
irreversible step can complete. Until the region has correct invariants, a small cleanup region can
|
|
91
|
+
ignore the signal. Record each point. Do not discard a cancellation signal and return an incorrect
|
|
92
|
+
success result.
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
**Positive:** An import stops between committed batches, closes its input, records a resume token,
|
|
97
|
+
and returns a clear cancellation result.
|
|
98
|
+
|
|
99
|
+
**Misuse:** A canceled HTTP request has active database work and spawned subprocesses with no owner.
|
|
100
|
+
|
|
101
|
+
**Athena/agent workflow:** A coordinator propagates an interrupted task to the subagents. The
|
|
102
|
+
coordinator collects the terminal state of each subagent and records all completed side effects.
|
|
103
|
+
|
|
104
|
+
## Related principles
|
|
105
|
+
|
|
106
|
+
- [P033 State-Safe Failure Semantics](p033-state-safe-failure-semantics.md)
|
|
107
|
+
- [P037 Idempotency Before Retry](p037-idempotency-before-retry.md)
|
|
108
|
+
- [P046 Resumability](p046-resumability.md)
|
|
109
|
+
- [P079 Explicit Ownership and Lifetimes](p079-explicit-ownership-and-lifetimes.md)
|
|
110
|
+
- [P083 Irreversible Actions Last](p083-irreversible-actions-last.md)
|
|
111
|
+
|
|
112
|
+
## References
|
|
113
|
+
|
|
114
|
+
### Source information
|
|
115
|
+
|
|
116
|
+
- No one primary source gives the general pattern. Do not record one language or framework as the
|
|
117
|
+
source.
|
|
118
|
+
- [Go Concurrency Patterns: Context](https://go.dev/blog/context) records a 2014 model that
|
|
119
|
+
transmits deadlines and cancellation to request-scoped work.
|
|
120
|
+
|
|
121
|
+
### Applicable information
|
|
122
|
+
|
|
123
|
+
- [gRPC Cancellation](https://grpc.io/docs/guides/cancellation/) gives cancellation propagation.
|
|
124
|
+
Applications must stop work for a canceled RPC.
|
|
125
|
+
- [Go: Canceling in-progress operations](https://go.dev/doc/database/cancel-operations) gives
|
|
126
|
+
a cancellation and cleanup example for database calls.
|
|
127
|
+
|
|
128
|
+
### More information
|
|
129
|
+
|
|
130
|
+
- [gRPC Deadlines](https://grpc.io/docs/guides/deadlines/) gives the relation between time bounds and
|
|
131
|
+
automatic cancellation. The guide gives the server application responsibility for spawned-work cleanup.
|
|
132
|
+
|
|
133
|
+
[Back to the engineering principles catalog](../README.md#p082)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# P083 — Irreversible Actions Last
|
|
2
|
+
|
|
3
|
+
## Definition
|
|
4
|
+
|
|
5
|
+
**Irreversible Actions Last** completes validation, reversible preparation, authorization, and
|
|
6
|
+
evidence collection before an irreversible external effect. A multistep workflow can have more than
|
|
7
|
+
one irreversible step. Put each irreversible step near the end of the workflow.
|
|
8
|
+
|
|
9
|
+
**Aliases:** none.
|
|
10
|
+
|
|
11
|
+
## Provenance
|
|
12
|
+
|
|
13
|
+
**Classification:** Athena synthesis.
|
|
14
|
+
|
|
15
|
+
No source gives this text. The rule includes change control, transaction
|
|
16
|
+
authorization, staged release, and rollback practice. The rule uses this order for software and agent
|
|
17
|
+
workflows.
|
|
18
|
+
|
|
19
|
+
## Decision rule
|
|
20
|
+
|
|
21
|
+
Before an irreversible step, complete all checks and reversible preparation. Immediately before the
|
|
22
|
+
specified operation, revalidate the mutable target and authority.
|
|
23
|
+
|
|
24
|
+
## How to apply
|
|
25
|
+
|
|
26
|
+
- Put steps in four groups: read-only, reversible, compensatable, and irreversible.
|
|
27
|
+
- Validate inputs and targets first. Then prepare only reversible state.
|
|
28
|
+
- With correct evidence, use previews, staging, backups, canaries, and dry runs.
|
|
29
|
+
- Bind approval and authorization to the publication target and parameters.
|
|
30
|
+
- After preparation, examine mutable facts again.
|
|
31
|
+
- Where possible, make the commit step atomic or idempotent.
|
|
32
|
+
- Record the outcome and all irreversible side effects.
|
|
33
|
+
|
|
34
|
+
## Diagram
|
|
35
|
+
|
|
36
|
+
Before the irreversible step, the workflow completes each reversible gate.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
flowchart LR
|
|
40
|
+
A["Validate input"] --> B["Prepare reversible state"]
|
|
41
|
+
B --> C["Preview specified operation"]
|
|
42
|
+
C --> D["Revalidate target and authority"]
|
|
43
|
+
D --> E{"All checks satisfactory?"}
|
|
44
|
+
E -->|No| F["Stop without irreversible effect"]
|
|
45
|
+
E -->|Yes| G["Irreversible operation"]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Language examples
|
|
49
|
+
|
|
50
|
+
Immediately before publication, the two examples revalidate the artifact target.
|
|
51
|
+
|
|
52
|
+
### Python
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
def publish(request: Request) -> Receipt:
|
|
56
|
+
artifact = prepare(request)
|
|
57
|
+
preview(artifact)
|
|
58
|
+
verify_target(artifact.target)
|
|
59
|
+
verify_authority(request.actor, artifact.target)
|
|
60
|
+
return publisher.publish(artifact)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Rust
|
|
64
|
+
|
|
65
|
+
```rust
|
|
66
|
+
fn publish(request: &Request) -> Result<Receipt, Error> {
|
|
67
|
+
let artifact = prepare(request)?;
|
|
68
|
+
preview(&artifact)?;
|
|
69
|
+
verify_target(&artifact.target)?;
|
|
70
|
+
verify_authority(&request.actor, &artifact.target)?;
|
|
71
|
+
publisher::publish(artifact)
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Boundaries and tensions
|
|
76
|
+
|
|
77
|
+
An irreversible operation can be the necessary result. The principle puts validation before the
|
|
78
|
+
operation but does not prevent the operation. Long preparation can make decisions incorrect. The last
|
|
79
|
+
gate examines mutable state again.
|
|
80
|
+
|
|
81
|
+
Compensation is not a reversal. Messages, charges, deletions, and public releases can have
|
|
82
|
+
external effects before compensation. Specified authorization is necessary for emergency paths.
|
|
83
|
+
|
|
84
|
+
## Examples
|
|
85
|
+
|
|
86
|
+
**Positive:** A release process assembles the artifact and does tests, staging, and target-revision
|
|
87
|
+
verification. The release process receives bound authorization and then moves production traffic.
|
|
88
|
+
|
|
89
|
+
**Misuse:** A checkout charges a payment method first. The checkout then validates inventory and delivery
|
|
90
|
+
details. The workflow has the incorrect assumption that a refund removes all effects.
|
|
91
|
+
|
|
92
|
+
**Athena/agent workflow:** An agent resolves the repository and issue body. The agent previews the
|
|
93
|
+
specified request and does an authority verification. The agent then creates the public GitHub issue.
|
|
94
|
+
|
|
95
|
+
## Related principles
|
|
96
|
+
|
|
97
|
+
- [P021 Evolutionary and Reversible Design](p021-evolutionary-and-reversible-design.md)
|
|
98
|
+
- [P061 Separate Decision from High-Impact Execution](p061-separate-decision-from-high-impact-execution.md)
|
|
99
|
+
- [P062 Human Approval for Irreversible or High-Risk Actions](p062-human-approval-for-irreversible-or-high-risk-actions.md)
|
|
100
|
+
- [P076 Parse, Then Validate, Then Operate](p076-parse-then-validate-then-operate.md)
|
|
101
|
+
- [P082 Design for Cancellation](p082-design-for-cancellation.md)
|
|
102
|
+
|
|
103
|
+
## References
|
|
104
|
+
|
|
105
|
+
### Source information
|
|
106
|
+
|
|
107
|
+
- No one primary source gives the general order. Athena uses a synthesis of transaction,
|
|
108
|
+
change-control, and release-safety practice.
|
|
109
|
+
|
|
110
|
+
### Applicable information
|
|
111
|
+
|
|
112
|
+
- [OWASP Transaction Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transaction_Authorization_Cheat_Sheet.html)
|
|
113
|
+
gives ordered state transitions and an authorization gate immediately before transaction
|
|
114
|
+
execution.
|
|
115
|
+
- [Google SRE Workbook: Canarying Releases](https://sre.google/workbook/canarying-releases/)
|
|
116
|
+
gives information about staged exposure, evaluation, and rollback as release safety mechanisms.
|
|
117
|
+
|
|
118
|
+
### More information
|
|
119
|
+
|
|
120
|
+
- [NIST SP 800-53 Revision 5](https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final) includes
|
|
121
|
+
configuration change control, impact analysis, authorization, testing, and documentation controls
|
|
122
|
+
for changes with governance.
|
|
123
|
+
|
|
124
|
+
[Back to the engineering principles catalog](../README.md#p083)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# P084 — Prefer Local Reasoning
|
|
2
|
+
|
|
3
|
+
## Definition
|
|
4
|
+
|
|
5
|
+
**Prefer Local Reasoning** makes a component clear from its contract, implementation, and local
|
|
6
|
+
collaborators. The component has no nonlocal hidden state, implicit configuration, or implicit
|
|
7
|
+
control flow. Its local contract identifies all necessary subsystem dependencies.
|
|
8
|
+
|
|
9
|
+
**Aliases:** local reasoning and locality of reasoning.
|
|
10
|
+
|
|
11
|
+
## Provenance
|
|
12
|
+
|
|
13
|
+
**Classification:** principle with source evidence.
|
|
14
|
+
|
|
15
|
+
No source records an initial author of the phrase. The rule uses modularity, information hiding,
|
|
16
|
+
structured programs, and the Law of Demeter. These practices decrease the nonlocal knowledge
|
|
17
|
+
necessary for a reader.
|
|
18
|
+
|
|
19
|
+
## Decision rule
|
|
20
|
+
|
|
21
|
+
Make each nonlocal correctness dependency explicit. When possible, move each invariant near the
|
|
22
|
+
enforcement code. The local contract must give sufficient information without knowledge of the full
|
|
23
|
+
system.
|
|
24
|
+
|
|
25
|
+
## How to apply
|
|
26
|
+
|
|
27
|
+
- Keep each invariant and the applicable state in the same module.
|
|
28
|
+
- Use explicit narrow interfaces to supply important dependencies.
|
|
29
|
+
- Use the minimum global state, hidden callbacks, reflection, and nonlocal effects.
|
|
30
|
+
- Keep each state transition clear and near the operation that starts the transition.
|
|
31
|
+
- Use types and contracts to show facts from a different component.
|
|
32
|
+
- Give a clear entry point for lower-level implementation detail.
|
|
33
|
+
|
|
34
|
+
## Diagram
|
|
35
|
+
|
|
36
|
+
The local contract supplies each necessary fact to the component.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
flowchart LR
|
|
40
|
+
A["Explicit inputs"] --> C["Local component"]
|
|
41
|
+
B["Dependency with a name"] --> C
|
|
42
|
+
C --> D["Clear result"]
|
|
43
|
+
E["Hidden global state"] -. "Do not use" .-> C
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Language examples
|
|
47
|
+
|
|
48
|
+
The two examples accept ASCII-decimal cents to 1,000,000 and basis points to 10,000, with the same
|
|
49
|
+
errors and integer half-up rule.
|
|
50
|
+
|
|
51
|
+
### Python
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
def parse_decimal(text: str, maximum: int, width: int) -> int:
|
|
55
|
+
if not text or len(text) > width or not text.isascii() or not text.isdecimal():
|
|
56
|
+
raise ValueError("invalid decimal value")
|
|
57
|
+
value = int(text)
|
|
58
|
+
if value > maximum:
|
|
59
|
+
raise ValueError("value outside specified range")
|
|
60
|
+
return value
|
|
61
|
+
|
|
62
|
+
def total_cents(price: str, rate: str) -> int:
|
|
63
|
+
price_value = parse_decimal(price, 1_000_000, 7)
|
|
64
|
+
rate_value = parse_decimal(rate, 10_000, 5)
|
|
65
|
+
return price_value + (price_value * rate_value + 5_000) // 10_000
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Rust
|
|
69
|
+
|
|
70
|
+
```rust
|
|
71
|
+
fn total_cents(price: &str, rate: &str) -> Result<u64, &'static str> {
|
|
72
|
+
let parse = |text: &str, maximum, width| -> Result<u64, &'static str> {
|
|
73
|
+
if text.is_empty() || text.len() > width || !text.bytes().all(|b| b.is_ascii_digit()) {
|
|
74
|
+
return Err("invalid decimal value");
|
|
75
|
+
}
|
|
76
|
+
let value = text.parse::<u64>().map_err(|_| "invalid decimal value")?;
|
|
77
|
+
if value > maximum { return Err("value outside specified range"); }
|
|
78
|
+
Ok(value)
|
|
79
|
+
};
|
|
80
|
+
let (price, rate) = (parse(price, 1_000_000, 7)?, parse(rate, 10_000, 5)?);
|
|
81
|
+
Ok(price + (price * rate + 5_000) / 10_000)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Boundaries and tensions
|
|
86
|
+
|
|
87
|
+
Local reasoning does not let components duplicate global policy or authoritative data. A component
|
|
88
|
+
can use an explicit interface to access a canonical source. Authority, traces, and transactions can
|
|
89
|
+
include more than one component. The architecture must show these control points and effects. Some
|
|
90
|
+
distributed invariants are nonlocal. Record each nonlocal invariant.
|
|
91
|
+
|
|
92
|
+
## Examples
|
|
93
|
+
|
|
94
|
+
**Positive:** A pricing function receives a typed pricing policy and order. The function does not
|
|
95
|
+
read mutable globals, environment variables, or an implicit request-local cache.
|
|
96
|
+
|
|
97
|
+
**Misuse:** A property assignment starts an observer that the contract does not show. The
|
|
98
|
+
observer in a different package mutates persistent state.
|
|
99
|
+
|
|
100
|
+
**Athena/agent workflow:** An agent uses the task, repository instructions, and
|
|
101
|
+
local implementation. The agent does not use memory about a different checkout without repository evidence.
|
|
102
|
+
|
|
103
|
+
## Related principles
|
|
104
|
+
|
|
105
|
+
- [P005 Modularity](p005-modularity.md)
|
|
106
|
+
- [P018 Information Hiding](p018-information-hiding.md)
|
|
107
|
+
- [P019 Explicit Contracts](p019-explicit-contracts.md)
|
|
108
|
+
- [P078 Single Source of Truth](p078-single-source-of-truth.md)
|
|
109
|
+
- [P085 Explicit Is Better Than Implicit](p085-explicit-is-better-than-implicit.md)
|
|
110
|
+
|
|
111
|
+
## References
|
|
112
|
+
|
|
113
|
+
### Source information
|
|
114
|
+
|
|
115
|
+
- [Object-Oriented Programming: An Objective Sense of Style](https://doi.org/10.1145/62084.62113)
|
|
116
|
+
is the 1988 primary Law of Demeter paper. The paper gives the relation between a small quantity of
|
|
117
|
+
collaborator knowledge, less coupling, and clear correctness analysis.
|
|
118
|
+
- [On the Criteria To Be Used in Decomposing Systems into Modules](https://doi.org/10.1145/361598.361623)
|
|
119
|
+
gives the information-hiding argument for clear module boundaries.
|
|
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
|
+
gives this complexity rule. If readers cannot quickly know what code does, code has too much complexity.
|
|
125
|
+
|
|
126
|
+
### More information
|
|
127
|
+
|
|
128
|
+
- [Google Go Style Guide](https://google.github.io/styleguide/go/guide.html) uses clarity and reader
|
|
129
|
+
context for the selection of correct implementations.
|
|
130
|
+
|
|
131
|
+
[Back to the engineering principles catalog](../README.md#p084)
|