@shanyucoder/flowgrid 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (779) hide show
  1. package/README.md +194 -0
  2. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/IntegrationContext.cs +56 -0
  3. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/IntegrationGen.csproj +16 -0
  4. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/NameUtil.cs +18 -0
  5. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Program.cs +265 -0
  6. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Templates/application_service.cs.scriban +27 -0
  7. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Templates/handoff.md.scriban +15 -0
  8. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Templates/infrastructure_mock.cs.scriban +20 -0
  9. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Templates/presenter.cs.scriban +41 -0
  10. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/Templates/service_test.cs.scriban +17 -0
  11. package/adapters/dotnet-integration/codegen/runners/IntegrationGen/YamlMap.cs +49 -0
  12. package/adapters/dotnet-integration/registries/dotnet-integration.codegen.registry.json +8 -0
  13. package/adapters/dotnet-line/codegen/runners/LineGen/LineContext.cs +43 -0
  14. package/adapters/dotnet-line/codegen/runners/LineGen/LineGen.csproj +16 -0
  15. package/adapters/dotnet-line/codegen/runners/LineGen/NameUtil.cs +12 -0
  16. package/adapters/dotnet-line/codegen/runners/LineGen/Program.cs +201 -0
  17. package/adapters/dotnet-line/codegen/runners/LineGen/TemplateRenderer.cs +22 -0
  18. package/adapters/dotnet-line/codegen/runners/LineGen/Templates/handoff.md.scriban +15 -0
  19. package/adapters/dotnet-line/codegen/runners/LineGen/Templates/service.cs.scriban +21 -0
  20. package/adapters/dotnet-line/codegen/runners/LineGen/Templates/service_interface.cs.scriban +20 -0
  21. package/adapters/dotnet-line/codegen/runners/LineGen/Templates/view_model.cs.scriban +28 -0
  22. package/adapters/dotnet-line/codegen/runners/LineGen/Templates/view_model_test.cs.scriban +22 -0
  23. package/adapters/dotnet-line/codegen/runners/LineGen/YamlMap.cs +49 -0
  24. package/adapters/dotnet-line/registries/dotnet-line.codegen.registry.json +8 -0
  25. package/adapters/fastapi/codegen/runners/fast_gen/__init__.py +1 -0
  26. package/adapters/fastapi/codegen/runners/fast_gen/__main__.py +3 -0
  27. package/adapters/fastapi/codegen/runners/fast_gen/cli.py +175 -0
  28. package/adapters/fastapi/codegen/runners/fast_gen/plan.py +285 -0
  29. package/adapters/fastapi/codegen/runners/fast_gen/read_spec.py +34 -0
  30. package/adapters/fastapi/codegen/runners/fast_gen/registry.py +9 -0
  31. package/adapters/fastapi/codegen/runners/fast_gen/wire.py +28 -0
  32. package/adapters/fastapi/codegen/runners/fast_gen/write_files.py +232 -0
  33. package/adapters/fastapi/codegen/runners/generate +5 -0
  34. package/adapters/fastapi/codegen/runners/validate-registry.mjs +54 -0
  35. package/adapters/fastapi/codegen/templates/presenter.py.j2 +11 -0
  36. package/adapters/fastapi/codegen/templates/router.py.j2 +69 -0
  37. package/adapters/fastapi/codegen/templates/schemas_request.py.j2 +26 -0
  38. package/adapters/fastapi/codegen/templates/schemas_response.py.j2 +7 -0
  39. package/adapters/fastapi/codegen/templates/service_create.py.j2 +10 -0
  40. package/adapters/fastapi/codegen/templates/service_delete.py.j2 +10 -0
  41. package/adapters/fastapi/codegen/templates/service_search.py.j2 +9 -0
  42. package/adapters/fastapi/codegen/templates/service_update.py.j2 +11 -0
  43. package/adapters/fastapi/codegen/templates/store.py.j2 +1 -0
  44. package/adapters/fastapi/codegen/templates/test_router.py.j2 +13 -0
  45. package/adapters/fastapi/registries/codegen.registry.json +47 -0
  46. package/adapters/fastapi/registries/common.registry.json +23 -0
  47. package/adapters/fastapi/registries/unit-test.registry.json +12 -0
  48. package/adapters/fastapi/unitgen/runners/fast_unit_gen/__init__.py +1 -0
  49. package/adapters/fastapi/unitgen/runners/fast_unit_gen/cli.py +188 -0
  50. package/adapters/fastapi/unitgen/runners/generate +5 -0
  51. package/adapters/fastapi/unitgen/runners/validate-registry.mjs +48 -0
  52. package/adapters/fastapi/unitgen/templates/test_service.py.j2 +12 -0
  53. package/adapters/laravel/codegen/runners/README.md +45 -0
  54. package/adapters/laravel/codegen/runners/generate.mjs +296 -0
  55. package/adapters/laravel/codegen/runners/lib/codegen-registry.mjs +60 -0
  56. package/adapters/laravel/codegen/runners/lib/detect-existing.mjs +84 -0
  57. package/adapters/laravel/codegen/runners/lib/exec-artisan.mjs +86 -0
  58. package/adapters/laravel/codegen/runners/lib/parse-tags.mjs +49 -0
  59. package/adapters/laravel/codegen/runners/lib/plan.mjs +122 -0
  60. package/adapters/laravel/codegen/runners/lib/read-spec.mjs +30 -0
  61. package/adapters/laravel/codegen/runners/lib/resolve-commands.mjs +234 -0
  62. package/adapters/laravel/codegen/runners/lib/stub-services.mjs +91 -0
  63. package/adapters/laravel/codegen/runners/lib/tag-plan.mjs +155 -0
  64. package/adapters/laravel/codegen/runners/lib/validate.mjs +77 -0
  65. package/adapters/laravel/codegen/runners/lib/workspace-analysis.mjs +202 -0
  66. package/adapters/laravel/codegen/runners/lib/write-handoff.mjs +149 -0
  67. package/adapters/laravel/codegen/runners/lib/write-manifest.mjs +81 -0
  68. package/adapters/laravel/codegen/runners/validate-registry.mjs +52 -0
  69. package/adapters/laravel/php/README.md +26 -0
  70. package/adapters/laravel/php/bin/unit-gen.php +307 -0
  71. package/adapters/laravel/php/bin/validate-registry.php +61 -0
  72. package/adapters/laravel/php/composer.json +16 -0
  73. package/adapters/laravel/php/src/ArtisanRunner.php +56 -0
  74. package/adapters/laravel/php/src/Autoload.php +15 -0
  75. package/adapters/laravel/php/src/CodegenManifest.php +28 -0
  76. package/adapters/laravel/php/src/ParseTags.php +62 -0
  77. package/adapters/laravel/php/src/ProjectResolver.php +100 -0
  78. package/adapters/laravel/php/src/SpecExtract.php +193 -0
  79. package/adapters/laravel/php/src/SpecReader.php +57 -0
  80. package/adapters/laravel/php/src/TemplateRenderer.php +134 -0
  81. package/adapters/laravel/php/src/UnitPlanner.php +396 -0
  82. package/adapters/laravel/php/src/UnitRegistry.php +100 -0
  83. package/adapters/laravel/php/src/WhenEval.php +111 -0
  84. package/adapters/laravel/php/src/WorkspaceInspector.php +240 -0
  85. package/adapters/laravel/php/src/WriteFiles.php +194 -0
  86. package/adapters/laravel/php/templates/actions/relationship-sync.behavior.test.php.stub +50 -0
  87. package/adapters/laravel/php/templates/controllers/controller-invoke.test.php.stub +34 -0
  88. package/adapters/laravel/php/templates/queries/chain-scope.behavior.test.php.stub +34 -0
  89. package/adapters/laravel/php/templates/requests/default-per-page.behavior.test.php.stub +19 -0
  90. package/adapters/laravel/php/templates/requests/request-enriched.test.php.stub +66 -0
  91. package/adapters/laravel/php/templates/requests/rules-keys.behavior.test.php.stub +19 -0
  92. package/adapters/laravel/php/templates/resources/nested-relations.behavior.test.php.stub +25 -0
  93. package/adapters/laravel/php/templates/resources/openapi-shape.behavior.test.php.stub +28 -0
  94. package/adapters/laravel/php/templates/support/ModuleTestSupport.php.stub +32 -0
  95. package/adapters/laravel/registries/codegen.registry.json +190 -0
  96. package/adapters/laravel/registries/unit-test.registry.json +179 -0
  97. package/adapters/laravel/shared/project.mjs +62 -0
  98. package/adapters/nestjs/README.md +16 -0
  99. package/adapters/nestjs/nest-unitgen/runners/README.md +17 -0
  100. package/adapters/nestjs/nest-unitgen/runners/generate.mjs +113 -0
  101. package/adapters/nestjs/nest-unitgen/runners/lib/render.mjs +14 -0
  102. package/adapters/nestjs/nest-unitgen/runners/lib/write-files.mjs +40 -0
  103. package/adapters/nestjs/nest-unitgen/runners/validate-registry.mjs +35 -0
  104. package/adapters/nestjs/nest-unitgen/templates/commands/create.handler.spec.ts.hbs +32 -0
  105. package/adapters/nestjs/nest-unitgen/templates/commands/delete.handler.spec.ts.hbs +32 -0
  106. package/adapters/nestjs/nest-unitgen/templates/commands/update.handler.spec.ts.hbs +32 -0
  107. package/adapters/nestjs/nest-unitgen/templates/handlers/search.handler.spec.ts.hbs +33 -0
  108. package/adapters/nestjs/nest-unitgen/templates/resource/entity.resource.spec.ts.hbs +22 -0
  109. package/adapters/nestjs/nestgen/runners/README.md +30 -0
  110. package/adapters/nestjs/nestgen/runners/generate.mjs +87 -0
  111. package/adapters/nestjs/nestgen/runners/lib/orm-fields.mjs +253 -0
  112. package/adapters/nestjs/nestgen/runners/lib/plan.mjs +124 -0
  113. package/adapters/nestjs/nestgen/runners/lib/read-spec.mjs +52 -0
  114. package/adapters/nestjs/nestgen/runners/lib/render.mjs +52 -0
  115. package/adapters/nestjs/nestgen/runners/lib/workspace-analysis.mjs +80 -0
  116. package/adapters/nestjs/nestgen/runners/lib/write-files.mjs +49 -0
  117. package/adapters/nestjs/nestgen/runners/validate-registry.mjs +36 -0
  118. package/adapters/nestjs/nestgen/templates/commands/create.command.ts.hbs +3 -0
  119. package/adapters/nestjs/nestgen/templates/commands/create.handler.ts.hbs +34 -0
  120. package/adapters/nestjs/nestgen/templates/commands/delete.command.ts.hbs +3 -0
  121. package/adapters/nestjs/nestgen/templates/commands/delete.handler.ts.hbs +33 -0
  122. package/adapters/nestjs/nestgen/templates/commands/update.command.ts.hbs +6 -0
  123. package/adapters/nestjs/nestgen/templates/commands/update.handler.ts.hbs +34 -0
  124. package/adapters/nestjs/nestgen/templates/entity.controller.ts.hbs +51 -0
  125. package/adapters/nestjs/nestgen/templates/entity.resource.ts.hbs +45 -0
  126. package/adapters/nestjs/nestgen/templates/module.module.ts.hbs +38 -0
  127. package/adapters/nestjs/nestgen/templates/orm/prisma.entity.ts.hbs +10 -0
  128. package/adapters/nestjs/nestgen/templates/orm/prisma.model.prisma.hbs +9 -0
  129. package/adapters/nestjs/nestgen/templates/orm/typeorm.entity.ts.hbs +20 -0
  130. package/adapters/nestjs/nestgen/templates/queries/search.handler.ts.hbs +36 -0
  131. package/adapters/nestjs/nestgen/templates/queries/search.query.ts.hbs +3 -0
  132. package/adapters/nestjs/registries/nest-codegen.registry.json +41 -0
  133. package/adapters/nestjs/registries/nest-unit-test.registry.json +31 -0
  134. package/adapters/nextjs/codegen/runners/README.md +68 -0
  135. package/adapters/nextjs/codegen/runners/generate.mjs +236 -0
  136. package/adapters/nextjs/codegen/runners/lib/component-resolve.mjs +79 -0
  137. package/adapters/nextjs/codegen/runners/lib/design-registry.mjs +333 -0
  138. package/adapters/nextjs/codegen/runners/lib/naming.mjs +236 -0
  139. package/adapters/nextjs/codegen/runners/lib/page-lifecycle.mjs +258 -0
  140. package/adapters/nextjs/codegen/runners/lib/plan.mjs +399 -0
  141. package/adapters/nextjs/codegen/runners/lib/read-spec.mjs +7 -0
  142. package/adapters/nextjs/codegen/runners/lib/render.mjs +47 -0
  143. package/adapters/nextjs/codegen/runners/lib/resolve-hub-id.mjs +288 -0
  144. package/adapters/nextjs/codegen/runners/lib/slots.mjs +121 -0
  145. package/adapters/nextjs/codegen/runners/lib/web-paths.mjs +64 -0
  146. package/adapters/nextjs/codegen/runners/lib/write-files.mjs +106 -0
  147. package/adapters/nextjs/codegen/runners/validate-registry.mjs +99 -0
  148. package/adapters/nextjs/codegen/templates/common/confirm-dialog.hbs +81 -0
  149. package/adapters/nextjs/codegen/templates/common/delete-flow.hbs +106 -0
  150. package/adapters/nextjs/codegen/templates/create/form.tsx.hbs +45 -0
  151. package/adapters/nextjs/codegen/templates/create/mock.ts.hbs +15 -0
  152. package/adapters/nextjs/codegen/templates/create/page.tsx.hbs +12 -0
  153. package/adapters/nextjs/codegen/templates/create/service.ts.hbs +25 -0
  154. package/adapters/nextjs/codegen/templates/create/useForm.ts.hbs +59 -0
  155. package/adapters/nextjs/codegen/templates/create/validation.ts.hbs +16 -0
  156. package/adapters/nextjs/codegen/templates/list/mock.ts.hbs +25 -0
  157. package/adapters/nextjs/codegen/templates/list/page.custom.tsx.hbs +65 -0
  158. package/adapters/nextjs/codegen/templates/list/page.tsx.hbs +37 -0
  159. package/adapters/nextjs/codegen/templates/list/service.ts.hbs +37 -0
  160. package/adapters/nextjs/codegen/templates/list/useList.ts.hbs +93 -0
  161. package/adapters/nextjs/codegen/templates/list/useListColumns.ts.hbs +27 -0
  162. package/adapters/nextjs/codegen/templates/list/useListExport.ts.hbs +31 -0
  163. package/adapters/nextjs/codegen/templates/list/useListFilters.ts.hbs +50 -0
  164. package/adapters/nextjs/codegen/templates/store/store.ts.hbs +28 -0
  165. package/adapters/nextjs/contractgen/runners/README.md +47 -0
  166. package/adapters/nextjs/contractgen/runners/generate.mjs +108 -0
  167. package/adapters/nextjs/contractgen/runners/lib/field-zod.mjs +83 -0
  168. package/adapters/nextjs/contractgen/runners/lib/naming.mjs +46 -0
  169. package/adapters/nextjs/contractgen/runners/lib/plan.mjs +147 -0
  170. package/adapters/nextjs/contractgen/runners/lib/render.mjs +57 -0
  171. package/adapters/nextjs/contractgen/runners/lib/write-files.mjs +54 -0
  172. package/adapters/nextjs/contractgen/runners/validate-registry.mjs +54 -0
  173. package/adapters/nextjs/contractgen/templates/index.ts.hbs +8 -0
  174. package/adapters/nextjs/contractgen/templates/read.schema.ts.hbs +22 -0
  175. package/adapters/nextjs/contractgen/templates/relationships.meta.ts.hbs +23 -0
  176. package/adapters/nextjs/contractgen/templates/types.ts.hbs +15 -0
  177. package/adapters/nextjs/contractgen/templates/write.schema.ts.hbs +11 -0
  178. package/adapters/nextjs/registries/contract-field.registry.json +22 -0
  179. package/adapters/nextjs/unitgen/runners/README.md +12 -0
  180. package/adapters/nextjs/unitgen/runners/generate.mjs +201 -0
  181. package/adapters/nextjs/unitgen/runners/lib/parse-tags.mjs +67 -0
  182. package/adapters/nextjs/unitgen/runners/lib/plan.mjs +563 -0
  183. package/adapters/nextjs/unitgen/runners/lib/read-codegen.mjs +42 -0
  184. package/adapters/nextjs/unitgen/runners/lib/render.mjs +32 -0
  185. package/adapters/nextjs/unitgen/runners/lib/resolve-model.mjs +28 -0
  186. package/adapters/nextjs/unitgen/runners/lib/unit-registry.mjs +52 -0
  187. package/adapters/nextjs/unitgen/runners/lib/write-files.mjs +103 -0
  188. package/adapters/nextjs/unitgen/runners/lib/write-spec-tags.mjs +37 -0
  189. package/adapters/nextjs/unitgen/runners/validate-registry.mjs +74 -0
  190. package/adapters/nextjs/unitgen/templates/hooks/use-form.test.ts.hbs +51 -0
  191. package/adapters/nextjs/unitgen/templates/hooks/use-list.test.ts.hbs +63 -0
  192. package/adapters/nextjs/unitgen/templates/models/schema.test.ts.hbs +24 -0
  193. package/adapters/nextjs/unitgen/templates/services/service.create.test.ts.hbs +28 -0
  194. package/adapters/nextjs/unitgen/templates/services/service.export.test.ts.hbs +20 -0
  195. package/adapters/nextjs/unitgen/templates/services/service.search.test.ts.hbs +25 -0
  196. package/adapters/nextjs/unitgen/templates/services/service.wire.test.ts.hbs +37 -0
  197. package/adapters/nextjs/unitgen/templates/validations/schemas.test.ts.hbs +19 -0
  198. package/adapters/nuxt4/codegen/runners/README.md +83 -0
  199. package/adapters/nuxt4/codegen/runners/generate.mjs +236 -0
  200. package/adapters/nuxt4/codegen/runners/lib/component-resolve.mjs +66 -0
  201. package/adapters/nuxt4/codegen/runners/lib/design-registry.mjs +332 -0
  202. package/adapters/nuxt4/codegen/runners/lib/naming.mjs +246 -0
  203. package/adapters/nuxt4/codegen/runners/lib/page-lifecycle.mjs +254 -0
  204. package/adapters/nuxt4/codegen/runners/lib/plan.mjs +370 -0
  205. package/adapters/nuxt4/codegen/runners/lib/read-spec.mjs +7 -0
  206. package/adapters/nuxt4/codegen/runners/lib/render.mjs +47 -0
  207. package/adapters/nuxt4/codegen/runners/lib/resolve-hub-id.mjs +288 -0
  208. package/adapters/nuxt4/codegen/runners/lib/slots.mjs +121 -0
  209. package/adapters/nuxt4/codegen/runners/lib/write-files.mjs +106 -0
  210. package/adapters/nuxt4/codegen/runners/validate-registry.mjs +121 -0
  211. package/adapters/nuxt4/codegen/templates/create/form.vue.hbs +26 -0
  212. package/adapters/nuxt4/codegen/templates/create/mock.ts.hbs +11 -0
  213. package/adapters/nuxt4/codegen/templates/create/model.schema.ts.hbs +14 -0
  214. package/adapters/nuxt4/codegen/templates/create/model.types.ts.hbs +9 -0
  215. package/adapters/nuxt4/codegen/templates/create/page.vue.hbs +11 -0
  216. package/adapters/nuxt4/codegen/templates/create/service.ts.hbs +25 -0
  217. package/adapters/nuxt4/codegen/templates/create/useForm.ts.hbs +29 -0
  218. package/adapters/nuxt4/codegen/templates/create/validation.ts.hbs +12 -0
  219. package/adapters/nuxt4/codegen/templates/list/mock.ts.hbs +27 -0
  220. package/adapters/nuxt4/codegen/templates/list/model.index.ts.hbs +2 -0
  221. package/adapters/nuxt4/codegen/templates/list/model.schema.ts.hbs +16 -0
  222. package/adapters/nuxt4/codegen/templates/list/model.types.ts.hbs +9 -0
  223. package/adapters/nuxt4/codegen/templates/list/page.custom.vue.hbs +105 -0
  224. package/adapters/nuxt4/codegen/templates/list/page.vue.hbs +55 -0
  225. package/adapters/nuxt4/codegen/templates/list/service.ts.hbs +37 -0
  226. package/adapters/nuxt4/codegen/templates/list/useList.ts.hbs +82 -0
  227. package/adapters/nuxt4/codegen/templates/list/useListColumns.ts.hbs +21 -0
  228. package/adapters/nuxt4/codegen/templates/list/useListExport.ts.hbs +26 -0
  229. package/adapters/nuxt4/codegen/templates/list/useListFilters.ts.hbs +45 -0
  230. package/adapters/nuxt4/codegen/templates/partials/component-stub.vue.hbs +44 -0
  231. package/adapters/nuxt4/codegen/templates/store/store.ts.hbs +30 -0
  232. package/adapters/nuxt4/unitgen/runners/README.md +12 -0
  233. package/adapters/nuxt4/unitgen/runners/generate.mjs +201 -0
  234. package/adapters/nuxt4/unitgen/runners/lib/parse-tags.mjs +49 -0
  235. package/adapters/nuxt4/unitgen/runners/lib/plan.mjs +567 -0
  236. package/adapters/nuxt4/unitgen/runners/lib/read-codegen.mjs +42 -0
  237. package/adapters/nuxt4/unitgen/runners/lib/render.mjs +32 -0
  238. package/adapters/nuxt4/unitgen/runners/lib/unit-registry.mjs +52 -0
  239. package/adapters/nuxt4/unitgen/runners/lib/write-files.mjs +103 -0
  240. package/adapters/nuxt4/unitgen/runners/lib/write-spec-tags.mjs +37 -0
  241. package/adapters/nuxt4/unitgen/runners/validate-registry.mjs +74 -0
  242. package/adapters/nuxt4/unitgen/templates/composables/use-form.test.ts.hbs +56 -0
  243. package/adapters/nuxt4/unitgen/templates/composables/use-list.test.ts.hbs +59 -0
  244. package/adapters/nuxt4/unitgen/templates/models/schema.test.ts.hbs +24 -0
  245. package/adapters/nuxt4/unitgen/templates/services/service.create.test.ts.hbs +28 -0
  246. package/adapters/nuxt4/unitgen/templates/services/service.export.test.ts.hbs +20 -0
  247. package/adapters/nuxt4/unitgen/templates/services/service.search.test.ts.hbs +25 -0
  248. package/adapters/nuxt4/unitgen/templates/services/service.wire.test.ts.hbs +37 -0
  249. package/adapters/nuxt4/unitgen/templates/validations/schemas.test.ts.hbs +19 -0
  250. package/adapters/shared/common-gen.mjs +599 -0
  251. package/adapters/shared/common-ui.catalog.json +224 -0
  252. package/adapters/shared/css-adapters/shadcn.mjs +56 -0
  253. package/adapters/shared/css-adapters/winforms.mjs +46 -0
  254. package/adapters/shared/css-gen.mjs +87 -0
  255. package/adapters/shared/fe-layout-profiles.mjs +74 -0
  256. package/adapters/shared/fe-ui-inventory.mjs +62 -0
  257. package/adapters/shared/i18n-merge.mjs +56 -0
  258. package/adapters/shared/read-fe-ir.mjs +64 -0
  259. package/adapters/shared/resolve-cli.mjs +16 -0
  260. package/adapters/shared/resolve-hub-id.mjs +381 -0
  261. package/adapters/shared/surface-common.mjs +41 -0
  262. package/bin/flowgrid-mcp.mjs +29 -0
  263. package/bin/flowgrid.mjs +915 -0
  264. package/bin/lib/agent-mcp.mjs +70 -0
  265. package/bin/lib/agent-profiles.mjs +127 -0
  266. package/bin/lib/audit-run.mjs +96 -0
  267. package/bin/lib/cli-update.mjs +254 -0
  268. package/bin/lib/doctor.mjs +163 -0
  269. package/bin/lib/harness-overlay.mjs +80 -0
  270. package/bin/lib/harness-sync.mjs +427 -0
  271. package/bin/lib/init-scaffold.mjs +158 -0
  272. package/bin/lib/npm-registry.mjs +45 -0
  273. package/bin/lib/project-gitignore.mjs +39 -0
  274. package/dist/codegen/adapters/run-be.d.ts +13 -0
  275. package/dist/codegen/adapters/run-be.js +190 -0
  276. package/dist/codegen/adapters/run-be.js.map +1 -0
  277. package/dist/codegen/adapters/run.d.ts +44 -0
  278. package/dist/codegen/adapters/run.js +146 -0
  279. package/dist/codegen/adapters/run.js.map +1 -0
  280. package/dist/codegen/config/project-root.d.ts +13 -0
  281. package/dist/codegen/config/project-root.js +64 -0
  282. package/dist/codegen/config/project-root.js.map +1 -0
  283. package/dist/codegen/mcp/tools.d.ts +2 -0
  284. package/dist/codegen/mcp/tools.js +138 -0
  285. package/dist/codegen/mcp/tools.js.map +1 -0
  286. package/dist/codegen/registries/common.d.ts +28 -0
  287. package/dist/codegen/registries/common.js +54 -0
  288. package/dist/codegen/registries/common.js.map +1 -0
  289. package/dist/dna/config/project-root.d.ts +12 -0
  290. package/dist/dna/config/project-root.js +41 -0
  291. package/dist/dna/config/project-root.js.map +1 -0
  292. package/dist/dna/profile/detect.d.ts +14 -0
  293. package/dist/dna/profile/detect.js +159 -0
  294. package/dist/dna/profile/detect.js.map +1 -0
  295. package/dist/dna/profile/manifest.d.ts +17 -0
  296. package/dist/dna/profile/manifest.js +10 -0
  297. package/dist/dna/profile/manifest.js.map +1 -0
  298. package/dist/docs/cli/engines.d.ts +13 -0
  299. package/dist/docs/cli/engines.js +53 -0
  300. package/dist/docs/cli/engines.js.map +1 -0
  301. package/dist/docs/config/docs-root.d.ts +8 -0
  302. package/dist/docs/config/docs-root.js +66 -0
  303. package/dist/docs/config/docs-root.js.map +1 -0
  304. package/dist/docs/mcp/tools.d.ts +2 -0
  305. package/dist/docs/mcp/tools.js +351 -0
  306. package/dist/docs/mcp/tools.js.map +1 -0
  307. package/dist/docs/scan/ids.d.ts +29 -0
  308. package/dist/docs/scan/ids.js +237 -0
  309. package/dist/docs/scan/ids.js.map +1 -0
  310. package/dist/docs/scan/links.d.ts +10 -0
  311. package/dist/docs/scan/links.js +98 -0
  312. package/dist/docs/scan/links.js.map +1 -0
  313. package/dist/docs/scan/route.d.ts +8 -0
  314. package/dist/docs/scan/route.js +114 -0
  315. package/dist/docs/scan/route.js.map +1 -0
  316. package/dist/graph/analyze/analyze-bullets.d.ts +17 -0
  317. package/dist/graph/analyze/analyze-bullets.js +137 -0
  318. package/dist/graph/analyze/analyze-bullets.js.map +1 -0
  319. package/dist/graph/analyze/analyze-spec.d.ts +12 -0
  320. package/dist/graph/analyze/analyze-spec.js +249 -0
  321. package/dist/graph/analyze/analyze-spec.js.map +1 -0
  322. package/dist/graph/analyze/api-routes.d.ts +66 -0
  323. package/dist/graph/analyze/api-routes.js +370 -0
  324. package/dist/graph/analyze/api-routes.js.map +1 -0
  325. package/dist/graph/analyze/context-orphan.d.ts +12 -0
  326. package/dist/graph/analyze/context-orphan.js +229 -0
  327. package/dist/graph/analyze/context-orphan.js.map +1 -0
  328. package/dist/graph/analyze/grill-check.d.ts +31 -0
  329. package/dist/graph/analyze/grill-check.js +92 -0
  330. package/dist/graph/analyze/grill-check.js.map +1 -0
  331. package/dist/graph/analyze/parity-check.d.ts +25 -0
  332. package/dist/graph/analyze/parity-check.js +406 -0
  333. package/dist/graph/analyze/parity-check.js.map +1 -0
  334. package/dist/graph/analyze/product-paths.d.ts +13 -0
  335. package/dist/graph/analyze/product-paths.js +29 -0
  336. package/dist/graph/analyze/product-paths.js.map +1 -0
  337. package/dist/graph/analyze/surface-paths.d.ts +13 -0
  338. package/dist/graph/analyze/surface-paths.js +29 -0
  339. package/dist/graph/analyze/surface-paths.js.map +1 -0
  340. package/dist/graph/config/load-config.d.ts +30 -0
  341. package/dist/graph/config/load-config.js +112 -0
  342. package/dist/graph/config/load-config.js.map +1 -0
  343. package/dist/graph/config/platform-repos.d.ts +36 -0
  344. package/dist/graph/config/platform-repos.js +124 -0
  345. package/dist/graph/config/platform-repos.js.map +1 -0
  346. package/dist/graph/config/resolve-paths.d.ts +45 -0
  347. package/dist/graph/config/resolve-paths.js +121 -0
  348. package/dist/graph/config/resolve-paths.js.map +1 -0
  349. package/dist/graph/db/index-store.d.ts +67 -0
  350. package/dist/graph/db/index-store.js +179 -0
  351. package/dist/graph/db/index-store.js.map +1 -0
  352. package/dist/graph/gen/run-command.d.ts +40 -0
  353. package/dist/graph/gen/run-command.js +110 -0
  354. package/dist/graph/gen/run-command.js.map +1 -0
  355. package/dist/graph/lexicon/infer-lane.d.ts +11 -0
  356. package/dist/graph/lexicon/infer-lane.js +28 -0
  357. package/dist/graph/lexicon/infer-lane.js.map +1 -0
  358. package/dist/graph/lexicon/load-lexicon.d.ts +60 -0
  359. package/dist/graph/lexicon/load-lexicon.js +492 -0
  360. package/dist/graph/lexicon/load-lexicon.js.map +1 -0
  361. package/dist/graph/mcp/tools.d.ts +9 -0
  362. package/dist/graph/mcp/tools.js +326 -0
  363. package/dist/graph/mcp/tools.js.map +1 -0
  364. package/dist/graph/registry/load-registries.d.ts +27 -0
  365. package/dist/graph/registry/load-registries.js +111 -0
  366. package/dist/graph/registry/load-registries.js.map +1 -0
  367. package/dist/graph/types.d.ts +208 -0
  368. package/dist/graph/types.js +11 -0
  369. package/dist/graph/types.js.map +1 -0
  370. package/dist/test/config/project-root.d.ts +5 -0
  371. package/dist/test/config/project-root.js +29 -0
  372. package/dist/test/config/project-root.js.map +1 -0
  373. package/dist/test/engines/run.d.ts +10 -0
  374. package/dist/test/engines/run.js +16 -0
  375. package/dist/test/engines/run.js.map +1 -0
  376. package/dist/test/mcp/tools.d.ts +2 -0
  377. package/dist/test/mcp/tools.js +43 -0
  378. package/dist/test/mcp/tools.js.map +1 -0
  379. package/dist/test/optional/fallback-evidence.d.ts +34 -0
  380. package/dist/test/optional/fallback-evidence.js +103 -0
  381. package/dist/test/optional/fallback-evidence.js.map +1 -0
  382. package/engines/cases/README.md +12 -0
  383. package/engines/cases/check-coverage.mjs +103 -0
  384. package/engines/cases/check-plans.mjs +31 -0
  385. package/engines/cases/gate.mjs +215 -0
  386. package/engines/cases/lib/audit-tc-traceability.mjs +139 -0
  387. package/engines/cases/lib/list-case-yaml.mjs +27 -0
  388. package/engines/cases/lib/parse-bundle-traceability.mjs +77 -0
  389. package/engines/cases/lib/render-github-catalog.mjs +141 -0
  390. package/engines/cases/lib/resolve-bundle-from-screen.mjs +73 -0
  391. package/engines/cases/lib/screen-facet-coverage.mjs +42 -0
  392. package/engines/cases/lib/validate-tc-schema.mjs +61 -0
  393. package/engines/cases/publish.mjs +4 -0
  394. package/engines/cases/render-cases.mjs +182 -0
  395. package/engines/cases/vitepress/config.ts +171 -0
  396. package/engines/cases/vitepress/theme/custom.css +418 -0
  397. package/engines/cases/vitepress/theme/index.ts +46 -0
  398. package/engines/codegen/adapters/shadcn.mjs +58 -0
  399. package/engines/codegen/adapters/winforms.mjs +46 -0
  400. package/engines/codegen/tokens.mjs +64 -0
  401. package/engines/docs/lib/load-dev-base-url.mjs +38 -0
  402. package/engines/docs/lib/markdown-table.mjs +65 -0
  403. package/engines/docs/lib/render-bundle-markdown.mjs +95 -0
  404. package/engines/docs/lib/render-design-tables.mjs +695 -0
  405. package/engines/docs/lib/render-github-catalog.mjs +194 -0
  406. package/engines/docs/lib/render-qa-list.mjs +57 -0
  407. package/engines/docs/lib/render-spec-markdown.mjs +19 -0
  408. package/engines/docs/lib/render-template.mjs +76 -0
  409. package/engines/docs/lib/route-page-probe.mjs +54 -0
  410. package/engines/docs/publish.mjs +4 -0
  411. package/engines/docs/render-docs.mjs +195 -0
  412. package/engines/docs/vitepress/config.ts +442 -0
  413. package/engines/docs/vitepress/surfaces-nav.mjs +171 -0
  414. package/engines/docs/vitepress/theme/custom.css +418 -0
  415. package/engines/docs/vitepress/theme/index.ts +46 -0
  416. package/engines/openapi/build-openapi-ui.mjs +72 -0
  417. package/engines/openapi/build-swagger-ui.mjs +72 -0
  418. package/engines/openapi/check-backend-spec.mjs +66 -0
  419. package/engines/openapi/gen-openapi.mjs +337 -0
  420. package/engines/openapi/render-backend-spec.mjs +170 -0
  421. package/engines/openapi/render-openapi.mjs +155 -0
  422. package/engines/shared/flowgrid-tests-docs.mjs +32 -0
  423. package/engines/spec/extract-i18n.mjs +74 -0
  424. package/engines/spec/legacy-dynamics-validate.mjs +67 -0
  425. package/engines/spec/lib/audit-api-gaps.mjs +198 -0
  426. package/engines/spec/lib/audit-bundle-gaps.mjs +582 -0
  427. package/engines/spec/lib/audit-e2e-coverage.mjs +381 -0
  428. package/engines/spec/lib/audit-fe-be-alignment.mjs +183 -0
  429. package/engines/spec/lib/audit-flow-gaps.mjs +151 -0
  430. package/engines/spec/lib/audit-legacy-gaps.mjs +73 -0
  431. package/engines/spec/lib/audit-scenario-coverage.mjs +175 -0
  432. package/engines/spec/lib/audit-testcase-bundle-cross.mjs +145 -0
  433. package/engines/spec/lib/audit-testcase-gaps.mjs +79 -0
  434. package/engines/spec/lib/audit-testcase-plan-gaps.mjs +131 -0
  435. package/engines/spec/lib/audit-testcase-tc.mjs +182 -0
  436. package/engines/spec/lib/audit-ux-affordance.mjs +269 -0
  437. package/engines/spec/lib/bundle-ir.mjs +360 -0
  438. package/engines/spec/lib/bundle-schema.mjs +199 -0
  439. package/engines/spec/lib/collect-screen-api-intents.mjs +69 -0
  440. package/engines/spec/lib/hydrate-design-api.mjs +58 -0
  441. package/engines/spec/lib/open-qa.mjs +66 -0
  442. package/engines/spec/lib/project-business-layout.mjs +214 -0
  443. package/engines/spec/lib/testcase-matrix-facets.mjs +9 -0
  444. package/engines/spec/merge-bundle.mjs +27 -0
  445. package/engines/spec/normalize-bundle-gen.mjs +69 -0
  446. package/engines/spec/split-all.mjs +78 -0
  447. package/engines/spec/split-bundle.mjs +45 -0
  448. package/engines/template-builder/runner.mjs +96 -0
  449. package/engines/template-builder/scanner.mjs +138 -0
  450. package/engines/testcase/_staging-from-portal/README-STAGING.md +13 -0
  451. package/engines/testcase/_staging-from-portal/runners/README.md +15 -0
  452. package/engines/testcase/_staging-from-portal/runners/generate.mjs +123 -0
  453. package/engines/testcase/_staging-from-portal/runners/lib/e2e-registry.mjs +77 -0
  454. package/engines/testcase/_staging-from-portal/runners/lib/plan.mjs +97 -0
  455. package/engines/testcase/_staging-from-portal/runners/lib/read-testcase.mjs +166 -0
  456. package/engines/testcase/_staging-from-portal/runners/lib/render.mjs +18 -0
  457. package/engines/testcase/_staging-from-portal/runners/lib/semantic-plan.mjs +178 -0
  458. package/engines/testcase/_staging-from-portal/runners/lib/write-files.mjs +42 -0
  459. package/engines/testcase/_staging-from-portal/runners/validate-registry.mjs +75 -0
  460. package/engines/testcase/_staging-from-portal/templates/page.ts.hbs +52 -0
  461. package/engines/testcase/_staging-from-portal/templates/partials/README.md +5 -0
  462. package/engines/testcase/_staging-from-portal/templates/spec.ts.hbs +214 -0
  463. package/engines/testcase/runners/README.md +27 -0
  464. package/engines/testcase/runners/generate-api.mjs +121 -0
  465. package/engines/testcase/runners/generate.mjs +161 -0
  466. package/engines/testcase/runners/lib/api-plan.mjs +64 -0
  467. package/engines/testcase/runners/lib/e2e-registry.mjs +77 -0
  468. package/engines/testcase/runners/lib/plan.mjs +123 -0
  469. package/engines/testcase/runners/lib/read-spec.mjs +37 -0
  470. package/engines/testcase/runners/lib/read-testcase.mjs +179 -0
  471. package/engines/testcase/runners/lib/render.mjs +18 -0
  472. package/engines/testcase/runners/lib/resolve-hub-id.mjs +324 -0
  473. package/engines/testcase/runners/lib/semantic-plan.mjs +178 -0
  474. package/engines/testcase/runners/lib/write-files.mjs +145 -0
  475. package/engines/testcase/runners/validate-registry.mjs +75 -0
  476. package/engines/testcase/templates/api.spec.ts.hbs +40 -0
  477. package/engines/testcase/templates/page.ts.hbs +69 -0
  478. package/engines/testcase/templates/partials/README.md +5 -0
  479. package/engines/testcase/templates/spec.ts.hbs +231 -0
  480. package/harness/agents/claude/rules/claude-flowgrid.mdc +9 -0
  481. package/harness/agents/cursor/rules/cursor-flowgrid.mdc +9 -0
  482. package/harness/agents/gemini_antigravity/rules/antigravity-mcp.mdc +10 -0
  483. package/harness/agents/kiro/rules/kiro-flowgrid.mdc +9 -0
  484. package/harness/be/adapters/dotnet-integration/skills/framework-rules-be/SKILL.md +21 -0
  485. package/harness/be/adapters/fastapi/skills/framework-rules-be/SKILL.md +27 -0
  486. package/harness/be/adapters/laravel/skills/framework-rules-be/SKILL.md +27 -0
  487. package/harness/be/extracts/artifactgraph-hooks-be.md +21 -0
  488. package/harness/be/extracts/risk-classes.md +69 -0
  489. package/harness/be/skills/api/SKILL.md +116 -0
  490. package/harness/be/skills/api-unit/SKILL.md +76 -0
  491. package/harness/be/skills/grill-api/SKILL.md +69 -0
  492. package/harness/be/skills/grill-api-unit/SKILL.md +57 -0
  493. package/harness/common/extracts/artifact-graph.md +23 -0
  494. package/harness/common/extracts/artifactgraph-hooks-core.md +17 -0
  495. package/harness/common/extracts/artifactgraph-phase-hooks.md +106 -0
  496. package/harness/common/extracts/core/agent-discipline.md +8 -0
  497. package/harness/common/extracts/docs-mark-detect.md +48 -0
  498. package/harness/common/extracts/docs-mark.md +62 -0
  499. package/harness/common/extracts/extract-registry.json +29 -0
  500. package/harness/common/extracts/ux-common-patterns.md +172 -0
  501. package/harness/common/rules/artifactgraph.mdc +26 -0
  502. package/harness/common/rules/cross-repo-index.mdc +47 -0
  503. package/harness/common/rules/flowgrid-ux-common.mdc +39 -0
  504. package/harness/common/rules/platform-code-size.mdc +24 -0
  505. package/harness/common/rules/team-flow-harness-state.mdc +12 -0
  506. package/harness/common/skills/business-impact-review/SKILL.md +106 -0
  507. package/harness/common/skills/configure-repo-maps/SKILL.md +58 -0
  508. package/harness/common/skills/docs-mark/SKILL.md +67 -0
  509. package/harness/common/skills/legacy/SKILL.md +29 -0
  510. package/harness/common/skills/ui-proposal/SKILL.md +28 -0
  511. package/harness/docs/extracts/agent-execution-protocol.md +31 -0
  512. package/harness/docs/extracts/architecture-core.md +71 -0
  513. package/harness/docs/extracts/artifactgraph-hooks-docs.md +15 -0
  514. package/harness/docs/extracts/artifactgraph-parity.md +10 -0
  515. package/harness/docs/extracts/business-process-trace.md +66 -0
  516. package/harness/docs/extracts/codegen/readiness.md +8 -0
  517. package/harness/docs/extracts/common-scope.md +65 -0
  518. package/harness/docs/extracts/docs-phase-hooks.md +22 -0
  519. package/harness/docs/extracts/extract-registry.docs.json +45 -0
  520. package/harness/docs/extracts/extract-registry.flowgrid-process.json +12 -0
  521. package/harness/docs/extracts/grill/validation.md +9 -0
  522. package/harness/docs/extracts/grill-docs-reconcile.md +5 -0
  523. package/harness/docs/extracts/qa-inbox.md +36 -0
  524. package/harness/docs/extracts/risk-classes.md +69 -0
  525. package/harness/docs/extracts/spec-core.md +5 -0
  526. package/harness/docs/extracts/spec-requirement.md +5 -0
  527. package/harness/docs/extracts/tpl-adr.md +23 -0
  528. package/harness/docs/extracts/tpl-arc42-chapter.md +29 -0
  529. package/harness/docs/extracts/tpl-cross-cutting.md +24 -0
  530. package/harness/docs/extracts/tpl-deployment.md +23 -0
  531. package/harness/docs/extracts/tpl-module.md +33 -0
  532. package/harness/docs/extracts/update-spec-delta.md +5 -0
  533. package/harness/docs/rules/agent-compliance.mdc +26 -0
  534. package/harness/docs/rules/docs-hub.mdc +54 -0
  535. package/harness/docs/rules/flowgrid-process.mdc +25 -0
  536. package/harness/docs/rules/team-flow-grill.mdc +31 -0
  537. package/harness/docs/rules/team-flow-harness-state.mdc +16 -0
  538. package/harness/docs/rules/team-flow-spec.mdc +36 -0
  539. package/harness/docs/schemas/flowgrid-docs/backend-api.schema.json +175 -0
  540. package/harness/docs/schemas/flowgrid-docs/missing-optional-event.schema.json +39 -0
  541. package/harness/docs/schemas/flowgrid-docs/spec.schema.json +643 -0
  542. package/harness/docs/schemas/flowgrid-docs/testcase.schema.json +29 -0
  543. package/harness/docs/schemas/flowgrid-process/missing-optional-event.schema.json +39 -0
  544. package/harness/docs/skills/adopt/SKILL.md +140 -0
  545. package/harness/docs/skills/api/SKILL.md +40 -0
  546. package/harness/docs/skills/api-integration/SKILL.md +110 -0
  547. package/harness/docs/skills/api-spec/SKILL.md +136 -0
  548. package/harness/docs/skills/api-update/SKILL.md +82 -0
  549. package/harness/docs/skills/architecture/SKILL.md +57 -0
  550. package/harness/docs/skills/architecture-grill/SKILL.md +29 -0
  551. package/harness/docs/skills/background-logic/SKILL.md +100 -0
  552. package/harness/docs/skills/build-templates/SKILL.md +47 -0
  553. package/harness/docs/skills/business-process/SKILL.md +109 -0
  554. package/harness/docs/skills/call-external/SKILL.md +32 -0
  555. package/harness/docs/skills/common/SKILL.md +46 -0
  556. package/harness/docs/skills/common-spec/SKILL.md +55 -0
  557. package/harness/docs/skills/cross-cutting/SKILL.md +33 -0
  558. package/harness/docs/skills/cross-entity-service/SKILL.md +32 -0
  559. package/harness/docs/skills/cross-service/SKILL.md +37 -0
  560. package/harness/docs/skills/db-erd/SKILL.md +29 -0
  561. package/harness/docs/skills/decision/SKILL.md +30 -0
  562. package/harness/docs/skills/deployment/SKILL.md +34 -0
  563. package/harness/docs/skills/docs-hub/SKILL.md +65 -0
  564. package/harness/docs/skills/grill/SKILL.md +46 -0
  565. package/harness/docs/skills/grill-api/SKILL.md +26 -0
  566. package/harness/docs/skills/grill-api-spec/SKILL.md +57 -0
  567. package/harness/docs/skills/grill-bqa/SKILL.md +119 -0
  568. package/harness/docs/skills/grill-common-spec/SKILL.md +43 -0
  569. package/harness/docs/skills/grill-dev/SKILL.md +172 -0
  570. package/harness/docs/skills/grill-docs/SKILL.md +79 -0
  571. package/harness/docs/skills/grill-integration-spec/SKILL.md +51 -0
  572. package/harness/docs/skills/module/SKILL.md +58 -0
  573. package/harness/docs/skills/openapi/SKILL.md +37 -0
  574. package/harness/docs/skills/overview/SKILL.md +42 -0
  575. package/harness/docs/skills/qa-resolve/SKILL.md +91 -0
  576. package/harness/docs/skills/spec/SKILL.md +240 -0
  577. package/harness/docs/skills/surfaces/SKILL.md +52 -0
  578. package/harness/docs/skills/update-spec/SKILL.md +83 -0
  579. package/harness/fe/adapters/dotnet-line/skills/framework-rules/SKILL.md +27 -0
  580. package/harness/fe/adapters/nextjs/skills/framework-rules/SKILL.md +29 -0
  581. package/harness/fe/adapters/nuxt4/skills/framework-rules/SKILL.md +33 -0
  582. package/harness/fe/extracts/artifactgraph-hooks-fe.md +15 -0
  583. package/harness/fe/extracts/risk-classes.md +69 -0
  584. package/harness/fe/rules/cross-repo-index-routing.mdc +24 -0
  585. package/harness/fe/rules/flowgrid-test-optional-accelerators.mdc +21 -0
  586. package/harness/fe/rules/platform-code-size.mdc +43 -0
  587. package/harness/fe/rules/platform-design-vocabulary.mdc +33 -0
  588. package/harness/fe/rules/team-flow-prototype.mdc +32 -0
  589. package/harness/fe/rules/team-flow-unit.mdc +27 -0
  590. package/harness/fe/skills/build-template-code/SKILL.md +42 -0
  591. package/harness/fe/skills/gen-common/SKILL.md +93 -0
  592. package/harness/fe/skills/grill-prototype/SKILL.md +41 -0
  593. package/harness/fe/skills/grill-test/SKILL.md +32 -0
  594. package/harness/fe/skills/grill-unit/SKILL.md +31 -0
  595. package/harness/fe/skills/model/SKILL.md +48 -0
  596. package/harness/fe/skills/prototype/SKILL.md +100 -0
  597. package/harness/fe/skills/test/SKILL.md +37 -0
  598. package/harness/fe/skills/unit/SKILL.md +55 -0
  599. package/harness/fe/skills/wire/SKILL.md +60 -0
  600. package/harness/shared/AGENTS.md +169 -0
  601. package/harness/shared/SSOT_AGENT_PROTOCOL.md +167 -0
  602. package/harness/shared/rules/flowgrid-code-optional-integrations.mdc +53 -0
  603. package/harness/shared/schemas/flowgrid-code/missing-optional-event.schema.json +62 -0
  604. package/harness/tests/extracts/artifactgraph-hooks-test.md +13 -0
  605. package/harness/tests/extracts/plans/readiness.md +14 -0
  606. package/harness/tests/rules/cross-repo-index-routing.mdc +24 -0
  607. package/harness/tests/rules/flowgrid-test-optional-accelerators.mdc +21 -0
  608. package/harness/tests/rules/plans-docs-first.mdc +13 -0
  609. package/harness/tests/skills/grill-testcase/SKILL.md +55 -0
  610. package/harness/tests/skills/scenario/SKILL.md +64 -0
  611. package/harness/tests/skills/test-api/SKILL.md +65 -0
  612. package/harness/tests/skills/testcase/SKILL.md +98 -0
  613. package/harness/tests/templates/SC.example.md +86 -0
  614. package/harness/tests/templates/TC.example-api.yaml +45 -0
  615. package/harness/tests/templates/TC.example.yaml +127 -0
  616. package/lexicon/registry-tags.en.txt +173 -0
  617. package/lexicon/testcase-taxonomy.en.txt +117 -0
  618. package/package.json +98 -0
  619. package/schemas/missing-optional-event.schema.json +37 -0
  620. package/schemas/testcase.schema.json +239 -0
  621. package/scripts/prepare-install.mjs +25 -0
  622. package/stacks/docs.json +21 -0
  623. package/stacks/dotnet-integration.json +66 -0
  624. package/stacks/dotnet-line.json +64 -0
  625. package/stacks/fastapi.json +98 -0
  626. package/stacks/generic.json +11 -0
  627. package/stacks/laravel.json +92 -0
  628. package/stacks/nextjs-nest.json +93 -0
  629. package/stacks/nextjs.json +132 -0
  630. package/stacks/nuxt4-nest.json +123 -0
  631. package/stacks/nuxt4.json +148 -0
  632. package/templates/project-skeleton/architecture/01-introduction/index.md +33 -0
  633. package/templates/project-skeleton/architecture/02-constraints/index.md +34 -0
  634. package/templates/project-skeleton/architecture/03-business-process/FLOW-login.md +101 -0
  635. package/templates/project-skeleton/architecture/03-business-process/FLOW-template.md +149 -0
  636. package/templates/project-skeleton/architecture/04-solution-strategy/index.md +26 -0
  637. package/templates/project-skeleton/architecture/07-deployment/index.md +26 -0
  638. package/templates/project-skeleton/architecture/08-cross-cutting/configuration.md +18 -0
  639. package/templates/project-skeleton/architecture/08-cross-cutting/index.md +27 -0
  640. package/templates/project-skeleton/architecture/08-cross-cutting/observability.md +18 -0
  641. package/templates/project-skeleton/architecture/08-cross-cutting/security.md +18 -0
  642. package/templates/project-skeleton/architecture/09-decisions/ADR-001-arc42-toc.md +31 -0
  643. package/templates/project-skeleton/architecture/09-decisions/index.md +13 -0
  644. package/templates/project-skeleton/architecture/10-quality/index.md +27 -0
  645. package/templates/project-skeleton/architecture/11-risks/index.md +25 -0
  646. package/templates/project-skeleton/architecture/12-glossary/index.md +31 -0
  647. package/templates/project-skeleton/architecture/index.md +1 -0
  648. package/templates/project-skeleton/architecture/model/workspace.dsl +71 -0
  649. package/templates/project-skeleton/index.md +2 -0
  650. package/templates/project-skeleton/overview/.gitkeep +1 -0
  651. package/templates/project-skeleton/overview/index.md +2 -0
  652. package/templates/project-skeleton/qa/README.md +11 -0
  653. package/templates/project-skeleton/qa/open/.gitkeep +0 -0
  654. package/templates/project-skeleton/surfaces/common/code/API-CMN-HEALTH-001/health.api.yaml +12 -0
  655. package/templates/project-skeleton/surfaces/common/code/API-CMN-HEALTH-001/index.md +12 -0
  656. package/templates/project-skeleton/surfaces/common/code/UI-CMN-EMPTY-001/empty.ui.yaml +14 -0
  657. package/templates/project-skeleton/surfaces/common/code/UI-CMN-EMPTY-001/index.md +11 -0
  658. package/templates/project-skeleton/surfaces/common/data-model/derived-data.md +26 -0
  659. package/templates/project-skeleton/surfaces/common/data-model/index.md +16 -0
  660. package/templates/project-skeleton/surfaces/common/index.md +32 -0
  661. package/templates/project-skeleton/surfaces/common/md/breadcrumb-flow/common-breadcrumb-flow.md +72 -0
  662. package/templates/project-skeleton/surfaces/common/md/buttons/common-buttons.md +160 -0
  663. package/templates/project-skeleton/surfaces/common/md/confirm-dialog/common-confirm-dialog.md +98 -0
  664. package/templates/project-skeleton/surfaces/common/md/data-table/common-data-table.md +91 -0
  665. package/templates/project-skeleton/surfaces/common/md/delete-flow/common-delete-flow.md +68 -0
  666. package/templates/project-skeleton/surfaces/common/md/feedback/common-feedback.md +140 -0
  667. package/templates/project-skeleton/surfaces/common/md/flat-design/common-flat-design.md +78 -0
  668. package/templates/project-skeleton/surfaces/common/md/form-validation/common-form-validation.md +74 -0
  669. package/templates/project-skeleton/surfaces/common/md/import-csv/common-import-csv.md +89 -0
  670. package/templates/project-skeleton/surfaces/common/md/list-page/common-list-page.md +102 -0
  671. package/templates/project-skeleton/surfaces/common/md/list-toolbar/common-list-toolbar.md +81 -0
  672. package/templates/project-skeleton/surfaces/common/md/navigation/common-navigation.md +70 -0
  673. package/templates/project-skeleton/surfaces/common/md/pagination/common-pagination.md +86 -0
  674. package/templates/project-skeleton/surfaces/common/md/search-filter/common-search-filter.md +96 -0
  675. package/templates/project-skeleton/surfaces/common/md/status-chip/common-status-chip.md +93 -0
  676. package/templates/project-skeleton/surfaces/common/md/table-action-column/common-table-action-column.md +90 -0
  677. package/templates/project-skeleton/surfaces/common/patterns/breadcrumb-flow.md +83 -0
  678. package/templates/project-skeleton/surfaces/common/patterns/delete-flow.md +30 -0
  679. package/templates/project-skeleton/surfaces/common/patterns/ui-spec.md +15 -0
  680. package/templates/project-skeleton/surfaces/common/yaml/breadcrumb-flow/common-breadcrumb-flow.bundle.yaml +60 -0
  681. package/templates/project-skeleton/surfaces/common/yaml/breadcrumb-flow/ir/design.yaml +13 -0
  682. package/templates/project-skeleton/surfaces/common/yaml/breadcrumb-flow/ir/legacy.yaml +11 -0
  683. package/templates/project-skeleton/surfaces/common/yaml/breadcrumb-flow/ir/spec.yaml +31 -0
  684. package/templates/project-skeleton/surfaces/common/yaml/buttons/common-buttons.bundle.yaml +147 -0
  685. package/templates/project-skeleton/surfaces/common/yaml/buttons/ir/design.yaml +13 -0
  686. package/templates/project-skeleton/surfaces/common/yaml/buttons/ir/legacy.yaml +11 -0
  687. package/templates/project-skeleton/surfaces/common/yaml/buttons/ir/spec.yaml +118 -0
  688. package/templates/project-skeleton/surfaces/common/yaml/confirm-dialog/common-confirm-dialog.bundle.yaml +89 -0
  689. package/templates/project-skeleton/surfaces/common/yaml/confirm-dialog/ir/design.yaml +13 -0
  690. package/templates/project-skeleton/surfaces/common/yaml/confirm-dialog/ir/legacy.yaml +11 -0
  691. package/templates/project-skeleton/surfaces/common/yaml/confirm-dialog/ir/spec.yaml +60 -0
  692. package/templates/project-skeleton/surfaces/common/yaml/data-table/common-data-table.bundle.yaml +85 -0
  693. package/templates/project-skeleton/surfaces/common/yaml/data-table/ir/design.yaml +13 -0
  694. package/templates/project-skeleton/surfaces/common/yaml/data-table/ir/legacy.yaml +11 -0
  695. package/templates/project-skeleton/surfaces/common/yaml/data-table/ir/spec.yaml +56 -0
  696. package/templates/project-skeleton/surfaces/common/yaml/delete-flow/common-delete-flow.bundle.yaml +59 -0
  697. package/templates/project-skeleton/surfaces/common/yaml/delete-flow/ir/design.yaml +13 -0
  698. package/templates/project-skeleton/surfaces/common/yaml/delete-flow/ir/legacy.yaml +11 -0
  699. package/templates/project-skeleton/surfaces/common/yaml/delete-flow/ir/spec.yaml +30 -0
  700. package/templates/project-skeleton/surfaces/common/yaml/design-system.bundle.yaml +29 -0
  701. package/templates/project-skeleton/surfaces/common/yaml/feedback/common-feedback.bundle.yaml +126 -0
  702. package/templates/project-skeleton/surfaces/common/yaml/feedback/ir/design.yaml +13 -0
  703. package/templates/project-skeleton/surfaces/common/yaml/feedback/ir/legacy.yaml +11 -0
  704. package/templates/project-skeleton/surfaces/common/yaml/feedback/ir/spec.yaml +97 -0
  705. package/templates/project-skeleton/surfaces/common/yaml/flat-design/common-flat-design.bundle.yaml +77 -0
  706. package/templates/project-skeleton/surfaces/common/yaml/flat-design/ir/design.yaml +13 -0
  707. package/templates/project-skeleton/surfaces/common/yaml/flat-design/ir/legacy.yaml +11 -0
  708. package/templates/project-skeleton/surfaces/common/yaml/flat-design/ir/spec.yaml +48 -0
  709. package/templates/project-skeleton/surfaces/common/yaml/form-validation/common-form-validation.bundle.yaml +66 -0
  710. package/templates/project-skeleton/surfaces/common/yaml/form-validation/ir/design.yaml +13 -0
  711. package/templates/project-skeleton/surfaces/common/yaml/form-validation/ir/legacy.yaml +11 -0
  712. package/templates/project-skeleton/surfaces/common/yaml/form-validation/ir/spec.yaml +37 -0
  713. package/templates/project-skeleton/surfaces/common/yaml/import-csv/common-import-csv.bundle.yaml +74 -0
  714. package/templates/project-skeleton/surfaces/common/yaml/import-csv/ir/design.yaml +13 -0
  715. package/templates/project-skeleton/surfaces/common/yaml/import-csv/ir/legacy.yaml +11 -0
  716. package/templates/project-skeleton/surfaces/common/yaml/import-csv/ir/spec.yaml +45 -0
  717. package/templates/project-skeleton/surfaces/common/yaml/list-page/common-list-page.bundle.yaml +90 -0
  718. package/templates/project-skeleton/surfaces/common/yaml/list-page/ir/design.yaml +13 -0
  719. package/templates/project-skeleton/surfaces/common/yaml/list-page/ir/legacy.yaml +14 -0
  720. package/templates/project-skeleton/surfaces/common/yaml/list-page/ir/spec.yaml +58 -0
  721. package/templates/project-skeleton/surfaces/common/yaml/list-toolbar/common-list-toolbar.bundle.yaml +86 -0
  722. package/templates/project-skeleton/surfaces/common/yaml/list-toolbar/ir/design.yaml +13 -0
  723. package/templates/project-skeleton/surfaces/common/yaml/list-toolbar/ir/legacy.yaml +12 -0
  724. package/templates/project-skeleton/surfaces/common/yaml/list-toolbar/ir/spec.yaml +56 -0
  725. package/templates/project-skeleton/surfaces/common/yaml/navigation/common-navigation.bundle.yaml +68 -0
  726. package/templates/project-skeleton/surfaces/common/yaml/navigation/ir/design.yaml +13 -0
  727. package/templates/project-skeleton/surfaces/common/yaml/navigation/ir/legacy.yaml +11 -0
  728. package/templates/project-skeleton/surfaces/common/yaml/navigation/ir/spec.yaml +39 -0
  729. package/templates/project-skeleton/surfaces/common/yaml/pagination/common-pagination.bundle.yaml +84 -0
  730. package/templates/project-skeleton/surfaces/common/yaml/pagination/ir/design.yaml +13 -0
  731. package/templates/project-skeleton/surfaces/common/yaml/pagination/ir/legacy.yaml +13 -0
  732. package/templates/project-skeleton/surfaces/common/yaml/pagination/ir/spec.yaml +53 -0
  733. package/templates/project-skeleton/surfaces/common/yaml/search-filter/common-search-filter.bundle.yaml +88 -0
  734. package/templates/project-skeleton/surfaces/common/yaml/search-filter/ir/design.yaml +13 -0
  735. package/templates/project-skeleton/surfaces/common/yaml/search-filter/ir/legacy.yaml +11 -0
  736. package/templates/project-skeleton/surfaces/common/yaml/search-filter/ir/spec.yaml +59 -0
  737. package/templates/project-skeleton/surfaces/common/yaml/status-chip/common-status-chip.bundle.yaml +89 -0
  738. package/templates/project-skeleton/surfaces/common/yaml/status-chip/ir/design.yaml +13 -0
  739. package/templates/project-skeleton/surfaces/common/yaml/status-chip/ir/legacy.yaml +11 -0
  740. package/templates/project-skeleton/surfaces/common/yaml/status-chip/ir/spec.yaml +60 -0
  741. package/templates/project-skeleton/surfaces/common/yaml/table-action-column/common-table-action-column.bundle.yaml +81 -0
  742. package/templates/project-skeleton/surfaces/common/yaml/table-action-column/ir/design.yaml +13 -0
  743. package/templates/project-skeleton/surfaces/common/yaml/table-action-column/ir/legacy.yaml +11 -0
  744. package/templates/project-skeleton/surfaces/common/yaml/table-action-column/ir/spec.yaml +52 -0
  745. package/templates/project-skeleton/surfaces/index.md +1 -0
  746. package/templates/schemas/backend-api.schema.json +174 -0
  747. package/templates/schemas/legacy-repos.schema.json +24 -0
  748. package/templates/schemas/platform-repos.schema.json +29 -0
  749. package/templates/schemas/spec.schema.json +718 -0
  750. package/templates/schemas/testcase.schema.json +28 -0
  751. package/templates/shared/AUTHORING-COMMON.md +109 -0
  752. package/templates/shared/api-contract-test.yaml +33 -0
  753. package/templates/shared/backend-api-integration.yaml +152 -0
  754. package/templates/shared/backend-api.bundle.yaml +177 -0
  755. package/templates/shared/backend-api.yaml +188 -0
  756. package/templates/shared/breadcrumb-flow.ejs +45 -0
  757. package/templates/shared/bundle-authoring.md +288 -0
  758. package/templates/shared/clients-line.yaml +18 -0
  759. package/templates/shared/default-layout.ejs +234 -0
  760. package/templates/shared/design-spec.yaml +85 -0
  761. package/templates/shared/entity-delta.example.yaml +45 -0
  762. package/templates/shared/feature.bundle.yaml +575 -0
  763. package/templates/shared/integration-adapter.bundle.yaml +77 -0
  764. package/templates/shared/integration-spec.yaml +37 -0
  765. package/templates/shared/ir-design.yaml +34 -0
  766. package/templates/shared/ir-legacy.yaml +12 -0
  767. package/templates/shared/ir-spec.yaml +18 -0
  768. package/templates/shared/line-client.bundle.yaml +65 -0
  769. package/templates/shared/mock-data.yaml +22 -0
  770. package/templates/shared/openapi.yaml +144 -0
  771. package/templates/shared/patterns/.gitkeep +0 -0
  772. package/templates/shared/patterns/admin-crud.pattern.yaml +37 -0
  773. package/templates/shared/qa-item.yaml +15 -0
  774. package/templates/shared/spec.yaml +162 -0
  775. package/templates/shared/testcase.yaml +2 -0
  776. package/templates/tests-skeleton/cases/README.md +5 -0
  777. package/templates/tests-skeleton/catalog/locale.yaml +7 -0
  778. package/templates/tests-skeleton/index.md +7 -0
  779. package/templates/tests-skeleton/scenarios/README.md +3 -0
@@ -0,0 +1,45 @@
1
+ # [Flow] <%= spec.title || spec.id %>
2
+
3
+ <% if (context.testcases && context.testcases.length) { %>
4
+ - **Testcase plans:** <%= context.testcases.map(tc => '`' + (tc.data.title || tc.data.id || tc.file) + '`').join(' · ') %> (hub: [base_test](https://github.com/raintr91/base_test))
5
+ <% } else { %>
6
+ - **Testcase plans:** [base_test](https://github.com/raintr91/base_test) (`pnpm cases:render` on tests hub) — see docs-hub TESTS-HUB
7
+ <% } %>
8
+
9
+ <%
10
+ const route = spec.ui?.routes?.[0];
11
+ const path = route?.path || '';
12
+ const testId = route?.pageTestId || '';
13
+ let screenLine = '- **Screen:** None';
14
+ if (path) {
15
+ const screen = context.renderScreenLink ? context.renderScreenLink(path) : '`' + path + '`';
16
+ const suffix = testId ? ` · \`${testId}\`` : '';
17
+ screenLine = `- **Screen:** ${screen}${suffix}`;
18
+ }
19
+ %>
20
+ <%= screenLine %>
21
+
22
+ > [!NOTE]
23
+ > This document was rendered using the specialized **breadcrumb-flow** template.
24
+
25
+ <% if (spec.summary) { %>
26
+ <%= spec.summary %>
27
+ <% } %>
28
+
29
+ <%
30
+ // Render other spec sections
31
+ const skipKeys = new Set(['id', 'title', 'summary', 'acceptance', 'ui', 'design', 'legacy', 'review', 'template']);
32
+ Object.entries(spec).forEach(([key, value]) => {
33
+ if (skipKeys.has(key) || value == null) return;
34
+ %>
35
+ ## <%= key %>
36
+
37
+ <% if (typeof value === 'string') { %>
38
+ <%= value %>
39
+ <% } else { %>
40
+ ```yaml
41
+ <%= context.stringify(value).trim() %>
42
+ ```
43
+ <% } %>
44
+
45
+ <% }); %>
@@ -0,0 +1,288 @@
1
+ # portal-feature-bundle/v1 — authoring rules (PHASE 1)
2
+
3
+ Hub: `docs/templates/feature.bundle.yaml` · split: `pnpm spec:split`
4
+
5
+ ## Top-level
6
+
7
+ | Key | Purpose |
8
+ |-----|---------|
9
+ | `page-id` | Screen identity (`cmp-adm-000-01`). Split copies this onto `ir/spec.yaml` as `page-id` (not `id`, so it does not collide with requirement/section ids). Legacy bundles may still use `id`. |
10
+ | `summary` | Phải trình bày dạng bullet. Bắt buộc có các tiêu đề (chuẩn Arc42 business): **mục tiêu nghiệp vụ** (business_goals), **các bên liên quan** (stakeholders), **kịch bản người dùng** (user_journey), **bối cảnh** (description, input liên kết cross-page/module, output) và **cách giải quyết** (tùy chọn). Mục đích để 100% Non-tech Stakeholder hiểu và duyệt. |
11
+ | `userStories` | **Khối User Stories chuyên sâu cho màn hình:** `primary`, `contextAndHandoff` (+ `screenAccess`), `scenarios` (5 kịch bản chuẩn + **scenario thứ 6 “Affordances UX”** khi màn có delete/filter/breadcrumb/disabled/import — xem `feature.bundle.yaml`), `acceptanceCriteria` (kèm checkbox UX khi áp dụng). **Split:** `pnpm spec:split` copy nguyên khối sang `ir/spec.yaml` (business prose); **không** tự sinh từ `design` — Agent phải cập nhật `userStories` khi bổ sung DSL/`#needs-component`/audit `UX_*`. Render → `## User Stories & Screen Journey` trong Markdown. |
12
+ | `spec` | Design v1 — actors, requirements, `ui.routes`, **`ui.list` / `ui.form` / `ui.detail`**, `acceptance`. **Không** author `spec.api` — API SSOT là `api/<seq>/01-backend-spec.yaml`. |
13
+ | `gen` | **Bắt buộc trước flowgrid gen:** `codegen.profile` (`auth` login/forgot/reset; `change-password`; `public`; `not-found`/`error`; `list`/`create`/`admin-crud`) + entity/module, `tags`, derived `ui.*`. `/grill-dev` ghi. Endpoint `action` ghi trên **01**, không trên bundle. |
14
+ | `legacy` | Legacy facts + evidence pointers |
15
+ | `design` | Nested **`sections[]`** (card/container/form + `meaning` + `purpose` + `visual` + `interaction` + `validation` + `messages` + `states` + `bind`/`db`) · **`nav`** (`screenAccess` & `sidebar.hierarchy`) · `zones[]` fallback · `behavior` · **`actions[]`** (onSuccess, onSpecificError, backgroundTrigger) |
16
+ | `review` | BA prose only — **không** split sang `ir/*` |
17
+
18
+ ## /spec authoring (complete when information exists)
19
+
20
+ - Fill `userStories` chi tiết theo mẫu trong `feature.bundle.yaml`. Tuyệt đối không để trống hoặc chỉ ghi 1 câu qua loa.
21
+ - **Quy tắc Khai báo Cách thức Truy cập Màn hình (screenAccess BẮT BUỘC):** Phải chọn đúng 1 trong 3 loại:
22
+ - `directRoute`: Dành cho trang truy cập trực tiếp bằng URL (Login, Register, Guest Page, Public Landing, 404). Khai báo `routePath`, `isPublic`.
23
+ - `sidebarMenu`: Dành cho Dashboard, Danh sách Admin CRUD. Khai báo `menuHierarchy` (mảng danh mục dropdown đa cấp `["Group", "Subgroup"]`), `menuLabel` (text nhãn menu), `icon`.
24
+ - `contextualAction`: Dành cho Trang chi tiết, Edit Modal, Settings. Khai báo `sourceScreen`, `triggerControl` (mô tả nút bấm kích hoạt từ màn hình A), `navigationType` (`pageRedirect`, `modalDialog`, `drawer`, `tabSwitch`).
25
+ - **Quy tắc Meaning vs Purpose BẮT BUỘC:** Trên từng element (section, item, column, filter, action), BẮT BUỘC khai báo cả 2 trường:
26
+ - `meaning`: **Ý nghĩa nghiệp vụ** — Bản chất kinh doanh của trường dữ liệu/nút bấm trong thế giới thực, ảnh hưởng đến luồng tính toán hay quyết định nào.
27
+ - `purpose`: **Mục đích thao tác** — Người dùng thao tác gì với control này trên UI (nhập, tìm kiếm, bấm, xem).
28
+ - **Thẩm định dữ liệu (Validation & Messages):** Mọi trường có `validation` (required, min/max, pattern, accept) PHẢI đi kèm trường `messages` chứa câu thông báo lỗi tiếng Việt tương ứng.
29
+ - **Hành động & Tương tác (Actions):** Nút bấm nộp/lưu phải có đầy đủ: `validateFormBeforeSubmit`, `feedback` (loadingText, disableWhileSubmitting), `apiRefs`, `onSuccess` (toast, navigation handoff, backgroundTrigger), `onSpecificError` (map lỗi 422, 409 conflict, 403), `onCommonError`.
30
+ - Fill `design.sections[]` as a **dynamic nested tree** for that page (any depth). Same node shape everywhere: `kind` + `meaning` + `purpose` + `visual` + `tags`/`extract` + `items[]` + nested `sections[]`. Do not assume login or any one layout.
31
+ - When the page has app chrome: `design.nav.sidebar.levels` (đa cấp) + `design.nav.breadcrumb`. Full-bleed pages: `sidebar.enabled: false`.
32
+ - Flat `design.zones[]` is only a fallback if there is no nested card tree.
33
+ - Fill the matching profile: list → `spec.ui.list`; form → `spec.ui.form` (do not merge form into the page shell); detail → `spec.ui.detail`.
34
+ - Do **not** dump the screen into `requirements` prose instead of inventory.
35
+ - **UI Metrics Policy:** DO NOT declare basic CSS properties (e.g., `font-size`, `padding`, exact colors) in feature specs. These are governed by the global Design System (e.g., Shadcn/Tailwind). Only declare them if the feature requires a specific, exceptional override.
36
+ - Missing hard facts → `#missing_info` on that field. Do not wait for grill to invent inventory.
37
+ - `/grill-bqa`, `/grill-dev`, `/grill-docs` only re-check, fill gaps, or fix conflicts.
38
+
39
+ ## spec (design v1) — có
40
+
41
+ - `actors`, `entities`, `relationships`
42
+ - `requirements` (BẮT BUỘC chứa Edge Cases. CHÚ Ý: Field Validations, State Machine, UI Permissions phải được map vào từng item trong `design.sections`, KHÔNG liệt kê chung chung ở đây)
43
+ - `ui.routes`, `ui.list`, `ui.form`, `ui.detail`, `ui.toolbar` (intent)
44
+ - `acceptance`
45
+
46
+ API: **chỉ** `…/api/<seq>/01-backend-spec.yaml` (`/api-spec`). Split **chiếu** `api.endpoints` (id/method/path/action) sang `ir/design.yaml` cho FE/bộ test — không author trên bundle.
47
+
48
+ ## spec — không (thuộc `gen`)
49
+
50
+ - `codegen`, `tags`
51
+ - root `ui.filters`, `ui.columns`, `ui.composition`, `ui.testIds` (derive after inventory exists)
52
+ - Prose layout blob — dùng `design.sections[]` (nested) + `design.nav` + `review.layoutNotes`
53
+
54
+ ## Split output
55
+
56
+ Split exists so agents **Read the entire `ir/design.yaml`** (tech) or **entire `ir/spec.yaml`** (prose). Do **not** instruct “only Read `design.sections` / `spec.ui` from the bundle” — that misses fields and is why IR is split.
57
+
58
+ Authoring (`/spec`, grill-*) still **writes** `*.bundle.yaml`, then split.
59
+
60
+ ### UX affordance ↔ `userStories` (before `pnpm spec:split`)
61
+
62
+ | Design / audit signal | Business layer (`userStories` → `ir/spec.yaml`) |
63
+ |----------------------|--------------------------------------------------|
64
+ | `design.nav.breadcrumb`, `CONFIRM_UX_BREADCRUMB_*` | Scenario **Initial Load** + scenario **Affordances UX**; AC deep link |
65
+ | `spec.ui.list.filters`, `CONFIRM_UX_FILTER_*` | Scenario **Initial Load** / **Affordances UX**; AC empty “no results” |
66
+ | `#pattern: delete-flow`, `UX_GAP_DELETE_*` | Scenario **Affordances UX** + **Exceptions**; AC delete confirm + result dialog |
67
+ | `disabledReason`, `UX_GAP_DISABLED_REASON` | Scenario **Affordances UX**; AC disabled explanation |
68
+ | Status column + chip, `CONFIRM_UX_STATUS_CHIP` | Scenario **Initial Load**; AC status readable |
69
+ | `#needs-component` / `#needs-ui` | `primary.iWant` or scenario step naming the custom block in Vietnamese |
70
+ | `flowgrid audit spec` `suggestedStoryPatch` on UX items | Apply verbatim to matching scenario step or AC |
71
+
72
+ **Không** chỉ ghi tech vào `design.actions` — stakeholder đọc `ir/spec.yaml` / rendered MD phải thấy cùng hành vi.
73
+
74
+ | Artifact | Đọc bởi | Nội dung |
75
+ |----------|---------|----------|
76
+ | `*.bundle.yaml` | **Ghi** `/spec`, grill-*; **đọc cả file** `/testcase`, `/grill-testcase` | Đầy đủ spec+gen+design+`userStories`; tests hub read-only |
77
+ | `ir/design.yaml` | **Đọc cả file** — grill-*, FE `/prototype`, codegen | Tech sau split; `api` chiếu từ 01. |
78
+ | `ir/spec.yaml` | VitePress + stakeholder | Business page + requirements/acceptance. Không id/tag/bind. `"Q&A"`. Không stub `legacy` rỗng. |
79
+ | `…/api/<seq>/01-backend-spec.yaml` | BE `/api`, `openapi:gen`, **author API** | Tech BE — SSOT duy nhất cho endpoint |
80
+ | `<slug>.md` | Người (BA/QA) | Render từ **`ir/spec.yaml`** (chưa split thì không có trang) |
81
+
82
+ Không còn `ir/legacy.yaml`. `legacy:` trên `ir/spec.yaml` chỉ khi có evidence thật.
83
+
84
+ Thiếu fact → `#missing_info` trên field đó. Grill không bịa CSS/API.
85
+
86
+ ## design.nav + nested sections (dynamic)
87
+
88
+ Cùng một schema cho mọi page. Agent điền cây theo màn thực tế — không dùng một màn (login, list, …) làm mặc định.
89
+
90
+ ```yaml
91
+ nav:
92
+ sidebar:
93
+ enabled: true # false nếu không có menu trái
94
+ position: left
95
+ levels: [] # { id, label, href, active, children[] } lồng đa cấp
96
+ breadcrumb: [] # { label, href }
97
+
98
+ **LƯU Ý ĐẶC BIỆT VỀ ĐA NGÔN NGỮ (i18n):**
99
+ 1. **Text hiển thị UI (cần i18n)**: Các thuộc tính như `label`, `value`, `copy.placeholder`, text của component lib... BẮT BUỘC dùng cho i18n (sẽ được map với file ngôn ngữ). Áp dụng cho các component lá như `input`, `text`, `button`, v.v.
100
+ 2. **Text ngữ cảnh (không i18n)**: Các thuộc tính giải thích/cấu trúc như `name`, `description`, `purpose` chỉ dùng cho BA/Dev, KHÔNG dùng để render UI, KHÔNG mang đi dịch. Tùy thuộc vào `kind` mà khai báo cho đúng bản chất, **tuyệt đối không dùng `label` để mô tả một node ẩn (như container)**.
101
+ - **BA**: `name`, `description`, `purpose`, `copy`, `position`, `color`, `visual` (width/height/max-*/scroll), `interaction`, `validation` (mặt UI), `db` (thông tin lưu trữ schema, field, enumMapping)
102
+ - **Tech**: `kind`/`widget`, `tags`, `extract`, `bind` (field/hidden/apiRef), `apiRefs`, `hidden`, `testId`, `states`
103
+
104
+ ```yaml
105
+ sections:
106
+ # LOẠI 1: KHỐI STATS BANNER / HEADER KPI CARD (#ui: Card, #ui: Badge)
107
+ - id: sec_kpi_banner
108
+ name: "Khối Thống Kê Tổng Quan"
109
+ kind: card
110
+ primitive: "#ui: Card" # Gắn tag primitive Shadcn UI
111
+ meaning: "Cung cấp chỉ số hiệu suất tổng quan của tài khoản giúp nhân viên đưa ra quyết định xử lý nhanh"
112
+ purpose: "Hiển thị các thẻ KPI thống kê tổng số bản ghi và trạng thái"
113
+ visual:
114
+ colorToken: "#common:card-surface"
115
+ className: "grid grid-cols-1 md:grid-cols-3 gap-4 p-6 bg-card border rounded-xl shadow-xs"
116
+ typography: "text-card-foreground"
117
+ dynamicProps:
118
+ layoutMode: "responsive-grid"
119
+ columns: 3
120
+ items:
121
+ - id: kpi_total_records
122
+ kind: badge
123
+ primitive: "#ui: Badge"
124
+ label: "Tổng hồ sơ"
125
+ meaning: "Số lượng bản ghi đang quản lý trong hệ thống"
126
+ purpose: "Theo dõi số lượng hồ sơ hiện có"
127
+ colorToken: "#common:primary"
128
+ visual:
129
+ className: "text-2xl font-bold tracking-tight text-primary"
130
+
131
+ # LOẠI 2: KHỐI FORM NHẬP LIỆU ĐỘNG (#ui: Form, #ui: Select, #ui: Input)
132
+ - id: sec_main_info
133
+ name: "Khối Thông Tin Nhập Liệu Hồ Sơ"
134
+ kind: form_grid
135
+ primitive: "#ui: Form"
136
+ meaning: "Gom nhóm các thuộc tính nhận diện cốt lõi của bản ghi phục vụ tra cứu và kiểm toán"
137
+ purpose: "Khu vực nhập liệu thông tin chính của hồ sơ"
138
+ visual:
139
+ className: "space-y-6 border p-6 rounded-xl bg-background shadow-xs"
140
+ layoutMode: "two-column"
141
+ dynamicProps:
142
+ responsiveGrid: "grid grid-cols-1 lg:grid-cols-2 gap-6"
143
+ sections:
144
+ # Component nhập liệu có validation & messages & styling
145
+ - id: fld_record_name
146
+ name: "Record Name Field"
147
+ kind: input
148
+ primitive: "#ui: Input"
149
+ label: "Tên hồ sơ"
150
+ meaning: "Tên định danh giao dịch của khách hàng dùng làm tiêu đề hiển thị trên mọi báo cáo"
151
+ purpose: "Nhập tên hồ sơ hiển thị"
152
+ visual:
153
+ className: "w-full focus:ring-2 focus:ring-ring"
154
+ copy:
155
+ placeholder: "Nhập tên đầy đủ..."
156
+ helper: "Tối thiểu 3 ký tự, không chứa ký tự đặc biệt"
157
+ bind:
158
+ field: record_name
159
+ db:
160
+ schema: records
161
+ field: name
162
+ validation:
163
+ required: true
164
+ minLength: 3
165
+ maxLength: 100
166
+ messages:
167
+ required: "Vui lòng nhập tên hồ sơ."
168
+ minLength: "Tên hồ sơ phải có ít nhất 3 ký tự."
169
+
170
+ # Component chọn có điều kiện động (Dropdown + States)
171
+ - id: fld_service_level
172
+ name: "Service Level Select"
173
+ kind: select
174
+ primitive: "#ui: Select"
175
+ label: "Cấp độ dịch vụ"
176
+ meaning: "Xác định gói dịch vụ để áp dụng chính sách giá và kích hoạt tự động Zalo VIP"
177
+ purpose: "Chọn gói dịch vụ áp dụng"
178
+ visual:
179
+ className: "w-full border-input"
180
+ bind:
181
+ field: service_level
182
+ db:
183
+ schema: records
184
+ field: service_level
185
+ enumMapping:
186
+ "STANDARD": "Tiêu chuẩn"
187
+ "PREMIUM": "Cao cấp VIP"
188
+ validation:
189
+ required: true
190
+ messages:
191
+ required: "Vui lòng chọn cấp độ dịch vụ."
192
+
193
+ # Component hiển thị động theo trạng thái
194
+ - id: fld_vip_request
195
+ name: "VIP Special Request"
196
+ kind: textarea
197
+ primitive: "#ui: Textarea"
198
+ label: "Yêu cầu đặc biệt cho gói VIP"
199
+ meaning: "Chi tiết yêu cầu cá nhân hóa bổ sung"
200
+ purpose: "Nhập ghi chú yêu cầu riêng cho gói dịch vụ VIP"
201
+ visual:
202
+ className: "col-span-full border-muted bg-muted/20"
203
+ states:
204
+ visibleWhen: "service_level == 'PREMIUM'"
205
+ ```
206
+
207
+ Minh họa lồng (không phải template cố định): container → card → form, hoặc sidebar → toolbar → table.
208
+
209
+ ## design.zones (flat fallback)
210
+
211
+ ```yaml
212
+ zones:
213
+ - id: search
214
+ label: Khu vực tìm kiếm
215
+ kind: container
216
+ items:
217
+ - id: keyword
218
+ kind: search
219
+ widget: search
220
+ label: Ô tìm kiếm
221
+ purpose: "User tìm bản ghi theo tên hoặc mã"
222
+ copy:
223
+ placeholder: Search by name or code
224
+ bind: { field: keyword }
225
+ ```
226
+
227
+ ## design.behavior (CRUD table trong md render)
228
+
229
+ ```yaml
230
+ behavior:
231
+ create: { enabled: true, surface: page }
232
+ delete: { enabled: true, mode: confirm_dialog }
233
+ ```
234
+
235
+ ## design.actions (API calls + UI error handling)
236
+
237
+ Không còn `bundle.spec.api`. Màn gọi API nào = `design.actions` (và button/item trong `sections`/`zones`) trên **`ir/design.yaml`** sau split.
238
+
239
+ - Unique API của màn: `apiRefs` (sau `/api-spec` ghi trio `api/<seq>/`).
240
+ - API đã có (màn khác / common): `tags: ["#reuse-api"]` + `reuseFrom: …/01-backend-spec.yaml`. **Không** tạo trio mới.
241
+
242
+ ```yaml
243
+ actions:
244
+ - id: submit_form
245
+ label: Submit Form
246
+ purpose: "Lưu form và báo kết quả cho user"
247
+ variant: primary
248
+ position: form_footer
249
+ trigger: button_click
250
+ apiRefs: [ feature.create ]
251
+ # tags: ["#reuse-api"]
252
+ # reuseFrom: surfaces/admin/CMP-01/auth/01/01/01/api/01/01-backend-spec.yaml
253
+ onSuccess:
254
+ - Navigate to list page
255
+ - Show success toast "Created successfully"
256
+ onCommonError:
257
+ override: false
258
+ notes: "Inherit #ui-common:error-handler (Global toast 500/401)"
259
+ onSpecificError:
260
+ - condition: "422 Validation"
261
+ notes: "Show inline field errors below inputs"
262
+ - condition: "403 IDOR"
263
+ notes: "Redirect to safety page, show warning"
264
+ ```
265
+
266
+ ## Agent output (/spec)
267
+
268
+ YAML only per schema. No explanation. No markdown.
269
+
270
+ ## Questions: AskQuestion wizard or hub `qa/open/`
271
+
272
+ Do **not** write `openQuestions` anywhere. Schema/render không còn field này.
273
+
274
+ - Member trả lời **ngay:** AskQuestion (options + Recommended + **Other**) → **STOP** → ghi field thật.
275
+ - Member chọn **Other** mà **chưa quyết:** `.cursor/extracts/qa-inbox.md` → `qa/open/QA-<bundle.id>-NNNN.yaml`. Đóng sau bằng **`/qa-resolve <id>` + giải pháp**.
276
+ - `grillStatus` có thể `done` khi vẫn còn file QA.
277
+
278
+ ## YAML Syntax & Escaping Rules
279
+
280
+ - **ALWAYS quote colons in strings:** Any string containing `:` (e.g., `summary: "Case 1: Token..."`, `label: "Hàng nút: [Secondary]"`) MUST be wrapped in double quotes `"..."`.
281
+ - **Multiline text:** Use `|` block scalar for multiline strings or list items containing formatting symbols.
282
+
283
+ ## ir/spec.yaml vs ir/design.yaml
284
+
285
+ `pnpm spec:split` ghi hai file. FlowGrid bộ docs grill **không** đọc `ir/*` khi author — chỉ bundle. Split ghi `"Q&A":` trên **`ir/spec.yaml`** (id `QA-<bundle.id>-NNNN` cách nhau bởi `, `) từ `qa/open/` — không nhét list vào bundle.
286
+
287
+ Downstream (UI gen, API gen, testcase) đọc **chỉ `ir/design.yaml`**. Thiếu file = split/spec chưa xong. Story/copy chưa đủ thì **bổ sung design** (bundle.gen + split), không đọc `ir/spec.yaml`. `ir/spec.yaml` chỉ văn mô tả + `legacy` + `qa` (id treo).
288
+
@@ -0,0 +1,18 @@
1
+ # clients.line — append to ir/spec.yaml when feature has shop-floor UI
2
+
3
+ clients:
4
+ line:
5
+ profile: kiosk # kiosk | tablet
6
+ screens:
7
+ - id: check-in
8
+ route: workforce/check-in
9
+ automationIds:
10
+ page: {module}-page
11
+ submit-btn: {module}-submit-btn
12
+ devices:
13
+ - badgeReader
14
+ api:
15
+ endpoints:
16
+ checkIn:
17
+ method: POST
18
+ path: /workforce/check-in
@@ -0,0 +1,234 @@
1
+ # <%= spec.title || spec.id %>
2
+
3
+ <% if (context.testcases && context.testcases.length) { %>
4
+ - **Testcase plans:** <%= context.testcases.map(tc => '`' + (tc.data.title || tc.data.id || tc.file) + '`').join(' · ') %> (hub: [base_test](https://github.com/raintr91/base_test))
5
+ <% } else { %>
6
+ - **Testcase plans:** [base_test](https://github.com/raintr91/base_test) (`pnpm cases:render` on tests hub) — see docs-hub TESTS-HUB
7
+ <% } %>
8
+
9
+ <%
10
+ const route = spec.ui?.routes?.[0];
11
+ const path = route?.path || '';
12
+ const testId = route?.pageTestId || '';
13
+ let screenLine = '- **Screen:** None';
14
+ if (path) {
15
+ const screen = context.renderScreenLink ? context.renderScreenLink(path) : '`' + path + '`';
16
+ const suffix = testId ? ` · \`${testId}\`` : '';
17
+ screenLine = `- **Screen:** ${screen}${suffix}`;
18
+ }
19
+ %>
20
+ <%= screenLine %>
21
+
22
+ <% if (spec.summary) { %>
23
+ <%= spec.summary %>
24
+ <% } %>
25
+
26
+ <% if (spec.userStories) { %>
27
+ ## User Stories & Screen Journey
28
+
29
+ <% if (typeof spec.userStories === 'string') { %>
30
+ <%= spec.userStories %>
31
+ <% } else if (Array.isArray(spec.userStories)) { %>
32
+ <% spec.userStories.forEach(story => { %>
33
+ ### <%= story.title || story.name || 'User Story' %>
34
+ <% if (story.asA || story.role) { %>
35
+ > **Là một** <%= story.asA || story.role %>,
36
+ > **Tôi muốn** <%= story.iWant || story.action %>,
37
+ > **Để** <%= story.soThat || story.benefit %>.
38
+ <% } else if (story.story) { %>
39
+ > <%= story.story %>
40
+ <% } %>
41
+
42
+ <% if (story.preConditions && story.preConditions.length) { %>
43
+ **Điều kiện tiên quyết (Pre-conditions):**
44
+ <% (Array.isArray(story.preConditions) ? story.preConditions : [story.preConditions]).forEach(p => { %>
45
+ - <%= p %>
46
+ <% }); %>
47
+ <% } %>
48
+
49
+ <% if (story.scenarios && story.scenarios.length) { %>
50
+ **Kịch bản chi tiết trên màn hình (Scenarios):**
51
+ <% story.scenarios.forEach(sc => { %>
52
+ - **<%= sc.name || sc.title %>:** <%= sc.description || sc.steps || sc %>
53
+ <% }); %>
54
+ <% } %>
55
+
56
+ <% if (story.acceptanceCriteria && story.acceptanceCriteria.length) { %>
57
+ **Tiêu chí nghiệm thu (Acceptance Criteria):**
58
+ <% (Array.isArray(story.acceptanceCriteria) ? story.acceptanceCriteria : [story.acceptanceCriteria]).forEach(ac => { %>
59
+ - [ ] <%= ac %>
60
+ <% }); %>
61
+ <% } %>
62
+
63
+ <% }); %>
64
+ <% } else if (typeof spec.userStories === 'object') { %>
65
+ <% if (spec.userStories.primary) { %>
66
+ ### User Story Chính
67
+ > **Là một** <%= spec.userStories.primary.asA || spec.userStories.primary.role %>,
68
+ > **Tôi muốn** <%= spec.userStories.primary.iWant || spec.userStories.primary.action %>,
69
+ > **Để** <%= spec.userStories.primary.soThat || spec.userStories.primary.benefit %>.
70
+ <% } %>
71
+
72
+ <% if (spec.userStories.contextAndHandoff) { %>
73
+ ### Cách thức Truy cập & Chuyển giao Màn hình (Screen Access & Handoff)
74
+ <% if (spec.userStories.contextAndHandoff.screenAccess) { %>
75
+ <% const sa = spec.userStories.contextAndHandoff.screenAccess; %>
76
+ - **Loại truy cập (Access Type):** `<%= sa.accessType || 'N/A' %>`
77
+ <% if (sa.accessType === 'directRoute' && sa.directRoute) { %>
78
+ - **Đường dẫn URL (Path Router):** `<%= sa.directRoute.routePath || '' %>` <%= sa.directRoute.isPublic ? '(Công khai / Public)' : '(Cần đăng nhập / Authenticated)' %>
79
+ <% } else if (sa.accessType === 'sidebarMenu' && sa.sidebarMenu) { %>
80
+ - **Menu Sidebar:** <%= sa.sidebarMenu.menuHierarchy ? sa.sidebarMenu.menuHierarchy.join(' > ') : '' %> > **<%= sa.sidebarMenu.menuLabel || '' %>**
81
+ <% } else if (sa.accessType === 'contextualAction' && sa.contextualAction) { %>
82
+ - **Kích hoạt từ (Triggered By):** <%= sa.contextualAction.triggerControl || '' %> từ màn hình `<%= sa.contextualAction.sourceScreen || '' %>` (Loại: `<%= sa.contextualAction.navigationType || 'pageRedirect' %>`)
83
+ <% } %>
84
+ <% } %>
85
+ - **Màn hình nguồn (Source Screen):** `<%= spec.userStories.contextAndHandoff.sourceScreen || 'Direct' %>`
86
+ <% if (spec.userStories.contextAndHandoff.inputsReceived && spec.userStories.contextAndHandoff.inputsReceived.length) { %>
87
+ - **Dữ liệu tiếp nhận (Inputs):** <%= Array.isArray(spec.userStories.contextAndHandoff.inputsReceived) ? spec.userStories.contextAndHandoff.inputsReceived.join(' · ') : spec.userStories.contextAndHandoff.inputsReceived %>
88
+ <% } %>
89
+ - **Điều hướng tiếp theo (Next Screen):** `<%= spec.userStories.contextAndHandoff.nextScreenOnSuccess || 'None' %>`
90
+ <% } %>
91
+
92
+ <% if (spec.userStories.scenarios && spec.userStories.scenarios.length) { %>
93
+ ### Kịch bản Chi tiết trên Màn hình (Scenarios)
94
+ <% spec.userStories.scenarios.forEach(sc => { %>
95
+ #### <%= sc.name || sc.title %>
96
+ <% if (sc.steps && sc.steps.length) { %>
97
+ <% (Array.isArray(sc.steps) ? sc.steps : [sc.steps]).forEach(step => { %>
98
+ - <%= step %>
99
+ <% }); %>
100
+ <% } else if (sc.description) { %>
101
+ <%= sc.description %>
102
+ <% } %>
103
+ <% }); %>
104
+ <% } %>
105
+
106
+ <% if (spec.userStories.acceptanceCriteria && spec.userStories.acceptanceCriteria.length) { %>
107
+ ### Tiêu chí Nghiệm thu (Acceptance Criteria)
108
+ <% spec.userStories.acceptanceCriteria.forEach(ac => { %>
109
+ - [ ] <%= ac %>
110
+ <% }); %>
111
+ <% } %>
112
+
113
+ <% } %>
114
+ <% } %>
115
+
116
+ <%
117
+ // 1. Executive Summary & Screen Journey
118
+ const pageSections = spec.sections || spec.design?.sections || [];
119
+ const pageActions = spec.actions || spec.design?.actions || [];
120
+ const pageStateMatrix = spec.stateMatrix || spec.design?.stateMatrix;
121
+
122
+ const page = {
123
+ nav: spec.nav || spec.design?.nav,
124
+ sections: pageSections,
125
+ zones: spec.zones || spec.design?.zones,
126
+ behavior: spec.behavior || spec.design?.behavior,
127
+ actions: pageActions
128
+ }
129
+ %>
130
+
131
+ <% if (pageStateMatrix) { %>
132
+ ## Ma Trận Trạng Thái Giao Diện & Phân Quyền (State & Permission Matrix)
133
+
134
+ <%- context.renderStateMatrixTable(pageStateMatrix) %>
135
+
136
+ <% } %>
137
+
138
+ <%
139
+ const validationTableMd = context.renderValidationDictionaryTable(pageSections);
140
+ if (validationTableMd) {
141
+ %>
142
+ ## Danh Mục Trường Nhập Liệu & Quy Tắc Kiểm Tra Hợp Lệ (Data Dictionary & Validation)
143
+
144
+ <%- validationTableMd %>
145
+
146
+ <% } %>
147
+
148
+ <%
149
+ const customWidgetMd = context.renderCustomWidgetSpecs(pageSections);
150
+ if (customWidgetMd) {
151
+ %>
152
+ <%- customWidgetMd %>
153
+
154
+ <% } %>
155
+
156
+ <%
157
+ const actionFlowsMd = context.renderActionFlowsDetailed(pageActions);
158
+ if (actionFlowsMd) {
159
+ %>
160
+ ## Đặc Tả Quy Trình Hành Động (Action Flows)
161
+
162
+ <%- actionFlowsMd %>
163
+
164
+ <% } else { %>
165
+ <%- context.renderPageComposition(page, { businessOnly: true }) %>
166
+ <% } %>
167
+
168
+ <%
169
+ const skipKeys = new Set([
170
+ 'id', 'page-id', 'title', 'summary', 'userStories', 'acceptance', 'ui', 'design', 'legacy', 'review', 'template',
171
+ 'nav', 'sections', 'zones', 'behavior', 'actions', 'stateMatrix', 'grillStatus', 'specOrigin',
172
+ 'status', 'owner', 'schema', 'qa', 'Q&A', 'pendingTechDebt', 'i18n', 'gen', '_meta'
173
+ ]);
174
+ Object.entries(spec).forEach(([key, value]) => {
175
+ if (skipKeys.has(key) || value == null) return;
176
+ %>
177
+ ## <%= key %>
178
+
179
+ <% if (typeof value === 'string') { %>
180
+ <%= value %>
181
+ <% } else { %>
182
+ ```yaml
183
+ <%= context.stringify(value).trim() %>
184
+ ```
185
+ <% } %>
186
+
187
+ <% }); %>
188
+
189
+ <% if (spec.pendingTechDebt && spec.pendingTechDebt.length) { %>
190
+ ## Pending tech debt
191
+
192
+ | ID | Status | Summary |
193
+ | --- | --- | --- |
194
+ <% spec.pendingTechDebt.forEach(d => { %>
195
+ | <%= d.id %> | <%= d.status %> | <%= d.summary || '' %> |
196
+ <% }); %>
197
+
198
+ <% } %>
199
+
200
+ <% if (spec.review && (spec.review.layoutNotes || spec.review.summary)) { %>
201
+ ## Review — layout notes
202
+
203
+ <% if (spec.review.layoutNotes) { %>
204
+ <% if (Array.isArray(spec.review.layoutNotes)) { %>
205
+ <%= spec.review.layoutNotes.map(n => `- ${n}`).join('\n') %>
206
+ <% } else { %>
207
+ - <%= spec.review.layoutNotes %>
208
+ <% } %>
209
+ <% } %>
210
+ <% } %>
211
+
212
+ <% if (spec.legacy && (spec.legacy.behaviors?.length || spec.legacy.fields?.length || spec.legacy.evidence?.length)) { %>
213
+ ## Legacy evidence
214
+
215
+ <% if (spec.legacy.behaviors && spec.legacy.behaviors.length) { %>
216
+ ### Behaviors
217
+
218
+ | ID | Fact | Confidence |
219
+ | --- | --- | --- |
220
+ <% spec.legacy.behaviors.forEach(b => { %>
221
+ | <%= b.id || '' %> | `<%= JSON.stringify(b.fact || {}) %>` | <%= b.confidence || '' %> |
222
+ <% }); %>
223
+ <% } %>
224
+
225
+ <% if (spec.legacy.fields && spec.legacy.fields.length) { %>
226
+ ### Fields
227
+
228
+ | Name | Via | Confidence |
229
+ | --- | --- | --- |
230
+ <% spec.legacy.fields.forEach(f => { %>
231
+ | <%= f.name || '' %> | <%= f.via || '' %> | <%= f.confidence || '' %> |
232
+ <% }); %>
233
+ <% } %>
234
+ <% } %>
@@ -0,0 +1,85 @@
1
+ # Design spec v1 — /spec (round 1)
2
+ # Do NOT add codegen, ui.filters, ui.columns, or portal-gen tags here.
3
+ # After /grill-docs → see docs/templates/spec.yaml (portal-gen-ready).
4
+
5
+ id: role-page-function
6
+ title: Feature title
7
+ status: draft
8
+ owner: portal-team
9
+ summary: Short business summary for BA, QA, dev, and AI.
10
+
11
+ actors: []
12
+ # - id: admin
13
+ # legacyRoleCode: master
14
+
15
+ entities: []
16
+ # - name: Entity
17
+ # table: entities
18
+ # importantFields: [id, name, created_at]
19
+
20
+ relationships: []
21
+
22
+ requirements:
23
+ - id: REQ-FEATURE-001
24
+ title: Main behavior
25
+ description: User can complete the main behavior.
26
+ priority: must
27
+
28
+ ui:
29
+ routes:
30
+ - path: /feature-path
31
+ legacyPath: /legacy/path
32
+ pageTestId: feature-page
33
+ # Page profiles for design v1. Keep prose short; move validation/source/message details to form fields.
34
+ validationMessages:
35
+ required: This field is required
36
+ email: Email format is invalid
37
+ phone: Phone number format is invalid
38
+ minLength: Must be at least {n} characters
39
+ maxLength: Must be at most {n} characters
40
+ min: Must be at least {n}
41
+ max: Must be at most {n}
42
+ pattern: Invalid format
43
+ list:
44
+ columns: []
45
+ filters: []
46
+ rowActions: []
47
+ bulkActions: []
48
+ pagination:
49
+ defaultPageSize: 20
50
+ pageSizeOptions: [20, 50, 100]
51
+ form:
52
+ layout:
53
+ mode: single-column # single-column | two-column | custom
54
+ sections: []
55
+ fields:
56
+ # - key: name
57
+ # label: Name
58
+ # type: string
59
+ # widget: text
60
+ # purpose: "Tên hiển thị trên hồ sơ"
61
+ # required: true
62
+ # validation:
63
+ # maxLength: 255
64
+ # messages:
65
+ # required: Name is required.
66
+ detail:
67
+ header:
68
+ titleField: name
69
+ subtitleField: code
70
+ sections: []
71
+ actions:
72
+ - id: edit
73
+ text: Edit
74
+ - id: delete
75
+ text: Delete
76
+
77
+ # api.endpoints — not authored here. spec:split copies from …/api/<seq>/01-backend-spec.yaml
78
+
79
+ acceptance:
80
+ - Main behavior is testable end to end.
81
+
82
+
83
+ notes:
84
+ - YAML is source of truth. Render with pnpm docs:render.
85
+ - Portal-gen blocks added in /grill-docs — see .cursor/extracts/codegen/readiness.md