spawnpack 0.1.12 → 0.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawnpack",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "Minecraft Bedrock addon project generator — scaffold your BP+RP in seconds",
5
5
  "author": "veedy-dev",
6
6
  "license": "MIT",
@@ -36,11 +36,34 @@ The governing loop for all work: **gather context → take action → verify wor
36
36
  VIOLATION CHECK: If you wrote library/framework code from memory without searching Exa first, you violated this rule.
37
37
  </rule>
38
38
 
39
- <rule name="no_comments" priority="high">
40
- DO NOT WRITE ANY COMMENTS OR JSDOCS unless explicitly requested.
41
- </rule>
42
-
43
- <rule name="forced_verification" priority="critical">
39
+ <rule name="no_comments" priority="high">
40
+ DO NOT WRITE ANY COMMENTS OR JSDOCS unless explicitly requested.
41
+ </rule>
42
+
43
+ <rule name="guard_before_try_catch" priority="critical">
44
+ **Default:** Do not add `try-catch` around normal synchronous application code or Minecraft Script API calls. Validate known preconditions with guard clauses, then call the API directly.
45
+
46
+ Before writing any `try-catch`, ALL of these must be true:
47
+ 1. A specific operation has a documented, observed, or otherwise evidenced exception that available guards cannot prevent. "It might throw" is not evidence.
48
+ 2. The `catch` performs necessary recovery, cleanup, boundary translation, or adds useful context before rethrowing.
49
+ 3. The `try` block is the narrowest possible scope—normally one genuinely fallible operation.
50
+
51
+ **Forbidden:**
52
+ - Speculative `try-catch` added "for safety" without evidence of an unavoidable exception.
53
+ - Empty `catch` blocks or catches whose only action is `return`, `continue`, or silently ignore the failure.
54
+ - Wrapping an entire event handler, tick callback, gameplay function, loop body, or multi-step state transition.
55
+ - Using exceptions to detect missing values, invalid entities, optional components, permissions, unloaded blocks, or other checkable state.
56
+ - Catching programmer errors such as bad assumptions, incorrect types, invalid property access, or broken invariants merely to keep execution going.
57
+ - Repeated or nested `try-catch` in per-tick or hot gameplay paths when a guard can prevent the failure.
58
+
59
+ A dormant `try` block is generally not the main performance problem; thrown exceptions are expensive, especially in hot paths. The primary reasons to avoid unnecessary catches are that they hide defects, duplicate cleanup, obscure control flow, and turn exceptions into normal branching.
60
+
61
+ Before reporting completion, search every changed file for `try` and `catch`. For each new or modified catch, identify the specific unguardable failure and the concrete recovery it performs. If you cannot do both, remove the `try-catch` and use guards or direct code instead.
62
+
63
+ VIOLATION CHECK: If a catch was added without an evidenced unguardable exception and meaningful recovery, this rule was violated.
64
+ </rule>
65
+
66
+ <rule name="forced_verification" priority="critical">
44
67
  Your internal tools mark file writes as successful if bytes hit disk. They do not check if the code compiles. You are FORBIDDEN from reporting a task as complete until you have:
45
68
  - Run the project's type-checker / compiler in strict mode (`tsc --noEmit` for TypeScript)
46
69
  - Run all configured linters
@@ -251,32 +274,40 @@ When working in a Regolith project and you need to inspect compilation output, c
251
274
  </guideline>
252
275
 
253
276
  <guideline name="guard_first_error_handling" priority="critical">
254
- Prefer **guard clauses** for predictable invalid state: missing values, unloaded or invalid entities, optional components, permissions, and known preconditions. `throw`, `try`, and `catch` are allowed when they are truly necessary: APIs can fail despite correct guards, you are crossing IO/persistence/parsing/async boundaries, or you need cleanup, recovery, or clearer error context.
277
+ Use **guard clauses** for every predictable invalid state: missing values, unloaded or invalid entities, optional components, permissions, and known preconditions. Once guards pass, call normal Script API methods directly. Do not wrap calls merely because an API could theoretically throw.
278
+
279
+ Use `try-catch` only at a proven failure boundary—such as parsing untrusted data, IO/persistence, cleanup that must run after failure, or a documented/observed API exception with no available precondition check. Keep the `try` block around only the fallible operation. Catching an error requires a deliberate recovery action; silent continuation is not recovery.
255
280
 
256
- Keep `catch` blocks narrow and purposeful. Do not use `try-catch` as normal control flow, to hide mistakes, or where a simple guard makes the failure impossible.
281
+ Decision test before adding `try-catch`:
282
+ 1. Can a value, validity flag, component, permission, or other precondition be checked first? Use a guard and do not catch.
283
+ 2. Is the exception merely hypothetical, with no documentation or observed stack trace? Do not catch.
284
+ 3. Can this scope recover, clean up, translate the boundary error, or rethrow with useful context? If not, let the error remain visible.
285
+ 4. Is the `try` block larger than the single fallible operation? Narrow it.
257
286
 
258
287
  ```typescript
259
288
  // ✅ CORRECT: Use guard clauses
260
- function processBlock(block: Block | undefined): void {
261
- if (!block) return;
262
- if (!block.isValid) return;
263
- const permutation = block.permutation;
289
+ function updatePlayerRotation(player: Player | undefined, rotation: Vector2): void {
290
+ if (!player?.isValid) return;
291
+ player.setRotation(rotation);
264
292
  }
265
293
 
266
294
  // ✅ CORRECT: Use try-catch only at a real failure boundary
267
- function loadSavedConfig(rawConfig: string): AddonConfig {
295
+ function loadSavedConfig(rawConfig: string): AddonConfig | undefined {
268
296
  try {
269
297
  return JSON.parse(rawConfig) as AddonConfig;
270
298
  } catch (error) {
271
- throw new Error("Saved addon config is not valid JSON", { cause: error });
299
+ console.warn("Saved addon config is not valid JSON", error);
300
+ return undefined;
272
301
  }
273
302
  }
274
303
 
275
- // ❌ WRONG: Catching instead of checking known state
276
- function processBlockBad(block: Block | undefined): void {
304
+ // ❌ WRONG: Speculative catches around normal API calls
305
+ function refreshPlayerRotationBad(player: Player): void {
277
306
  try {
278
- const permutation = block!.permutation;
307
+ const requestedRotation = player.getRotation();
308
+ player.setRotation(requestedRotation);
279
309
  } catch {
310
+ return;
280
311
  }
281
312
  }
282
313
  ```
@@ -36,11 +36,34 @@ The governing loop for all work: **gather context → take action → verify wor
36
36
  VIOLATION CHECK: If you wrote library/framework code from memory without searching Exa first, you violated this rule.
37
37
  </rule>
38
38
 
39
- <rule name="no_comments" priority="high">
40
- DO NOT WRITE ANY COMMENTS OR JSDOCS unless explicitly requested.
41
- </rule>
42
-
43
- <rule name="forced_verification" priority="critical">
39
+ <rule name="no_comments" priority="high">
40
+ DO NOT WRITE ANY COMMENTS OR JSDOCS unless explicitly requested.
41
+ </rule>
42
+
43
+ <rule name="guard_before_try_catch" priority="critical">
44
+ **Default:** Do not add `try-catch` around normal synchronous application code or Minecraft Script API calls. Validate known preconditions with guard clauses, then call the API directly.
45
+
46
+ Before writing any `try-catch`, ALL of these must be true:
47
+ 1. A specific operation has a documented, observed, or otherwise evidenced exception that available guards cannot prevent. "It might throw" is not evidence.
48
+ 2. The `catch` performs necessary recovery, cleanup, boundary translation, or adds useful context before rethrowing.
49
+ 3. The `try` block is the narrowest possible scope—normally one genuinely fallible operation.
50
+
51
+ **Forbidden:**
52
+ - Speculative `try-catch` added "for safety" without evidence of an unavoidable exception.
53
+ - Empty `catch` blocks or catches whose only action is `return`, `continue`, or silently ignore the failure.
54
+ - Wrapping an entire event handler, tick callback, gameplay function, loop body, or multi-step state transition.
55
+ - Using exceptions to detect missing values, invalid entities, optional components, permissions, unloaded blocks, or other checkable state.
56
+ - Catching programmer errors such as bad assumptions, incorrect types, invalid property access, or broken invariants merely to keep execution going.
57
+ - Repeated or nested `try-catch` in per-tick or hot gameplay paths when a guard can prevent the failure.
58
+
59
+ A dormant `try` block is generally not the main performance problem; thrown exceptions are expensive, especially in hot paths. The primary reasons to avoid unnecessary catches are that they hide defects, duplicate cleanup, obscure control flow, and turn exceptions into normal branching.
60
+
61
+ Before reporting completion, search every changed file for `try` and `catch`. For each new or modified catch, identify the specific unguardable failure and the concrete recovery it performs. If you cannot do both, remove the `try-catch` and use guards or direct code instead.
62
+
63
+ VIOLATION CHECK: If a catch was added without an evidenced unguardable exception and meaningful recovery, this rule was violated.
64
+ </rule>
65
+
66
+ <rule name="forced_verification" priority="critical">
44
67
  Your internal tools mark file writes as successful if bytes hit disk. They do not check if the code compiles. You are FORBIDDEN from reporting a task as complete until you have:
45
68
  - Run the project's type-checker / compiler in strict mode (`tsc --noEmit` for TypeScript)
46
69
  - Run all configured linters
@@ -251,32 +274,40 @@ When working in a Regolith project and you need to inspect compilation output, c
251
274
  </guideline>
252
275
 
253
276
  <guideline name="guard_first_error_handling" priority="critical">
254
- Prefer **guard clauses** for predictable invalid state: missing values, unloaded or invalid entities, optional components, permissions, and known preconditions. `throw`, `try`, and `catch` are allowed when they are truly necessary: APIs can fail despite correct guards, you are crossing IO/persistence/parsing/async boundaries, or you need cleanup, recovery, or clearer error context.
277
+ Use **guard clauses** for every predictable invalid state: missing values, unloaded or invalid entities, optional components, permissions, and known preconditions. Once guards pass, call normal Script API methods directly. Do not wrap calls merely because an API could theoretically throw.
278
+
279
+ Use `try-catch` only at a proven failure boundary—such as parsing untrusted data, IO/persistence, cleanup that must run after failure, or a documented/observed API exception with no available precondition check. Keep the `try` block around only the fallible operation. Catching an error requires a deliberate recovery action; silent continuation is not recovery.
255
280
 
256
- Keep `catch` blocks narrow and purposeful. Do not use `try-catch` as normal control flow, to hide mistakes, or where a simple guard makes the failure impossible.
281
+ Decision test before adding `try-catch`:
282
+ 1. Can a value, validity flag, component, permission, or other precondition be checked first? Use a guard and do not catch.
283
+ 2. Is the exception merely hypothetical, with no documentation or observed stack trace? Do not catch.
284
+ 3. Can this scope recover, clean up, translate the boundary error, or rethrow with useful context? If not, let the error remain visible.
285
+ 4. Is the `try` block larger than the single fallible operation? Narrow it.
257
286
 
258
287
  ```typescript
259
288
  // ✅ CORRECT: Use guard clauses
260
- function processBlock(block: Block | undefined): void {
261
- if (!block) return;
262
- if (!block.isValid) return;
263
- const permutation = block.permutation;
289
+ function updatePlayerRotation(player: Player | undefined, rotation: Vector2): void {
290
+ if (!player?.isValid) return;
291
+ player.setRotation(rotation);
264
292
  }
265
293
 
266
294
  // ✅ CORRECT: Use try-catch only at a real failure boundary
267
- function loadSavedConfig(rawConfig: string): AddonConfig {
295
+ function loadSavedConfig(rawConfig: string): AddonConfig | undefined {
268
296
  try {
269
297
  return JSON.parse(rawConfig) as AddonConfig;
270
298
  } catch (error) {
271
- throw new Error("Saved addon config is not valid JSON", { cause: error });
299
+ console.warn("Saved addon config is not valid JSON", error);
300
+ return undefined;
272
301
  }
273
302
  }
274
303
 
275
- // ❌ WRONG: Catching instead of checking known state
276
- function processBlockBad(block: Block | undefined): void {
304
+ // ❌ WRONG: Speculative catches around normal API calls
305
+ function refreshPlayerRotationBad(player: Player): void {
277
306
  try {
278
- const permutation = block!.permutation;
307
+ const requestedRotation = player.getRotation();
308
+ player.setRotation(requestedRotation);
279
309
  } catch {
310
+ return;
280
311
  }
281
312
  }
282
313
  ```