spawnpack 0.1.11 → 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.11",
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
@@ -242,37 +265,49 @@ PLAN:
242
265
  <domain_context name="minecraft_bedrock">
243
266
  **Context**: Minecraft Bedrock Add-On Development (BP/RP JSONs, Script API).
244
267
 
245
- <guideline name="research_first" priority="critical">
246
- ALWAYS use Exa to search the latest Minecraft Script API documentation before implementing. APIs change every major update — never trust memory.
247
- </guideline>
248
-
268
+ <guideline name="research_first" priority="critical">
269
+ ALWAYS use Exa to search the latest Minecraft Script API documentation before implementing. APIs change every major update — never trust memory.
270
+ </guideline>
271
+
272
+ <guideline name="regolith_compilation_output" priority="high">
273
+ When working in a Regolith project and you need to inspect compilation output, check `.regolith/tmp` instead of the output paths printed by Regolith. Entries inside `.regolith/tmp` may be symlinks; read them through those paths without canonicalizing or resolving them so you do not trigger unnecessary permission requests.
274
+ </guideline>
275
+
249
276
  <guideline name="guard_first_error_handling" priority="critical">
250
- 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.
251
280
 
252
- 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.
253
286
 
254
287
  ```typescript
255
288
  // ✅ CORRECT: Use guard clauses
256
- function processBlock(block: Block | undefined): void {
257
- if (!block) return;
258
- if (!block.isValid) return;
259
- const permutation = block.permutation;
289
+ function updatePlayerRotation(player: Player | undefined, rotation: Vector2): void {
290
+ if (!player?.isValid) return;
291
+ player.setRotation(rotation);
260
292
  }
261
293
 
262
294
  // ✅ CORRECT: Use try-catch only at a real failure boundary
263
- function loadSavedConfig(rawConfig: string): AddonConfig {
295
+ function loadSavedConfig(rawConfig: string): AddonConfig | undefined {
264
296
  try {
265
297
  return JSON.parse(rawConfig) as AddonConfig;
266
298
  } catch (error) {
267
- 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;
268
301
  }
269
302
  }
270
303
 
271
- // ❌ WRONG: Catching instead of checking known state
272
- function processBlockBad(block: Block | undefined): void {
304
+ // ❌ WRONG: Speculative catches around normal API calls
305
+ function refreshPlayerRotationBad(player: Player): void {
273
306
  try {
274
- const permutation = block!.permutation;
307
+ const requestedRotation = player.getRotation();
308
+ player.setRotation(requestedRotation);
275
309
  } catch {
310
+ return;
276
311
  }
277
312
  }
278
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
@@ -242,37 +265,49 @@ PLAN:
242
265
  <domain_context name="minecraft_bedrock">
243
266
  **Context**: Minecraft Bedrock Add-On Development (BP/RP JSONs, Script API).
244
267
 
245
- <guideline name="research_first" priority="critical">
246
- ALWAYS use Exa to search the latest Minecraft Script API documentation before implementing. APIs change every major update — never trust memory.
247
- </guideline>
248
-
268
+ <guideline name="research_first" priority="critical">
269
+ ALWAYS use Exa to search the latest Minecraft Script API documentation before implementing. APIs change every major update — never trust memory.
270
+ </guideline>
271
+
272
+ <guideline name="regolith_compilation_output" priority="high">
273
+ When working in a Regolith project and you need to inspect compilation output, check `.regolith/tmp` instead of the output paths printed by Regolith. Entries inside `.regolith/tmp` may be symlinks; read them through those paths without canonicalizing or resolving them so you do not trigger unnecessary permission requests.
274
+ </guideline>
275
+
249
276
  <guideline name="guard_first_error_handling" priority="critical">
250
- 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.
251
280
 
252
- 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.
253
286
 
254
287
  ```typescript
255
288
  // ✅ CORRECT: Use guard clauses
256
- function processBlock(block: Block | undefined): void {
257
- if (!block) return;
258
- if (!block.isValid) return;
259
- const permutation = block.permutation;
289
+ function updatePlayerRotation(player: Player | undefined, rotation: Vector2): void {
290
+ if (!player?.isValid) return;
291
+ player.setRotation(rotation);
260
292
  }
261
293
 
262
294
  // ✅ CORRECT: Use try-catch only at a real failure boundary
263
- function loadSavedConfig(rawConfig: string): AddonConfig {
295
+ function loadSavedConfig(rawConfig: string): AddonConfig | undefined {
264
296
  try {
265
297
  return JSON.parse(rawConfig) as AddonConfig;
266
298
  } catch (error) {
267
- 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;
268
301
  }
269
302
  }
270
303
 
271
- // ❌ WRONG: Catching instead of checking known state
272
- function processBlockBad(block: Block | undefined): void {
304
+ // ❌ WRONG: Speculative catches around normal API calls
305
+ function refreshPlayerRotationBad(player: Player): void {
273
306
  try {
274
- const permutation = block!.permutation;
307
+ const requestedRotation = player.getRotation();
308
+ player.setRotation(requestedRotation);
275
309
  } catch {
310
+ return;
276
311
  }
277
312
  }
278
313
  ```