@techninja/clearstack 0.3.16 → 0.3.19

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/docs/BUILD_LOG.md CHANGED
@@ -204,6 +204,14 @@ These are the significant corrections:
204
204
  - **Fix:** Cast params to `any` before accessing custom properties
205
205
  - **Documented in:** JSDOC_TYPING.md → `list` Connector Params
206
206
 
207
+ ### Array model prototype items persist as real data
208
+
209
+ - **Expected:** `items: [{ sku: '', quantity: 0 }]` only defines the schema
210
+ - **Actual:** The prototype item exists as a real entry in the array at runtime
211
+ - **Impact:** Cart showed a ghost item with empty sku and 0 quantity; Stripe rejected the 0-price line item
212
+ - **Fix:** Always filter array model data with `.filter(i => i.sku)` before use
213
+ - **Documented in:** STATE_AND_ROUTING.md → Store Array Properties
214
+
207
215
  ---
208
216
 
209
217
  ## Metrics
@@ -250,3 +258,102 @@ These are the significant corrections:
250
258
  5. **The spec improves through implementation.** 9 significant corrections were
251
259
  made to the spec based on what we learned building the proof. The spec is
252
260
  now more accurate than if it had been written in isolation.
261
+
262
+ ---
263
+
264
+ ## StatiCart: Second Project Validation
265
+
266
+ StatiCart is a full e-commerce platform built on Clearstack — the second
267
+ project built against the spec, validating that the patterns hold beyond
268
+ the original POC. Three phases (catalog, cart, polish) were completed in
269
+ a single LLM session.
270
+
271
+ ### Velocity
272
+
273
+ | Metric | Value |
274
+ | --- | --- |
275
+ | Phases completed | 3 of 8 |
276
+ | Components created | 7 (2 atoms, 2 molecules, 2 organisms, 0 templates) |
277
+ | Pages created | 5 (catalog, product-detail, cart, order-success, order-cancelled) |
278
+ | Store models | 2 (Product enumerable, CartState singleton) |
279
+ | Utilities | 4 (formatPrice, setPageMeta, productVariants, statusColors) |
280
+ | Tests | 41 (10 node, 31 browser) |
281
+ | Spec checks | 9/9 passing |
282
+ | Files over 150 lines | 0 (2 hit the limit, both split successfully) |
283
+
284
+ Three phases of a real app in one session. No blocked-on-framework moments.
285
+ Every blocker was a hybrids runtime behavior, not a Clearstack constraint.
286
+
287
+ ### What the 150-Line Limit Actually Did
288
+
289
+ The limit forced two splits during this build:
290
+
291
+ 1. `shared.css` hit 203 lines after adding page layout styles → split into
292
+ `pages.css`. Later `pages.css` hit 163 → split into `pages-cart.css`.
293
+ 2. `product-detail-view.js` hit 154 after adding the image gallery →
294
+ extracted `productVariants.js` utility.
295
+
296
+ Both splits improved the code. The page styles split by concern (catalog
297
+ vs cart) which made each file scannable. The utility extraction made
298
+ `effectivePrice`/`effectiveStock` reusable and independently testable.
299
+
300
+ Without the limit, these would have stayed as 300-line monoliths. The
301
+ LLM would have needed to re-read them on every edit, and the utility
302
+ functions would never have gotten their own test file.
303
+
304
+ ### What the Spec Documentation Prevented
305
+
306
+ The Clearstack spec docs prevented several classes of bugs entirely:
307
+
308
+ - **No `../` imports.** The import map alias rule (`#store/`, `#atoms/`)
309
+ was enforced from the first file. Zero refactoring of import paths.
310
+ - **`shadow: false` everywhere.** No time wasted on shadow DOM styling
311
+ issues. Global CSS just worked.
312
+ - **Named event handlers.** No "button doesn't work" debugging from
313
+ inline arrows in nested templates.
314
+ - **`store.connect.get` returns `{}`.** The localStorage pattern was
315
+ correct on first write for CartState.
316
+ - **Template functions over template components.** No host context bugs.
317
+
318
+ ### What the Spec Didn't Prevent (New Discoveries)
319
+
320
+ Five new hybrids gotchas were found and documented:
321
+
322
+ 1. **Empty arrays throw** — `items: []` needs a prototype item
323
+ 2. **`id` is reserved in nested models** — even inside array prototypes
324
+ 3. **Enumerable models need `@type {any}`** — tsc can't type `id: true`
325
+ 4. **List store descriptors need 3 casts** — descriptor, ready(), and map()
326
+ 5. **`list` connector params need cast** — `ModelIdentifier` not plain object
327
+ 6. **Array prototype items persist as real data** — the prototype item
328
+ used to define the array shape is included in the actual data
329
+
330
+ All six are hybrids type system friction, not architectural issues. The
331
+ runtime behavior is correct — it's the JSDoc/tsc layer that struggles.
332
+ Each was fixed in under 2 minutes once identified.
333
+
334
+ ### Test Runner Discovery
335
+
336
+ `@web/test-runner` doesn't support browser import maps. A custom
337
+ `resolveImport` plugin was needed to map `#prefix/` aliases to absolute
338
+ paths. This is now documented in TESTING.md with the full config pattern.
339
+
340
+ ### Framework Reuse Validation
341
+
342
+ The Clearstack scaffolder (`npm run spec update`) worked correctly for
343
+ doc syncing. The config overwrite issue (jsconfig.json, eslint.config.js)
344
+ was found and fixed upstream — `update` now skips existing configs unless
345
+ `--force` is passed. This validates the "dependency, not template" model.
346
+
347
+ ### Key Insight
348
+
349
+ The speed came from **not having to make architectural decisions**. The
350
+ spec answered every "where does this go" question before it was asked:
351
+ store models in `src/store/`, atoms vs molecules vs organisms, CSS in
352
+ per-component files registered in `components.css`, pages in `src/pages/`.
353
+ The LLM never had to ask "how should I structure this?" — it read the
354
+ spec and built.
355
+
356
+ This is the core value proposition: **Clearstack trades flexibility for
357
+ velocity.** A team (or LLM) that knows the spec can build without
358
+ discussion. The constraints aren't limitations — they're decisions that
359
+ have already been made.
@@ -197,6 +197,20 @@ function toggle(host) {
197
197
  }
198
198
  ```
199
199
 
200
+ ```javascript
201
+ // BAD — silent catch hides the failure completely
202
+ try {
203
+ store.clear([Model]);
204
+ } catch {
205
+ /* list may not exist */
206
+ }
207
+ ```
208
+
209
+ **Never use empty `catch` blocks.** If you catch to prevent crashing,
210
+ you must `console.warn` or `console.error` so the failure is visible.
211
+ Silent catches turn bugs into ghosts — things "just don't work" with
212
+ zero console output to trace.
213
+
200
214
  ### ✅ Do
201
215
 
202
216
  ```javascript
@@ -215,6 +229,15 @@ function toggle(host) {
215
229
  }
216
230
  ```
217
231
 
232
+ ```javascript
233
+ // GOOD — catch to prevent crash, but log so failures are visible
234
+ try {
235
+ store.clear([Model]);
236
+ } catch (e) {
237
+ console.warn('[store] clear failed:', e.message);
238
+ }
239
+ ```
240
+
218
241
  ---
219
242
 
220
243
  ### ✅ Always Do This
@@ -251,10 +274,24 @@ export const fullName = (user) => `${user.firstName} ${user.lastName}`;
251
274
 
252
275
  ---
253
276
 
254
- ## File Size: Soft Warnings Before Hard Limits
277
+ ## File Size: Why 150 Lines
278
+
279
+ The 150-line limit isn't about the number — it's about **context cost**.
280
+ A 400-line file isn't hard to scroll through, but it's expensive to
281
+ _hold in mind_. Humans can only reason about a limited scope at once.
282
+ LLMs face the same constraint differently: every token spent reading a
283
+ bloated file is a token not spent on the actual task. Small files mean
284
+ context is spent on _building_, not on _understanding what you're
285
+ looking at_.
286
+
287
+ When every file is small enough to comprehend in one pass, both humans
288
+ and LLMs can generate, review, and modify code without re-reading
289
+ unrelated sections. Refactors become safe because the blast radius of
290
+ any change is one small file. The limit forces decomposition into
291
+ concept-sized units — not arbitrary chunks, but files where each one
292
+ answers a single question.
255
293
 
256
- The 150-line limit is a hard gate in CI, but treat **~120 lines as a yellow
257
- light.** When a file passes 120 lines:
294
+ Treat **~120 lines as a yellow light.** When a file passes 120 lines:
258
295
 
259
296
  1. Add a `// SPLIT CANDIDATE:` comment noting where a logical split could happen
260
297
  2. Continue working — don't split mid-feature
@@ -270,7 +307,9 @@ function moveObj(o, dx, dy) { ... }
270
307
  ### When a File Exceeds 150 Lines
271
308
 
272
309
  The **only correct response** is to split the file into two or more files.
273
- Never do any of the following to reduce line count:
310
+ The concepts have outgrown the container find the seam between them
311
+ and give each its own file. Never do any of the following to reduce
312
+ line count:
274
313
 
275
314
  - Remove or shorten JSDoc comments
276
315
  - Collapse multi-line expressions onto one line
@@ -370,7 +409,8 @@ npm run spec all
370
409
  npm run spec code # line counts (code files ≤150)
371
410
  npm run spec docs # line counts (doc files ≤500)
372
411
  npm run spec imports # import map aliases (no ../)
373
- npm run spec types # JSDoc types (tsc --checkJs)
412
+ npm run spec types # all jsconfigs (auto-discovered)
413
+ npm run spec types frontend # just .configs/jsconfig.json
374
414
  npm run spec audit # security audit
375
415
 
376
416
  # Parent keys run all children
@@ -13,8 +13,8 @@
13
13
  TypeScript's `tsc` compiler validates JSDoc annotations via `--checkJs`,
14
14
  giving us compile-time type checking without a build step.
15
15
 
16
- A `jsconfig.json` at the project root enables `checkJs: true`. Running
17
- `npm run typecheck` invokes `tsc --project jsconfig.json` which:
16
+ A `jsconfig.json` at `.configs/jsconfig.json` enables `checkJs: true` for
17
+ frontend code. Running `npm run spec types` invokes `tsc` against it.
18
18
 
19
19
  1. Reads all `.js` files in `src/` and `scripts/`
20
20
  2. Parses JSDoc annotations as type information
@@ -24,6 +24,27 @@ A `jsconfig.json` at the project root enables `checkJs: true`. Running
24
24
  This means `@typedef`, `@type`, `@param`, and `@returns` are not just
25
25
  documentation — they are **enforced types**.
26
26
 
27
+ ### Multiple Type Configs
28
+
29
+ The spec checker auto-discovers `jsconfig.json` files in subdirectories.
30
+ If your project has a separate backend (e.g. `api/`) with its own
31
+ dependencies and module resolution, add `api/jsconfig.json`:
32
+
33
+ ```
34
+ your-project/
35
+ ├── .configs/jsconfig.json ← frontend (src/, scripts/)
36
+ └── api/jsconfig.json ← backend (api/, auto-discovered)
37
+ ```
38
+
39
+ ```bash
40
+ npm run spec types # runs all discovered jsconfigs
41
+ npm run spec types frontend # just .configs/jsconfig.json
42
+ npm run spec types api # just api/jsconfig.json
43
+ ```
44
+
45
+ The child key matches the directory name. Both must pass for
46
+ `npm run spec all` to succeed.
47
+
27
48
  ---
28
49
 
29
50
  ## Component Properties
@@ -151,4 +172,4 @@ list: async (params) => {
151
172
  - Keep JSDoc blocks to 3–5 lines. No novels.
152
173
  - Use `/** @type {any} */ (expr)` for framework type limitations (e.g.
153
174
  `store.pending()` on array results) — document why with a comment.
154
- - Run `npm run typecheck` before committing. Zero errors required.
175
+ - Run `npm run spec types` before committing. Zero errors required.