@jskit-ai/agent-docs 0.1.256 → 0.1.258

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 (230) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +88 -35
  2. package/guide/agent/app-extras/assistant.md +28 -28
  3. package/guide/agent/app-setup/authentication.md +36 -17
  4. package/guide/agent/app-setup/database-layer.md +116 -17
  5. package/guide/agent/app-setup/existing-application-migration.md +29 -25
  6. package/guide/agent/app-setup/multi-homing.md +94 -48
  7. package/guide/agent/app-setup/run-an-accounts-hub.md +6 -4
  8. package/guide/agent/framework/client-features.md +496 -0
  9. package/guide/agent/framework/crud-operations.md +5 -5
  10. package/guide/agent/framework/translation.md +4 -3
  11. package/guide/agent/framework/typed-features.md +1104 -0
  12. package/guide/agent/framework/ui-operations.md +2 -2
  13. package/guide/agent/index.md +6 -1
  14. package/package.json +1 -1
  15. package/patterns/feature-package/PATTERN.md +104 -10
  16. package/patterns/feature-package/example/booking-engine/package.json +9 -4
  17. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
  18. package/patterns/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
  19. package/patterns/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
  20. package/patterns/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
  21. package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
  22. package/patterns/feature-package/example/booking-engine/src/server/types.js +12 -0
  23. package/patterns/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
  24. package/patterns/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
  25. package/patterns/feature-package/example/variations/availabilityEngineActions.js +26 -0
  26. package/patterns/feature-package/example/variations/customKnexRepository.js +32 -26
  27. package/patterns/feature-package/example/variations/invoiceRollupActions.js +26 -0
  28. package/patterns/feature-package/example/variations/orchestratorService.js +24 -19
  29. package/patterns/feature-package/example/variations/types.js +7 -0
  30. package/patterns/minimal-foundation/PATTERN.md +30 -1
  31. package/patterns/minimal-foundation/example/AGENTS.md +14 -0
  32. package/patterns/minimal-foundation/example/bin/develop.js +10 -5
  33. package/patterns/minimal-foundation/example/eslint.config.mjs +21 -2
  34. package/patterns/minimal-foundation/example/package.json +5 -4
  35. package/patterns/minimal-foundation/example/playwright.config.mjs +1 -1
  36. package/patterns/minimal-foundation/example/server/lib/envFile.js +19 -0
  37. package/patterns/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
  38. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
  39. package/patterns/minimal-foundation/example/server.js +32 -29
  40. package/patterns/minimal-foundation/example/tests/server/smoke.test.js +2 -1
  41. package/patterns/shell-foundation/PATTERN.md +29 -0
  42. package/patterns/shell-foundation/example/AGENTS.md +14 -0
  43. package/patterns/shell-foundation/example/bin/develop.js +10 -5
  44. package/patterns/shell-foundation/example/eslint.config.mjs +21 -2
  45. package/patterns/shell-foundation/example/package.json +6 -5
  46. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  47. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
  48. package/patterns/shell-foundation/example/playwright.config.mjs +1 -1
  49. package/patterns/shell-foundation/example/server/lib/envFile.js +19 -0
  50. package/patterns/shell-foundation/example/server/lib/loggerOptions.js +15 -0
  51. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
  52. package/patterns/shell-foundation/example/server.js +32 -29
  53. package/patterns/shell-foundation/example/tests/server/smoke.test.js +2 -1
  54. package/reference/autogen/KERNEL_MAP.md +14 -8
  55. package/reference/autogen/PATTERN_INDEX.md +37 -37
  56. package/reference/autogen/README.md +2 -0
  57. package/reference/autogen/packages/agent-docs.md +70 -26
  58. package/reference/autogen/packages/agent-runtime.md +129 -0
  59. package/reference/autogen/packages/agent.md +149 -0
  60. package/reference/autogen/packages/architecture-inspector.md +97 -44
  61. package/reference/autogen/packages/assistant-core.md +786 -292
  62. package/reference/autogen/packages/assistant-runtime.md +182 -57
  63. package/reference/autogen/packages/assistant-voice-sherpa.md +4 -0
  64. package/reference/autogen/packages/assistant-voice.md +54 -8
  65. package/reference/autogen/packages/auth-core.md +44 -13
  66. package/reference/autogen/packages/auth-provider-local-core.md +86 -34
  67. package/reference/autogen/packages/auth-provider-local-db-core.md +1 -2
  68. package/reference/autogen/packages/auth-provider-oidc-core.md +10 -4
  69. package/reference/autogen/packages/auth-provider-supabase-core.md +52 -66
  70. package/reference/autogen/packages/auth-web.md +19 -11
  71. package/reference/autogen/packages/connectors-catalog.md +71 -43
  72. package/reference/autogen/packages/connectors-core.md +42 -4
  73. package/reference/autogen/packages/console-core.md +27 -14
  74. package/reference/autogen/packages/crud-core.md +178 -170
  75. package/reference/autogen/packages/database-runtime-mysql.md +0 -2
  76. package/reference/autogen/packages/database-runtime-postgres.md +0 -2
  77. package/reference/autogen/packages/database-runtime.md +39 -10
  78. package/reference/autogen/packages/http-runtime.md +79 -57
  79. package/reference/autogen/packages/json-rest-api-core.md +11 -8
  80. package/reference/autogen/packages/kernel.md +144 -83
  81. package/reference/autogen/packages/oidc-issuer-core.md +49 -20
  82. package/reference/autogen/packages/payments-core.md +20 -3
  83. package/reference/autogen/packages/realtime.md +47 -22
  84. package/reference/autogen/packages/resource-core.md +1 -1
  85. package/reference/autogen/packages/resource-crud-core.md +64 -26
  86. package/reference/autogen/packages/rewarded-core.md +47 -36
  87. package/reference/autogen/packages/shell-web.md +7 -10
  88. package/reference/autogen/packages/storage-runtime.md +6 -2
  89. package/reference/autogen/packages/uploads-runtime.md +10 -2
  90. package/reference/autogen/packages/users-core.md +73 -71
  91. package/reference/autogen/packages/workspaces-core.md +121 -106
  92. package/reference/autogen/packages/workspaces-web.md +1 -2
  93. package/reference/autogen/tooling/config-eslint.md +302 -0
  94. package/reference/autogen/tooling/jskit-catalog.md +28 -18
  95. package/reference/autogen/tooling/jskit-release.md +35 -20
  96. package/reference/autogen/tooling/testUtils.md +3 -1
  97. package/skills/jskit/SKILL.md +3 -2
  98. package/skills/jskit/references/app-operations.md +1 -1
  99. package/skills/jskit/references/client-features.md +491 -0
  100. package/skills/jskit/references/crud-form-actions.md +1 -1
  101. package/skills/jskit/references/crud-operations.md +7 -7
  102. package/skills/jskit/references/existing-application-migration.md +31 -27
  103. package/skills/jskit/references/heuristics/INDEX.md +5 -1
  104. package/skills/jskit/references/heuristics/child-cruds.md +1 -1
  105. package/skills/jskit/references/heuristics/client-features.md +66 -0
  106. package/skills/jskit/references/heuristics/client-requests.md +1 -1
  107. package/skills/jskit/references/heuristics/crud-authoring.md +12 -2
  108. package/skills/jskit/references/heuristics/crud-links.md +1 -1
  109. package/skills/jskit/references/heuristics/crud-repository-mapping.md +3 -3
  110. package/skills/jskit/references/heuristics/filters.md +1 -1
  111. package/skills/jskit/references/heuristics/live-actions.md +1 -1
  112. package/skills/jskit/references/heuristics/page-redirects.md +1 -1
  113. package/skills/jskit/references/heuristics/page-scaffolding.md +1 -1
  114. package/skills/jskit/references/heuristics/placements.md +1 -1
  115. package/skills/jskit/references/heuristics/row-policies.md +1 -1
  116. package/skills/jskit/references/heuristics/server-search.md +1 -1
  117. package/skills/jskit/references/heuristics/surfaces.md +1 -1
  118. package/skills/jskit/references/heuristics/typed-features.md +100 -0
  119. package/skills/jskit/references/heuristics/ui-contract.md +1 -1
  120. package/skills/jskit/references/heuristics/ui-testing.md +4 -4
  121. package/skills/jskit/references/material-3.md +2 -2
  122. package/skills/jskit/references/multi-homing.md +96 -50
  123. package/skills/jskit/references/pattern-index.md +37 -37
  124. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +30 -1
  125. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +14 -0
  126. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +10 -5
  127. package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +21 -2
  128. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +5 -4
  129. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +1 -1
  130. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/envFile.js +19 -0
  131. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
  132. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
  133. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +32 -29
  134. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +2 -1
  135. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +29 -0
  136. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +14 -0
  137. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +10 -5
  138. package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +21 -2
  139. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +6 -5
  140. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  141. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
  142. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +1 -1
  143. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/envFile.js +19 -0
  144. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/loggerOptions.js +15 -0
  145. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
  146. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +32 -29
  147. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +2 -1
  148. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/ApplicationAiFeature.js +4 -2
  149. package/skills/jskit/references/patterns/auth/accounts-hub/PATTERN.md +2 -1
  150. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  151. package/skills/jskit/references/patterns/auth/accounts-hub/example/server/hubPaths.js +9 -3
  152. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +25 -12
  153. package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +7 -1
  154. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  155. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  156. package/skills/jskit/references/patterns/connectors/ai-connections/PATTERN.md +16 -1
  157. package/skills/jskit/references/patterns/connectors/ai-connections/example/ai-model.js +12 -3
  158. package/skills/jskit/references/patterns/connectors/ai-connections/example/perplexity-answer.js +15 -4
  159. package/skills/jskit/references/patterns/connectors/api-key-connection/PATTERN.md +9 -1
  160. package/skills/jskit/references/patterns/connectors/api-key-connection/example/connections.js +5 -2
  161. package/skills/jskit/references/patterns/connectors/aws-storage-queries/PATTERN.md +13 -3
  162. package/skills/jskit/references/patterns/connectors/aws-storage-queries/example/s3-transfer.js +14 -3
  163. package/skills/jskit/references/patterns/connectors/calendar-cli/PATTERN.md +8 -0
  164. package/skills/jskit/references/patterns/connectors/calendar-cli/example/knexfile.js +1 -1
  165. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  166. package/skills/jskit/references/patterns/connectors/calendar-cli/example/scripts/calendar.js +8 -4
  167. package/skills/jskit/references/patterns/connectors/event-delivery/PATTERN.md +1 -1
  168. package/skills/jskit/references/patterns/connectors/firebase-messaging/PATTERN.md +10 -0
  169. package/skills/jskit/references/patterns/connectors/firebase-messaging/example/server/notifications.js +8 -0
  170. package/skills/jskit/references/patterns/connectors/google-ads-search/PATTERN.md +18 -7
  171. package/skills/jskit/references/patterns/connectors/google-ads-search/example/ads-setup.js +13 -5
  172. package/skills/jskit/references/patterns/connectors/oauth-connection/PATTERN.md +1 -1
  173. package/skills/jskit/references/patterns/connectors/paddle-catalogue/PATTERN.md +11 -2
  174. package/skills/jskit/references/patterns/connectors/paddle-catalogue/example/create-products.js +5 -2
  175. package/skills/jskit/references/patterns/connectors/public-image/PATTERN.md +10 -1
  176. package/skills/jskit/references/patterns/connectors/public-image/example/logo-url.js +4 -1
  177. package/skills/jskit/references/patterns/connectors/redshift-queries/PATTERN.md +1 -1
  178. package/skills/jskit/references/patterns/connectors/source-scanning/PATTERN.md +13 -2
  179. package/skills/jskit/references/patterns/connectors/source-scanning/example/source-scanner.js +9 -0
  180. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +102 -23
  181. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +3 -2
  182. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/types.js +5 -0
  183. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +54 -1
  184. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +16 -5
  185. package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +2 -2
  186. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  187. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +1 -1
  188. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +16 -5
  189. package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +2 -2
  190. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  191. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +1 -1
  192. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  193. package/skills/jskit/references/patterns/rewards/google-rewarded/example/GoogleRewardedDeliveryProvider.js +1 -1
  194. package/skills/jskit/references/patterns/rewards/google-rewarded/example/googlePublisherTag.js +5 -11
  195. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +104 -10
  196. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +9 -4
  197. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
  198. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
  199. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
  200. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
  201. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
  202. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/types.js +12 -0
  203. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
  204. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
  205. package/skills/jskit/references/patterns/server/feature-package/example/variations/availabilityEngineActions.js +26 -0
  206. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +32 -26
  207. package/skills/jskit/references/patterns/server/feature-package/example/variations/invoiceRollupActions.js +26 -0
  208. package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +24 -19
  209. package/skills/jskit/references/patterns/server/feature-package/example/variations/types.js +7 -0
  210. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +16 -1
  211. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +3 -2
  212. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/types.js +5 -0
  213. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +4 -3
  214. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +2 -9
  215. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/types.js +5 -0
  216. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +42 -17
  217. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/WorkspaceInvitationsFeature.js +27 -0
  218. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +11 -10
  219. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteMailer.js +27 -0
  220. package/skills/jskit/references/translation.md +5 -4
  221. package/skills/jskit/references/typed-features.md +1099 -0
  222. package/skills/jskit/references/ui-operations.md +3 -3
  223. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
  224. package/patterns/feature-package/example/booking-engine/src/server/actions.js +0 -24
  225. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
  226. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
  227. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
  228. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +0 -24
  229. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
  230. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
@@ -0,0 +1,491 @@
1
+ <!-- Generated from `packages/agent-docs/site/guide/framework/client-features.md`. -->
2
+
3
+ # Client features
4
+
5
+ Read this page before writing or reviewing JSKIT client code: a composable, a
6
+ Vue component, a client factory or a client provider. It is the client half of
7
+ [typed features](typed-features.md): the same rule, the same
8
+ `readable-check: allow` vocabulary and the same size limits, applied to Vue.
9
+ `clientFeaturesConfig` makes the rules a machine can see errors
10
+ ([checks](#checks)); the others are checked by reading.
11
+
12
+ The [client features heuristic](heuristics/client-features.md)
13
+ maps keywords and lint findings to the section that fixes them.
14
+
15
+ ## The rule
16
+
17
+ > Every collaborator client code uses arrives through its options, props,
18
+ > injection or provider capabilities, typed where it is received and required,
19
+ > never probed, so each call has one visible destination.
20
+
21
+ - A **collaborator** is an object or function with behaviour that code calls:
22
+ an adapter, an API client, a state object with methods, a callback, a router.
23
+ Plain data (a label, a list, a record) is not one.
24
+ - A **composable** is a `use<Name>()` function that holds Vue state; a **client
25
+ factory** is a `create<Name>()` that holds none.
26
+
27
+ ## Simplicity
28
+
29
+ ### Simple to reason about
30
+
31
+ **A reader follows each flow top to bottom: plain functions, direct calls,
32
+ names that say what they do.** Satisfying a rule by adding a layer, a
33
+ registry, a pass-through wrapper, meta-programming or a one-use abstraction is
34
+ wrong, and so is splitting a file into many tiny modules to meet a size limit.
35
+
36
+ Signs of over-cleverness: a `create*` that only forwards to another; handlers
37
+ built in a loop or from strings; `Object.fromEntries(… .map(…))` to build an
38
+ API; a `Proxy`; a factory used once; a registry for two entries; a module of
39
+ one three-line helper; files named `utils2`, `part1` or `…Helpers`.
40
+
41
+ Why: the rules exist so code is easy to follow; a contortion that silences one
42
+ defeats it.
43
+
44
+ ```js
45
+ // good: the contract is required, so the calls are direct
46
+ function resend(messageId) {
47
+ return controller.resend(messageId);
48
+ }
49
+
50
+ // bad: a computed layer that hides two probes
51
+ const operations = Object.fromEntries(["find", "resend"].map((name) => [name, (...args) => controller.value?.[name]?.(...args)]));
52
+ ```
53
+
54
+ When a rule seems to force a contortion, take the direct reading that meets
55
+ its intent, and report the case so the rule can be narrowed.
56
+
57
+ ## Types and collaborators
58
+
59
+ ### Client types
60
+
61
+ **A package's client types live in `src/client/types.js`, exported as
62
+ `./client/types` when another package uses them: one `@typedef` per value its
63
+ client code hands out or receives across files.** That is a composable's
64
+ result (`ReturnType<typeof useX>`), a client factory's result, and each
65
+ contract an application implements, written once with its optional members
66
+ marked `?`. Kernel capabilities come from `@jskit-ai/kernel/client/types`:
67
+ `ClientComponents`, `ClientVueApp`, `ClientRouter`, `ClientPinia`,
68
+ `ClientQueryClient`, `ClientEnv`, `ClientSurfaceRuntime`, `ClientSurfaceMode`
69
+ and `ClientLogger`.
70
+
71
+ Why: a parameter that names its type sends a reader to one file.
72
+
73
+ ```js
74
+ // good: src/client/types.js
75
+ /** @typedef {ReturnType<typeof import("./useAttachmentQueue.js").useAttachmentQueue>} AttachmentQueue */
76
+ /**
77
+ * What an application supplies to render a conversation.
78
+ * @typedef {object} ConversationAdapter
79
+ * @property {(text: string) => Promise<void>} send
80
+ * @property {MessageDelivery} [delivery] Present when the application tracks delivery.
81
+ */
82
+ export {};
83
+
84
+ // bad: the shape is whatever the caller passed
85
+ function useConversationActions({ adapter }) {
86
+ ```
87
+
88
+ ### Typed options
89
+
90
+ **A composable, client factory or helper destructures its options in its
91
+ signature and types them with a JSDoc `@param`.** An options object's `= {}`
92
+ stays only where a real caller passes nothing and every member has its own
93
+ default.
94
+
95
+ Why: the same one-step reading as server code; `useX(options)` read in the
96
+ body hides what it needs.
97
+
98
+ ```js
99
+ // good
100
+ /** @param {{ uploadAttachment: AttachmentUpload, onUploaded: (attachment: Attachment) => void }} options */
101
+ function useAttachments({ uploadAttachment, onUploaded }) {
102
+
103
+ // bad
104
+ function useAttachments(options = {}) {
105
+ const upload = options.uploadAttachment;
106
+ ```
107
+
108
+ ### Required options
109
+
110
+ **A collaborator every real caller passes is required: no `= null`, `= {}` or
111
+ no-op default, no `typeof x === "function"` probe and no `x?.()` call.** A
112
+ default that is the production implementation stays (`now = Date.now`).
113
+
114
+ Why: a probe gives each call a second outcome that production never takes.
115
+
116
+ ```js
117
+ // good
118
+ function useAttachments({ uploadAttachment }) {
119
+
120
+ // bad: every caller passes uploadAttachment, yet it is probed
121
+ function useAttachments({ uploadAttachment = null } = {}) {
122
+ if (typeof uploadAttachment !== "function") return;
123
+ ```
124
+
125
+ ### Absent options
126
+
127
+ **What a real caller leaves out takes one of the server's two forms.** A
128
+ per-call callback (`onError`, `onProgress`) defaults to a named no-op and is
129
+ called plainly. An optional operation, a contract member some real caller
130
+ omits, is typed `?`, received with no default, probed once with an
131
+ `optional operation:` allow comment, and branched on that one boolean.
132
+
133
+ - When the member is read live (an application binding behind a getter), probe
134
+ it where it is called, with one allow comment, through one local reader
135
+ function when several sites call it.
136
+ - In a template, call it in the binding, `adapter.actions.reload?.()`, with one
137
+ HTML allow comment directly above the element's opening tag; it covers that
138
+ element's bindings, not its children's. Never `a?.b && a.b()`.
139
+ - A maybe-ref input (`MaybeRefOrGetter<T>`) is read with Vue's `toValue()`.
140
+ - A function whose one job is normalizing a documented external value of
141
+ several shapes carries one `input validation:` allow comment directly above
142
+ it, which covers the probes in its own body. Nowhere else: never over a
143
+ composable, a `setup()` or a function that does more than normalize.
144
+
145
+ A test-only omission counts for none of these: complete the double.
146
+
147
+ Why: one spelling for "may be absent" across server and client, and one probe
148
+ instead of one per call.
149
+
150
+ ```js
151
+ // good
152
+ function ignoreProgress() {}
153
+ function useUpload({ onProgress = ignoreProgress }) {
154
+ onProgress(0);
155
+ }
156
+ /** @param {{ deleteAttachment?: AttachmentDelete }} options */
157
+ function useAttachments({ deleteAttachment }) {
158
+ // readable-check: allow method-probe - optional operation: a read-only queue has no deleteAttachment, so removal stays local
159
+ const canDelete = typeof deleteAttachment === "function";
160
+ }
161
+ const text = toValue(source);
162
+
163
+ // bad
164
+ function useUpload({ onProgress = null }) {
165
+ onProgress?.(0);
166
+ }
167
+ const text = typeof source === "function" ? source() : source.value;
168
+ ```
169
+
170
+ ```html
171
+ <!-- good -->
172
+ <!-- readable-check: allow optional-call - optional operation: a read-only transcript has no reload -->
173
+ <v-btn :disabled="loading" @click="adapter.actions.reload?.()" />
174
+
175
+ <!-- bad -->
176
+ <v-btn v-if="adapter.actions?.reload" @click="adapter.actions.reload()" />
177
+ ```
178
+
179
+ ### Platform probes
180
+
181
+ **A probe of a host object lives in one helper per package,
182
+ `hasWindowFunction(name)`, with one `platform object:` allow comment, and is
183
+ imported.**
184
+
185
+ Why: one treatment per probe kind; copies of a `window` probe drift.
186
+
187
+ ```js
188
+ // good: src/client/browser.js
189
+ /** Whether the page's window has the named function; outside a browser there is no window. */
190
+ function hasWindowFunction(name) {
191
+ // readable-check: allow method-probe - platform object: window and its functions exist only in a browser
192
+ return typeof window !== "undefined" && typeof window[name] === "function";
193
+ }
194
+
195
+ // bad, in five places
196
+ if (typeof window !== "undefined" && typeof window.clearTimeout === "function") window.clearTimeout(timer);
197
+ ```
198
+
199
+ ### Client providers
200
+
201
+ **A client provider follows the server's token rules: `requires`, `optional`
202
+ and `provides` one per line, hooks typed with the kernel's or the owner's
203
+ types, registration in `setup()`, a replaceable value as an `optional` token
204
+ with a named default, and no module-level registry.**
205
+
206
+ Why: client providers are capabilities like server features; a slot filled by
207
+ a setter or a module map has no visible owner.
208
+
209
+ ```js
210
+ // good
211
+ const ConversationClientProvider = defineProvider({
212
+ id: "conversation.web.client",
213
+ requires: {
214
+ components: "client.components"
215
+ },
216
+ /** @param {{ components: import("@jskit-ai/kernel/client/types").ClientComponents }} capabilities */
217
+ setup({ components }) {
218
+ components.register("conversation.web.settings.element", ConversationSettingsElement);
219
+ }
220
+ });
221
+
222
+ // bad
223
+ const components = new Map();
224
+ export function registerComponent(id, component) { components.set(id, component); }
225
+ ```
226
+
227
+ ### Injected values
228
+
229
+ **`inject()` takes the owner's exported key, never a literal. A required value
230
+ is `inject(KEY)`; one that may be absent is `inject(KEY, NAMED_DEFAULT)` with
231
+ the named default exported beside the key. The binding names its type.** A
232
+ key another package owns is imported, with its type and disabled default, from
233
+ that package; a consumer that cannot depend on it writes the key in place,
234
+ typed, with a named `NO_*` default.
235
+
236
+ Why: injection is the client's capability lookup: one key, one type, one
237
+ resolution.
238
+
239
+ ```js
240
+ // good
241
+ /** @type {import("@jskit-ai/workspaces-web/client/types").WorkspaceScopeSupport} */
242
+ const support = inject(WORKSPACE_SCOPE_KEY, NO_WORKSPACE_SCOPE);
243
+
244
+ // bad
245
+ const support = inject("workspaceScope", null);
246
+ if (!support || typeof support.readRouteScope !== "function") return FALLBACK;
247
+ ```
248
+
249
+ ## Components
250
+
251
+ ### Collaborator props
252
+
253
+ **Every prop has a `type` and is required or has a real default. A prop the
254
+ component calls is `required: true`, typed with a `PropType` cast to its
255
+ typedef, and called without `?.`.** A collaborator prop that real callers
256
+ genuinely leave out keeps `default: null`, is typed `PropType<X | null>`,
257
+ carries one `optional operation:` allow comment and is branched on once.
258
+
259
+ Why: a `default: null` collaborator is a probe at every use; a chain of `?.`
260
+ calls on one adapter hides which parts are really optional.
261
+
262
+ ```js
263
+ // good
264
+ const props = defineProps({
265
+ state: { type: /** @type {import("vue").PropType<GoalState>} */ (Object), required: true }
266
+ });
267
+ const canSet = computed(() => !props.state.loading && props.state.available);
268
+
269
+ // bad
270
+ const props = defineProps({ state: { type: Object, default: null } });
271
+ const canSet = computed(() => typeof props.state?.set === "function");
272
+ ```
273
+
274
+ ### Declared emits
275
+
276
+ **`defineEmits()` lists every event the component emits, including those a
277
+ composable emits through the `emit` it receives.**
278
+
279
+ Why: the declaration is the component's event contract, and an undeclared
280
+ event also falls through as a DOM listener.
281
+
282
+ ```js
283
+ // good
284
+ const emit = defineEmits(["close", "closed"]);
285
+
286
+ // bad
287
+ const emit = defineEmits(["close"]);
288
+ emit("closed");
289
+ ```
290
+
291
+ ### Presenting scripts
292
+
293
+ **A component's `<script>` presents: props, emits, element refs, display
294
+ `computed`s and handlers that call a composable or emit.** Requests, state
295
+ machines, timers, parsing and projections live in a composable or a plain
296
+ module, moved verbatim. Split by concern into a few cohesive pieces; a large
297
+ style block moves to `<style scoped src="./X.css">`. Never a subcomponent made
298
+ only to shrink a file: it changes scoped styles and slots.
299
+
300
+ Why: logic in a composable is read and tested without mounting a component.
301
+
302
+ ```text
303
+ good: Transcript.vue (template and presentation), useTranscriptScroll.js,
304
+ transcriptEntries.js (pure projection), Transcript.css via <style scoped src>
305
+ bad: Transcript.vue, 1,600 lines: rendering, scroll anchoring, delivery state and 500 lines of CSS
306
+ ```
307
+
308
+ ## Composables
309
+
310
+ ### Fixed result shape
311
+
312
+ **A composable returns one object literal of named members, the same on every
313
+ path: nothing assigned after construction, no spread of another composable's
314
+ result, no conditional keys, and never `Object.freeze`.** That includes a
315
+ result a callback builds: a wrapper passes what the result needs into the
316
+ callback instead of patching what it returned. An extension that needs the
317
+ object it extends is listed in the literal (`application: null`) and filled
318
+ once right after construction, with a `cycle:` allow comment. A plain
319
+ `create*` that holds no Vue state keeps `Object.freeze`.
320
+
321
+ Why: a fixed shape keeps the type true; and `reactive()` leaves a frozen
322
+ object unproxied while `proxyRefs()` (applied to a `setup()` return and to
323
+ `defineExpose()`) throws on one, so Vue state is never frozen.
324
+
325
+ ```js
326
+ // good
327
+ const suggestions = useSuggestions();
328
+ return { messages, send, suggestions };
329
+ const runtime = app.runWithContext(() => createRuntime(readers, retain));
330
+
331
+ // bad
332
+ return Object.freeze({ messages, send, ...useSuggestions() });
333
+ const runtime = app.runWithContext(() => createRuntime(readers));
334
+ runtime.retain = retain;
335
+ ```
336
+
337
+ ### Effect order
338
+
339
+ **Splitting a composable keeps its `watch()` and `watchEffect()` calls in the
340
+ original composable, in their creation order, calling the extracted module's
341
+ functions.**
342
+
343
+ Why: pre-flush watchers in one scope run in trigger order, so moving them into
344
+ a helper composable can reorder an application's callbacks.
345
+
346
+ ```js
347
+ // good: useConversation.js keeps its watchers in order
348
+ watch(messages, (next) => scroll.follow(next));
349
+ watch(draft, (text) => drafts.save(text));
350
+
351
+ // bad: one watcher moved into useDrafts(), now created before the scroll watcher
352
+ const drafts = useDrafts(draft);
353
+ watch(messages, (next) => scroll.follow(next));
354
+ ```
355
+
356
+ ### Released listeners
357
+
358
+ **Everything client code starts, it stops: each `addEventListener`,
359
+ `setInterval`, observer and `.on()` is released in `onScopeDispose` or
360
+ `onBeforeUnmount`, or registered with `{ once: true }` or an `AbortSignal`
361
+ aborted there.** A listener on an object the code creates with `new` and drops
362
+ with it (its own socket, closed in `disconnect`) goes with that object.
363
+
364
+ Why: a listener that outlives its component leaks memory and fires against
365
+ unmounted state.
366
+
367
+ ```js
368
+ // good
369
+ onMounted(() => window.addEventListener("resize", measure));
370
+ onBeforeUnmount(() => window.removeEventListener("resize", measure));
371
+
372
+ // bad
373
+ onMounted(() => window.addEventListener("resize", () => measure()));
374
+ ```
375
+
376
+ ### Module state
377
+
378
+ **State lives inside the composable or factory that owns it. A module-level
379
+ `let`, `ref()` or `reactive()` exists only when every instance on the page
380
+ must share it, with a `shared resource:` allow comment.** A private memo
381
+ cache nothing fills from outside stays.
382
+
383
+ Why: module scope is shared by every component instance and every application
384
+ on the page, and survives unmounting.
385
+
386
+ ```js
387
+ // good: each composer owns its draft
388
+ function useComposer() {
389
+ const draft = ref("");
390
+ }
391
+ // readable-check: allow module-state - shared resource: every attachment queue on the page draws ids from one sequence
392
+ let attachmentClientSequence = 0;
393
+
394
+ // bad: every composer on the page shares one draft
395
+ let pendingDraft = "";
396
+ ```
397
+
398
+ ## Helpers and sizes
399
+
400
+ ### One helper per package
401
+
402
+ **A pure helper exists once in a package and is imported; one the kernel owns
403
+ (`isRecord`, `normalizeText`) comes from
404
+ `@jskit-ai/kernel/shared/support/normalize`; one client and server code both
405
+ need lives in the package's `src/shared`.**
406
+
407
+ Why: copies drift, and the next reader cannot tell which is right.
408
+
409
+ ```js
410
+ // good
411
+ import { isRecord } from "@jskit-ai/kernel/shared/support/normalize";
412
+
413
+ // bad: a copy in src/client/lib/api.js
414
+ function isRecord(value) { return Boolean(value) && typeof value === "object" && !Array.isArray(value); }
415
+ ```
416
+
417
+ ### Size limits
418
+
419
+ **Files stay under 750 lines and functions under 600; a `.vue` file counts
420
+ whole: template, script and style.** Split by concern
421
+ ([presenting scripts](#presenting-scripts)), never into tiny modules
422
+ ([simple to reason about](#simple-to-reason-about)).
423
+
424
+ Why: a reader holds one concern at a time.
425
+
426
+ ```text
427
+ good: Transcript.vue 420 lines, useTranscriptScroll.js 180, transcriptEntries.js 240
428
+ bad: Transcript.vue 1,600 lines; or eight 90-line files named transcriptPart1.js to transcriptPart8.js
429
+ ```
430
+
431
+ ## Checks
432
+
433
+ ### Running the checks
434
+
435
+ `clientFeaturesConfig(globs)` makes the client rules errors for the client
436
+ code the globs select, Vue components included and tests excluded. A new
437
+ application lists all of it; an existing one lists each client tree as it
438
+ converts it, and nothing else changes until it does:
439
+
440
+ ```js
441
+ import { baseConfig, clientFeaturesConfig, typedFeaturesConfig, vueConfig } from "@jskit-ai/config-eslint/server";
442
+
443
+ export default [
444
+ ...baseConfig,
445
+ ...typedFeaturesConfig(["packages/*/src/server/**", "packages/*/src/shared/**"]),
446
+ ...vueConfig,
447
+ ...clientFeaturesConfig(["packages/*/src/client/**", "src/**"])
448
+ ];
449
+ ```
450
+
451
+ It runs the typed-features rules that read client code, with `use*`
452
+ composables counted as factories and templates read for probes, and the
453
+ client-only rules below. The server's action and error rules do not apply.
454
+
455
+ ### Lint rules
456
+
457
+ | Rule | Reports | Section |
458
+ | --- | --- | --- |
459
+ | `jskit/typed-inject` | `inject()` with a literal key, an untyped binding, or a `null` / `{}` default | [Injected values](#injected-values) |
460
+ | `jskit/collaborator-props` | a prop the component calls that is optional with no named default, or typed only `Object` | [Collaborator props](#collaborator-props) |
461
+ | `jskit/fixed-result-shape` | behaviour assigned to a `use*` / `create*` result after it is built, also one a wrapper's callback built | [Fixed result shape](#fixed-result-shape) |
462
+ | `jskit/no-frozen-vue-state` | `Object.freeze` over refs, computeds or reactive state | [Fixed result shape](#fixed-result-shape) |
463
+ | `jskit/released-listeners` | a listener, interval, observer or subscription the file starts and never releases | [Released listeners](#released-listeners) |
464
+ | `jskit/no-module-state` | a module-level `let`, `ref()` or `reactive()` | [Module state](#module-state) |
465
+ | `vue/require-prop-types`, `vue/require-default-prop`, `vue/require-valid-default-prop`, `vue/no-required-prop-with-default` | a prop without a type, optional without a default, or both | [Collaborator props](#collaborator-props) |
466
+ | `vue/require-explicit-emits` | an emitted event the component does not declare | [Declared emits](#declared-emits) |
467
+
468
+ The typed-features rules keep their own sections:
469
+ [`typed-dependencies`](typed-features.md#typed-collaborators),
470
+ [`required-collaborators`](typed-features.md#required-collaborators),
471
+ [`no-duplicate-helper`](typed-features.md#one-helper-per-package),
472
+ [`no-factory-spread`](typed-features.md#named-members) and the
473
+ rest. In client code, `no-slot-setter` reports only a setter named like a slot
474
+ (`setProvider`), `frozen-factory-result` leaves Vue state unfrozen, and
475
+ `no-duplicate-helper` compares a client helper with the whole package, server
476
+ and shared code included.
477
+
478
+ Simplicity, effect order and presenting scripts are checked by reading.
479
+
480
+ ### Exceptions
481
+
482
+ Client exceptions use the
483
+ [typed features exceptions](typed-features.md#exceptions): a
484
+ comment on the line before the finding, naming the rule or the finding, with a
485
+ reason prefix. Client code adds three placements:
486
+
487
+ | Placement | The exception |
488
+ | --- | --- |
489
+ | `// readable-check: allow module-state - shared resource: <what the page shares>` | module state every instance on the page shares on purpose |
490
+ | `<!-- readable-check: allow optional-call - optional operation: <what lacks it> -->` above an element | that element's bindings call an optional operation |
491
+ | `// readable-check: allow method-probe - input validation: <the shapes>` above a function | the probes of a function whose one job is normalizing an external value of several shapes |
@@ -1,4 +1,4 @@
1
- <!-- Generated from `packages/agent-docs/site/guide/framework/crud-form-actions.md` by `npm run agent-docs:build`. -->
1
+ <!-- Generated from `packages/agent-docs/site/guide/framework/crud-form-actions.md`. -->
2
2
 
3
3
  # Record form actions and validation
4
4
 
@@ -1,4 +1,4 @@
1
- <!-- Generated from `packages/agent-docs/site/guide/framework/crud-operations.md` by `npm run agent-docs:build`. -->
1
+ <!-- Generated from `packages/agent-docs/site/guide/framework/crud-operations.md`. -->
2
2
 
3
3
  # CRUD operations
4
4
 
@@ -311,7 +311,7 @@ behavior. An explicit `client` override receives the same request options.
311
311
  Server authorization is unchanged.
312
312
 
313
313
  For custom form actions, see
314
- [record form actions](./crud-form-actions.md).
314
+ [record form actions](crud-form-actions.md).
315
315
 
316
316
  ## Strict temporal values
317
317
 
@@ -332,11 +332,11 @@ make a live table or a generator the sole source of truth. Inspect schemas for
332
332
  adoption and diagnosis; inspection is optional.
333
333
 
334
334
  Read [ordering and recovery](https://mobily-enterprises.github.io/jskit-ai/guide/app-setup/database-layer#directory-order-comes-before-filenames)
335
- before schema work; check Knex configuration and ledger.
336
- `createKnexMigrationConfigFromApp()` uses `sortDirsSeparately: true`: root
337
- `migrations/`, sorted package directories, then `migrations/constraints/`.
338
- Timestamps order only within directories. Keep tables/columns with their package;
339
- put cross-package foreign keys in the final phase.
335
+ before schema work; check Knex configuration and ledger. Package table
336
+ migrations run first, then root `migrations/`, then the constraints phases.
337
+ Timestamps order only within directories. Root migrations may reference package
338
+ tables; keep tables/columns with their package and put foreign keys between
339
+ packages in a constraints phase.
340
340
 
341
341
  MySQL/MariaDB can leave committed DDL without a ledger entry. Check columns and
342
342
  keys separately; `hasColumn()` is insufficient. Validate existing definitions,
@@ -1,4 +1,4 @@
1
- <!-- Generated from `packages/agent-docs/site/guide/app-setup/existing-application-migration.md` by `npm run agent-docs:build`. -->
1
+ <!-- Generated from `packages/agent-docs/site/guide/app-setup/existing-application-migration.md`. -->
2
2
 
3
3
  # Migrate an existing application
4
4
 
@@ -61,7 +61,9 @@ Model product domains through `defineFeature()` when they own a real capability
61
61
  or operation boundary. A Feature declares stable named `requires`, optional
62
62
  inputs, and `provides`; `setup()` receives those values directly and returns
63
63
  only the promised outputs. Named actions capture the exact feature APIs they
64
- need. Register structural catalogue entries during `setup()` and reserve
64
+ need. Write Features and providers as [typed features](typed-features.md):
65
+ each collaborator is declared, typed where it is received, and never probed.
66
+ Register structural catalogue entries during `setup()` and reserve
65
67
  `boot()` for long-lived work that starts after composition. `shutdown()` stops
66
68
  that work. The runtime shuts Features down in reverse order and keeps going
67
69
  after one fails; it then rejects with an `AggregateError` holding one error per
@@ -230,8 +232,8 @@ Invitation creation, acceptance and refusal now own their managed transactions:
230
232
  - Replace `members.createInvite(..., { trx })` with
231
233
  `members.prepareInvite(..., { trx })`, save the application association/receipt,
232
234
  commit, then call `members.sendInvite(...)` without `trx`.
233
- - Move related acceptance writes into
234
- `pendingInvitations.registerAcceptanceParticipant(fn)` during feature setup.
235
+ - Move related acceptance writes into a function provided as the
236
+ `workspaces.invite-acceptance-participant` capability.
235
237
  Acceptance/refusal reject borrowed transactions; revocation can still join one.
236
238
  - Terminal repository transitions reject accepted/revoked invitations. Mailer
237
239
  exceptions return a fixed message to keep tokens out of provider diagnostics.
@@ -239,7 +241,7 @@ Invitation creation, acceptance and refusal now own their managed transactions:
239
241
  Participant writes roll back together. Preserve transaction outcomes when handling
240
242
  errors: completion-hook failures cannot undo a commit, and expiry revocation
241
243
  commits before returning 409. See the
242
- [workspace invitation contract and example](./multi-homing.md#transactional-invitation-participation).
244
+ [workspace invitation contract and example](multi-homing.md#transactional-invitation-participation).
243
245
  Action IDs, response shapes and schema are unchanged.
244
246
 
245
247
  The first coordinated release includes
@@ -257,11 +259,13 @@ historical migration when moving it so the existing Knex ledger continues to
257
259
  recognize it. Basenames must be unique across the effective graph.
258
260
 
259
261
  Keep cross-package foreign keys and other dependency-sensitive constraints in
260
- application `migrations/constraints/`, the final phase of
261
- `createKnexMigrationConfigFromApp()`. It uses `sortDirsSeparately: true`: root
262
- `migrations/` runs before the sorted package directories, and filenames only
263
- order work within their own directory. A later timestamp in a package does not
264
- defer its foreign key until another package has created the parent table.
262
+ a constraints phase of `createKnexMigrationConfigFromApp()`: the referencing
263
+ package's own `constraints/` subdirectory, which runs after root `migrations/`,
264
+ or application `migrations/constraints/`, which runs last. It uses
265
+ `sortDirsSeparately: true`: the sorted package directories run before root
266
+ `migrations/`, and filenames only order work within their own directory. A later
267
+ timestamp in a package does not defer its foreign key until another package has
268
+ created the parent table.
265
269
  Follow the [database ordering and partial-failure recovery rules](https://mobily-enterprises.github.io/jskit-ai/guide/app-setup/database-layer#directory-order-comes-before-filenames),
266
270
  including independent checks for columns and constraints after MySQL or MariaDB
267
271
  DDL fails. Seeds are not migrations: run one explicit application-owned,
@@ -312,17 +316,16 @@ Do not conflate these identities:
312
316
 
313
317
  An application with accounts has the standard managed-preview login: retain
314
318
  the app-owned `tools/preview-identity` executable, or add it from
315
- `auth/auth-surface` when it is missing, and declare it under
316
- `#### Preview identity` in the web-presented Vibe64 `Outputs` target exactly as
317
- that pattern shows. JSKIT owns the executable/library pattern, Vibe64 owns
318
- the declaration's grammar and runtime behavior, and Genesis transports the
319
- consumer-owned section without interpreting it. The executable calls the
319
+ `auth/auth-surface` when it is missing, pass it the preview host's protocol id
320
+ and hostnames, and declare it to the host as that pattern shows. JSKIT owns
321
+ the executable/library pattern; the host owns the declaration's grammar, its
322
+ protocol id and its runtime behavior. The executable calls the
320
323
  `@jskit-ai/auth-web` server-side managed-preview library; it does not need a
321
324
  framework CLI. Never expose the exchange secret in browser code, a URL, client
322
325
  environment, logs, or source.
323
326
 
324
327
  Managed Playwright uses the host-provided
325
- `VIBE64_PLAYWRIGHT_STORAGE_STATE`, relative URLs, and the existing managed
328
+ `PLAYWRIGHT_STORAGE_STATE`, relative URLs, and the existing managed
326
329
  server. Direct-local tests may instead use `loginAsExistingUser()` from
327
330
  `@jskit-ai/auth-web/test/playwright` with a server-only development secret.
328
331
  Do not mix those two authentication modes or start a duplicate server against
@@ -348,10 +351,11 @@ do not accept a visually similar screen as behavioral equivalence.
348
351
 
349
352
  ## 7. Reconcile, then Deslop as a distinct pass
350
353
 
351
- When the project uses Genesis, run an explicit reconciliation after the port is
352
- functionally green. Compare the implemented source with the current Blueprint,
353
- selected Stack, Program, resources, managed skills, and effective workspace and
354
- Outputs recipes. Update stale citations and declarations to describe what now
354
+ When the project keeps authoritative project documentation, run an explicit
355
+ reconciliation after the port is functionally green. Compare the implemented
356
+ source with its current product description, selected stack, subsystem notes,
357
+ resources, managed skills, and effective workspace and output recipes. Update
358
+ stale citations and declarations to describe what now
355
359
  exists. Do not duplicate an inherited setup recipe merely to make the project
356
360
  look self-contained.
357
361
 
@@ -376,10 +380,10 @@ evidence in ordinary source, configuration, command output, and tests:
376
380
  1. **Behavior:** focused tests and the full managed browser suite are green
377
381
  against an isolated disposable database. Use the managed host and server
378
382
  when supplied.
379
- 2. **Reconciliation:** a dedicated Genesis reconciliation confirms the
380
- Blueprint, Stack, Program, resources, managed skills, and effective setup and
381
- Outputs recipes match the implementation. For a project without Genesis,
382
- reconcile its equivalent authoritative product and host documentation.
383
+ 2. **Reconciliation:** a dedicated reconciliation confirms the project's
384
+ authoritative product and host documentation (product description, selected
385
+ stack, subsystem notes, resources, managed skills, and effective setup and
386
+ output recipes) matches the implementation.
383
387
  3. **Deslop:** a distinct JSKIT Deslop pass, including the selected Material 3
384
388
  audit where UI is affected, removes obsolete framework residue without
385
389
  changing legitimate behavior.
@@ -395,9 +399,9 @@ Do not satisfy a gate by adding a completion ledger or generated conformance
395
399
  state. If a command cannot run, report the missing evidence rather than marking
396
400
  the port complete.
397
401
 
398
- ## Downstream proof: DogAndGroom
402
+ ## Downstream proof: a production port
399
403
 
400
- DogAndGroom validated this procedure on a substantial existing product rather
404
+ A production application validated this procedure on a substantial existing product rather
401
405
  than a sample. The port redistributed 66 historical migrations among 43 owning
402
406
  packages while retaining globally unique basenames and putting cross-package
403
407
  constraints last. Its imported database ledger remained read-only and
@@ -411,7 +415,7 @@ and safety behavior. Obsolete framework generators, provenance markers,
411
415
  service-location wiring, and empty extension modules were removed without
412
416
  flattening those workflows.
413
417
 
414
- After a separate Genesis reconciliation and JSKIT/Material Deslop, its focused
418
+ After a separate reconciliation and JSKIT/Material Deslop, its focused
415
419
  checks, 339 server tests, client tests, production build, database proofs, and
416
420
  all 105 managed Playwright cases passed. These numbers are downstream evidence
417
421
  that the method scales; they are not template targets or state that another