@jskit-ai/agent-docs 0.1.131 → 0.1.133

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 (171) hide show
  1. package/guide/agent/app-extras/assistant.md +29 -605
  2. package/guide/agent/app-extras/mobile-capacitor.md +29 -362
  3. package/guide/agent/app-extras/realtime.md +29 -277
  4. package/guide/agent/app-setup/a-more-interesting-shell.md +44 -815
  5. package/guide/agent/app-setup/authentication.md +43 -1073
  6. package/guide/agent/app-setup/console.md +26 -298
  7. package/guide/agent/app-setup/database-layer.md +110 -790
  8. package/guide/agent/app-setup/existing-application-migration.md +273 -0
  9. package/guide/agent/app-setup/initial-scaffolding.md +50 -784
  10. package/guide/agent/app-setup/multi-homing.md +39 -712
  11. package/guide/agent/app-setup/quickstart.md +43 -179
  12. package/guide/agent/app-setup/users.md +34 -353
  13. package/guide/agent/index.md +17 -23
  14. package/package.json +2 -2
  15. package/patterns/INDEX.md +7 -7
  16. package/patterns/child-cruds.md +3 -3
  17. package/patterns/client-requests.md +6 -6
  18. package/patterns/crud-authoring.md +94 -0
  19. package/patterns/crud-links.md +1 -1
  20. package/patterns/feature-package/PATTERN.md +108 -0
  21. package/patterns/feature-package/example/booking-engine/package.json +48 -0
  22. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  23. package/patterns/feature-package/example/booking-engine/src/server/actions.js +26 -0
  24. package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  25. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  26. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  27. package/patterns/feature-package/example/variations/customKnexRepository.js +34 -0
  28. package/patterns/feature-package/example/variations/orchestratorService.js +23 -0
  29. package/patterns/filters.md +8 -8
  30. package/patterns/live-actions.md +5 -18
  31. package/patterns/minimal-foundation/PATTERN.md +98 -0
  32. package/patterns/minimal-foundation/example/.nvmrc +1 -0
  33. package/patterns/minimal-foundation/example/AGENTS.md +17 -0
  34. package/patterns/minimal-foundation/example/Procfile +2 -0
  35. package/patterns/minimal-foundation/example/app.json +14 -0
  36. package/patterns/minimal-foundation/example/bin/develop.js +71 -0
  37. package/patterns/minimal-foundation/example/bin/server.js +8 -0
  38. package/patterns/minimal-foundation/example/config/public.js +40 -0
  39. package/patterns/minimal-foundation/example/config/server.js +1 -0
  40. package/patterns/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  41. package/patterns/minimal-foundation/example/eslint.config.mjs +19 -0
  42. package/patterns/minimal-foundation/example/favicon.svg +7 -0
  43. package/patterns/minimal-foundation/example/gitignore +9 -0
  44. package/patterns/minimal-foundation/example/index.html +13 -0
  45. package/patterns/minimal-foundation/example/jsconfig.json +8 -0
  46. package/patterns/minimal-foundation/example/package.json +57 -0
  47. package/patterns/minimal-foundation/example/packages/main/package.json +42 -0
  48. package/patterns/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  49. package/patterns/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  50. package/patterns/minimal-foundation/example/playwright.config.mjs +31 -0
  51. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  52. package/patterns/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  53. package/patterns/minimal-foundation/example/server.js +195 -0
  54. package/patterns/minimal-foundation/example/src/App.vue +13 -0
  55. package/patterns/minimal-foundation/example/src/main.js +85 -0
  56. package/patterns/minimal-foundation/example/src/pages/home/index.vue +48 -0
  57. package/patterns/minimal-foundation/example/src/pages/home.vue +13 -0
  58. package/patterns/minimal-foundation/example/src/views/NotFound.vue +13 -0
  59. package/patterns/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  60. package/patterns/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  61. package/patterns/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  62. package/patterns/minimal-foundation/example/vite.config.mjs +81 -0
  63. package/patterns/page-scaffolding.md +20 -17
  64. package/patterns/placements.md +17 -15
  65. package/patterns/row-policies.md +4 -5
  66. package/patterns/server-search.md +3 -3
  67. package/patterns/shell-foundation/PATTERN.md +104 -0
  68. package/patterns/shell-foundation/example/.nvmrc +1 -0
  69. package/patterns/shell-foundation/example/AGENTS.md +17 -0
  70. package/patterns/shell-foundation/example/Procfile +2 -0
  71. package/patterns/shell-foundation/example/app.json +14 -0
  72. package/patterns/shell-foundation/example/bin/develop.js +71 -0
  73. package/patterns/shell-foundation/example/bin/server.js +8 -0
  74. package/patterns/shell-foundation/example/config/public.js +40 -0
  75. package/patterns/shell-foundation/example/config/server.js +1 -0
  76. package/patterns/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  77. package/patterns/shell-foundation/example/eslint.config.mjs +19 -0
  78. package/patterns/shell-foundation/example/favicon.svg +7 -0
  79. package/patterns/shell-foundation/example/gitignore +9 -0
  80. package/patterns/shell-foundation/example/index.html +13 -0
  81. package/patterns/shell-foundation/example/jsconfig.json +8 -0
  82. package/patterns/shell-foundation/example/package.json +59 -0
  83. package/patterns/shell-foundation/example/packages/main/package.json +56 -0
  84. package/patterns/shell-foundation/example/packages/main/src/client/index.js +9 -0
  85. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  86. package/patterns/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  87. package/patterns/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  88. package/patterns/shell-foundation/example/playwright.config.mjs +31 -0
  89. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  90. package/patterns/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  91. package/patterns/shell-foundation/example/server.js +195 -0
  92. package/patterns/shell-foundation/example/src/App.vue +11 -0
  93. package/patterns/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  94. package/patterns/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  95. package/patterns/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  96. package/patterns/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  97. package/patterns/shell-foundation/example/src/error.js +19 -0
  98. package/patterns/shell-foundation/example/src/main.js +85 -0
  99. package/patterns/shell-foundation/example/src/pages/home/index.vue +116 -0
  100. package/patterns/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  101. package/patterns/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  102. package/patterns/shell-foundation/example/src/pages/home/settings.vue +109 -0
  103. package/patterns/shell-foundation/example/src/pages/home.vue +20 -0
  104. package/patterns/shell-foundation/example/src/placement.js +56 -0
  105. package/patterns/shell-foundation/example/src/placementTopology.js +149 -0
  106. package/patterns/shell-foundation/example/src/views/NotFound.vue +13 -0
  107. package/patterns/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  108. package/patterns/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  109. package/patterns/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  110. package/patterns/shell-foundation/example/tests/server/smoke.test.js +16 -0
  111. package/patterns/shell-foundation/example/vite.config.mjs +81 -0
  112. package/patterns/ui-contract.md +56 -0
  113. package/patterns/ui-testing.md +10 -12
  114. package/reference/autogen/KERNEL_MAP.md +29 -107
  115. package/reference/autogen/PATTERN_INDEX.md +230 -0
  116. package/reference/autogen/README.md +4 -8
  117. package/reference/autogen/packages/agent-docs.md +259 -0
  118. package/reference/autogen/packages/assistant-core.md +3 -3
  119. package/reference/autogen/packages/assistant-runtime.md +32 -17
  120. package/reference/autogen/packages/auth-core.md +31 -33
  121. package/reference/autogen/packages/auth-provider-local-core.md +4 -12
  122. package/reference/autogen/packages/auth-provider-local-db-core.md +4 -4
  123. package/reference/autogen/packages/auth-provider-supabase-core.md +14 -18
  124. package/reference/autogen/packages/auth-web.md +42 -22
  125. package/reference/autogen/packages/console-core.md +8 -25
  126. package/reference/autogen/packages/console-web.md +5 -5
  127. package/reference/autogen/packages/crud-core.md +61 -17
  128. package/reference/autogen/packages/database-runtime-mysql.md +12 -2
  129. package/reference/autogen/packages/database-runtime-postgres.md +12 -2
  130. package/reference/autogen/packages/database-runtime.md +26 -25
  131. package/reference/autogen/packages/google-rewarded-core.md +19 -104
  132. package/reference/autogen/packages/http-runtime.md +4 -8
  133. package/reference/autogen/packages/http-web.md +32 -0
  134. package/reference/autogen/packages/json-rest-api-core.md +4 -6
  135. package/reference/autogen/packages/kernel.md +109 -390
  136. package/reference/autogen/packages/mobile-capacitor.md +2 -13
  137. package/reference/autogen/packages/realtime.md +29 -26
  138. package/reference/autogen/packages/resource-crud-core.md +6 -0
  139. package/reference/autogen/packages/shell-web.md +69 -54
  140. package/reference/autogen/packages/storage-runtime.md +3 -3
  141. package/reference/autogen/packages/uploads-image-web.md +0 -1
  142. package/reference/autogen/packages/uploads-runtime.md +3 -3
  143. package/reference/autogen/packages/users-core.md +45 -90
  144. package/reference/autogen/packages/users-web.md +5 -7
  145. package/reference/autogen/packages/workspaces-core.md +53 -74
  146. package/reference/autogen/packages/workspaces-web.md +15 -16
  147. package/reference/autogen/tooling/jskit-catalog.md +34 -0
  148. package/reference/autogen/tooling/testUtils.md +4 -4
  149. package/skills/jskit/SKILL.md +38 -31
  150. package/skills/jskit/references/app-operations.md +68 -53
  151. package/skills/jskit/references/crud-operations.md +58 -106
  152. package/skills/jskit/references/material-3.md +1 -1
  153. package/skills/jskit/references/ui-operations.md +41 -44
  154. package/templates/app/AGENTS.md +7 -3
  155. package/guide/agent/app-setup/upgrade-beta-1-to-final.md +0 -252
  156. package/guide/agent/app-setup/working-with-the-jskit-cli.md +0 -325
  157. package/guide/agent/generators/advanced-cruds.md +0 -1935
  158. package/guide/agent/generators/crud-generators.md +0 -948
  159. package/guide/agent/generators/intro.md +0 -65
  160. package/guide/agent/generators/row-policies.md +0 -537
  161. package/guide/agent/generators/ui-generators.md +0 -690
  162. package/patterns/crud-scaffolding.md +0 -198
  163. package/patterns/generated-ui-contract-tracking.md +0 -66
  164. package/reference/autogen/packages/assistant.md +0 -68
  165. package/reference/autogen/packages/crud-server-generator.md +0 -215
  166. package/reference/autogen/packages/crud-ui-generator.md +0 -192
  167. package/reference/autogen/packages/feature-server-generator.md +0 -65
  168. package/reference/autogen/packages/ui-generator.md +0 -127
  169. package/reference/autogen/tooling/create-app.md +0 -317
  170. package/reference/autogen/tooling/jskit-cli.md +0 -933
  171. package/reference/autogen/tooling/test-support.md +0 -27
@@ -19,9 +19,9 @@ Ask first:
19
19
  - whether there are presets such as "Today", "Last 7 Days", or "Only Archived"
20
20
 
21
21
  Default JSKIT client pattern:
22
- 1. Generated CRUD list pages include a page-local `listFilters.js` file next to `index.vue`.
22
+ 1. CRUD list pages use a page-local `listFilters.js` file next to `index.vue`.
23
23
  2. Put client filter definitions in that file with `defineCrudListFilters(...)`.
24
- 3. The generated `index.vue` passes `listFilters` into `useCrudListScreen(...)`; the shared list screen builds `useCrudListFilters(listFilters)`, passes `filterRuntime.queryParams` into the list request, and renders `CrudListFilterSurface`.
24
+ 3. The app-owned `index.vue` passes `listFilters` into `useCrudListScreen(...)`; the shared list screen builds `useCrudListFilters(listFilters)`, passes `filterRuntime.queryParams` into the list request, and renders `CrudListFilterSurface`.
25
25
  4. If `listFilters` is empty, the filter surface renders nothing and the page behaves like a normal searchable list.
26
26
  5. The AI/app author is responsible for ensuring the server accepts and applies the query params declared in `listFilters.js`.
27
27
  6. For lookup-backed filters, use `useCrudListFilterLookups(...)` when the page needs remote options or readable chip labels.
@@ -47,7 +47,7 @@ const listFilters = defineCrudListFilters({
47
47
  });
48
48
  ```
49
49
 
50
- Generated client shape:
50
+ Client shape:
51
51
  - `src/pages/<surface>/<resource>/listFilters.js`
52
52
  - `const listFilters = defineCrudListFilters({ ... })`
53
53
  - `useCrudListScreen({ ..., listFilters })`
@@ -77,8 +77,8 @@ Exact file checklist:
77
77
  `listFilterQueryValidator`
78
78
  - update the provider's `createJsonRestResourceScopeOptions(...)` call so `searchSchema: listFilterContract.jsonRestSearchSchema` is merged into the internal JSON REST resource
79
79
  - update `packages/<crud>/src/server/repository.js` so list queries pass `listFilterContract.toJsonRestQuery(query)` into `buildJsonRestQueryParams(...)`
80
- - update the generated page-local `listFilters.js` first; only edit `index.vue` if a specialist lookup label/runtime integration is needed
81
- - for lookup-backed filters, wire `useCrudListFilterLookups(...)` beside the existing generated filter runtime instead of replacing `CrudListFilterSurface`
80
+ - update the page-local `listFilters.js` first; only edit `index.vue` if a specialist lookup label/runtime integration is needed
81
+ - for lookup-backed filters, wire `useCrudListFilterLookups(...)` beside the existing filter runtime instead of replacing `CrudListFilterSurface`
82
82
 
83
83
  Standard route and action query composition:
84
84
 
@@ -154,7 +154,7 @@ Avoid:
154
154
  - appending a list-filter validator after `createStandardCrudListQueryValidators(...)` when it belongs in the dedicated `listFilterQueryValidator` option
155
155
  - hand-rolled preset apply/reset/active-state helpers when `useCrudListFilters(..., { presets })`, `applyPreset(...)`, and `matchesPreset(...)` fit
156
156
  - per-screen `useList()` wrappers for lookup-backed filters when `useCrudListFilterLookups(...)` fits
157
- - editing generated `.vue` files just to add basic filter controls; use the page-local `listFilters.js` seam first
157
+ - editing `.vue` files just to add basic filter controls; use the page-local `listFilters.js` seam first
158
158
  - overloading `q` with structured filter meaning
159
159
  - inline filter-definition objects passed into `useCrudListFilters(...)`, `createCrudListFilters(...)`, or `createCrudListFilterContract(...)`; keep definitions in a named module
160
160
  - assigning a default to `filterRuntime.values` after `useCrudListScreen(...)` has started; that changes the query after construction and can issue a second initial request
@@ -162,7 +162,7 @@ Avoid:
162
162
  Good shape:
163
163
  - `src/pages/home/customers/listFilters.js`
164
164
  - `const listFilters = defineCrudListFilters({ status: { type: "enum", ... } })`
165
- - generated page passes `listFilters` into `useCrudListScreen(...)`
165
+ - page passes `listFilters` into `useCrudListScreen(...)`
166
166
  - shared screen runtime passes `filterRuntime.queryParams` into the list request
167
167
  - `packages/receivals/src/shared/receivalListFilters.js`
168
168
  - `createCrudListFilterContract(RECEIVAL_LIST_FILTER_DEFINITIONS, { columns, invalidValues: "reject" })`
@@ -178,7 +178,7 @@ Preset contract notes:
178
178
  - if the URL contains `status=archived&status=bogus`, a preset for only `archived` should not render as active while the `bogus` chip is still visible
179
179
 
180
180
  Review checks:
181
- - one filter definition source of truth: generated page-local `listFilters.js` for client-only filters, or a shared CRUD-package module when server code imports the same definitions
181
+ - one filter definition source of truth: page-local `listFilters.js` for client-only filters, or a shared CRUD-package module when server code imports the same definitions
182
182
  - server validator, JSON REST search schema, and repository query projection derived from that source through `createCrudListFilterContract(...)`
183
183
  - route and action boundaries independently compose
184
184
  `createStandardCrudListQueryValidators(...)`, using the dedicated
@@ -12,26 +12,13 @@ Rules:
12
12
  - Prefer `useCommand()` for live actions.
13
13
  - Prefer form runtimes such as `useCrudAddEdit()` or `useAddEdit()` for real forms.
14
14
  - Prefer `useCrudList()` and `useCrudView()` for routed CRUD loading and URL resolution.
15
- - For ordinary routed CRUD record deletion, generate the supported lane instead
16
- of rebuilding it page by page:
17
-
18
- ```bash
19
- npx --no-install jskit generate crud-ui-generator crud notes \
20
- --resource-file packages/notes/src/shared/noteResource.js \
21
- --id-param noteId \
22
- --display-fields title,body \
23
- --parent-title contextual \
24
- --navigation-role primary \
25
- --delete-confirmation
26
- ```
27
-
28
- `--delete-confirmation` requires generated list and view pages plus a shared
29
- resource with a `DELETE` operation. It extends the view through the public
30
- `CrudViewScreen` `actions` slot with `CrudDeleteAction` and wires it to
15
+ - For ordinary routed CRUD record deletion, start from the package-owned CRUD
16
+ UI pattern instead of rebuilding it page by page. Its view screen uses the
17
+ public `CrudViewScreen` `actions` slot with `CrudDeleteAction` and wires it to
31
18
  `useCrudDeleteAction()`: the shared component owns the alert dialog,
32
19
  `useCommand()` owns the request state, the shared resource owns the DELETE
33
20
  contract, and successful deletion invalidates the list query and navigates
34
- to the generated list route.
21
+ to the list route.
35
22
 
36
23
  Good live-action pattern:
37
24
 
@@ -51,5 +38,5 @@ Avoid:
51
38
 
52
39
  - manually hand-rolling fetch logic for a standard live action when `useCommand()` fits
53
40
  - inspecting private `http-web` internals or creating a page-local transport
54
- for generated record deletion
41
+ for standard record deletion
55
42
  - pushing derived write rules into the client just because the action is small
@@ -0,0 +1,98 @@
1
+ ---
2
+ id: app/minimal-foundation
3
+ title: Minimal JSKIT application foundation
4
+ summary: A concrete Fastify, Vue, and JSKIT application foundation for products that do not yet need the full adaptive shell.
5
+ keywords: app, fastify, foundation, minimal, server, vite, vue
6
+ requires: @jskit-ai/http-runtime, @jskit-ai/kernel
7
+ ---
8
+
9
+ # Minimal JSKIT application foundation
10
+
11
+ ## Use when
12
+
13
+ Use this pattern when establishing a new JSKIT web application in an existing
14
+ project repository and the product does not yet need the full adaptive shell,
15
+ settings navigation, or placement topology. It provides a working server,
16
+ client bootstrap, app-local provider package, one public surface, linting, unit
17
+ tests, browser tests, and the normal build entrypoints.
18
+
19
+ The example is a concrete application named `reading-room`. Copy the useful
20
+ files into the project root, rename the application in normal source and
21
+ package metadata, and then edit the product-facing page. The files become
22
+ ordinary application source immediately.
23
+
24
+ ## Do not use when
25
+
26
+ Do not use this pattern when the application already has an established
27
+ server/client foundation. Do not replace a working app merely to make it
28
+ resemble the example. Prefer the shell foundation when responsive navigation,
29
+ settings, or placement contributions are already clear requirements.
30
+
31
+ ## Product decisions
32
+
33
+ Decide the application name, first useful route, public versus authenticated
34
+ surface access, and whether the product needs the adaptive shell. These are
35
+ product decisions for the user and agent; this pattern does not ask a
36
+ questionnaire or infer tenancy, authentication, or database requirements.
37
+
38
+ ## Invariants
39
+
40
+ - Preserve `.git` and all unrelated project and agent context.
41
+ - Refuse or resolve real destination-file collisions before copying.
42
+ - Keep `packages/main` limited to app composition and lightweight glue.
43
+ - Use package public APIs; do not deep-import package internals.
44
+ - Keep one server entry, one client bootstrap, and explicit surface access.
45
+ - Keep one app-owned `npm run develop` entry that runs the API on loopback and
46
+ Vite on the host-supplied preview port; do not require a host to infer or
47
+ supervise framework-specific processes.
48
+ - Treat copied files as app-owned source. Do not add provenance, ownership
49
+ markers, receipts, ledgers, or operation-history state.
50
+ - Keep browser dependencies aligned with the execution environment that will
51
+ run the tests. Vibe64 supplies its exact managed Playwright version.
52
+
53
+ ## Framework APIs
54
+
55
+ The example composes `@jskit-ai/kernel` for provider/runtime composition and
56
+ `@jskit-ai/http-runtime` for the web runtime. `packages/main` demonstrates the
57
+ app-local provider boundary. Vite, Vue Router, Pinia, Vuetify, Fastify, and Vue
58
+ Query remain normal application dependencies.
59
+
60
+ ## Example files
61
+
62
+ `example/` is a complete concrete application tree. Copy only after inspecting
63
+ collisions. Rename `example/gitignore` to `.gitignore` in the application;
64
+ the neutral filename ensures npm publishes the reference asset. Managed preview
65
+ identity belongs to the authentication surface pattern, not the neutral
66
+ foundation.
67
+
68
+ Important starting points are:
69
+
70
+ - `example/package.json`
71
+ - `example/server.js`, `example/bin/server.js`, and `example/bin/develop.js`
72
+ - `example/src/main.js` and `example/src/App.vue`
73
+ - `example/config/public.js`
74
+ - `example/packages/main/`
75
+ - `example/tests/`
76
+
77
+ ## Variation points
78
+
79
+ Rename the package and title, replace the home page with the first real
80
+ product surface, add capabilities through their owning packages, and change
81
+ surface access deliberately. Add authentication, database, CRUD, shell, or
82
+ mobile patterns only when chosen. Do not pre-emptively include them.
83
+
84
+ ## Verification
85
+
86
+ After adapting the example, install the declared packages once and run
87
+ `npm run develop` for the live application. Then run the application's lint,
88
+ server tests, client tests, production build, and focused browser smoke.
89
+ Confirm `/api/health` and the first product route.
90
+
91
+ ## Avoid
92
+
93
+ - Do not run a scaffold questionnaire.
94
+ - Do not create a temporary app and copy its result over the project.
95
+ - Do not force-overwrite an existing repository.
96
+ - Do not keep `reading-room` names that no longer describe the product.
97
+ - Do not add a hidden file recording that this pattern was copied.
98
+ - Do not turn the example into a field interpolation language.
@@ -0,0 +1,17 @@
1
+ # App Agent Instructions
2
+
3
+ Use current project context, JSKIT public APIs, and the installed JSKIT pattern
4
+ index as the source of truth for application work.
5
+
6
+ Recommended references:
7
+
8
+ - `node_modules/@jskit-ai/agent-docs/guide/agent/index.md`
9
+ - `node_modules/@jskit-ai/agent-docs/patterns/INDEX.md`
10
+
11
+ Before database, schema, CRUD, repository, or persistence work, inspect the
12
+ relevant package-owned pattern from
13
+ `node_modules/@jskit-ai/agent-docs/reference/autogen/PATTERN_INDEX.md`.
14
+
15
+ Copied pattern source is ordinary application source. Do not add generator
16
+ provenance, receipts, completion ledgers, or tooling-operation history. Keep
17
+ changes scoped to the user request and verify runtime behavior directly.
@@ -0,0 +1,2 @@
1
+ release: npm run db:migrate
2
+ web: npm run start
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "reading-room",
3
+ "healthchecks": {
4
+ "web": [
5
+ {
6
+ "type": "startup",
7
+ "name": "web-ready",
8
+ "description": "Application responds to /api/health",
9
+ "path": "/api/health",
10
+ "attempts": 6
11
+ }
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,71 @@
1
+ import { spawn } from "node:child_process";
2
+ import { startServer } from "../server.js";
3
+
4
+ const LOOPBACK_HOST = "127.0.0.1";
5
+
6
+ function requiredPort(value, fallback = 3000) {
7
+ const normalized = String(value || "").trim();
8
+ const parsed = Number.parseInt(normalized || String(fallback), 10);
9
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65_535) {
10
+ throw new Error(`Invalid development port: ${normalized || "(empty)"}.`);
11
+ }
12
+ return parsed;
13
+ }
14
+
15
+ function waitForChild(child) {
16
+ return new Promise((resolve, reject) => {
17
+ child.once("error", reject);
18
+ child.once("exit", (code, signal) => resolve({ code, signal }));
19
+ });
20
+ }
21
+
22
+ const previewHost = String(process.env.HOST || "").trim() || "0.0.0.0";
23
+ const previewPort = requiredPort(process.env.PORT);
24
+ let apiServer = null;
25
+ let viteProcess = null;
26
+ let requestedSignal = "";
27
+
28
+ function requestShutdown(signal) {
29
+ requestedSignal = signal;
30
+ if (viteProcess && !viteProcess.killed) {
31
+ viteProcess.kill(signal);
32
+ }
33
+ }
34
+
35
+ process.once("SIGINT", () => requestShutdown("SIGINT"));
36
+ process.once("SIGTERM", () => requestShutdown("SIGTERM"));
37
+
38
+ try {
39
+ apiServer = await startServer({ host: LOOPBACK_HOST, port: 0 });
40
+ const apiPort = requiredPort(apiServer.server.address()?.port);
41
+ const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
42
+ viteProcess = spawn(
43
+ npmCommand,
44
+ ["run", "dev", "--", "--host", previewHost, "--port", String(previewPort), "--strictPort"],
45
+ {
46
+ cwd: process.cwd(),
47
+ env: {
48
+ ...process.env,
49
+ HOST: previewHost,
50
+ PORT: String(previewPort),
51
+ VITE_API_PROXY_TARGET: `http://${LOOPBACK_HOST}:${apiPort}`,
52
+ VITE_DEV_PORT: String(previewPort)
53
+ },
54
+ stdio: "inherit"
55
+ }
56
+ );
57
+
58
+ const result = await waitForChild(viteProcess);
59
+ if (!requestedSignal && result.code !== 0) {
60
+ throw new Error(
61
+ `Vite development server stopped unexpectedly (${result.signal || `exit ${result.code ?? "unknown"}`}).`
62
+ );
63
+ }
64
+ } catch (error) {
65
+ console.error("Failed to start the development application:", error);
66
+ process.exitCode = 1;
67
+ } finally {
68
+ if (apiServer) {
69
+ await apiServer.close().catch(() => {});
70
+ }
71
+ }
@@ -0,0 +1,8 @@
1
+ import { startServer } from "../server.js";
2
+
3
+ try {
4
+ await startServer();
5
+ } catch (error) {
6
+ console.error("Failed to start reading-room server:", error);
7
+ process.exitCode = 1;
8
+ }
@@ -0,0 +1,40 @@
1
+ import { surfaceAccessPolicies } from "./surfaceAccessPolicies.js";
2
+
3
+ export const config = {};
4
+
5
+ config.surfaceModeAll = "all";
6
+ config.surfaceDefaultId = "home";
7
+ config.webRootAllowed = "no";
8
+ config.surfaceAccessPolicies = surfaceAccessPolicies;
9
+ config.mobile = {
10
+ enabled: false,
11
+ strategy: "",
12
+ appId: "",
13
+ appName: "",
14
+ assetMode: "bundled",
15
+ devServerUrl: "",
16
+ apiBaseUrl: "",
17
+ auth: {
18
+ callbackPath: "/auth/login",
19
+ customScheme: "",
20
+ appLinkDomains: []
21
+ },
22
+ android: {
23
+ packageName: "",
24
+ minSdk: 26,
25
+ targetSdk: 35,
26
+ versionCode: 1,
27
+ versionName: "1.0.0"
28
+ }
29
+ };
30
+ config.surfaceDefinitions = {};
31
+ config.surfaceDefinitions.home = {
32
+ id: "home",
33
+ label: "Home",
34
+ pagesRoot: "home",
35
+ enabled: true,
36
+ requiresAuth: false,
37
+ requiresWorkspace: false,
38
+ accessPolicyId: "public",
39
+ origin: ""
40
+ };
@@ -0,0 +1 @@
1
+ export const config = {};
@@ -0,0 +1,3 @@
1
+ export const surfaceAccessPolicies = {};
2
+
3
+ surfaceAccessPolicies.public = {};
@@ -0,0 +1,19 @@
1
+ import { baseConfig, nodeConfig, vueConfig, webConfig } from "@jskit-ai/config-eslint/server";
2
+
3
+ export default [
4
+ {
5
+ ignores: ["dist/**", "node_modules/**", "coverage/**", "test-results/**", ".jskit/**"]
6
+ },
7
+ {
8
+ files: ["src/pages/**/*.vue"],
9
+ languageOptions: {
10
+ globals: {
11
+ definePage: "readonly"
12
+ }
13
+ }
14
+ },
15
+ ...baseConfig,
16
+ ...vueConfig,
17
+ ...webConfig,
18
+ ...nodeConfig
19
+ ];
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
+ <rect width="64" height="64" rx="12" fill="#111827" />
3
+ <path
4
+ d="M20 16h24v8H28v20c0 6-4 10-10 10h-2v-8h2c2 0 2-1 2-3V16z"
5
+ fill="#22d3ee"
6
+ />
7
+ </svg>
@@ -0,0 +1,9 @@
1
+ node_modules/
2
+ dist/
3
+ coverage/
4
+ test-results/
5
+ # Generated by vue-router/vite on the first dev or build scan.
6
+ src/typed-router.d.ts
7
+ .env
8
+ .env.*
9
+ !.env.example
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+ <title>Reading Room</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.js"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": ["src/*"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "reading-room",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Minimal JSKIT base app (Fastify + Vue)",
7
+ "engines": {
8
+ "node": "26.x"
9
+ },
10
+ "scripts": {
11
+ "server": "node ./bin/server.js",
12
+ "server:all": "node ./bin/server.js",
13
+ "server:home": "SERVER_SURFACE=home node ./bin/server.js",
14
+ "start": "node ./bin/server.js",
15
+ "develop": "node ./bin/develop.js",
16
+ "dev": "vite",
17
+ "dev:all": "vite",
18
+ "dev:home": "VITE_SURFACE=home vite",
19
+ "build": "vite build",
20
+ "build:all": "vite build",
21
+ "build:home": "VITE_SURFACE=home vite build",
22
+ "preview": "vite preview",
23
+ "lint": "eslint .",
24
+ "test": "node --test",
25
+ "test:client": "vitest run tests/client",
26
+ "test:e2e": "playwright test tests/e2e",
27
+ "verify": "npm run lint && npm run test && npm run test:client && npm run build"
28
+ },
29
+ "dependencies": {
30
+ "@local/main": "file:packages/main",
31
+ "@fastify/static": "^10.1.3",
32
+ "@jskit-ai/kernel": "0.1.161",
33
+ "@tanstack/vue-query": "^5.101.0",
34
+ "fastify": "^5.8.5",
35
+ "json-rest-schema": "^1.0.17",
36
+ "pinia": "^3.0.4",
37
+ "vue": "^3.5.38",
38
+ "vue-router": "^5.1.0",
39
+ "vuetify": "^4.1.2",
40
+ "@jskit-ai/http-runtime": "0.1.159"
41
+ },
42
+ "devDependencies": {
43
+ "@jskit-ai/agent-docs": "0.1.133",
44
+ "@jskit-ai/config-eslint": "0.1.158",
45
+ "@playwright/test": "1.61.1",
46
+ "@vitejs/plugin-vue": "^6.0.7",
47
+ "eslint": "^10.8.0",
48
+ "vite": "^8.2.1",
49
+ "vite-plugin-vuetify": "^2.1.3",
50
+ "vitest": "^4.1.9"
51
+ },
52
+ "allowScripts": {
53
+ "fsevents@2.3.2": true,
54
+ "fsevents@2.3.3": true,
55
+ "vue-demi@0.14.10": true
56
+ }
57
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@local/main",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "exports": {
7
+ "./shared": "./src/shared/index.js"
8
+ },
9
+ "description": "App-local runtime composition and lightweight glue.",
10
+ "jskit": {
11
+ "kind": "runtime",
12
+ "capabilities": {
13
+ "provides": [],
14
+ "requires": []
15
+ },
16
+ "metadata": {
17
+ "jskit": {
18
+ "ownershipGuidance": {
19
+ "title": "App-local main lane",
20
+ "summary": "Keep @local/main focused on app composition and lightweight glue. Substantial server features should become dedicated packages instead of growing inside packages/main.",
21
+ "responsibilities": [
22
+ "packages/main server code: bootstraps app-local configuration and lightweight wiring only",
23
+ "substantial server features: author a dedicated app-local package from the relevant framework pattern",
24
+ "packages/main: do not add service/controller/route/repository feature trees here"
25
+ ],
26
+ "examples": [
27
+ "packages/booking-engine owns booking operations",
28
+ "packages/availability-engine owns availability orchestration"
29
+ ]
30
+ }
31
+ },
32
+ "server": {
33
+ "routes": []
34
+ },
35
+ "ui": {
36
+ "routes": [],
37
+ "elements": [],
38
+ "overrides": []
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared entrypoint for code used by both client and server.
3
+ *
4
+ * Keep this for genuinely app-local shared glue only.
5
+ *
6
+ * Example:
7
+ * export * from "./schemas/index.js";
8
+ * export * from "./constants/index.js";
9
+ */
10
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * App-local shared transport validators/resources live here.
3
+ * Dedicated feature packages should keep their own schemas with the feature.
4
+ *
5
+ * Example:
6
+ * import { createSchema } from "json-rest-schema";
7
+ *
8
+ * export const helloQuerySchema = createSchema({
9
+ * name: { type: "string", minLength: 1, maxLength: 80 }
10
+ * });
11
+ *
12
+ * export const helloResponseSchema = {
13
+ * type: "object",
14
+ * additionalProperties: false,
15
+ * required: ["ok", "message"],
16
+ * properties: {
17
+ * ok: { type: "boolean" },
18
+ * message: { type: "string", minLength: 1 }
19
+ * }
20
+ * };
21
+ */
22
+ export {};
@@ -0,0 +1,31 @@
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ const managedBaseUrl = String(process.env.PLAYWRIGHT_BASE_URL || "")
4
+ .trim()
5
+ .replace(/\/+$/u, "");
6
+ const baseURL = managedBaseUrl || "http://127.0.0.1:4173";
7
+ const storageState = String(process.env.VIBE64_PLAYWRIGHT_STORAGE_STATE || "").trim();
8
+
9
+ export default defineConfig({
10
+ testDir: "./tests/e2e",
11
+ timeout: 60_000,
12
+ expect: {
13
+ timeout: 10_000
14
+ },
15
+ use: {
16
+ baseURL,
17
+ headless: true,
18
+ ...(storageState ? { storageState } : {})
19
+ },
20
+ ...(managedBaseUrl ? {} : {
21
+ webServer: {
22
+ command: "npm run build && node ./bin/server.js",
23
+ env: {
24
+ PORT: "4173"
25
+ },
26
+ url: `${baseURL}/api/health`,
27
+ reuseExistingServer: true,
28
+ timeout: 180_000
29
+ }
30
+ })
31
+ });
@@ -0,0 +1,45 @@
1
+ import { createRequire } from "node:module";
2
+ import { surfaceRuntime } from "./surfaceRuntime.js";
3
+
4
+ const require = createRequire(import.meta.url);
5
+
6
+ function toPort(value, fallback = 3000) {
7
+ const parsed = Number.parseInt(String(value || "").trim(), 10);
8
+ if (Number.isInteger(parsed) && parsed > 0) {
9
+ return parsed;
10
+ }
11
+ return fallback;
12
+ }
13
+
14
+ let envLoaded = false;
15
+
16
+ function ensureRuntimeEnvLoaded() {
17
+ if (envLoaded) {
18
+ return;
19
+ }
20
+ try {
21
+ const dotenvModule = require("dotenv");
22
+ const loadDotEnv = dotenvModule?.config;
23
+ if (typeof loadDotEnv === "function") {
24
+ loadDotEnv();
25
+ }
26
+ } catch {
27
+ // dotenv is optional in base-shell; bundles can add it when needed.
28
+ }
29
+ envLoaded = true;
30
+ }
31
+
32
+ function resolveRuntimeEnv() {
33
+ ensureRuntimeEnvLoaded();
34
+ const serverSurface = surfaceRuntime.normalizeSurfaceMode(
35
+ process.env.JSKIT_SERVER_SURFACE || process.env.SERVER_SURFACE
36
+ );
37
+ return {
38
+ ...process.env,
39
+ SERVER_SURFACE: serverSurface,
40
+ PORT: toPort(process.env.PORT, 3000),
41
+ HOST: String(process.env.HOST || "").trim() || "0.0.0.0"
42
+ };
43
+ }
44
+
45
+ export { resolveRuntimeEnv };
@@ -0,0 +1,10 @@
1
+ import { createSurfaceRuntime } from "@jskit-ai/kernel/shared/surface/runtime";
2
+ import { config } from "../../config/public.js";
3
+
4
+ const surfaceRuntime = createSurfaceRuntime({
5
+ allMode: config.surfaceModeAll,
6
+ surfaces: config.surfaceDefinitions,
7
+ defaultSurfaceId: config.surfaceDefaultId
8
+ });
9
+
10
+ export { surfaceRuntime };