clawpowers 1.1.4 → 2.2.0

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 (131) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/COMPATIBILITY.md +13 -0
  3. package/KNOWN_LIMITATIONS.md +19 -0
  4. package/LICENSE +44 -0
  5. package/LICENSING.md +10 -0
  6. package/README.md +378 -210
  7. package/SECURITY.md +52 -0
  8. package/dist/index.d.ts +1477 -0
  9. package/dist/index.js +3464 -0
  10. package/dist/index.js.map +1 -0
  11. package/native/Cargo.lock +4863 -0
  12. package/native/Cargo.toml +73 -0
  13. package/native/crates/canonical/Cargo.toml +24 -0
  14. package/native/crates/canonical/src/lib.rs +673 -0
  15. package/native/crates/compression/Cargo.toml +20 -0
  16. package/native/crates/compression/benches/compression_bench.rs +42 -0
  17. package/native/crates/compression/src/lib.rs +393 -0
  18. package/native/crates/evm-eth/Cargo.toml +13 -0
  19. package/native/crates/evm-eth/src/lib.rs +105 -0
  20. package/native/crates/fee/Cargo.toml +15 -0
  21. package/native/crates/fee/src/lib.rs +281 -0
  22. package/native/crates/index/Cargo.toml +16 -0
  23. package/native/crates/index/src/lib.rs +277 -0
  24. package/native/crates/policy/Cargo.toml +17 -0
  25. package/native/crates/policy/src/lib.rs +614 -0
  26. package/native/crates/security/Cargo.toml +22 -0
  27. package/native/crates/security/src/lib.rs +478 -0
  28. package/native/crates/tokens/Cargo.toml +13 -0
  29. package/native/crates/tokens/src/lib.rs +534 -0
  30. package/native/crates/verification/Cargo.toml +23 -0
  31. package/native/crates/verification/src/lib.rs +333 -0
  32. package/native/crates/wallet/Cargo.toml +20 -0
  33. package/native/crates/wallet/src/lib.rs +261 -0
  34. package/native/crates/x402/Cargo.toml +30 -0
  35. package/native/crates/x402/src/lib.rs +423 -0
  36. package/native/ffi/Cargo.toml +34 -0
  37. package/native/ffi/build.rs +4 -0
  38. package/native/ffi/index.node +0 -0
  39. package/native/ffi/src/lib.rs +352 -0
  40. package/native/ffi/tests/integration.rs +354 -0
  41. package/native/pyo3/Cargo.toml +26 -0
  42. package/native/pyo3/pyproject.toml +16 -0
  43. package/native/pyo3/src/lib.rs +407 -0
  44. package/native/pyo3/tests/test_smoke.py +180 -0
  45. package/native/wasm/Cargo.toml +44 -0
  46. package/native/wasm/pkg/.gitignore +6 -0
  47. package/native/wasm/pkg/clawpowers_wasm.d.ts +208 -0
  48. package/native/wasm/pkg/clawpowers_wasm.js +872 -0
  49. package/native/wasm/pkg/clawpowers_wasm_bg.wasm +0 -0
  50. package/native/wasm/pkg/clawpowers_wasm_bg.wasm.d.ts +40 -0
  51. package/native/wasm/pkg/package.json +17 -0
  52. package/native/wasm/pkg-node/.gitignore +6 -0
  53. package/native/wasm/pkg-node/clawpowers_wasm.d.ts +143 -0
  54. package/native/wasm/pkg-node/clawpowers_wasm.js +798 -0
  55. package/native/wasm/pkg-node/clawpowers_wasm_bg.wasm +0 -0
  56. package/native/wasm/pkg-node/clawpowers_wasm_bg.wasm.d.ts +40 -0
  57. package/native/wasm/pkg-node/package.json +13 -0
  58. package/native/wasm/src/lib.rs +433 -0
  59. package/package.json +71 -44
  60. package/src/skills/catalog.ts +435 -0
  61. package/src/skills/executor.ts +56 -0
  62. package/src/skills/index.ts +3 -0
  63. package/src/skills/itp/SKILL.md +112 -0
  64. package/src/skills/loader.ts +193 -0
  65. package/.claude-plugin/manifest.json +0 -19
  66. package/.codex/INSTALL.md +0 -36
  67. package/.cursor-plugin/manifest.json +0 -21
  68. package/.opencode/INSTALL.md +0 -52
  69. package/ARCHITECTURE.md +0 -69
  70. package/bin/clawpowers.js +0 -625
  71. package/bin/clawpowers.sh +0 -91
  72. package/docs/demo/clawpowers-demo.cast +0 -197
  73. package/docs/demo/clawpowers-demo.gif +0 -0
  74. package/docs/launch-images/25-skills-breakdown.jpg +0 -0
  75. package/docs/launch-images/clawpowers-vs-superpowers.jpg +0 -0
  76. package/docs/launch-images/economic-code-optimization.jpg +0 -0
  77. package/docs/launch-images/native-vs-bridge-2.jpg +0 -0
  78. package/docs/launch-images/native-vs-bridge.jpg +0 -0
  79. package/docs/launch-images/post1-hero-lobster.jpg +0 -0
  80. package/docs/launch-images/post2-dashboard.jpg +0 -0
  81. package/docs/launch-images/post3-superpowers.jpg +0 -0
  82. package/docs/launch-images/post4-before-after.jpg +0 -0
  83. package/docs/launch-images/post5-install-now.jpg +0 -0
  84. package/docs/launch-images/ultimate-stack.jpg +0 -0
  85. package/docs/launch-posts.md +0 -76
  86. package/docs/quickstart-first-transaction.md +0 -204
  87. package/gemini-extension.json +0 -32
  88. package/hooks/session-start +0 -205
  89. package/hooks/session-start.cmd +0 -43
  90. package/hooks/session-start.js +0 -163
  91. package/runtime/demo/README.md +0 -78
  92. package/runtime/demo/x402-mock-server.js +0 -230
  93. package/runtime/feedback/analyze.js +0 -621
  94. package/runtime/feedback/analyze.sh +0 -546
  95. package/runtime/init.js +0 -210
  96. package/runtime/init.sh +0 -178
  97. package/runtime/metrics/collector.js +0 -361
  98. package/runtime/metrics/collector.sh +0 -308
  99. package/runtime/payments/ledger.js +0 -305
  100. package/runtime/payments/ledger.sh +0 -262
  101. package/runtime/payments/pipeline.js +0 -455
  102. package/runtime/persistence/store.js +0 -433
  103. package/runtime/persistence/store.sh +0 -303
  104. package/skill.json +0 -106
  105. package/skills/agent-bounties/SKILL.md +0 -553
  106. package/skills/agent-payments/SKILL.md +0 -479
  107. package/skills/brainstorming/SKILL.md +0 -233
  108. package/skills/content-pipeline/SKILL.md +0 -282
  109. package/skills/cross-project-knowledge/SKILL.md +0 -345
  110. package/skills/dispatching-parallel-agents/SKILL.md +0 -305
  111. package/skills/economic-code-optimization/SKILL.md +0 -265
  112. package/skills/executing-plans/SKILL.md +0 -255
  113. package/skills/finishing-a-development-branch/SKILL.md +0 -260
  114. package/skills/formal-verification-lite/SKILL.md +0 -441
  115. package/skills/learn-how-to-learn/SKILL.md +0 -235
  116. package/skills/market-intelligence/SKILL.md +0 -323
  117. package/skills/meta-skill-evolution/SKILL.md +0 -325
  118. package/skills/prospecting/SKILL.md +0 -454
  119. package/skills/receiving-code-review/SKILL.md +0 -225
  120. package/skills/requesting-code-review/SKILL.md +0 -206
  121. package/skills/security-audit/SKILL.md +0 -353
  122. package/skills/self-healing-code/SKILL.md +0 -369
  123. package/skills/subagent-driven-development/SKILL.md +0 -244
  124. package/skills/systematic-debugging/SKILL.md +0 -355
  125. package/skills/test-driven-development/SKILL.md +0 -416
  126. package/skills/using-clawpowers/SKILL.md +0 -160
  127. package/skills/using-git-worktrees/SKILL.md +0 -261
  128. package/skills/validator/SKILL.md +0 -281
  129. package/skills/verification-before-completion/SKILL.md +0 -254
  130. package/skills/writing-plans/SKILL.md +0 -276
  131. package/skills/writing-skills/SKILL.md +0 -260
@@ -1,355 +0,0 @@
1
- ---
2
- name: systematic-debugging
3
- description: Hypothesis-driven debugging with evidence collection. Activate when you encounter unexpected behavior, a failing test, or a bug report.
4
- version: 1.0.0
5
- requires:
6
- tools: [bash, git]
7
- runtime: false
8
- metrics:
9
- tracks: [hypotheses_tested, time_to_root_cause, false_positives, reopen_rate]
10
- improves: [hypothesis_quality, evidence_collection_speed, known_issue_match_rate]
11
- ---
12
-
13
- # Systematic Debugging
14
-
15
- ## When to Use
16
-
17
- Apply this skill when:
18
-
19
- - A test is failing and the cause isn't immediately obvious
20
- - A bug report describes behavior that shouldn't happen
21
- - Code that worked before suddenly doesn't
22
- - A production alert is firing
23
- - You've tried 2+ fixes without understanding why they work or don't
24
-
25
- **Skip when:**
26
- - The cause is obvious from the error message (typo, import missing, syntax error)
27
- - You've seen this exact error before and know the fix
28
- - It's a configuration issue, not a logic bug
29
-
30
- **Decision tree:**
31
- ```
32
- Is the error message self-explanatory?
33
- ├── Yes → fix it directly
34
- └── No → Have you seen this pattern before?
35
- ├── Yes → apply the known fix, verify, document
36
- └── No → systematic-debugging ← YOU ARE HERE
37
- ```
38
-
39
- ## Core Methodology
40
-
41
- ### Persistent Hypothesis Memory
42
-
43
- Before forming any new hypotheses, check if this error pattern has been seen before. Pattern-matching known bugs is 10-100x faster than fresh investigation.
44
-
45
- **Step 0: Check the hypothesis memory store**
46
-
47
- ```bash
48
- # Compute error signature hash from the error message + test name
49
- ERROR_MSG="ConnectionPool timeout after 50 requests"
50
- ERROR_SIG=$(echo "$ERROR_MSG" | md5)
51
-
52
- # Look up prior debugging sessions for this error pattern
53
- KNOWN=$(bash runtime/persistence/store.sh get "debug:hypothesis:$ERROR_SIG:winning" 2>/dev/null)
54
-
55
- if [[ -n "$KNOWN" ]]; then
56
- echo "=== Known error pattern found ==="
57
- echo "Previously solved. Winning hypothesis:"
58
- echo "$KNOWN"
59
- echo ""
60
- # Start directly with the previously successful hypothesis
61
- # Verify it applies to the current context before applying
62
- fi
63
- ```
64
-
65
- **Storage format** — every hypothesis tree is stored keyed by error signature:
66
-
67
- ```bash
68
- # After solving a bug, always persist the result
69
- ERROR_SIG=$(echo "$ERROR_MSG" | md5)
70
- RESOLVE_TIME=$(( END_TS - START_TS ))
71
-
72
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:error_msg" "$ERROR_MSG"
73
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:hypotheses_tried" "$H1|$H2|$H3"
74
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:winning" "$WINNING_HYPOTHESIS"
75
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:root_cause" "$ROOT_CAUSE"
76
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:fix_summary" "$FIX_SUMMARY"
77
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:time_to_resolution" "$RESOLVE_TIME"
78
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:project" "$(basename $(git rev-parse --show-toplevel))"
79
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:timestamp" "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
80
- ```
81
-
82
- **Fuzzy search for similar patterns** (when exact hash doesn't match):
83
-
84
- ```bash
85
- # Search by keyword across all stored hypotheses
86
- bash runtime/persistence/store.sh list "debug:hypothesis:*:error_msg" | while read key; do
87
- VALUE=$(bash runtime/persistence/store.sh get "$key")
88
- if echo "$VALUE" | grep -qi "connection\|pool\|timeout"; then
89
- SIG=$(echo "$key" | awk -F: '{print $3}')
90
- echo "=== Similar error ==="
91
- echo "Error: $VALUE"
92
- echo "Winning hypothesis: $(bash runtime/persistence/store.sh get "debug:hypothesis:$SIG:winning")"
93
- echo "Time to resolve: $(bash runtime/persistence/store.sh get "debug:hypothesis:$SIG:time_to_resolution")s"
94
- echo ""
95
- fi
96
- done
97
- ```
98
-
99
- **After 10+ debugging sessions, the memory pays dividends:**
100
-
101
- | Scenario | Without memory | With memory |
102
- |---------|---------------|-------------|
103
- | Same error exact match | 30-90 min investigation | < 2 min (known fix) |
104
- | Similar error pattern | 20-60 min | 5-10 min (start from best hypothesis) |
105
- | Novel error | Same as before | Same — no false acceleration |
106
-
107
- **When to override the memory:**
108
- - The error signature matches but the context differs (different library version, different project type)
109
- - The previously winning hypothesis was marked as "project-specific"
110
- - The fix was a workaround, not a root cause fix
111
-
112
- ```bash
113
- # Flag a fix as project-specific (won't suggest for other projects)
114
- bash runtime/persistence/store.sh set "debug:hypothesis:$ERROR_SIG:scope" "project-specific"
115
- ```
116
-
117
- ### The Scientific Debugging Loop
118
-
119
- ```
120
- Observe → Form hypothesis → Design experiment → Execute → Collect evidence → Conclude → Repeat
121
- ```
122
-
123
- Never skip steps. The most common debugging failure is jumping from "observe" directly to "try a fix" — which produces random mutations until something accidentally works, with no understanding of why.
124
-
125
- ### Step 1: Observation (Gather All Evidence First)
126
-
127
- Before forming any hypothesis, collect:
128
-
129
- **Required evidence:**
130
- - [ ] Exact error message (full stack trace, not a summary)
131
- - [ ] Steps to reproduce (minimal reproducible case)
132
- - [ ] What changed recently (git log since last known good)
133
- - [ ] Environment (OS, language version, dependency versions)
134
- - [ ] Frequency (always, intermittent, under specific conditions)
135
-
136
- **Observation template:**
137
- ```markdown
138
- ## Bug Observation
139
-
140
- **Error:** [Paste exact error/stack trace]
141
- **Reproduces:** [Always / Intermittent (N/M times) / Only when X]
142
- **Environment:** [OS, runtime version, key dependency versions]
143
- **Last known good:** [commit hash or date when this worked]
144
- **Recent changes:** [output of: git log --oneline --since="3 days ago"]
145
- **Minimal repro:**
146
- [Smallest possible code that triggers the error]
147
- ```
148
-
149
- **The minimal repro is not optional.** Debugging without a minimal repro is debugging the wrong problem. Strip everything until you have the smallest code that still fails.
150
-
151
- ### Step 2: Hypothesis Formation
152
-
153
- From the observation, generate 2-4 hypotheses. Rules:
154
-
155
- - Each hypothesis must be **specific** (names a cause, not a category)
156
- - Each hypothesis must be **falsifiable** (an experiment can prove it wrong)
157
- - Hypotheses must be **ranked by probability** (investigate most likely first)
158
-
159
- **Bad hypothesis:** "There might be an issue with the database"
160
- **Good hypothesis:** "The connection pool is exhausted because we're not releasing connections in the error path of `process_payment()`"
161
-
162
- **Hypothesis template:**
163
- ```markdown
164
- ## Hypothesis N: [Specific cause]
165
-
166
- **Mechanism:** [How this cause produces the observed symptom]
167
- **Probability:** [High/Medium/Low] because [reason]
168
- **Experiment:** [Specific test that proves or disproves this hypothesis]
169
- **Expected evidence if TRUE:** [What you'd see if this is the cause]
170
- **Expected evidence if FALSE:** [What you'd see if this is not the cause]
171
- ```
172
-
173
- ### Step 3: Experiments (Investigate, Don't Fix)
174
-
175
- **Critical rule:** Run experiments to gather evidence, not to fix the bug. The fix comes after you understand the cause.
176
-
177
- **Experiment types:**
178
-
179
- **Isolation:** Narrow the failure scope
180
- ```bash
181
- # Does it fail with a fresh database?
182
- docker run --rm -e POSTGRES_DB=test postgres:15
183
- python -m pytest tests/test_payment.py --db-url postgresql://localhost/test
184
-
185
- # Does it fail with a specific user only?
186
- python -m pytest tests/test_payment.py -k "user_123"
187
- ```
188
-
189
- **Binary search:** Git bisect for regressions
190
- ```bash
191
- git bisect start
192
- git bisect bad HEAD
193
- git bisect good v2.3.1 # last known good
194
- git bisect run python -m pytest tests/test_payment.py -x
195
- # Git finds the exact commit that introduced the bug
196
- ```
197
-
198
- **Logging:** Add targeted logging at the hypothesis boundary
199
- ```python
200
- # Don't add logging everywhere — add it exactly where the hypothesis predicts the failure
201
- import logging
202
- logger = logging.getLogger(__name__)
203
-
204
- def process_payment(payment_id: str):
205
- conn = get_db_connection()
206
- logger.debug(f"process_payment: got connection {id(conn)}, pool size: {pool.size()}")
207
- try:
208
- # ... payment logic
209
- return result
210
- except Exception as e:
211
- logger.error(f"process_payment FAILED: {e}, conn being released: {id(conn)}")
212
- # BUG: connection not released here → pool exhaustion
213
- raise # Fix: conn.close() before raise
214
- ```
215
-
216
- **State inspection:** Check system state at the failure point
217
- ```bash
218
- # Check connection pool state before/during/after
219
- psql -c "SELECT count(*), state FROM pg_stat_activity GROUP BY state;"
220
-
221
- # Check event queue depth
222
- redis-cli LLEN payment_queue
223
-
224
- # Check file descriptor usage
225
- lsof -p $(pgrep -f payment_service) | wc -l
226
- ```
227
-
228
- ### Step 4: Evidence Collection
229
-
230
- After each experiment, record what you found:
231
-
232
- ```markdown
233
- ## Evidence: Hypothesis N Test
234
-
235
- **Experiment run:** [command or action taken]
236
- **Result:** [what actually happened]
237
- **Conclusion:** [does this support or refute the hypothesis?]
238
- **Next step:** [if supported: deeper investigation | if refuted: next hypothesis]
239
- ```
240
-
241
- **Never interpret evidence to fit the hypothesis.** If the experiment contradicts the hypothesis, the hypothesis is wrong. Form a new one.
242
-
243
- ### Step 5: Root Cause Identification
244
-
245
- When an experiment strongly confirms a hypothesis:
246
-
247
- 1. State the root cause precisely: "The root cause is [mechanism], which occurs because [condition], resulting in [symptom]"
248
- 2. Trace back: Is this the root cause or a symptom of a deeper cause? Ask "why" 3-5 times.
249
- 3. Identify the fix that addresses the root cause, not just the symptom.
250
-
251
- **Root cause template:**
252
- ```markdown
253
- ## Root Cause
254
-
255
- **Statement:** [precise description of the cause]
256
- **Why it happens:** [condition that triggers it]
257
- **Why it wasn't caught:** [test gap, code review miss, etc.]
258
-
259
- **Fix:** [specific code change that addresses the root cause]
260
- **Regression test:** [test that would have caught this]
261
- **Prevention:** [process change to prevent this class of bug]
262
- ```
263
-
264
- ### Step 6: Fix and Verify
265
-
266
- 1. Apply the minimal fix (don't refactor while fixing — that's scope creep)
267
- 2. Verify the original reproduction case no longer fails
268
- 3. Verify the fix doesn't break other tests
269
- 4. Write the regression test
270
- 5. Commit fix and test together
271
-
272
- ## ClawPowers Enhancement
273
-
274
- When `~/.clawpowers/` runtime is initialized:
275
-
276
- **Persistent Hypothesis Tree:**
277
-
278
- The full investigation is saved and never lost between sessions:
279
-
280
- ```bash
281
- # Save investigation state
282
- bash runtime/persistence/store.sh set "debug:payment-pool-exhaustion:observation" "ConnectionPool timeout after 50 requests"
283
- bash runtime/persistence/store.sh set "debug:payment-pool-exhaustion:hypothesis1" "Connection not released in error path"
284
- bash runtime/persistence/store.sh set "debug:payment-pool-exhaustion:h1_result" "CONFIRMED: no conn.close() in except block"
285
- bash runtime/persistence/store.sh set "debug:payment-pool-exhaustion:root_cause" "Missing conn.close() in process_payment error path"
286
- bash runtime/persistence/store.sh set "debug:payment-pool-exhaustion:fix_commit" "a3f9b2c"
287
- ```
288
-
289
- If debugging spans multiple sessions, resume with:
290
- ```bash
291
- bash runtime/persistence/store.sh list "debug:payment-pool-exhaustion:*"
292
- ```
293
-
294
- **Known-Issue Pattern Matching:**
295
-
296
- Past root causes are searchable. Before forming hypotheses:
297
- ```bash
298
- bash runtime/persistence/store.sh list "debug:*:root_cause" | grep -i "connection"
299
- # → Found 2 prior connection-related bugs
300
- # → Shows fixes applied, saving re-investigation time
301
- ```
302
-
303
- **Debugging Metrics:**
304
-
305
- ```bash
306
- bash runtime/metrics/collector.sh record \
307
- --skill systematic-debugging \
308
- --outcome success \
309
- --duration 1800 \
310
- --notes "payment-pool: 3 hypotheses, 1 correct, git bisect narrowed to 1 commit"
311
- ```
312
-
313
- Tracks: time-to-root-cause, hypothesis accuracy rate, which experiment types are most effective.
314
-
315
- ## Anti-Patterns
316
-
317
- | Anti-Pattern | Why It Fails | Correct Approach |
318
- |-------------|-------------|-----------------|
319
- | "Try-and-see" debugging | Random mutations, no understanding | Form hypothesis before changing code |
320
- | Fixing without reproducing | Can't verify the fix worked | Minimal repro first, always |
321
- | Investigating without isolation | Debugging the wrong level | Binary search / isolate the scope first |
322
- | Multiple changes at once | Can't attribute which change fixed it | One change per experiment |
323
- | Interpreting evidence to fit hypothesis | Confirmation bias, wrong fix | Evidence disproves or confirms; update hypothesis |
324
- | Debugging by adding logs everywhere | Signal-to-noise ratio collapses | Targeted logging at hypothesis boundary only |
325
- | Not writing regression test | Same bug recurs | Regression test is non-optional |
326
- | Fixing symptoms, not root cause | Bug returns in a different form | Ask "why" 3-5 times to reach root cause |
327
-
328
- ## Examples
329
-
330
- ### Example 1: Intermittent Test Failure
331
-
332
- **Observation:** `test_concurrent_writes` fails 20% of the time with `AssertionError: expected 100 rows, got 97-99`
333
-
334
- **Hypothesis 1:** Race condition — concurrent writes arrive after the assertion reads
335
- - Experiment: Add sleep(0.1) before assertion
336
- - Result: Still fails
337
- - Conclusion: Not a timing issue
338
-
339
- **Hypothesis 2:** Lost update — concurrent transactions overwrite each other
340
- - Experiment: Add row-level locking to write path
341
- - Result: 0 failures in 100 runs
342
- - Conclusion: CONFIRMED — missing `SELECT FOR UPDATE` in the read-modify-write cycle
343
-
344
- **Root cause:** `update_counter()` reads then writes without a lock — concurrent execution loses updates.
345
-
346
- ### Example 2: Production Alert
347
-
348
- **Observation:** Memory usage grows 50MB/hour until OOM restart
349
-
350
- **Hypothesis 1:** Memory leak — objects not garbage collected
351
- - Experiment: `objgraph.most_common_types()` before and after request batches
352
- - Result: `WeakValueDictionary` count grows monotonically
353
- - Conclusion: CONFIRMED — cache holds strong refs despite `WeakValue` (values are themselves containers)
354
-
355
- **Root cause:** Cache stores lists as values, lists are containers that prevent GC of their contents.