Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/design-principles.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ the phased build plan should be traceable back to one of these.
- **Safety over speed.** The consequences of a bug are data loss in production systems, so a
feature must be *safe* and *safe-by-default* before it is fast. Speed work (parallelism,
watermark optimization) only lands on top of a proven-correct path.
- <a id="make-mistakes-hard-to-commit"></a>**Make mistakes hard to commit.** An action that is
hard to undo needs explicit, specific intent: a typed acknowledgement naming its target, never
one inferred from an absence or granted broadly. When the engine cannot tell intent from
accident, it refuses. This is why a desired file that no longer lists a column refuses
rather than drops it, and why the destructive acknowledgement names one table and exists only
where the operator wrote the statement.
- **Decisions, not options.** Prefer sensible defaults over configuration knobs; non-default
options are poorly tested and a source of surprise. The engine should make the right call
for the user rather than expose another flag.
Expand Down
6 changes: 4 additions & 2 deletions docs/invariants.md
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,8 @@ Each refusal is a preflight **error with a stated reason** — never a warning,
intent is explicit. The rename-overlap pattern Spirit refuses (one `ALTER` that renames a
column and reuses or retypes it) is unrepresentable: PostgreSQL parses a rename as its own
statement and the front door admits one statement (`TestClassifyRejectsARename*`). *Source:*
[low-level-design § declarative safety rules](low-level-design.md#safety-rules-inherited-philosophy-surprise-free-decisions-not-options), Spirit.
[low-level-design § declarative safety rules](low-level-design.md#safety-rules-inherited-philosophy-surprise-free-decisions-not-options),
[make mistakes hard to commit](design-principles.md#make-mistakes-hard-to-commit), Spirit.
- **RF-5** — The dangerous literal never runs silently: risky statements with a safer native
idiom get the idiom (reported) or a recommendation; running as-submitted requires a loud,
typed, audited acknowledgement: `--force` on the routes it governs, or `--accept-blocking`
Expand Down Expand Up @@ -1414,7 +1415,8 @@ Each refusal is a preflight **error with a stated reason** — never a warning,
`TestRunAllowDestructiveDoesNotLiftADropIndexRefusal`, `TestAdmitDestructive`,
`TestMigrateDryRunReportsTheDestructiveRefusal`, `TestAllowDestructiveFlagGrammar`,
`demo/tour.sh` (`refused_destructive`). *Source:*
[design principles](design-principles.md#declarative-review-first-workflow),
[design principles](design-principles.md#declarative-review-first-workflow)
([make mistakes hard to commit](design-principles.md#make-mistakes-hard-to-commit)),
SchemaBot's `--allow-unsafe` acknowledgement for destructive plans.
- **RF-11** — A table is judged idle only when the connected server's statistics prove no use
inside the window: no other session holds a lock on it, both last-scan times are recorded
Expand Down
Loading