Data Loss Gate — Confirmation Before Destructive Operations
Convention: see conventions/brain-first.md —
inspect the actual target before proposing deletion: get_backlinks,
gbrain graph <slug>, git log on the underlying files. The confirmation
card below is only as good as the inspection behind it.
Convention: see _brain-filing-rules.md —
the post-confirmation deletion log files date-keyed under daily/.
What This Is
A gate that fires BEFORE any destructive operation and requires explicit user
confirmation. The agent stops, presents a recoverability card, and waits.
Scope honesty: this gate is a routing convention — the harness resolves it
into context when a destructive intent matches, and a well-behaved agent
follows it. It is NOT an operation-boundary enforcement: nothing in the gbrain
runtime mechanically blocks a delete if the skill never loads. (A native
confirm gate at the operation boundary is a filed TODO; until it lands, this
convention is the line of defense.) Some CLI surfaces carry their own flag
gates — e.g. gbrain sources remove requires --confirm-destructive — but
the flag confirms that the AGENT is sure. This skill exists to confirm that
the USER is.
When This Fires
Before ANY of these operations:
Shell / filesystem level:
rm -rf on any directory with data
rm / unlink on more than 10 files
sed -i that modifies more than 10 files
git rm on tracked files
- Truncating or stripping content from files in bulk
- Overwriting files with smaller versions (content stripping)
- Any operation described as "cleanup" or "freeing space" that touches data files
Brain / database level (gbrain-specific):
- Bulk forget — scripting or looping
gbrain forget <fact-id> over many
facts. One forget is a considered, idempotent act; a forget sweep is data loss.
- Page-delete sweeps —
gbrain delete <slug> in a loop, or any script that
sweeps delete_page across a set of slugs. Deletes are soft (recoverable via
gbrain restore <slug>) until purged — say so on the card, then gate anyway:
a sweep that's wrong in bulk is expensive to un-wrong in bulk.
gbrain purge-deleted — permanently removes soft-deleted pages. This is
the point of no return for the soft-delete safety net.
- Source removal —
gbrain sources remove <id> deletes the source AND
every page in it. The --confirm-destructive flag does not substitute for
the card.
- Mount removal —
gbrain mounts remove <id> only removes the local
registration (the mounted brain's database survives; re-add to recover). Gate
it anyway when the flow ALSO plans to delete the mount's underlying database
or files — then the full card applies to those.
- Raw-SQL truncation — any
DROP TABLE, TRUNCATE, or DELETE without a
narrow WHERE against the brain database, via any path (psql, a migration
script, an engine executeRaw call).
- Deleting database rows in bulk; dropping tables, collections, or indexes.
What To Do
Step 1: STOP before executing
Do NOT run the destructive command. Inspect the actual target first
(backlinks, graph edges, git history, file contents — whatever grounds the
card), then present the user with:
Step 2: The Confirmation Card
⚠️ DATA DELETION — Confirmation Required
What: [exactly what will be deleted/modified]
Count: [number of files/rows/pages/facts affected]
Size: [how much data will be removed]
Location: [exact paths, slugs, or source/mount ids]
Why: [the reason for the deletion]
Recoverable?
- [ ] Backed up to a remote (git remote, database backup, object storage)
- [ ] In git history (can git checkout)
- [ ] Soft-deleted in the brain (restorable via `gbrain restore` until purged)
- [ ] Re-fetchable from an upstream source (which one, how long)
- [ ] NOT recoverable — permanent data loss
What we'd lose:
- [specific data/capability that would be gone]
- [any downstream systems that depend on this data]
Alternative to deletion:
- [compress instead of delete?]
- [move to cold storage?]
- [archive to a remote backup?]
- [soft-delete and defer the purge?]
Proceed? (yes/no)
Step 3: Wait for explicit "yes"
- Do NOT proceed on "ok", "sure", "go ahead" — require "yes" or "do it"
- If the user says "wait" or asks a question, answer it and re-present the card
- If the user says "no", stop immediately and suggest alternatives
For the mechanics of presenting the gate and stopping the turn, use the
ask-user choice-gate pattern — this skill supplies the
card content and the explicit-yes strictness; ask-user supplies the
stop-and-wait discipline.
Step 4: Execute with logging
After confirmation:
- Log what was deleted to
daily/notes/YYYY-MM-DD.md under ## Data Deletions
- Include: timestamp, what, count, size, recovery path
- If the deletion is large (>1GB or >1000 files/pages), do it in chunks with
progress updates
No Exception Classes
There are no categories of data that are disposable by default. Old logs, git
stash entries, build artifacts, caches — each of these has, at some point,
been the source of truth for something. Disposability is a property of the
SPECIFIC target, verified by inspecting it (backlinks, git status, what
depends on it, whether it's re-fetchable and at what cost) — never a property
of its category. If the inspection genuinely shows the target is ephemeral and
regenerable, the card is quick to fill out and the user's "yes" is quick to
get. That's the cost of the gate working.
Why This Exists
A downstream agent once deleted a multi-gigabyte cache of raw source files
from its brain's data directory to free disk space. The files looked like
"just cache" — but they were the source data for a planned feature. The data
happened to be re-fetchable from its upstream source, but the deletion was
still wrong because:
- It destroyed work that had a planned use
- It happened without the data owner's consent
- The "cleanup" framing made it seem safe when it wasn't
The rule: if it's data and it's bulk, ASK FIRST. Always.
Anti-Patterns
- ❌ "These are just cache files" — cache files can be the source of truth
- ❌ "We can re-fetch from the API" — re-fetching costs time, money, and may not produce identical data
- ❌ "It's gitignored so it doesn't matter" — gitignored ≠ unimportant
- ❌ "The disk is full, I need to free space NOW" — even under pressure, ask first
- ❌ "I'll clean up and tell the user after" — the confirmation must come BEFORE the deletion
- ❌ "It's only a soft delete" — a wrong sweep is still expensive to un-wrong in bulk, and purge makes it permanent
- ❌ "The command already has --confirm-destructive" — the flag confirms the agent's intent, not the user's consent
- ❌ Presenting deletion as the only option without listing alternatives
Dedup (sharp boundaries)
- conventions/test-before-bulk.md —
the write-side sibling. test-before-bulk gates bulk WRITE quality (test 3-5
items before running 170); data-loss-gate gates bulk DESTRUCTION (confirm
before deleting anything in bulk). A flow that rewrites pages in place needs
both: test-before-bulk for the new content, data-loss-gate for what the
rewrite destroys.
- ask-user — the confirmation MECHANICS (2-4
options, escape hatch, stop the turn, handle the response). data-loss-gate
is a specialized caller: it supplies the destructive-op card and the
strict explicit-yes rule ("ok" is not consent). Route to ask-user for any
non-destructive decision gate.
- maintain — brain health checks and routine
cleanup (orphans, backlinks, stale detection). maintain FINDS candidates
for cleanup; when acting on them crosses into bulk deletion, data-loss-gate
fires before execution. "Check brain health" routes to maintain, not here.
Contract
This skill guarantees:
- No destructive operation in scope (the "When This Fires" list) executes
before the confirmation card is presented and the user answers with an
explicit "yes" / "do it".
- The card always includes the recoverability checklist, what-we'd-lose, and
at least one alternative to deletion.
- Confirmed deletions are logged to
daily/notes/YYYY-MM-DD.md under
## Data Deletions with timestamp, scope, and recovery path.
- Routing matches the canonical triggers in the frontmatter.
- Output written under the directories listed in
writes_to:.
- Privacy contract preserved: no real names, no fork-specific filesystem path
literals, no upstream-fork references.
The full behavior contract is documented in the body sections above; this
section exists for the conformance test.
Output Format
Two artifacts:
- The confirmation card (pre-execution) — the exact fenced block in
Step 2, presented via the ask-user stop-and-wait pattern. The turn ends
after the card; no further tool calls until the user responds.
- The deletion log entry (post-execution, only after explicit "yes") —
appended to
daily/notes/YYYY-MM-DD.md:
## Data Deletions
- **[HH:MM]** [what was deleted] — [count], [size]. Reason: [why].
Recovery: [backup/git/restore path, or "none — permanent"].
1---
2name: data-loss-gate
3version: 1.0.0
4description: >
5 Confirmation gate before any bulk delete, cleanup, or destructive operation
6 that could result in data loss — shell-level (rm -rf, git rm, bulk sed) or
7 brain-level (bulk forget, delete sweeps, purge-deleted, source removal,
8 raw-SQL truncation). Presents a recoverability card and requires an explicit
9 "yes" from the user before proceeding. Routing convention, not an
10 operation-boundary enforcement.
11triggers:
12 - "bulk delete"
13 - "wipe the"
14 - "rm -rf"
15 - "purge the"
16 - "truncate"
17 - "free up space"
18 - "bulk forget"
19 - "remove the source"
20 - "drop the table"
21mutating: true
22writes_pages: true
23writes_to:
24 - daily/
25upstream: data-loss-gate@fc834ee
26# Brain-first applies in its inspection form: before deleting brain pages,
27# check backlinks / graph dependencies (get_backlinks, graph) so the card's
28# "what we'd lose" section is grounded in the actual target, not guesses.
29brain_first: true
30---
31
32# Data Loss Gate — Confirmation Before Destructive Operations
33
34> **Convention:** see [conventions/brain-first.md](../conventions/brain-first.md) —
35> inspect the actual target before proposing deletion: `get_backlinks`,
36> `gbrain graph <slug>`, `git log` on the underlying files. The confirmation
37> card below is only as good as the inspection behind it.
38>
39> **Convention:** see [_brain-filing-rules.md](../_brain-filing-rules.md) —
40> the post-confirmation deletion log files date-keyed under `daily/`.
41
42## What This Is
43
44A gate that fires BEFORE any destructive operation and requires explicit user
45confirmation. The agent stops, presents a recoverability card, and waits.
46
47**Scope honesty:** this gate is a routing convention — the harness resolves it
48into context when a destructive intent matches, and a well-behaved agent
49follows it. It is NOT an operation-boundary enforcement: nothing in the gbrain
50runtime mechanically blocks a delete if the skill never loads. (A native
51confirm gate at the operation boundary is a filed TODO; until it lands, this
52convention is the line of defense.) Some CLI surfaces carry their own flag
53gates — e.g. `gbrain sources remove` requires `--confirm-destructive` — but
54the flag confirms that the AGENT is sure. This skill exists to confirm that
55the USER is.
56
57## When This Fires
58
59**Before ANY of these operations:**
60
61Shell / filesystem level:
62
63- `rm -rf` on any directory with data
64- `rm` / `unlink` on more than 10 files
65- `sed -i` that modifies more than 10 files
66- `git rm` on tracked files
67- Truncating or stripping content from files in bulk
68- Overwriting files with smaller versions (content stripping)
69- Any operation described as "cleanup" or "freeing space" that touches data files
70
71Brain / database level (gbrain-specific):
72
73- **Bulk forget** — scripting or looping `gbrain forget <fact-id>` over many
74 facts. One forget is a considered, idempotent act; a forget sweep is data loss.
75- **Page-delete sweeps** — `gbrain delete <slug>` in a loop, or any script that
76 sweeps `delete_page` across a set of slugs. Deletes are soft (recoverable via
77 `gbrain restore <slug>`) until purged — say so on the card, then gate anyway:
78 a sweep that's wrong in bulk is expensive to un-wrong in bulk.
79- **`gbrain purge-deleted`** — permanently removes soft-deleted pages. This is
80 the point of no return for the soft-delete safety net.
81- **Source removal** — `gbrain sources remove <id>` deletes the source AND
82 every page in it. The `--confirm-destructive` flag does not substitute for
83 the card.
84- **Mount removal** — `gbrain mounts remove <id>` only removes the local
85 registration (the mounted brain's database survives; re-add to recover). Gate
86 it anyway when the flow ALSO plans to delete the mount's underlying database
87 or files — then the full card applies to those.
88- **Raw-SQL truncation** — any `DROP TABLE`, `TRUNCATE`, or `DELETE` without a
89 narrow `WHERE` against the brain database, via any path (psql, a migration
90 script, an engine `executeRaw` call).
91- Deleting database rows in bulk; dropping tables, collections, or indexes.
92
93## What To Do
94
95### Step 1: STOP before executing
96
97Do NOT run the destructive command. Inspect the actual target first
98(backlinks, graph edges, git history, file contents — whatever grounds the
99card), then present the user with:
100
101### Step 2: The Confirmation Card
102
103```
104⚠️ DATA DELETION — Confirmation Required
105
106What: [exactly what will be deleted/modified]
107Count: [number of files/rows/pages/facts affected]
108Size: [how much data will be removed]
109Location: [exact paths, slugs, or source/mount ids]
110
111Why: [the reason for the deletion]
112
113Recoverable?
114- [ ] Backed up to a remote (git remote, database backup, object storage)
115- [ ] In git history (can git checkout)
116- [ ] Soft-deleted in the brain (restorable via `gbrain restore` until purged)
117- [ ] Re-fetchable from an upstream source (which one, how long)
118- [ ] NOT recoverable — permanent data loss
119
120What we'd lose:
121- [specific data/capability that would be gone]
122- [any downstream systems that depend on this data]
123
124Alternative to deletion:
125- [compress instead of delete?]
126- [move to cold storage?]
127- [archive to a remote backup?]
128- [soft-delete and defer the purge?]
129
130Proceed? (yes/no)
131```
132
133### Step 3: Wait for explicit "yes"
134
135- Do NOT proceed on "ok", "sure", "go ahead" — require "yes" or "do it"
136- If the user says "wait" or asks a question, answer it and re-present the card
137- If the user says "no", stop immediately and suggest alternatives
138
139For the mechanics of presenting the gate and stopping the turn, use the
140[ask-user](../ask-user/SKILL.md) choice-gate pattern — this skill supplies the
141card content and the explicit-yes strictness; ask-user supplies the
142stop-and-wait discipline.
143
144### Step 4: Execute with logging
145
146After confirmation:
147
1481. Log what was deleted to `daily/notes/YYYY-MM-DD.md` under `## Data Deletions`
1492. Include: timestamp, what, count, size, recovery path
1503. If the deletion is large (>1GB or >1000 files/pages), do it in chunks with
151 progress updates
152
153## No Exception Classes
154
155There are no categories of data that are disposable by default. Old logs, git
156stash entries, build artifacts, caches — each of these has, at some point,
157been the source of truth for something. Disposability is a property of the
158SPECIFIC target, verified by inspecting it (backlinks, git status, what
159depends on it, whether it's re-fetchable and at what cost) — never a property
160of its category. If the inspection genuinely shows the target is ephemeral and
161regenerable, the card is quick to fill out and the user's "yes" is quick to
162get. That's the cost of the gate working.
163
164## Why This Exists
165
166A downstream agent once deleted a multi-gigabyte cache of raw source files
167from its brain's data directory to free disk space. The files looked like
168"just cache" — but they were the source data for a planned feature. The data
169happened to be re-fetchable from its upstream source, but the deletion was
170still wrong because:
171
1721. It destroyed work that had a planned use
1732. It happened without the data owner's consent
1743. The "cleanup" framing made it seem safe when it wasn't
175
176**The rule: if it's data and it's bulk, ASK FIRST. Always.**
177
178## Anti-Patterns
179
180- ❌ "These are just cache files" — cache files can be the source of truth
181- ❌ "We can re-fetch from the API" — re-fetching costs time, money, and may not produce identical data
182- ❌ "It's gitignored so it doesn't matter" — gitignored ≠ unimportant
183- ❌ "The disk is full, I need to free space NOW" — even under pressure, ask first
184- ❌ "I'll clean up and tell the user after" — the confirmation must come BEFORE the deletion
185- ❌ "It's only a soft delete" — a wrong sweep is still expensive to un-wrong in bulk, and purge makes it permanent
186- ❌ "The command already has --confirm-destructive" — the flag confirms the agent's intent, not the user's consent
187- ❌ Presenting deletion as the only option without listing alternatives
188
189## Dedup (sharp boundaries)
190
191- **[conventions/test-before-bulk.md](../conventions/test-before-bulk.md)** —
192 the write-side sibling. test-before-bulk gates bulk WRITE quality (test 3-5
193 items before running 170); data-loss-gate gates bulk DESTRUCTION (confirm
194 before deleting anything in bulk). A flow that rewrites pages in place needs
195 both: test-before-bulk for the new content, data-loss-gate for what the
196 rewrite destroys.
197- **[ask-user](../ask-user/SKILL.md)** — the confirmation MECHANICS (2-4
198 options, escape hatch, stop the turn, handle the response). data-loss-gate
199 is a specialized caller: it supplies the destructive-op card and the
200 strict explicit-yes rule ("ok" is not consent). Route to ask-user for any
201 non-destructive decision gate.
202- **[maintain](../maintain/SKILL.md)** — brain health checks and routine
203 cleanup (orphans, backlinks, stale detection). maintain FINDS candidates
204 for cleanup; when acting on them crosses into bulk deletion, data-loss-gate
205 fires before execution. "Check brain health" routes to maintain, not here.
206
207## Contract
208
209This skill guarantees:
210
211- No destructive operation in scope (the "When This Fires" list) executes
212 before the confirmation card is presented and the user answers with an
213 explicit "yes" / "do it".
214- The card always includes the recoverability checklist, what-we'd-lose, and
215 at least one alternative to deletion.
216- Confirmed deletions are logged to `daily/notes/YYYY-MM-DD.md` under
217 `## Data Deletions` with timestamp, scope, and recovery path.
218- Routing matches the canonical triggers in the frontmatter.
219- Output written under the directories listed in `writes_to:`.
220- Privacy contract preserved: no real names, no fork-specific filesystem path
221 literals, no upstream-fork references.
222
223The full behavior contract is documented in the body sections above; this
224section exists for the conformance test.
225
226## Output Format
227
228Two artifacts:
229
2301. **The confirmation card** (pre-execution) — the exact fenced block in
231 Step 2, presented via the ask-user stop-and-wait pattern. The turn ends
232 after the card; no further tool calls until the user responds.
2332. **The deletion log entry** (post-execution, only after explicit "yes") —
234 appended to `daily/notes/YYYY-MM-DD.md`:
235
236```markdown
237## Data Deletions
238
239- **[HH:MM]** [what was deleted] — [count], [size]. Reason: [why].
240 Recovery: [backup/git/restore path, or "none — permanent"].
241```