@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 +107 -0
- package/docs/CONVENTIONS.md +45 -5
- package/docs/JSDOC_TYPING.md +24 -3
- package/docs/PLATFORM_STACKING.md +486 -0
- package/docs/QUICKSTART.md +2 -2
- package/docs/STATE_AND_ROUTING.md +54 -49
- package/docs/TESTING.md +52 -19
- package/lib/check.js +26 -50
- package/lib/init.js +5 -0
- package/lib/platform-files.js +113 -0
- package/lib/platform.js +52 -0
- package/lib/spec-config.js +55 -0
- package/lib/spec-utils.js +5 -2
- package/lib/update.js +8 -0
- package/package.json +1 -1
- package/templates/fullstack/src/store/realtimeSync.js +4 -4
- package/templates/shared/.configs/eslint.config.js +1 -0
- package/templates/shared/.configs/web-test-runner.config.js +28 -1
- package/templates/shared/docs/clearstack/CONVENTIONS.md +45 -5
- package/templates/shared/docs/clearstack/JSDOC_TYPING.md +24 -3
- package/templates/shared/docs/clearstack/QUICKSTART.md +2 -2
- package/templates/shared/docs/clearstack/STATE_AND_ROUTING.md +54 -49
- package/templates/shared/docs/clearstack/TESTING.md +52 -19
- package/templates/shared/docs/clearstack/BUILD_LOG.md +0 -252
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.
|
package/docs/CONVENTIONS.md
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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
|
-
|
|
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 #
|
|
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
|
package/docs/JSDOC_TYPING.md
CHANGED
|
@@ -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
|
|
17
|
-
`npm run
|
|
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
|
|
175
|
+
- Run `npm run spec types` before committing. Zero errors required.
|