snice 7.0.2 → 7.1.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 (304) hide show
  1. package/.agents/skills/snice/SKILL.md +4 -0
  2. package/.agents/skills/snice/references/core-kitchen-sink.ts +39 -1
  3. package/README.md +59 -14
  4. package/adapters/react/SniceProvider.js +2 -2
  5. package/adapters/react/SniceRouter.js +2 -2
  6. package/adapters/react/matchRoute.js +2 -2
  7. package/adapters/react/useRequestHandler.js +2 -2
  8. package/bin/analyzer-contracts.js +6 -1
  9. package/bin/postinstall.js +59 -0
  10. package/bin/project-analyzer.js +466 -5
  11. package/bin/snice.js +3 -0
  12. package/dist/app-context.d.ts +11 -0
  13. package/dist/cdn/accordion/snice-accordion.js +2 -2
  14. package/dist/cdn/action-bar/snice-action-bar.js +2 -2
  15. package/dist/cdn/activity-feed/snice-activity-feed.js +2 -2
  16. package/dist/cdn/alert/snice-alert.js +2 -2
  17. package/dist/cdn/app-tiles/snice-app-tiles.js +2 -2
  18. package/dist/cdn/approval-flow/snice-approval-flow.js +2 -2
  19. package/dist/cdn/audio-recorder/snice-audio-recorder.js +2 -2
  20. package/dist/cdn/availability/snice-availability.js +2 -2
  21. package/dist/cdn/avatar/snice-avatar.js +2 -2
  22. package/dist/cdn/avatar-group/snice-avatar-group.js +2 -2
  23. package/dist/cdn/badge/snice-badge.js +2 -2
  24. package/dist/cdn/banner/snice-banner.js +2 -2
  25. package/dist/cdn/binpack/snice-binpack.js +2 -2
  26. package/dist/cdn/book/snice-book.js +2 -2
  27. package/dist/cdn/booking/snice-booking.js +2 -2
  28. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +2 -2
  29. package/dist/cdn/button/snice-button.js +2 -2
  30. package/dist/cdn/calendar/snice-calendar.js +2 -2
  31. package/dist/cdn/camera/snice-camera.js +2 -2
  32. package/dist/cdn/camera-annotate/snice-camera-annotate.js +2 -2
  33. package/dist/cdn/candlestick/snice-candlestick.js +2 -2
  34. package/dist/cdn/card/snice-card.js +2 -2
  35. package/dist/cdn/carousel/snice-carousel.js +2 -2
  36. package/dist/cdn/cart/snice-cart.js +2 -2
  37. package/dist/cdn/chart/snice-chart.js +2 -2
  38. package/dist/cdn/chat/snice-chat.js +2 -2
  39. package/dist/cdn/checkbox/snice-checkbox.js +2 -2
  40. package/dist/cdn/chip/snice-chip.js +2 -2
  41. package/dist/cdn/code-block/snice-code-block.js +2 -2
  42. package/dist/cdn/color-display/snice-color-display.js +2 -2
  43. package/dist/cdn/color-picker/snice-color-picker.js +2 -2
  44. package/dist/cdn/command-palette/snice-command-palette.js +2 -2
  45. package/dist/cdn/comments/snice-comments.js +2 -2
  46. package/dist/cdn/countdown/snice-countdown.js +2 -2
  47. package/dist/cdn/cropper/snice-cropper.js +2 -2
  48. package/dist/cdn/data-card/snice-data-card.js +2 -2
  49. package/dist/cdn/date-picker/snice-date-picker.js +2 -2
  50. package/dist/cdn/date-range-picker/snice-date-range-picker.js +2 -2
  51. package/dist/cdn/date-time-picker/snice-date-time-picker.js +2 -2
  52. package/dist/cdn/diff/snice-diff.js +2 -2
  53. package/dist/cdn/divider/snice-divider.js +2 -2
  54. package/dist/cdn/doc/snice-doc.js +2 -2
  55. package/dist/cdn/draw/snice-draw.js +2 -2
  56. package/dist/cdn/drawer/snice-drawer.js +2 -2
  57. package/dist/cdn/empty-state/snice-empty-state.js +2 -2
  58. package/dist/cdn/estimate/snice-estimate.js +2 -2
  59. package/dist/cdn/file-gallery/snice-file-gallery.js +2 -2
  60. package/dist/cdn/file-upload/snice-file-upload.js +2 -2
  61. package/dist/cdn/flip-card/snice-flip-card.js +2 -2
  62. package/dist/cdn/flow/snice-flow.js +2 -2
  63. package/dist/cdn/form-layout/snice-form-layout.js +2 -2
  64. package/dist/cdn/funnel/snice-funnel.js +2 -2
  65. package/dist/cdn/gantt/snice-gantt.js +2 -2
  66. package/dist/cdn/gauge/snice-gauge.js +2 -2
  67. package/dist/cdn/grid/snice-grid.js +2 -2
  68. package/dist/cdn/heatmap/snice-heatmap.js +2 -2
  69. package/dist/cdn/image/snice-image.js +2 -2
  70. package/dist/cdn/input/snice-input.js +2 -2
  71. package/dist/cdn/invoice/snice-invoice.js +2 -2
  72. package/dist/cdn/kanban/snice-kanban.js +2 -2
  73. package/dist/cdn/key-value/snice-key-value.js +2 -2
  74. package/dist/cdn/kpi/snice-kpi.js +2 -2
  75. package/dist/cdn/layout/README.md +17 -2
  76. package/dist/cdn/layout/snice-layout.js +1656 -11
  77. package/dist/cdn/layout/snice-layout.js.map +1 -1
  78. package/dist/cdn/layout/snice-layout.min.js +379 -2
  79. package/dist/cdn/layout/snice-layout.min.js.map +1 -1
  80. package/dist/cdn/leaderboard/snice-leaderboard.js +2 -2
  81. package/dist/cdn/link/snice-link.js +2 -2
  82. package/dist/cdn/link-preview/snice-link-preview.js +2 -2
  83. package/dist/cdn/list/snice-list.js +2 -2
  84. package/dist/cdn/location/snice-location.js +2 -2
  85. package/dist/cdn/login/snice-login.js +2 -2
  86. package/dist/cdn/map/snice-map.js +2 -2
  87. package/dist/cdn/markdown/snice-markdown.js +2 -2
  88. package/dist/cdn/masonry/snice-masonry.js +2 -2
  89. package/dist/cdn/menu/snice-menu.js +2 -2
  90. package/dist/cdn/message-strip/snice-message-strip.js +2 -2
  91. package/dist/cdn/modal/snice-modal.js +2 -2
  92. package/dist/cdn/music-player/snice-music-player.js +2 -2
  93. package/dist/cdn/nav/snice-nav.js +2 -2
  94. package/dist/cdn/network-graph/snice-network-graph.js +2 -2
  95. package/dist/cdn/notification-center/snice-notification-center.js +2 -2
  96. package/dist/cdn/order-tracker/snice-order-tracker.js +2 -2
  97. package/dist/cdn/org-chart/snice-org-chart.js +2 -2
  98. package/dist/cdn/pagination/snice-pagination.js +2 -2
  99. package/dist/cdn/paint/snice-paint.js +2 -2
  100. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +2 -2
  101. package/dist/cdn/permission-matrix/snice-permission-matrix.js +2 -2
  102. package/dist/cdn/podcast-player/snice-podcast-player.js +2 -2
  103. package/dist/cdn/popover/snice-popover.js +2 -2
  104. package/dist/cdn/pricing-table/snice-pricing-table.js +2 -2
  105. package/dist/cdn/product-card/snice-product-card.js +2 -2
  106. package/dist/cdn/progress/snice-progress.js +2 -2
  107. package/dist/cdn/progress-ring/snice-progress-ring.js +2 -2
  108. package/dist/cdn/qr-code/snice-qr-code.js +2 -2
  109. package/dist/cdn/qr-reader/snice-qr-reader.js +2 -2
  110. package/dist/cdn/radio/snice-radio.js +2 -2
  111. package/dist/cdn/range-slider/snice-range-slider.js +2 -2
  112. package/dist/cdn/rating/snice-rating.js +2 -2
  113. package/dist/cdn/receipt/snice-receipt.js +2 -2
  114. package/dist/cdn/recipe/snice-recipe.js +3 -3
  115. package/dist/cdn/recipe/snice-recipe.js.map +1 -1
  116. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  117. package/dist/cdn/recipe/snice-recipe.min.js.map +1 -1
  118. package/dist/cdn/runtime/README.md +2 -2
  119. package/dist/cdn/runtime/snice-runtime.esm.js +3725 -3336
  120. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  121. package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
  122. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  123. package/dist/cdn/runtime/snice-runtime.js +3727 -3335
  124. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  125. package/dist/cdn/runtime/snice-runtime.min.js +1 -1
  126. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  127. package/dist/cdn/sankey/snice-sankey.js +2 -2
  128. package/dist/cdn/segmented-control/snice-segmented-control.js +2 -2
  129. package/dist/cdn/select/snice-select.js +2 -2
  130. package/dist/cdn/skeleton/snice-skeleton.js +2 -2
  131. package/dist/cdn/slider/snice-slider.js +2 -2
  132. package/dist/cdn/sortable/snice-sortable.js +2 -2
  133. package/dist/cdn/sparkline/snice-sparkline.js +2 -2
  134. package/dist/cdn/spinner/snice-spinner.js +2 -2
  135. package/dist/cdn/split-button/snice-split-button.js +2 -2
  136. package/dist/cdn/split-pane/snice-split-pane.js +2 -2
  137. package/dist/cdn/spotlight/snice-spotlight.js +2 -2
  138. package/dist/cdn/stat-group/snice-stat-group.js +2 -2
  139. package/dist/cdn/step-input/snice-step-input.js +2 -2
  140. package/dist/cdn/stepper/snice-stepper.js +2 -2
  141. package/dist/cdn/switch/snice-switch.js +2 -2
  142. package/dist/cdn/table/README.md +6 -2
  143. package/dist/cdn/table/snice-table.esm.js +366 -56
  144. package/dist/cdn/table/snice-table.esm.js.map +1 -1
  145. package/dist/cdn/table/snice-table.esm.min.js +107 -46
  146. package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
  147. package/dist/cdn/table/snice-table.js +367 -59
  148. package/dist/cdn/table/snice-table.js.map +1 -1
  149. package/dist/cdn/table/snice-table.min.js +155 -94
  150. package/dist/cdn/table/snice-table.min.js.map +1 -1
  151. package/dist/cdn/tabs/snice-tabs.js +2 -2
  152. package/dist/cdn/tag/snice-tag.js +2 -2
  153. package/dist/cdn/tag-input/snice-tag-input.js +2 -2
  154. package/dist/cdn/terminal/snice-terminal.js +3 -2
  155. package/dist/cdn/terminal/snice-terminal.js.map +1 -1
  156. package/dist/cdn/terminal/snice-terminal.min.js +1 -0
  157. package/dist/cdn/terminal/snice-terminal.min.js.map +1 -1
  158. package/dist/cdn/testimonial/snice-testimonial.js +2 -2
  159. package/dist/cdn/textarea/snice-textarea.js +2 -2
  160. package/dist/cdn/time-picker/snice-time-picker.js +2 -2
  161. package/dist/cdn/time-range-picker/snice-time-range-picker.js +2 -2
  162. package/dist/cdn/timeline/snice-timeline.js +2 -2
  163. package/dist/cdn/timer/snice-timer.js +2 -2
  164. package/dist/cdn/toast/snice-toast.js +2 -2
  165. package/dist/cdn/tooltip/snice-tooltip.js +2 -2
  166. package/dist/cdn/tree/snice-tree.js +2 -2
  167. package/dist/cdn/treemap/snice-treemap.js +2 -2
  168. package/dist/cdn/user-card/snice-user-card.js +2 -2
  169. package/dist/cdn/video-player/README.md +1 -1
  170. package/dist/cdn/video-player/snice-video-player.js +3 -2
  171. package/dist/cdn/video-player/snice-video-player.js.map +1 -1
  172. package/dist/cdn/video-player/snice-video-player.min.js +1 -0
  173. package/dist/cdn/video-player/snice-video-player.min.js.map +1 -1
  174. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +2 -2
  175. package/dist/cdn/waterfall/snice-waterfall.js +2 -2
  176. package/dist/cdn/weather/snice-weather.js +2 -2
  177. package/dist/cdn/work-order/snice-work-order.js +2 -2
  178. package/dist/components/recipe/snice-recipe.js +1 -1
  179. package/dist/components/recipe/snice-recipe.js.map +1 -1
  180. package/dist/components/table/snice-table.d.ts +1 -0
  181. package/dist/components/table/snice-table.js +18 -2
  182. package/dist/components/table/snice-table.js.map +1 -1
  183. package/dist/components/table/table-tree-data.js +1 -0
  184. package/dist/components/table/table-tree-data.js.map +1 -1
  185. package/dist/components/terminal/snice-terminal.js +1 -0
  186. package/dist/components/terminal/snice-terminal.js.map +1 -1
  187. package/dist/components/video-player/snice-video-player.js +1 -0
  188. package/dist/components/video-player/snice-video-player.js.map +1 -1
  189. package/dist/context-provider.d.ts +16 -0
  190. package/dist/daemon-target.d.ts +10 -0
  191. package/dist/daemon.d.ts +10 -0
  192. package/dist/index.cjs +3721 -3329
  193. package/dist/index.cjs.map +1 -1
  194. package/dist/index.d.ts +3 -0
  195. package/dist/index.esm.js +3719 -3330
  196. package/dist/index.esm.js.map +1 -1
  197. package/dist/index.iife.js +3721 -3329
  198. package/dist/index.iife.js.map +1 -1
  199. package/dist/keyboard-filter.d.ts +25 -0
  200. package/dist/on.d.ts +1 -1
  201. package/dist/parts.d.ts +0 -17
  202. package/dist/react/SniceProvider.js +2 -2
  203. package/dist/react/SniceRouter.js +2 -2
  204. package/dist/react/index.js +2 -2
  205. package/dist/react/matchRoute.js +2 -2
  206. package/dist/react/useRequestHandler.js +2 -2
  207. package/dist/request-response.d.ts +9 -1
  208. package/dist/symbols.cjs +11 -2
  209. package/dist/symbols.cjs.map +1 -1
  210. package/dist/symbols.d.ts +3 -0
  211. package/dist/symbols.esm.js +9 -3
  212. package/dist/symbols.esm.js.map +1 -1
  213. package/dist/testing.d.ts +1 -1
  214. package/dist/transitions.cjs +2 -2
  215. package/dist/transitions.esm.js +2 -2
  216. package/dist/types/app-context.d.ts +9 -58
  217. package/dist/types/daemon.d.ts +8 -0
  218. package/dist/types/dispatch-options.d.ts +2 -0
  219. package/dist/types/index.d.ts +1 -0
  220. package/dist/types/on-options.d.ts +5 -0
  221. package/dist/types/request-options.d.ts +2 -0
  222. package/dist/types/respond-options.d.ts +2 -0
  223. package/docs/ai/DEVELOPMENT.md +15 -1
  224. package/docs/ai/README.md +5 -1
  225. package/docs/ai/api.md +13 -4
  226. package/docs/ai/architecture.md +50 -1
  227. package/docs/ai/cli.md +9 -0
  228. package/docs/ai/components/avatar.md +8 -8
  229. package/docs/ai/components/breadcrumbs.md +2 -1
  230. package/docs/ai/components/button.md +2 -7
  231. package/docs/ai/components/calendar.md +1 -1
  232. package/docs/ai/components/camera.md +1 -1
  233. package/docs/ai/components/chart.md +3 -1
  234. package/docs/ai/components/code-block.md +2 -2
  235. package/docs/ai/components/date-picker.md +5 -19
  236. package/docs/ai/components/date-range-picker.md +4 -12
  237. package/docs/ai/components/draw.md +5 -5
  238. package/docs/ai/components/drawer.md +4 -4
  239. package/docs/ai/components/form-layout.md +2 -0
  240. package/docs/ai/components/icons.md +7 -16
  241. package/docs/ai/components/key-value.md +3 -22
  242. package/docs/ai/components/layout.md +8 -12
  243. package/docs/ai/components/leaderboard.md +2 -2
  244. package/docs/ai/components/link-preview.md +4 -3
  245. package/docs/ai/components/login.md +11 -0
  246. package/docs/ai/components/markdown.md +7 -0
  247. package/docs/ai/components/masonry.md +6 -0
  248. package/docs/ai/components/menu.md +1 -1
  249. package/docs/ai/components/modal.md +7 -0
  250. package/docs/ai/components/notification-center.md +5 -4
  251. package/docs/ai/components/radio.md +7 -0
  252. package/docs/ai/components/rating.md +3 -3
  253. package/docs/ai/components/select.md +4 -13
  254. package/docs/ai/components/spotlight.md +2 -0
  255. package/docs/ai/components/table.md +1 -4
  256. package/docs/ai/components/tag-input.md +6 -0
  257. package/docs/ai/components/terminal.md +6 -0
  258. package/docs/ai/components/tooltip.md +10 -16
  259. package/docs/ai/components/tree.md +2 -2
  260. package/docs/ai/components/video-player.md +5 -0
  261. package/docs/ai/components/waterfall.md +7 -0
  262. package/docs/ai/daemons.md +80 -0
  263. package/docs/ai/decorators.md +6 -4
  264. package/docs/ai/events.md +35 -0
  265. package/docs/ai/patterns.md +45 -1
  266. package/docs/ai/request-response.md +26 -9
  267. package/docs/ai/routing.md +16 -1
  268. package/docs/cli.md +7 -0
  269. package/docs/components/breadcrumbs.md +2 -1
  270. package/docs/components/calendar.md +1 -1
  271. package/docs/components/camera.md +1 -1
  272. package/docs/components/chart.md +1 -1
  273. package/docs/components/code-block.md +13 -4
  274. package/docs/components/color-picker.md +6 -5
  275. package/docs/components/date-time-picker.md +14 -0
  276. package/docs/components/diff.md +2 -1
  277. package/docs/components/draw.md +5 -5
  278. package/docs/components/drawer.md +4 -4
  279. package/docs/components/input.md +1 -0
  280. package/docs/components/layout.md +20 -22
  281. package/docs/components/leaderboard.md +10 -3
  282. package/docs/components/link-preview.md +11 -9
  283. package/docs/components/login.md +4 -0
  284. package/docs/components/menu.md +1 -1
  285. package/docs/components/modal.md +1 -0
  286. package/docs/components/nav.md +1 -0
  287. package/docs/components/network-graph.md +1 -0
  288. package/docs/components/notification-center.md +2 -1
  289. package/docs/components/product-card.md +1 -0
  290. package/docs/components/qr-reader.md +1 -0
  291. package/docs/components/rating.md +4 -4
  292. package/docs/components/select.md +1 -0
  293. package/docs/components/spotlight.md +2 -0
  294. package/docs/components/tabs.md +1 -0
  295. package/docs/components/terminal.md +3 -0
  296. package/docs/components/textarea.md +1 -1
  297. package/docs/components/time-picker.md +14 -0
  298. package/docs/components/tooltip.md +2 -0
  299. package/docs/components/tree.md +2 -2
  300. package/docs/daemons.md +200 -0
  301. package/docs/events.md +92 -2
  302. package/docs/request-response.md +20 -13
  303. package/docs/routing.md +25 -1
  304. package/package.json +6 -4
@@ -8,6 +8,10 @@ description: Build, modify, debug, or review applications and components that us
8
8
  Use the documentation shipped with the exact installed Snice version. Do not
9
9
  reconstruct Snice APIs from Lit or generic web-component conventions.
10
10
 
11
+ If a consuming project does not yet contain `.agents/skills/snice/SKILL.md`,
12
+ run `npx snice init-ai` from that project root before writing Snice code. This
13
+ installs version-matched guidance plus `AGENTS.md` and `CLAUDE.md` pointers.
14
+
11
15
  ## Locate the reference
12
16
 
13
17
  Use the first directory that exists:
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import {
11
11
  ContextAwareFetcher,
12
+ type Response,
12
13
  SniceElement,
13
14
  adopted,
14
15
  classMap,
@@ -19,6 +20,7 @@ import {
19
20
  controller,
20
21
  createRequestHandler,
21
22
  css,
23
+ daemon,
22
24
  debounce,
23
25
  dispatch,
24
26
  dispose,
@@ -81,6 +83,23 @@ interface KitchenContext extends AppContext {
81
83
  token: string;
82
84
  }
83
85
 
86
+ @daemon
87
+ class KitchenDaemon {
88
+ status = 'ready';
89
+
90
+ @respond('daemon-status')
91
+ currentStatus() {
92
+ return this.status;
93
+ }
94
+
95
+ @dispatch('daemon-status-changed')
96
+ statusChanged() {
97
+ return this.status;
98
+ }
99
+ }
100
+
101
+ const kitchenDaemon = new KitchenDaemon();
102
+
84
103
  const fetcher = new ContextAwareFetcher();
85
104
  fetcher.use('request', function (request, next) {
86
105
  const { token } = this.application as KitchenContext;
@@ -96,7 +115,11 @@ export const { page, navigate, initialize } = Router({
96
115
  target: '#app',
97
116
  type: 'hash',
98
117
  layout: 'kitchen-shell',
99
- context: { user: null, token: '' } satisfies KitchenContext,
118
+ context: {
119
+ user: null,
120
+ token: '',
121
+ daemons: { kitchen: kitchenDaemon }
122
+ } satisfies KitchenContext,
100
123
  fetcher
101
124
  });
102
125
 
@@ -220,6 +243,21 @@ class KitchenView extends SniceElement {
220
243
  return user as User;
221
244
  }
222
245
 
246
+ @request('daemon-status', { daemon: 'kitchen' })
247
+ async *loadDaemonStatus(): Response<string> {
248
+ return await (yield {});
249
+ }
250
+
251
+ async normalizedDaemonStatus() {
252
+ const status: string = await this.loadDaemonStatus();
253
+ return status.toUpperCase();
254
+ }
255
+
256
+ @on('daemon-status-changed', { daemon: 'kitchen' })
257
+ daemonStatusChanged(event: CustomEvent<string>) {
258
+ this.status.text = event.detail;
259
+ }
260
+
223
261
  @observe('resize', '.panel')
224
262
  resized(_entries: ResizeObserverEntry[]) {}
225
263
 
package/README.md CHANGED
@@ -62,7 +62,7 @@ class RealTimeUserLoader { ... }
62
62
  @on('click', 'button') fn(e: Event) { ... }
63
63
  @dispatch('value-changed') fn(val: string) => Event Detail
64
64
  @context() fn(ctx: Context) { ... }
65
- @request('user') fn(): () => Request;
65
+ @request('user') async *fn(): Response<User> { return yield {}; }
66
66
  @respond('user') fn(req) => Response;
67
67
  ```
68
68
 
@@ -510,8 +510,8 @@ This pattern is useful when:
510
510
 
511
511
  ```typescript
512
512
  // Controller responds to requests
513
- @element('app-controller')
514
- class AppController extends HTMLElement {
513
+ @controller('app-controller')
514
+ class AppController {
515
515
  private currentUser = { name: 'Alice', role: 'admin' };
516
516
 
517
517
  @respond('user')
@@ -523,32 +523,75 @@ class AppController extends HTMLElement {
523
523
  // Element makes requests
524
524
  @element('user-badge')
525
525
  class UserBadge extends HTMLElement {
526
+ @state() private user: User | null = null;
527
+
526
528
  @request('user')
527
- getUser!: () => any;
529
+ async *getUser(): Response<User> {
530
+ return yield {};
531
+ }
528
532
 
529
533
  @ready()
530
- init() {
531
- const user = this.getUser();
534
+ async init() {
535
+ const user = await this.getUser();
536
+ this.user = user;
532
537
  console.log('Current user:', user);
533
538
  }
534
539
 
535
540
  @render()
536
541
  renderContent() {
537
- const user = this.getUser();
538
- return html`<div>Welcome, ${user.name}!</div>`;
542
+ return html`<div>Welcome, ${this.user?.name ?? 'Guest'}!</div>`;
539
543
  }
540
544
  }
541
- ```
542
545
 
543
- **Usage:**
544
- ```html
545
- <app-controller>
546
- <user-badge></user-badge>
547
- </app-controller>
546
+ // A parent template attaches the responder by class.
547
+ html`<user-badge controller=${AppController}></user-badge>`;
548
548
  ```
549
549
 
550
550
  See [Request/Response documentation](./docs/request-response.md) for details.
551
551
 
552
+ ### Daemons
553
+
554
+ Daemons are explicitly constructed, app-owned objects with state and a lifecycle.
555
+ They support both request/response and event communication without requiring an
556
+ element or a global singleton:
557
+
558
+ ```typescript
559
+ @daemon
560
+ class SessionDaemon {
561
+ @respond('get-session')
562
+ getSession() { return this.session; }
563
+
564
+ @dispatch('session-changed')
565
+ changed() { return this.session; }
566
+ }
567
+
568
+ const session = new SessionDaemon();
569
+ const release = provideContext(appRoot, { daemons: { session } });
570
+
571
+ // Elements/controllers use the context address, not SessionDaemon.
572
+ @request('get-session', { daemon: 'session' })
573
+ async *loadSession(): Response<Session | null> {
574
+ return yield {};
575
+ }
576
+ ```
577
+
578
+ Router provides its `context` through the same mechanism. There is no implicit
579
+ construction or global registry, and multiple instances remain independent. See
580
+ [Daemons](./docs/daemons.md) for lifecycle, testing, and both communication models.
581
+
582
+ ### Project Organization
583
+
584
+ Keep application roles easy to find: pages in `src/pages/`, reusable visual
585
+ elements in `src/components/`, attached behavior in `src/controllers/`, and
586
+ app-owned services in `src/daemons/`. `src/router.ts` constructs and exports the
587
+ router pieces; `src/main.ts` imports page modules and calls `initialize()`.
588
+
589
+ Pages orchestrate a route. When several storage/server/timer operations collect
590
+ inside one page, or substantial non-visual logic is repeated across pages, move
591
+ that behavior into a controller. `snice check` reports folder and extraction
592
+ guidance as non-blocking suggestions while treating broken Router construction
593
+ as an error.
594
+
552
595
  ## Template Syntax
553
596
 
554
597
  ### Auto-Rendering with Differential Updates
@@ -939,6 +982,7 @@ See [DEVELOPMENT.md](./DEVELOPMENT.md) for build system details
939
982
  - [Declarative Rendering](./docs/rendering.md) - Bindings, control flow, reactivity, render roots, and async values
940
983
  - [Binding Channels](./docs/bindings.md) - Detailed DOM destinations, value/removal rules, events, spreads, sentinels, and forms
941
984
  - [Controllers API](./docs/controllers.md) - Data fetching, business logic, and controller patterns
985
+ - [Daemons](./docs/daemons.md) - Explicit app-context state/lifecycle objects with request/response and event communication
942
986
  - [Routing API](./docs/routing.md) - Router setup, pages, route params, and navigation
943
987
  - [Guards and Layouts](./docs/guards-and-layouts.md) - Protecting routes, page wrappers, and transitions
944
988
  - [Placards API](./docs/placards.md) - Rich page metadata for dynamic navigation and discovery
@@ -952,6 +996,7 @@ See [DEVELOPMENT.md](./DEVELOPMENT.md) for build system details
952
996
 
953
997
  ### Developer Documentation
954
998
  - [DEVELOPMENT.md](./DEVELOPMENT.md) - Build system, testing, and contributing to Snice
999
+ - [Dumb-agent gauntlet](./.ai/gauntlet.md) - Maintainer-only local model loop for hardening `snice check`
955
1000
 
956
1001
  ## License
957
1002
 
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * snice v7.0.1
3
- * A decorator-driven web component library with differential rendering, routing, controllers, and 130+ ready-made UI components. Use as much or as little as you want. Zero dependencies, works anywhere.
2
+ * snice v7.0.3
3
+ * A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * snice v7.0.1
3
- * A decorator-driven web component library with differential rendering, routing, controllers, and 130+ ready-made UI components. Use as much or as little as you want. Zero dependencies, works anywhere.
2
+ * snice v7.0.3
3
+ * A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * snice v7.0.1
3
- * A decorator-driven web component library with differential rendering, routing, controllers, and 130+ ready-made UI components. Use as much or as little as you want. Zero dependencies, works anywhere.
2
+ * snice v7.0.3
3
+ * A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * snice v7.0.1
3
- * A decorator-driven web component library with differential rendering, routing, controllers, and 130+ ready-made UI components. Use as much or as little as you want. Zero dependencies, works anywhere.
2
+ * snice v7.0.3
3
+ * A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
6
6
  *
@@ -18,7 +18,7 @@ export const ANALYZER_CONTRACTS = {
18
18
  "componentFamilies": 134,
19
19
  "componentModules": 188,
20
20
  "reactWrappers": 193,
21
- "rootExports": 110
21
+ "rootExports": 115
22
22
  },
23
23
  "rootExports": [
24
24
  "AdoptedOptions",
@@ -29,6 +29,7 @@ export const ANALYZER_CONTRACTS = {
29
29
  "ContextOptions",
30
30
  "ControllerClass",
31
31
  "CreateRequestHandlerOptions",
32
+ "DaemonMap",
32
33
  "DispatchOptions",
33
34
  "Duration",
34
35
  "ElementOptions",
@@ -57,6 +58,7 @@ export const ANALYZER_CONTRACTS = {
57
58
  "RequestRoute",
58
59
  "RequestRouteMap",
59
60
  "RespondOptions",
61
+ "Response",
60
62
  "ResponseMiddleware",
61
63
  "RouteParams",
62
64
  "Router",
@@ -83,6 +85,7 @@ export const ANALYZER_CONTRACTS = {
83
85
  "controller",
84
86
  "createRequestHandler",
85
87
  "css",
88
+ "daemon",
86
89
  "debounce",
87
90
  "detachController",
88
91
  "dispatch",
@@ -91,6 +94,7 @@ export const ANALYZER_CONTRACTS = {
91
94
  "escapeAttr",
92
95
  "escapeHtml",
93
96
  "getBodyScrollLockCount",
97
+ "getContext",
94
98
  "getController",
95
99
  "getSymbol",
96
100
  "html",
@@ -107,6 +111,7 @@ export const ANALYZER_CONTRACTS = {
107
111
  "once",
108
112
  "parseDuration",
109
113
  "property",
114
+ "provideContext",
110
115
  "query",
111
116
  "queryAll",
112
117
  "ready",
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { closeSync, openSync, writeSync } from 'node:fs';
4
+
5
+ export const AI_INIT_MESSAGE = [
6
+ '',
7
+ 'Snice installed. Add version-matched AI guidance to this project:',
8
+ ' npx snice init-ai',
9
+ ''
10
+ ].join('\n');
11
+
12
+ function isSilent(env) {
13
+ return String(env.npm_config_loglevel ?? '').toLowerCase() === 'silent';
14
+ }
15
+
16
+ /**
17
+ * npm 7+ captures dependency lifecycle output by default. Prefer stdout when
18
+ * it is already visible, otherwise write directly to an interactive terminal.
19
+ * Every terminal operation is best-effort so installation can never fail just
20
+ * because the recommendation could not be displayed.
21
+ */
22
+ export function showAiInitMessage({
23
+ env = process.env,
24
+ platform = process.platform,
25
+ stdout = process.stdout,
26
+ open = openSync,
27
+ write = writeSync,
28
+ close = closeSync
29
+ } = {}) {
30
+ if (isSilent(env)) return false;
31
+
32
+ if (stdout.isTTY) {
33
+ stdout.write(AI_INIT_MESSAGE);
34
+ return true;
35
+ }
36
+
37
+ if (!env.CI) {
38
+ let terminal;
39
+ try {
40
+ terminal = open(platform === 'win32' ? '\\\\.\\CONOUT$' : '/dev/tty', 'w');
41
+ write(terminal, AI_INIT_MESSAGE);
42
+ close(terminal);
43
+ return true;
44
+ } catch {
45
+ if (terminal !== undefined) {
46
+ try { close(terminal); } catch {}
47
+ }
48
+ }
49
+ }
50
+
51
+ try {
52
+ stdout.write(AI_INIT_MESSAGE);
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ showAiInitMessage();