@jskit-ai/agent-docs 0.1.279 → 0.1.280

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 (113) hide show
  1. package/guide/agent/app-extras/assistant.md +123 -0
  2. package/guide/agent/app-setup/authentication.md +34 -3
  3. package/guide/agent/app-setup/database-layer.md +35 -6
  4. package/guide/agent/app-setup/material-3-migration.md +38 -9
  5. package/guide/agent/app-setup/multi-homing.md +8 -2
  6. package/guide/agent/app-setup/upgrading-jskit.md +30 -0
  7. package/guide/agent/app-setup/users.md +9 -1
  8. package/guide/agent/framework/material-3.md +111 -71
  9. package/guide/agent/framework/sanity-checks.md +180 -0
  10. package/guide/agent/framework/translation.md +4 -0
  11. package/guide/agent/framework/typed-features.md +158 -105
  12. package/guide/agent/framework/ui-operations.md +3 -1
  13. package/guide/agent/index.md +3 -0
  14. package/package.json +2 -2
  15. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  16. package/patterns/minimal-foundation/PATTERN.md +6 -2
  17. package/patterns/minimal-foundation/example/AGENTS.md +10 -0
  18. package/patterns/minimal-foundation/example/package.json +6 -6
  19. package/patterns/minimal-foundation/example/playwright.config.mjs +3 -0
  20. package/patterns/minimal-foundation/example/src/main.js +3 -2
  21. package/patterns/minimal-foundation/example/vite.config.mjs +3 -1
  22. package/patterns/shell-foundation/PATTERN.md +4 -1
  23. package/patterns/shell-foundation/example/AGENTS.md +10 -0
  24. package/patterns/shell-foundation/example/package.json +7 -7
  25. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  26. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +3 -0
  27. package/patterns/shell-foundation/example/playwright.config.mjs +3 -0
  28. package/patterns/shell-foundation/example/src/components/menus/SectionTabLinkItem.vue +42 -0
  29. package/patterns/shell-foundation/example/src/main.js +3 -2
  30. package/patterns/shell-foundation/example/src/pages/home.vue +1 -1
  31. package/patterns/shell-foundation/example/src/views/NotFound.vue +1 -1
  32. package/patterns/shell-foundation/example/vite.config.mjs +3 -1
  33. package/reference/autogen/PATTERN_INDEX.md +37 -37
  34. package/reference/autogen/packages/agent-docs.md +4 -0
  35. package/reference/autogen/packages/assistant-runtime.md +27 -2
  36. package/reference/autogen/packages/auth-web.md +10 -0
  37. package/reference/autogen/packages/crud-core.md +3 -0
  38. package/reference/autogen/packages/http-web.md +0 -4
  39. package/reference/autogen/packages/json-rest-api-core.md +17 -4
  40. package/reference/autogen/packages/kernel.md +10 -1
  41. package/reference/autogen/packages/material-web.md +2 -1
  42. package/reference/autogen/packages/shell-web.md +84 -0
  43. package/reference/autogen/packages/users-web.md +5 -2
  44. package/reference/autogen/packages/workspaces-core.md +2 -0
  45. package/reference/autogen/tooling/jskit-catalog.md +52 -5
  46. package/reference/autogen/tooling/testUtils.md +15 -1
  47. package/skills/jskit/SKILL.md +15 -5
  48. package/skills/jskit/references/heuristics/INDEX.md +3 -1
  49. package/skills/jskit/references/heuristics/row-policies.md +3 -3
  50. package/skills/jskit/references/heuristics/typed-features.md +7 -7
  51. package/skills/jskit/references/heuristics/ui-testing.md +8 -7
  52. package/skills/jskit/references/material-3.md +111 -71
  53. package/skills/jskit/references/multi-homing.md +8 -2
  54. package/skills/jskit/references/pattern-index.md +37 -37
  55. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +6 -2
  56. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +10 -0
  57. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +6 -6
  58. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +3 -0
  59. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +3 -2
  60. package/skills/jskit/references/patterns/app/minimal-foundation/example/vite.config.mjs +3 -1
  61. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +4 -1
  62. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +10 -0
  63. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +7 -7
  64. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  65. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +3 -0
  66. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +3 -0
  67. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/SectionTabLinkItem.vue +42 -0
  68. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +3 -2
  69. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home.vue +1 -1
  70. package/skills/jskit/references/patterns/app/shell-foundation/example/src/views/NotFound.vue +1 -1
  71. package/skills/jskit/references/patterns/app/shell-foundation/example/vite.config.mjs +3 -1
  72. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  73. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +18 -5
  74. package/skills/jskit/references/patterns/auth/auth-surface/example/src/components/AppBrand.vue +17 -0
  75. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/login.vue +2 -2
  76. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/reset-password.vue +2 -2
  77. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/signout.vue +2 -2
  78. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/LoginView.vue +6 -1
  79. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/ResetPasswordView.vue +6 -1
  80. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/SignOutView.vue +6 -1
  81. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  82. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  83. package/skills/jskit/references/patterns/connectors/aws-storage-queries/example/formats/package.json +1 -1
  84. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  85. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console.vue +1 -1
  86. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
  87. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  88. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  89. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  90. package/skills/jskit/references/patterns/rewards/google-rewarded/example/googlePublisherTag.js +5 -2
  91. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  92. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +11 -6
  93. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/SectionTabLinkItem.vue +42 -0
  94. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home.vue +1 -1
  95. package/skills/jskit/references/patterns/shell/application-shell/example/src/views/NotFound.vue +1 -1
  96. package/skills/jskit/references/patterns/ui/page-and-placement/PATTERN.md +6 -0
  97. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports.vue +9 -4
  98. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placementTopology.js +5 -3
  99. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +24 -3
  100. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsNotificationsSection.vue +1 -1
  101. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsPreferencesSection.vue +2 -1
  102. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsProfileSection.vue +3 -2
  103. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account/[section].vue +23 -0
  104. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account.vue +4 -3
  105. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
  106. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
  107. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue +3 -3
  108. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/root.vue +1 -1
  109. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/root.vue +1 -1
  110. package/skills/jskit/references/sanity-checks.md +180 -0
  111. package/skills/jskit/references/translation.md +4 -0
  112. package/skills/jskit/references/typed-features.md +158 -105
  113. package/skills/jskit/references/ui-operations.md +3 -1
@@ -43,10 +43,6 @@ Local functions
43
43
  - `isActionExecuting(action)`
44
44
  - `actionLabel(action = {})`
45
45
 
46
- ### `src/client/components/CrudListCreateAction.vue`
47
- Exports
48
- - None
49
-
50
46
  ### `src/client/components/CrudListDateFilterControl.vue`
51
47
  Exports
52
48
  - None
@@ -19,16 +19,16 @@ Exports
19
19
  - `addResourceIfMissing(api, scopeName, resourceConfig)`
20
20
  - `buildJsonRestQueryParams(resourceType = "", query = {}, { include = undefined } = {})`
21
21
  - `createJsonRestResourceScopeOptions(resource = {}, { writeSerializers = {}, normalizeId, rowPolicy, searchSchema, queryFields } = {})`
22
- - `createJsonRestContext(context = null)`
23
- - `extractJsonRestCollectionRows(payload)`
24
- - `queryAllJsonRestCollectionRows(resource, { queryParams, ...params }, context)`
22
+ - `createJsonRestContext`
23
+ - `extractJsonRestCollectionRows`
24
+ - `queryAllJsonRestCollectionDocument`
25
+ - `queryAllJsonRestCollectionRows`
25
26
  - `returnNullWhenJsonRestResourceMissing(run)`
26
27
  - `returnBadRequestWhenJsonRestFieldsetInvalid(run)`
27
28
  - `resolveWorkspaceScopeValue(context = null)`
28
29
  - `resolveUserScopeValue(context = null)`
29
30
  - `createJsonRestApiHost({ knex, logger })`
30
31
  Local functions
31
- - `isPlainJsonRestObject(value)`
32
32
  - `cloneJsonRestResourceValue(value, { writeSerializers = {} } = {})`
33
33
  - `normalizeScopeValue(value)`
34
34
  - `normalizeJsonRestFilterValue(value)`
@@ -47,6 +47,19 @@ Local functions
47
47
  Exports
48
48
  - `JsonRestApiProvider`
49
49
 
50
+ ### `src/server/jsonRestCollectionReads.js`
51
+ Exports
52
+ - `createJsonRestContext(context = null)`
53
+ - `extractJsonRestCollectionRows(payload)`
54
+ - `queryAllJsonRestCollectionDocument(resource, params, context)`
55
+ - `queryAllJsonRestCollectionRows(resource, params, context)`
56
+ Local functions
57
+ - `readEveryJsonRestCollectionPage(resource, { queryParams, ...params }, context, { caller, onPage })`
58
+
59
+ ### `src/server/jsonRestValues.js`
60
+ Exports
61
+ - `isPlainJsonRestObject(value)`
62
+
50
63
  ### `src/server/types.js`
51
64
  Exports
52
65
  - `type RuntimeJsonRestApi`
@@ -536,6 +536,8 @@ Local functions
536
536
  - `ignoreBootstrapStep()`
537
537
  - `installAppPlugins(app, appPlugins = [])`
538
538
  - `isSurfaceRootRecord(record)`
539
+ - `hostsChildViews(record)`
540
+ - `hashScrollMargin(hash)`
539
541
 
540
542
  ### `client/shellRouting.js`
541
543
  Exports
@@ -579,6 +581,9 @@ Exports
579
581
  Exports
580
582
  - `installedClientModules`
581
583
  - `bootInstalledClientModules(context = {})`
584
+ - `VUETIFY_LAYER_ORDER`
585
+ - `namedCascadeLayers(css)`
586
+ - `checkVuetifyLayerOrder(stylesheets = [])`
582
587
  - `CLIENT_BOOTSTRAP_VIRTUAL_ID`
583
588
  - `CLIENT_BOOTSTRAP_RESOLVED_ID`
584
589
  - `createVirtualModuleSource(clientModules, localePackageIds)`
@@ -593,6 +598,7 @@ Exports
593
598
  - `resolveInstalledViteProxyEntries(installedPackages = [], { proxyTarget = "" } = {})`
594
599
  - `createJskitClientBootstrapPlugin({ proxyTarget = "" } = {})`
595
600
  Local functions
601
+ - `builtPageStylesheets(bundle)`
596
602
  - `isLocalScopePackageId(value)`
597
603
  - `readJsonFile(filePath, fallback)`
598
604
  - `hasClientExport(packageJson)`
@@ -637,7 +643,10 @@ Exports
637
643
  Local functions
638
644
  - `normalizeActionDomain(value, { context = "domain" } = {})`
639
645
  - `normalizeStringArray(value, fieldName)`
640
- - `normalizeActionSchema(value, fieldName, { required = false, defaultMode = "" } = {})`
646
+ - `schemaFieldDefinitions(value)`
647
+ - `refuseOneOfFields(fields, fieldName, parentPath = "")`
648
+ - `refuseOneOfField(definition, fieldName, path)`
649
+ - `normalizeActionSchema(value, fieldName, { required = false, defaultMode = "", refuseOneOf = false } = {})`
641
650
  - `normalizeActionPermission(permission, actionId)`
642
651
  - `normalizeActionExtensions(value)`
643
652
  - `normalizeActionEvents(value, actionId)`
@@ -33,8 +33,9 @@ Exports
33
33
  ### `src/client/index.js`
34
34
  Exports
35
35
  - `materialThemes`
36
- - `createMaterialVuetifyOptions({ seed = DEFAULT_SEED, colors = {}, icons = {} } = {})`
36
+ - `createMaterialVuetifyOptions({ seed = DEFAULT_SEED, colors = {}, icons = {}, typography = {} } = {})`
37
37
  Local functions
38
+ - `typefaceVariables({ brand = ROBOTO_FLEX, plain = ROBOTO_FLEX } = {})`
38
39
  - `appIconAliases(icons)`
39
40
 
40
41
  ### `src/client/symbols.js`
@@ -125,15 +125,25 @@ Exports
125
125
  ### `src/client/components/ShellPageActionsTarget.vue`
126
126
  Exports
127
127
  - None
128
+ Local functions
129
+ - `itemProps(entry)`
128
130
 
129
131
  ### `src/client/components/ShellPageTitle.vue`
130
132
  Exports
131
133
  - None
132
134
 
135
+ ### `src/client/components/ShellPrimaryAction.vue`
136
+ Exports
137
+ - None
138
+
133
139
  ### `src/client/components/ShellRouteTransition.vue`
134
140
  Exports
135
141
  - None
136
142
 
143
+ ### `src/client/components/ShellSectionTabLinkItem.vue`
144
+ Exports
145
+ - None
146
+
137
147
  ### `src/client/components/ShellSurfaceAwareMenuLinkItem.vue`
138
148
  Exports
139
149
  - None
@@ -186,6 +196,10 @@ Exports
186
196
  Exports
187
197
  - `useShellOutletPlacements(target, context = {})`
188
198
 
199
+ ### `src/client/composables/useShellPageClose.js`
200
+ Exports
201
+ - `useShellPageClose({ label, close })`
202
+
189
203
  ### `src/client/composables/useShellPageTitle.js`
190
204
  Exports
191
205
  - `useShellPageTitle(title)`
@@ -296,8 +310,10 @@ Exports
296
310
  - `ShellMenuLinkItem`
297
311
  - `ShellSurfaceAwareMenuLinkItem`
298
312
  - `ShellTabLinkItem`
313
+ - `ShellSectionTabLinkItem`
299
314
  - `ShellPageActions`
300
315
  - `ShellPageAction`
316
+ - `ShellPrimaryAction`
301
317
  - `ShellListDetail`
302
318
  - `ShellUpButton`
303
319
  - `ShellPageTitle`
@@ -305,6 +321,7 @@ Exports
305
321
  - `useShellAppBar`
306
322
  - `useShellLayoutState`
307
323
  - `useShellPageTitle`
324
+ - `useShellPageClose`
308
325
  - `useShellWindowSizeClass`
309
326
  - `useShellNavigation`
310
327
  - `leaveApp`
@@ -350,9 +367,11 @@ Exports
350
367
  - `createShellNavigationRuntime({ router })`
351
368
  - `resolvePageParent(matched)`
352
369
  - `resolvePageTitle(matched)`
370
+ - `type ShellPageClose`
353
371
  Local functions
354
372
  - `normalizeTrail(value)`
355
373
  - `cssAttributeValue(value)`
374
+ - `createClaimStack()`
356
375
 
357
376
  ### `src/client/navigation/usePaths.js`
358
377
  Exports
@@ -552,6 +571,7 @@ Exports
552
571
  - `resolveShellDrawerPresentation({ modal = false, open = false, desktopClosedMode = "rail" } = {})`
553
572
  - `resolveShellDrawerToggleLabel({ modal = false, open = false } = {})`
554
573
  - `shellLayoutHasDrawer({ menuSlot = false, menuCount = 0, identityCount = 0, bottomNavigationCount = 0 } = {})`
574
+ - `shellLayoutHasNavigationBar({ bottomNavigationCount = 0, menuCount = 0 } = {})`
555
575
 
556
576
  ### `src/client/support/drawerWidth.js`
557
577
  Exports
@@ -602,6 +622,18 @@ Exports
602
622
  - `VUETIFY_ICONS_KEY`
603
623
  - `filledIconAlias(icon, aliases)`
604
624
 
625
+ ### `src/client/support/pageActions.js`
626
+ Exports
627
+ - `NO_SHELL_PAGE_ACTIONS_REGISTRY`
628
+ - `SHELL_PAGE_ACTIONS_REGISTRY_KEY`
629
+ - `createShellPageActionsRegistry({ isCompact })`
630
+ - `overflowEntries(entries, compact)`
631
+ - `type ShellPageActionState`
632
+ - `type ShellPageActionEntry`
633
+ - `type ShellPageActionsRegistry`
634
+ Local functions
635
+ - `documentOrder(left, right)`
636
+
605
637
  ### `src/client/support/primaryNavigation.js`
606
638
  Exports
607
639
  - `normalizeComparablePathname(value = "")`
@@ -654,6 +686,14 @@ Exports
654
686
 
655
687
  ### fixtures
656
688
 
689
+ ### `fixtures/adaptive-shell/src/ActionsFormPage.vue`
690
+ Exports
691
+ - None
692
+
693
+ ### `fixtures/adaptive-shell/src/ActionsPage.vue`
694
+ Exports
695
+ - None
696
+
657
697
  ### `fixtures/adaptive-shell/src/App.vue`
658
698
  Exports
659
699
  - None
@@ -662,6 +702,22 @@ Exports
662
702
  Exports
663
703
  - None
664
704
 
705
+ ### `fixtures/adaptive-shell/src/ButtonStatesPage.vue`
706
+ Exports
707
+ - None
708
+
709
+ ### `fixtures/adaptive-shell/src/ComponentsPage.vue`
710
+ Exports
711
+ - None
712
+ Local functions
713
+ - `jumpToLastBooking()`
714
+
715
+ ### `fixtures/adaptive-shell/src/FeedbackPage.vue`
716
+ Exports
717
+ - None
718
+ Local functions
719
+ - `press(name)`
720
+
665
721
  ### `fixtures/adaptive-shell/src/main.js`
666
722
  Exports
667
723
  - None
@@ -684,6 +740,10 @@ Exports
684
740
  Exports
685
741
  - `records`
686
742
 
743
+ ### `fixtures/adaptive-shell/src/ReportsPage.vue`
744
+ Exports
745
+ - None
746
+
687
747
  ### `fixtures/adaptive-shell/src/ScreenPage.vue`
688
748
  Exports
689
749
  - None
@@ -692,6 +752,10 @@ Exports
692
752
  Exports
693
753
  - None
694
754
 
755
+ ### `fixtures/adaptive-shell/src/StatusButton.vue`
756
+ Exports
757
+ - None
758
+
695
759
  ### `fixtures/adaptive-shell/src/StudioPage.vue`
696
760
  Exports
697
761
  - None
@@ -701,10 +765,26 @@ Exports
701
765
  - `theme`
702
766
  - `adminTheme`
703
767
 
768
+ ### `fixtures/adaptive-shell/src/TitleClaim.vue`
769
+ Exports
770
+ - None
771
+
704
772
  ### `fixtures/adaptive-shell/vite.config.mjs`
705
773
  Exports
706
774
  - None
707
775
 
776
+ ### `fixtures/production-build/src/App.vue`
777
+ Exports
778
+ - None
779
+
780
+ ### `fixtures/production-build/src/main.js`
781
+ Exports
782
+ - None
783
+
784
+ ### `fixtures/production-build/vite.config.mjs`
785
+ Exports
786
+ - None
787
+
708
788
  ### patterns
709
789
 
710
790
  ### `patterns/application-shell/example/expected-existing/src/App.vue`
@@ -731,6 +811,10 @@ Exports
731
811
  Exports
732
812
  - None
733
813
 
814
+ ### `patterns/application-shell/example/src/components/menus/SectionTabLinkItem.vue`
815
+ Exports
816
+ - None
817
+
734
818
  ### `patterns/application-shell/example/src/components/menus/SurfaceAwareMenuLinkItem.vue`
735
819
  Exports
736
820
  - None
@@ -34,8 +34,7 @@ Exports
34
34
  Exports
35
35
  - None
36
36
  Local functions
37
- - `normalizeSection(value)`
38
- - `readRouteSection()`
37
+ - `sectionTarget(value)`
39
38
 
40
39
  ### `src/client/components/ProfileClientElement.vue`
41
40
  Exports
@@ -213,6 +212,10 @@ Exports
213
212
  Exports
214
213
  - None
215
214
 
215
+ ### `patterns/account-settings/example/src/pages/account/[section].vue`
216
+ Exports
217
+ - None
218
+
216
219
  ### `patterns/account-settings/example/src/pages/account/index.vue`
217
220
  Exports
218
221
  - None
@@ -47,6 +47,8 @@ Exports
47
47
  - `createRepository({ api })`
48
48
  - `normalizeMembershipRecord(payload)`
49
49
  - `normalizeMemberSummaryRow(row)`
50
+ Local functions
51
+ - `memberSummaryFromMembership(row)`
50
52
 
51
53
  ### `src/server/common/repositories/workspacesRepository.js`
52
54
  Exports
@@ -74,12 +74,20 @@ Local functions
74
74
 
75
75
  ### `scripts/material3-source.mjs`
76
76
  Exports
77
+ - `DEFAULT_IMPORT`
78
+ - `TEMPLATE_TAG`
79
+ - `VOID_TAGS`
77
80
  - `HEX_COLOUR`
81
+ - `balancedFrom(text, start, open = "{", close = "}")`
78
82
  - `blankCssComments(source)`
79
83
  - `blankHtmlComments(source)`
80
84
  - `blankJsComments(source)`
85
+ - `enclosingObject(text, offset)`
86
+ - `exclusiveBranches(left, right)`
81
87
  - `kebab(name)`
82
88
  - `lineIndex(text)`
89
+ - `localComponent(file, specifier, known)`
90
+ - `readConditionalBranches(template)`
83
91
  - `readDeclarations(css, offset)`
84
92
  - `readExceptions(source)`
85
93
  - `readInlineDeclarations(text, offset)`
@@ -99,11 +107,13 @@ Exports
99
107
  - `formatNavigationReport(result)`
100
108
  Local functions
101
109
  - `hexPattern()`
110
+ - `channelColour()`
102
111
  - `quotedHex()`
103
112
  - `isNavigationRule(rule)`
104
113
  - `isSkippedDirectory(name)`
105
114
  - `isSourceFile(relativePath)`
106
- - `walk(projectRoot, directory, files)`
115
+ - `isFrameworkPackage(projectRoot, directory)`
116
+ - `walk(projectRoot, directory, files, wholeApp = false)`
107
117
  - `collectFiles(projectRoot, paths)`
108
118
  - `createReporter(file, source, { navigationOnly = false } = {})`
109
119
  - `checkCode(code, offset, { report, themed })`
@@ -141,10 +151,8 @@ Local functions
141
151
  - `navigatesFromControl(tag, script)`
142
152
  - `attribute(tag, name)`
143
153
  - `visibleText(inner)`
144
- - `isBackTag(tag)`
154
+ - `isBackComponentName(name)`
145
155
  - `looksLikeBack(tag)`
146
- - `balancedFrom(text, start, open = "{", close = "}")`
147
- - `enclosingObject(text, offset)`
148
156
  - `stringValue(text, key)`
149
157
  - `readMainNavigation(sources)`
150
158
  - `computedPlacementPart(placement)`
@@ -156,9 +164,19 @@ Local functions
156
164
  - `routeDeclarations(source)`
157
165
  - `readPage(file, source)`
158
166
  - `createShellBarReader(appFiles, read, tag = SHELL_UP_TAG)`
159
- - `localComponent(file, specifier, known)`
167
+ - `shellPlacement(file, source, drawsShellBar, known, barTag = SHELL_UP_TAG)`
168
+ - `rendersOutsideLayouts(code, name)`
169
+ - `judgePackageRoute(route, { surfaces, appShell, drawsShellBar, isDestination, isAddress, readable, report })`
160
170
  - `pageKey(file)`
161
171
 
172
+ ### `scripts/package-routes.mjs`
173
+ Exports
174
+ - `readPackageRoutes(root, known)`
175
+ Local functions
176
+ - `isRecord(value)`
177
+ - `clientEntryOf(manifest, directory)`
178
+ - `readRouteComponents(entry, code, known)`
179
+
162
180
  ### `scripts/pattern-assets.mjs`
163
181
  Exports
164
182
  - `PATTERN_DOCUMENT_NAME`
@@ -218,6 +236,34 @@ Local functions
218
236
  - `alignLockManifestRecord(lockRecord, manifest, localPackageNames)`
219
237
  - `preparePackageLockForInstall(projectRoot, manifests, packageLockPath)`
220
238
 
239
+ ### `scripts/test-budget.mjs`
240
+ Exports
241
+ - `BUDGET_VARIABLE`
242
+ - `testConcurrency({ env = process.env, parallelism = os.availableParallelism() } = {})`
243
+
244
+ ### `scripts/test-command.mjs`
245
+ Exports
246
+ - `planTestRuns(args, { cwd = process.cwd(), concurrency = testConcurrency() } = {})`
247
+ - `runTests(args)`
248
+ Local functions
249
+ - `findTestFiles(patterns, cwd)`
250
+ - `readAloneFiles(files, cwd)`
251
+ - `runNode(args)`
252
+
253
+ ### `scripts/test-runs.mjs`
254
+ Exports
255
+ - `checkTestRuns({ projectRoot, manifests })`
256
+ - `formatTestRunsReport(result)`
257
+ Local functions
258
+ - `commandsOf(script)`
259
+ - `isProgram(token, name)`
260
+ - `runsNodeTest(tokens)`
261
+ - `runnerArguments(tokens, runner)`
262
+ - `configOption(args)`
263
+ - `lineOf(contents, needle, after = "")`
264
+ - `findConfig(directory, explicit, names)`
265
+ - `checkRunnerConfig({ root, configPath, directory, runner, report })`
266
+
221
267
  ### `scripts/verify-packages.mjs`
222
268
  Exports
223
269
  - `main()`
@@ -234,3 +280,4 @@ Local functions
234
280
  - `validateMigrationsAfter(packageJson)`
235
281
  - `validateMigrationDirectory(packageName, absoluteDirectory, relativeDirectory, migrationOwners)`
236
282
  - `validatePackage(packageRecord, localVersions, migrationOwners)`
283
+ - `verifyTestRuns()`
@@ -14,13 +14,22 @@ Use this on demand; do not load the full index at startup.
14
14
 
15
15
  ### root
16
16
 
17
+ ### `browserExpect.mjs`
18
+ Exports
19
+ - `expect`
20
+
17
21
  ### `browserFixture.mjs`
18
22
  Exports
19
23
  - `createChromiumLaunchOptions({ env = process.env } = {})`
20
24
  - `reservePort()`
25
+ - `sharedBrowserFixture(viteOptions)`
21
26
  - `startCapturedProcess(command, args, { cwd, env = {} } = {})`
22
- - `startViteFixture({ fixtureRoot, configFile = "vite.config.mjs", env = {}, port: requestedPort } = {})`
27
+ - `startViteFixture({ fixtureRoot, configFile = "vite.config.mjs", env = {}, port: requestedPort, cacheDir: requestedCacheDir } = {})`
23
28
  - `stopProcess(runtime)`
29
+ Local functions
30
+ - `stopChild(child)`
31
+ - `takeCacheDir(configPath)`
32
+ - `returnCacheDir(configPath, cacheDir)`
24
33
 
25
34
  ### `fakeFastify.mjs`
26
35
  Exports
@@ -34,3 +43,8 @@ Exports
34
43
  - `readMaterialStyles(page, probes)`
35
44
  Local functions
36
45
  - `comparePixels(page, actual, expected)`
46
+ - `waitForStillPage(page)`
47
+
48
+ ### `viteFixtureServer.mjs`
49
+ Exports
50
+ - None
@@ -58,6 +58,8 @@ manifests, migrations, tests, and runtime behaviour are the evidence.
58
58
  also read [Material 3](references/material-3.md) completely before acting.
59
59
  - For a UI pass (the changes, a section, or the whole app), also read
60
60
  [UI pass](references/ui-pass.md) completely.
61
+ - Before writing a list, save, batch or test, a refactor, or calling work
62
+ done, read [sanity checks](references/sanity-checks.md).
61
63
 
62
64
  These are complete operational references required by this skill. Do not load
63
65
  irrelevant references or other docs.
@@ -122,8 +124,16 @@ whole changeset. Use the current-state owners in application operations and
122
124
  Playwright for affected UI. There is no current JSKIT Doctor command; ignore
123
125
  old CLI authoring-history diagnoses. Never expose environment values.
124
126
 
125
- Tests and requests take the time their work needs, no more: a list reads each
126
- table once, a row policy is bounded by the rows it reads, list and batch paths
127
- have a query budget tested at realistic row counts, and test databases restore
128
- a stored snapshot instead of replaying migrations. Find why a check is slow;
129
- never raise its time limit. Typed features' repository and Tests rules say how.
127
+ Tests and requests take the time their work needs, no more: count a list's or
128
+ save's queries at a few rows and at a realistic number and
129
+ judge whether they grow with the rows, and read the suite's time and its
130
+ slowest files. Find why a check is slow; never raise its time limit. Typed
131
+ features' repository and Tests rules say how.
132
+
133
+ Test files run in parallel by default, bounded by the machine: a script runs
134
+ `jskit test`, never `node --test` or a fixed `--test-concurrency`, and
135
+ Playwright's `workers` and Vitest's `maxWorkers` are `testConcurrency()` from
136
+ `@jskit-ai/jskit-catalog/test-budget`; plain `jskit check` fails anything else.
137
+ Files that collide when run together get isolated (their own port, temporary
138
+ directory and database), never serialised. A file that truly must run alone
139
+ says why on its first line, `// jskit-test: alone - <reason>`.
@@ -44,7 +44,9 @@ How to use it:
44
44
  - [crud-repository-mapping.md](./crud-repository-mapping.md)
45
45
  - row policy, permission filtering, visibility before pagination, recursive CTE, descendants, package cycle, `RowPolicyPlugin`, row policy cost, slow writes through a policy, access check per history item
46
46
  - [row-policies.md](./row-policies.md)
47
- - typed features, server feature, provider, service, repository, collaborator, `typeof`, `= null`, `setProvider`, `register`, `input || {}`, `payload = {}`, `async execute`, `Object.freeze`, `requires`, `optional`, `types.js`, `RuntimeKnex`, `silentLogger`, `create<Name>Actions`, `ActionSpecifications`, request context, `api.resources.x.query`, every row, list stops at 20 rows, `queryAllJsonRestCollectionRows`, `jskit/*` lint findings, `readable-check: allow`, `optional operation:`, `process.env`, `AppError` code, `Object.assign(new Error`, `idempotency`, `…ForTests` export, file or function size, read per row, N+1 queries, slow endpoint, query budget, realistic row counts, slow tests, raised timeout, `migrate.latest()` in tests, test database snapshot
47
+ - typed features, server feature, provider, service, repository, collaborator, `typeof`, `= null`, `setProvider`, `register`, `input || {}`, `payload = {}`, `async execute`, `Object.freeze`, `requires`, `optional`, `types.js`, `RuntimeKnex`, `silentLogger`, `create<Name>Actions`, `ActionSpecifications`, request context, `api.resources.x.query`, every row, list stops at 20 rows, `queryAllJsonRestCollectionRows`, `jskit/*` lint findings, `readable-check: allow`, `optional operation:`, `process.env`, `AppError` code, `Object.assign(new Error`, `idempotency`, `…ForTests` export, file or function size, read per row, N+1 queries, slow endpoint, query budget, realistic row counts, slow tests, raised timeout, `migrate.latest()` in tests, test database snapshot, `--test-concurrency=1`, `node --test`, `jskit test`, `testConcurrency()`, `V64_TEST_CONCURRENCY`, Playwright `workers`, Vitest `maxWorkers`, tests one file at a time, test files colliding in parallel, `jskit-test: alone`, `test/*` findings of `jskit check`
48
48
  - [typed-features.md](./typed-features.md)
49
49
  - client features, composable, `use<Name>`, Vue component, client provider, props, emits, `inject`, `provide`, `ref`, `reactive`, `watch`, `addEventListener`, `setInterval`, module state, `Object.freeze` on a composable, `?.()` in a template, `jskit/typed-inject`, `jskit/collaborator-props`, `jskit/fixed-result-shape`, `jskit/released-listeners`, `jskit/no-module-state`, `jskit/no-frozen-vue-state`, `clientFeaturesConfig`, `shared resource:`
50
50
  - [client-features.md](./client-features.md)
51
+ - sanity checks, is this sane, query count that grows with the rows, a list that stops at 20 or 100 rows, `createDocument()` per row of a batch, `jskit test`, one file at a time, test database preparation, `TEST_DB_NAME`, `mode: "patch"`, a route `rateLimit` nothing tests, `input.workspaceId`, a refactor or consolidation that drops behaviour, a JSKIT update, a changed theme or Vuetify default, `jskit.surface` with a parent, an assistant tool's output contract, a screen that renders everything, feedback covering an action, `NODE_ENV=production`, a production start
52
+ - [Sanity checks](../sanity-checks.md)
@@ -39,9 +39,9 @@ Package composition:
39
39
 
40
40
  Cost:
41
41
 
42
- - a policy's cost follows the rows its query reads: add a join, `EXISTS` or subquery correlated with the row through `column()` and `value()`, on indexed columns
42
+ - a policy's cost follows the rows its query reads: add a join, `EXISTS` or subquery correlated with the row through `column()` and `value()`, on indexed columns; look at its SQL too, since a statement that runs to kilobytes is planned again on every read that carries it
43
43
  - never load the subject's whole history (every source, notice or grant they were ever linked to) to build an `IN` list, and never call another owner's access check per item of it; another package's grant is a predicate contribution
44
- - the policy runs on every single-record read, including the read-back after `createDocument()` and `patchDocumentById()` (`returning: "full"`) and the lookup before `patch` and `delete`, so a write pays it once per row it writes
44
+ - the policy runs on every single-record read, including the read-back after `createDocument()` and `patchDocumentById()` (`returning: "full"`, their default) and the lookup before `patch` and `delete`, so a write pays it once per row it writes
45
45
  - a write decides access once, inside its transaction; a batch write that would pay an expensive read-back per row follows the typed features guide's [Bounded access checks](../typed-features.md#bounded-access-checks)
46
46
 
47
47
  Child-resource rules:
@@ -58,7 +58,7 @@ Testing:
58
58
  - assert hidden direct records behave as not found
59
59
  - assert children and includes do not leak records
60
60
  - assert package and provider dependencies stay one-way
61
- - run one read and one write for a subject with a short history and with a realistic long one (hundreds of linked rows), and assert the same query count
61
+ - count the queries of one read and one write for a subject with a short history and with a realistic long one (hundreds of linked rows), and fail when the count grows with the history
62
62
 
63
63
  AnyAPI boundary:
64
64
 
@@ -63,10 +63,10 @@ ends with the same link.
63
63
  - [One helper per package](../typed-features.md#one-helper-per-package)
64
64
  - `options?.trx || options?.transaction`, a hand-read actor, cursor or created id
65
65
  - [One reader per fact](../typed-features.md#one-reader-per-fact)
66
- - `api.resources.x.query(…)` with no `page` for a list, `queryDocuments(query)` with no `limit` in a service, a list that stops at 20 rows
66
+ - `api.resources.x.query(…)` with no `page` for a list, `queryDocuments(query)` with no `limit` in a service, a list that stops at 20 rows, `page: { size: 500 }` or `limit: 500` that returns 100 rows
67
67
  - [Every row](../typed-features.md#every-row)
68
- - `await getDocumentById(…)`, `queryDocuments(…)` or a service `get` inside a loop or a `Promise.all` over a list, a single-record helper reused for a list, N+1 queries, a slow list endpoint
69
- - [One read per table](../typed-features.md#one-read-per-table)
68
+ - `await getDocumentById(…)`, `queryDocuments(…)` or a service `get` inside a loop or a `Promise.all` over a list, a single-record helper reused for a list, N+1 queries, a list whose query count grows with its rows, a slow list endpoint
69
+ - [Lists read related rows in batches](../typed-features.md#lists-read-related-rows-in-batches)
70
70
  - a `rowPolicy` that loads a person's whole history or calls an access check per item, `createDocument` per row of a batch, a write that gets slower as history grows
71
71
  - [Bounded access checks](../typed-features.md#bounded-access-checks)
72
72
  - a route that queries storage, `boot*.js` holding routes
@@ -85,10 +85,10 @@ ends with the same link.
85
85
  - [Tests are not callers](../typed-features.md#tests-are-not-callers)
86
86
  - `…ForTests`, `__reset…`, `testOnly…` exports (`jskit/no-test-only-export`)
87
87
  - [No test-only exports](../typed-features.md#no-test-only-exports)
88
- - a list, batch or write test with one to three rows, no query count, a slow endpoint first seen with real data
89
- - [Budgets at realistic counts](../typed-features.md#budgets-at-realistic-counts)
90
- - a raised `{ timeout }`, `test.setTimeout()`, `--test-timeout` or Playwright `timeout`, retries or a request loop that absorbs slowness, a slow suite
91
- - [Time limits are not fixes](../typed-features.md#time-limits-are-not-fixes)
88
+ - a list, batch or write test with one to three rows, no query count, a fixed query ceiling tuned to pass, a slow endpoint first seen with real data
89
+ - [Query counts at realistic sizes](../typed-features.md#query-counts-at-realistic-sizes)
90
+ - `node --test --test-concurrency=1`, `workers: 1`, `fileParallelism: false`, a suite that runs one file at a time, test files that collide when run together, `test/*` findings of `jskit check`
91
+ - [Test files run in parallel](../typed-features.md#test-files-run-in-parallel)
92
92
  - `knex.migrate.latest()` in each test file, a template database rebuilt by migrating, test preparation slower than its tests
93
93
  - [Test databases are prepared once](../typed-features.md#test-databases-are-prepared-once)
94
94
  - a file over 750 lines, a function over 600 (`max-lines`, `max-lines-per-function`), a data module
@@ -64,16 +64,17 @@ collision before connecting. Include disposable cleanup between browser starts
64
64
  in the regression: one test's teardown must not erase another test's migrations.
65
65
 
66
66
  Do not drop/recreate the database, replay completed migrations, build every
67
- module fixture, or run a production frontend build for each focused check.
68
- Choose small fixture sets for the selected suite; realistic row counts belong
69
- in the database tests that hold each endpoint's query budget. Fresh-schema
67
+ module fixture, or run a production frontend build for each focused check. A
68
+ build made once for a whole run is different: it is the fix when a development
69
+ server makes every page load slow. Choose small fixture sets for the selected
70
+ suite; realistic row counts belong in the database tests that compare each
71
+ endpoint's query counts. Fresh-schema
70
72
  migration tests and production-artifact tests are separate operations. Measure
71
73
  migration, fixture, and server startup time and fix the slow phase; never retry
72
74
  a slow launch, or raise its deadline or a spec's timeout, to absorb it. A page
73
- that needs a longer timeout to load is a slow endpoint to fix (typed features'
74
- Time limits are not fixes). When a host supplies a managed target, use its
75
- scoped suite command so one startup serves the whole batch and cleanup
76
- restores normal Preview.
75
+ that needs a longer timeout to load is a slow endpoint to fix. When a host
76
+ supplies a managed target, use its scoped suite command so one startup serves
77
+ the whole batch and cleanup restores normal Preview.
77
78
 
78
79
  ## Keep browser evidence focused
79
80