@starci/skills 1.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 (321) hide show
  1. package/INDEX.md +74 -0
  2. package/INDEX.vi.md +75 -0
  3. package/README.md +44 -0
  4. package/README.vi.md +43 -0
  5. package/SKILL.md +135 -0
  6. package/SKILL.vi.md +128 -0
  7. package/alias/INDEX.md +104 -0
  8. package/alias/INDEX.vi.md +104 -0
  9. package/alias/alias.json +297 -0
  10. package/bin/starci-skills.mjs +219 -0
  11. package/knowledge/INDEX.md +22 -0
  12. package/knowledge/INDEX.vi.md +22 -0
  13. package/knowledge/grammars/starci/DNA.md +146 -0
  14. package/knowledge/grammars/starci/DNA.vi.md +146 -0
  15. package/knowledge/grammars/starci/INDEX.md +25 -0
  16. package/knowledge/grammars/starci/INDEX.vi.md +25 -0
  17. package/knowledge/grammars/starci/family.md +50 -0
  18. package/knowledge/grammars/starci/family.vi.md +50 -0
  19. package/knowledge/grammars/starci/idioms.md +120 -0
  20. package/knowledge/grammars/starci/idioms.vi.md +121 -0
  21. package/knowledge/grammars/starci/playbook.md +36 -0
  22. package/knowledge/grammars/starci/playbook.vi.md +35 -0
  23. package/knowledge/patterns/be/INDEX.md +29 -0
  24. package/knowledge/patterns/be/INDEX.vi.md +29 -0
  25. package/knowledge/patterns/be/comment.md +80 -0
  26. package/knowledge/patterns/be/comment.vi.md +80 -0
  27. package/knowledge/patterns/be/error.md +86 -0
  28. package/knowledge/patterns/be/error.vi.md +86 -0
  29. package/knowledge/patterns/be/folder.md +87 -0
  30. package/knowledge/patterns/be/folder.vi.md +86 -0
  31. package/knowledge/patterns/be/function.md +80 -0
  32. package/knowledge/patterns/be/function.vi.md +80 -0
  33. package/knowledge/patterns/be/imports.md +79 -0
  34. package/knowledge/patterns/be/imports.vi.md +79 -0
  35. package/knowledge/patterns/be/naming.md +87 -0
  36. package/knowledge/patterns/be/naming.vi.md +87 -0
  37. package/knowledge/patterns/be/test.md +79 -0
  38. package/knowledge/patterns/be/test.vi.md +79 -0
  39. package/knowledge/patterns/be/typing.md +73 -0
  40. package/knowledge/patterns/be/typing.vi.md +73 -0
  41. package/knowledge/patterns/fe/INDEX.md +29 -0
  42. package/knowledge/patterns/fe/INDEX.vi.md +29 -0
  43. package/knowledge/patterns/fe/comment.md +70 -0
  44. package/knowledge/patterns/fe/comment.vi.md +70 -0
  45. package/knowledge/patterns/fe/error.md +61 -0
  46. package/knowledge/patterns/fe/error.vi.md +61 -0
  47. package/knowledge/patterns/fe/folder.md +98 -0
  48. package/knowledge/patterns/fe/folder.vi.md +95 -0
  49. package/knowledge/patterns/fe/function.md +70 -0
  50. package/knowledge/patterns/fe/function.vi.md +70 -0
  51. package/knowledge/patterns/fe/imports.md +87 -0
  52. package/knowledge/patterns/fe/imports.vi.md +87 -0
  53. package/knowledge/patterns/fe/naming.md +77 -0
  54. package/knowledge/patterns/fe/naming.vi.md +77 -0
  55. package/knowledge/patterns/fe/test.md +73 -0
  56. package/knowledge/patterns/fe/test.vi.md +73 -0
  57. package/knowledge/patterns/fe/typing.md +67 -0
  58. package/knowledge/patterns/fe/typing.vi.md +67 -0
  59. package/knowledge/ui/INDEX.md +101 -0
  60. package/knowledge/ui/INDEX.vi.md +101 -0
  61. package/knowledge/ui/composition/INDEX.md +60 -0
  62. package/knowledge/ui/composition/INDEX.vi.md +63 -0
  63. package/knowledge/ui/composition/accent.md +73 -0
  64. package/knowledge/ui/composition/accent.vi.md +74 -0
  65. package/knowledge/ui/composition/action.md +55 -0
  66. package/knowledge/ui/composition/action.vi.md +56 -0
  67. package/knowledge/ui/composition/coverage.md +37 -0
  68. package/knowledge/ui/composition/coverage.vi.md +37 -0
  69. package/knowledge/ui/composition/cta.md +79 -0
  70. package/knowledge/ui/composition/cta.vi.md +79 -0
  71. package/knowledge/ui/composition/feedback.md +55 -0
  72. package/knowledge/ui/composition/feedback.vi.md +56 -0
  73. package/knowledge/ui/composition/hierarchy.md +83 -0
  74. package/knowledge/ui/composition/hierarchy.vi.md +82 -0
  75. package/knowledge/ui/composition/layout.md +91 -0
  76. package/knowledge/ui/composition/layout.vi.md +93 -0
  77. package/knowledge/ui/composition/responsive.md +67 -0
  78. package/knowledge/ui/composition/responsive.vi.md +67 -0
  79. package/knowledge/ui/composition/state.md +105 -0
  80. package/knowledge/ui/composition/state.vi.md +106 -0
  81. package/knowledge/ui/presentation/INDEX.md +94 -0
  82. package/knowledge/ui/presentation/INDEX.vi.md +69 -0
  83. package/knowledge/ui/presentation/boundary.md +170 -0
  84. package/knowledge/ui/presentation/boundary.vi.md +169 -0
  85. package/knowledge/ui/presentation/font.md +155 -0
  86. package/knowledge/ui/presentation/font.vi.md +156 -0
  87. package/knowledge/ui/presentation/gap.md +181 -0
  88. package/knowledge/ui/presentation/gap.vi.md +181 -0
  89. package/knowledge/ui/presentation/margin.md +168 -0
  90. package/knowledge/ui/presentation/margin.vi.md +171 -0
  91. package/knowledge/ui/presentation/measure.md +174 -0
  92. package/knowledge/ui/presentation/measure.vi.md +178 -0
  93. package/knowledge/ui/presentation/overflow.md +142 -0
  94. package/knowledge/ui/presentation/overflow.vi.md +142 -0
  95. package/knowledge/ui/presentation/padding.md +293 -0
  96. package/knowledge/ui/presentation/padding.vi.md +292 -0
  97. package/knowledge/ui/presentation/surface.md +166 -0
  98. package/knowledge/ui/presentation/surface.vi.md +166 -0
  99. package/knowledge/ui/presentation/text-flow.md +123 -0
  100. package/knowledge/ui/presentation/text-flow.vi.md +123 -0
  101. package/knowledge/ui/presentation/tone.md +114 -0
  102. package/knowledge/ui/presentation/tone.vi.md +113 -0
  103. package/knowledge/ui/proof/INDEX.md +55 -0
  104. package/knowledge/ui/proof/INDEX.vi.md +55 -0
  105. package/knowledge/ui/proof/accessibility.md +67 -0
  106. package/knowledge/ui/proof/accessibility.vi.md +68 -0
  107. package/knowledge/ui/proof/contrast.md +58 -0
  108. package/knowledge/ui/proof/contrast.vi.md +57 -0
  109. package/knowledge/ui/proof/focus.md +76 -0
  110. package/knowledge/ui/proof/focus.vi.md +76 -0
  111. package/knowledge/ui/proof/motion.md +63 -0
  112. package/knowledge/ui/proof/motion.vi.md +64 -0
  113. package/knowledge/ui/proof/render-truth.md +63 -0
  114. package/knowledge/ui/proof/render-truth.vi.md +63 -0
  115. package/operators/INDEX.md +199 -0
  116. package/operators/INDEX.vi.md +199 -0
  117. package/operators/architecture-decide/errors.json +115 -0
  118. package/operators/architecture-decide/operator.json +20 -0
  119. package/operators/architecture-decide/operator.md +133 -0
  120. package/operators/architecture-decide/operator.vi.md +130 -0
  121. package/operators/architecture-decide/self-test.mjs +221 -0
  122. package/operators/architecture-decide/validate.mjs +112 -0
  123. package/operators/backend-source-apply/errors.json +66 -0
  124. package/operators/backend-source-apply/operator.json +20 -0
  125. package/operators/backend-source-apply/operator.md +189 -0
  126. package/operators/backend-source-apply/operator.vi.md +185 -0
  127. package/operators/backend-source-apply/self-test.mjs +257 -0
  128. package/operators/backend-source-apply/validate.mjs +240 -0
  129. package/operators/business-decide/errors.json +78 -0
  130. package/operators/business-decide/operator.json +20 -0
  131. package/operators/business-decide/operator.md +176 -0
  132. package/operators/business-decide/operator.vi.md +174 -0
  133. package/operators/business-decide/self-test.mjs +225 -0
  134. package/operators/business-decide/validate.mjs +277 -0
  135. package/operators/content-generate/errors.json +106 -0
  136. package/operators/content-generate/operator.json +21 -0
  137. package/operators/content-generate/operator.md +155 -0
  138. package/operators/content-generate/operator.vi.md +155 -0
  139. package/operators/content-generate/self-test.mjs +288 -0
  140. package/operators/content-generate/validate.mjs +196 -0
  141. package/operators/errors.json +178 -0
  142. package/operators/frontend-direction-decide/errors.json +135 -0
  143. package/operators/frontend-direction-decide/operator.json +21 -0
  144. package/operators/frontend-direction-decide/operator.md +167 -0
  145. package/operators/frontend-direction-decide/operator.vi.md +167 -0
  146. package/operators/frontend-direction-decide/self-test.mjs +226 -0
  147. package/operators/frontend-direction-decide/validate.mjs +146 -0
  148. package/operators/frontend-presentation-resolve/errors.json +42 -0
  149. package/operators/frontend-presentation-resolve/operator.json +19 -0
  150. package/operators/frontend-presentation-resolve/operator.md +142 -0
  151. package/operators/frontend-presentation-resolve/operator.vi.md +140 -0
  152. package/operators/frontend-presentation-resolve/self-test.mjs +163 -0
  153. package/operators/frontend-presentation-resolve/validate.mjs +143 -0
  154. package/operators/frontend-source-apply/errors.json +30 -0
  155. package/operators/frontend-source-apply/operator.json +20 -0
  156. package/operators/frontend-source-apply/operator.md +127 -0
  157. package/operators/frontend-source-apply/operator.vi.md +126 -0
  158. package/operators/frontend-source-apply/self-test.mjs +214 -0
  159. package/operators/frontend-source-apply/validate.mjs +133 -0
  160. package/operators/frontend-surface-audit/errors.json +5 -0
  161. package/operators/frontend-surface-audit/operator.json +22 -0
  162. package/operators/frontend-surface-audit/operator.md +121 -0
  163. package/operators/frontend-surface-audit/operator.vi.md +121 -0
  164. package/operators/frontend-surface-audit/self-test.mjs +185 -0
  165. package/operators/frontend-surface-audit/validate.mjs +127 -0
  166. package/operators/git-publish/errors.json +54 -0
  167. package/operators/git-publish/operator.json +20 -0
  168. package/operators/git-publish/operator.md +180 -0
  169. package/operators/git-publish/operator.vi.md +178 -0
  170. package/operators/git-publish/self-test.mjs +177 -0
  171. package/operators/git-publish/validate.mjs +106 -0
  172. package/operators/platform-operate/errors.json +90 -0
  173. package/operators/platform-operate/operator.json +22 -0
  174. package/operators/platform-operate/operator.md +162 -0
  175. package/operators/platform-operate/operator.vi.md +160 -0
  176. package/operators/platform-operate/self-test.mjs +202 -0
  177. package/operators/platform-operate/validate.mjs +193 -0
  178. package/operators/quality-verify/errors.json +54 -0
  179. package/operators/quality-verify/operator.json +20 -0
  180. package/operators/quality-verify/operator.md +185 -0
  181. package/operators/quality-verify/operator.vi.md +177 -0
  182. package/operators/quality-verify/self-test.mjs +210 -0
  183. package/operators/quality-verify/validate.mjs +197 -0
  184. package/operators/release-deploy/errors.json +158 -0
  185. package/operators/release-deploy/operator.json +23 -0
  186. package/operators/release-deploy/operator.md +183 -0
  187. package/operators/release-deploy/operator.vi.md +181 -0
  188. package/operators/release-deploy/self-test.mjs +235 -0
  189. package/operators/release-deploy/validate.mjs +129 -0
  190. package/operators/uat-verify/errors.json +78 -0
  191. package/operators/uat-verify/operator.json +25 -0
  192. package/operators/uat-verify/operator.md +162 -0
  193. package/operators/uat-verify/operator.vi.md +161 -0
  194. package/operators/uat-verify/self-test.mjs +270 -0
  195. package/operators/uat-verify/validate.mjs +202 -0
  196. package/operators/workspace-bind/errors.json +90 -0
  197. package/operators/workspace-bind/operator.json +21 -0
  198. package/operators/workspace-bind/operator.md +148 -0
  199. package/operators/workspace-bind/operator.vi.md +148 -0
  200. package/operators/workspace-bind/self-test.mjs +205 -0
  201. package/operators/workspace-bind/validate.mjs +152 -0
  202. package/package.json +50 -0
  203. package/readiness/initialization/workspaces/commit-policy.json +91 -0
  204. package/readiness/initialization/workspaces/config.schema.json +35 -0
  205. package/readiness/initialization/workspaces/device-state.schema.json +54 -0
  206. package/readiness/initialization/workspaces/local-route.schema.json +206 -0
  207. package/readiness/initialization/workspaces/portable-route.schema.json +200 -0
  208. package/resources/INDEX.md +96 -0
  209. package/resources/INDEX.vi.md +99 -0
  210. package/resources/agents/profiles/claude.json +131 -0
  211. package/resources/agents/profiles/openai.json +131 -0
  212. package/resources/orchestrator.json +71 -0
  213. package/resources/tools.json +85 -0
  214. package/routing.json +272 -0
  215. package/scripts/alias-registry.mjs +31 -0
  216. package/scripts/device-state.mjs +497 -0
  217. package/scripts/device-state.spec.mjs +18 -0
  218. package/scripts/errors-registry.mjs +68 -0
  219. package/scripts/generate-alias-doc.mjs +66 -0
  220. package/scripts/generate-grammar-dna.mjs +387 -0
  221. package/scripts/generate-operators-index.mjs +95 -0
  222. package/scripts/generate-presentation-owned.mjs +681 -0
  223. package/scripts/install-cli.spec.mjs +74 -0
  224. package/scripts/json-schema.mjs +94 -0
  225. package/scripts/operator-md.mjs +96 -0
  226. package/scripts/run-operator-self-tests.mjs +36 -0
  227. package/scripts/validate-alias.mjs +165 -0
  228. package/scripts/validate-defaults.mjs +72 -0
  229. package/scripts/validate-knowledge-citations.mjs +90 -0
  230. package/scripts/validate-operator.mjs +125 -0
  231. package/scripts/validate-request.mjs +80 -0
  232. package/scripts/validate-resources.mjs +117 -0
  233. package/scripts/validate-response.mjs +141 -0
  234. package/scripts/validate-routing.mjs +91 -0
  235. package/scripts/validate-step.mjs +50 -0
  236. package/scripts/validate-templates.mjs +226 -0
  237. package/scripts/validate-templates.spec.mjs +144 -0
  238. package/scripts/validate-workflows.mjs +106 -0
  239. package/scripts/workspace-portable.mjs +389 -0
  240. package/scripts/workspace-portable.spec.mjs +246 -0
  241. package/templates/README.md +47 -0
  242. package/templates/README.vi.md +45 -0
  243. package/templates/changes.example.md +27 -0
  244. package/templates/grammars.template.md +34 -0
  245. package/templates/kinds/architecture-decision.contract.json +14 -0
  246. package/templates/kinds/architecture-decision.skeleton.md +52 -0
  247. package/templates/kinds/backend-source-application.contract.json +10 -0
  248. package/templates/kinds/backend-source-application.skeleton.md +34 -0
  249. package/templates/kinds/business-promise-authority.contract.json +13 -0
  250. package/templates/kinds/business-promise-authority.skeleton.md +67 -0
  251. package/templates/kinds/capture.schema.json +33 -0
  252. package/templates/kinds/changes.contract.json +10 -0
  253. package/templates/kinds/changes.skeleton.md +26 -0
  254. package/templates/kinds/checks.schema.json +44 -0
  255. package/templates/kinds/claims.schema.json +165 -0
  256. package/templates/kinds/conformance.schema.json +15 -0
  257. package/templates/kinds/content-brief.contract.json +12 -0
  258. package/templates/kinds/content-brief.skeleton.md +45 -0
  259. package/templates/kinds/content-generation-receipt.contract.json +11 -0
  260. package/templates/kinds/content-generation-receipt.skeleton.md +40 -0
  261. package/templates/kinds/content-review.contract.json +11 -0
  262. package/templates/kinds/content-review.skeleton.md +45 -0
  263. package/templates/kinds/contract.schema.json +28 -0
  264. package/templates/kinds/coverage-matrix.schema.json +86 -0
  265. package/templates/kinds/coverage.schema.json +62 -0
  266. package/templates/kinds/current-state.schema.json +40 -0
  267. package/templates/kinds/delta.schema.json +95 -0
  268. package/templates/kinds/e2e.schema.json +63 -0
  269. package/templates/kinds/frontend-direction-decision.contract.json +93 -0
  270. package/templates/kinds/frontend-direction-decision.skeleton.md +68 -0
  271. package/templates/kinds/frontend-presentation-resolution.contract.json +11 -0
  272. package/templates/kinds/frontend-presentation-resolution.skeleton.md +32 -0
  273. package/templates/kinds/frontend-source-application.contract.json +10 -0
  274. package/templates/kinds/frontend-source-application.skeleton.md +30 -0
  275. package/templates/kinds/frontend-surface-audit.contract.json +52 -0
  276. package/templates/kinds/frontend-surface-audit.skeleton.md +32 -0
  277. package/templates/kinds/gate-result.schema.json +64 -0
  278. package/templates/kinds/git-publication.contract.json +82 -0
  279. package/templates/kinds/git-publication.skeleton.md +61 -0
  280. package/templates/kinds/independent-critique.contract.json +9 -0
  281. package/templates/kinds/independent-critique.skeleton.md +28 -0
  282. package/templates/kinds/inventory.schema.json +35 -0
  283. package/templates/kinds/model.schema.json +99 -0
  284. package/templates/kinds/mutations.schema.json +65 -0
  285. package/templates/kinds/platform-operation-receipt.contract.json +76 -0
  286. package/templates/kinds/platform-operation-receipt.skeleton.md +54 -0
  287. package/templates/kinds/probes.schema.json +130 -0
  288. package/templates/kinds/proof.schema.json +17 -0
  289. package/templates/kinds/quality-verification.contract.json +87 -0
  290. package/templates/kinds/quality-verification.skeleton.md +58 -0
  291. package/templates/kinds/release-deployment.contract.json +85 -0
  292. package/templates/kinds/release-deployment.skeleton.md +67 -0
  293. package/templates/kinds/route.schema.json +293 -0
  294. package/templates/kinds/stack-model.schema.json +90 -0
  295. package/templates/kinds/uat-capture.schema.json +35 -0
  296. package/templates/kinds/uat-flow-verification.contract.json +11 -0
  297. package/templates/kinds/uat-flow-verification.skeleton.md +47 -0
  298. package/templates/kinds/uat-snapshot.schema.json +96 -0
  299. package/templates/kinds/uat-verdicts.schema.json +41 -0
  300. package/templates/kinds/ui-coverage.schema.json +77 -0
  301. package/templates/kinds/verdicts.schema.json +39 -0
  302. package/templates/kinds/workspace-route-binding.contract.json +12 -0
  303. package/templates/kinds/workspace-route-binding.skeleton.md +60 -0
  304. package/templates/kinds/writes.schema.json +37 -0
  305. package/templates/operator.template.md +73 -0
  306. package/templates/patterns.template.md +31 -0
  307. package/templates/step/request.schema.json +42 -0
  308. package/templates/step/response.schema.json +144 -0
  309. package/templates/ui-composition.template.md +36 -0
  310. package/templates/ui-presentation.template.md +57 -0
  311. package/templates/ui-proof.template.md +34 -0
  312. package/workflows/README.md +37 -0
  313. package/workflows/README.vi.md +37 -0
  314. package/workflows/backend-feature.json +59 -0
  315. package/workflows/content-unit.json +19 -0
  316. package/workflows/frontend-new-surface.json +81 -0
  317. package/workflows/frontend-reconstruct.json +67 -0
  318. package/workflows/frontend-refine.json +67 -0
  319. package/workflows/frontend-with-uat.json +78 -0
  320. package/workflows/full-feature.json +104 -0
  321. package/workflows/release.json +29 -0
@@ -0,0 +1,104 @@
1
+ # Alias
2
+
3
+ Mọi nơi một operator được đọc, theo alias, gom theo vùng. Sinh từ `alias/alias.json` (sổ cho máy) và mọi `operator.json` bởi `scripts/generate-alias-doc.mjs`; `--check` chạy trong `npm test`. Operator chỉ đọc những alias mà bảng Context trong `operator.md` của nó gọi tên; trang này là toàn bộ từ vựng mà các bảng đó lấy ra. Phân giải theo tiền tố đăng ký dài nhất, đuôi đường dẫn thu hẹp alias, đoạn trong ngoặc nhọn do lần gọi cung cấp.
4
+
5
+ ## Workspaces — vùng làm việc
6
+
7
+ Vùng làm việc: các checkout đã route của project đang bind, và khai báo, route, port, danh tính để tìm ra chúng.
8
+
9
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
10
+ | --- | --- | --- | --- | --- | --- | --- |
11
+ | `@workspaces` | `<project>`, `<role>` | `<checkout:project/role> (any routed checkout named explicitly, for cross-project reads: @workspaces/nivo/fe)` | fingerprint + sourceHead (git rev-parse HEAD of the checkout) | — | — | A checkout of another project. The bound project's own are @workspaces/fe and @workspaces/be. |
12
+ | `@workspaces/be` | — | `<checkout:input.project.id/be> (diskPath from <Source>/.workspaces/local/routes/<project>/be/config.json); friendly segments: /husky, /package, /gates (see segments)` | fingerprint + sourceHead (git rev-parse HEAD of the checkout) | `backend.source.apply` | — | The routed backend checkout of the bound project. |
13
+ | `@workspaces/device-state` | — | `<Source>/.workspaces/device-state.json (sealed keys live in <Source>/.workspaces/local/credentials/*.key.enc and are bound by name, never read)` | fingerprint | — | — | Machine identity and the encrypted credential roster reference. |
14
+ | `@workspaces/fe` | — | `<checkout:input.project.id/fe> (diskPath from <Source>/.workspaces/local/routes/<project>/fe/config.json); friendly segments: /husky, /package, /gates, /grammar (see segments)` | fingerprint + sourceHead (git rev-parse HEAD of the checkout) | `frontend.source.apply` | — | The routed frontend checkout of the bound project. |
15
+ | `@workspaces/local/routes` | — | `<Source>/.workspaces/local/routes/<project>/<role>/config.json` | fingerprint | `workspace.bind` | — | Machine-local hydrated routes; project the declarations onto this disk. Ignored by Git. |
16
+ | `@workspaces/ports` | — | `<Source>/.workspaces/ports/<project>.json` | fingerprint | — | — | Port projection: project offset and application slots. Endpoints are derived, never typed. |
17
+ | `@workspaces/projects` | — | `<Source>/.workspaces/projects/<project>/<role>.json` | fingerprint | — | — | Portable route declarations, tracked. The only place a route is declared. |
18
+
19
+ ## Grammar — gói
20
+
21
+ Gói @starci/grammar như app đang resolve: sự thật duy nhất về việc component sở hữu gì.
22
+
23
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
24
+ | --- | --- | --- | --- | --- | --- | --- |
25
+ | `@grammar` | `<family>` | `the @starci/grammar package as the bound app resolves it (file:packages/grammar inside @workspaces/fe today, source 0.4.2; @remote/npm publishes 0.3.0), narrowed to one family <family>: @grammar/core, @grammar/heritage, @grammar/offset-pop; @grammar/common is the shared layer every family imports` | package.json version + the resolved location's fingerprint (checkout head for file:, tarball integrity for npm) | — | — | The Grammar as it runs: Common renderers, props, owned relationships, data-contract claims, and the family's own CSS. The only fact about what a component owns. |
26
+
27
+ ## Knowledge — luật
28
+
29
+ Luật chuẩn trong cây này: luật UI phổ quát (ui), khẩu vị của họ (grammars), quy ước code (patterns). Chỉ đọc; chủ mới sửa.
30
+
31
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
32
+ | --- | --- | --- | --- | --- | --- | --- |
33
+ | `@knowledge/grammars` | — | `<Source>/.claude/knowledge/grammars/<family>/ (DNA.md generated from the package; idioms.md and playbook.md are the owner's taste; family.md holds the visual DNA and the gap table)` | fingerprint per file; DNA.md additionally binds the package version and checkout head it was generated from | — | — | How the family composes: the owner's taste (idioms, playbook) and what exists (DNA). Never the Grammar itself; where a taste row disagrees with @grammar, @grammar is the fact and the row is the finding. |
34
+ | `@knowledge/patterns` | — | `<Source>/.claude/knowledge/patterns/ (fe/, be/)` | fingerprint per file; rule inventory = every `## PREFIX-n` heading in the folder | — | — | Code conventions counted from the two live sources; a rule cites two real paths. |
35
+ | `@knowledge/ui` | — | `<Source>/.claude/knowledge/ui/ (composition/, presentation/, proof/; a sub-path narrows: @knowledge/ui/presentation)` | fingerprint per file; rule inventory = every `## PREFIX-n` heading in the folder | — | — | Universal UI law: what a tree must contain, which value an app boundary takes, what is only true once rendered. |
36
+
37
+ ## Worktrees — thẩm quyền và bằng chứng máy-cục-bộ
38
+
39
+ Thẩm quyền và bằng chứng máy-cục-bộ ngoài mọi checkout: head nghiệp vụ, UAT pair, nợ, khuôn, runtime owner dùng chung.
40
+
41
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
42
+ | --- | --- | --- | --- | --- | --- | --- |
43
+ | `@worktrees/_templates` | — | `<Source>/.worktrees/_templates/ (businesses/, debts/, sessions/, uat/)` | fingerprint per file | — | — | Authority templates for new heads, debts, sessions, and UAT pairs. Consumed, never modified. |
44
+ | `@worktrees/businesses` | — | `<Source>/.worktrees/businesses/ (features/<featureId>/model.json; business-registry-v1.json is the head index; objects/sha256/ the content store)` | content address from business-registry-v1.json featureHeads.&lt;featureId&gt;.head, with authorityStatus | `business.decide` | — | Business promise heads. Its own git worktree; a head binds by content address even before its commit lands. |
45
+ | `@worktrees/debts` | — | `<Source>/.worktrees/debts/ (be.md, fe.md, per-item files)` | fingerprint per file | — | — | Owner-approved quality debts. A debt without a live approval here is not a debt. |
46
+ | `@worktrees/sessions` | — | `<Source>/.worktrees/sessions/<sessionId>/ (state.json; step-<N>/parallel-<M>/ branches, each with request/ and response/ — see @dynamic; central-runtime/ is the shared runtime owner registry outside any session)` | fingerprint per file read | `*` | — | The session container. Operators do not read it directly; they read @dynamic. |
47
+ | `@worktrees/sessions/central-runtime` | — | `<Source>/.worktrees/sessions/central-runtime/owner.json (generation-<n>-ready.json and logs/ beside it)` | fingerprint + generation | `platform.operate` | — | The shared runtime owner: generation, status, endpoints, health evidence. Callers consume, never own. |
48
+ | `@worktrees/uat` | — | `<Source>/.worktrees/uat/<flow>/ (flow.md: cases in order and named assertions; account.json: username, role, credential name of the single shared UAT password sealed at .stacks/<env>/secrets/uat.enc; seed/records.json and seed/expected.json; runs/<runId>/ append-only: result.json, verdicts.json, captures/<case>.png, sheet.png; latest -> the newest run). <case> narrows to one case of the flow` | fingerprint of snapshot.json and result.json | `uat.verify` | — | UAT authority per flow: the frozen flow, its dedicated account, its seed, and the append-only history of every run with the commit it verified. |
49
+
50
+ ## Remote — internet
51
+
52
+ Internet. Registry, git remote, kho image, run CI, object storage. Đọc qua mạng; bind bằng version, digest hay head quan sát được.
53
+
54
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
55
+ | --- | --- | --- | --- | --- | --- | --- |
56
+ | `@remote/ghcr` | `<image>` | `ghcr.io/<image>@<digest>` | digest | `release.deploy` | — | Immutable release images. A tag is never a binding; a digest is. |
57
+ | `@remote/git` | `<project>`, `<role>` | `the origin URL in @workspaces/local/routes/<project>/<role> (repository.gitRepository)` | observed remote head (git ls-remote) at invocation time | `git.publish` | — | The publication target; fast-forwardness is decided against this observation. |
58
+ | `@remote/github-actions` | `<runId>` | `GitHub Actions run <runId> of the routed repository` | run id + conclusion | — | — | CI evidence of a build or rollout, read only. |
59
+ | `@remote/minio` | `<contentId>`, `<locale>` | `MinIO object contents/<contentId>/<locale>.json through the routed runtime` | fingerprint of the fetched object | `content.generate` | — | Authored lesson content as served, not as drafted. |
60
+ | `@remote/npm` | `<package>` | `the npm registry entry for <package>, e.g. @remote/npm/@starci/grammar@0.3.0` | version + tarball integrity | — | — | Published packages. A version is the binding; latest never is. |
61
+
62
+ ## Dynamic — sinh trong phiên
63
+
64
+ Sinh trong phiên hiện tại bởi một bước trước và xoá cùng phiên. Không tồn tại trước lần chạy.
65
+
66
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
67
+ | --- | --- | --- | --- | --- | --- | --- |
68
+ | `@dynamic` | `<kind>` | `<Source>/.worktrees/sessions/<sessionId>/step-<N>/parallel-<M>/ — one branch of one step. request/request.json is the gate in (orchestrator writes it); response/ is the agent's: response.json (gate out), response.md and other markdown kinds, data/<name>.json, artifacts/<file>; a nested exchange adds <exchange>/request/ and <exchange>/response/. A kind is passed by explicit path in request.json inputs, from the session root. Dynamic files are passed as kinds (templates/kinds/<kind>), never as aliases. The session folder is created by the orchestrator and deleted when git.publish finishes; a blocked run keeps it for resume` | kind contract or schema under templates/kinds; response.json fields is the registry of what a branch produced | `*` | — | Everything produced inside the session and nothing that existed before it. Always dynamic; typed by kind. |
69
+
70
+ ## undefined
71
+
72
+
73
+
74
+ | Alias | Tham số | Trỏ tới | Bind | Ai ghi | Operator ràng | Mục đích |
75
+ | --- | --- | --- | --- | --- | --- | --- |
76
+ | `@tools/browsercontrol` | — | `resources/tools.json#tools.browsercontrol` | mode declared in operator.json → resources.tools; modes: never \| required | — | — | Drive a real browser against a served route: navigate, act, capture screenshots and DOM measurements. |
77
+ | `@tools/ci` | — | `resources/tools.json#tools.ci` | mode declared in operator.json → resources.tools; modes: never \| read \| dispatch | — | — | Observe or dispatch continuous-integration runs. |
78
+ | `@tools/container` | — | `resources/tools.json#tools.container` | mode declared in operator.json → resources.tools; modes: never \| read \| operate | — | — | Inspect or operate containers and images: compose services, GHCR images by digest. |
79
+ | `@tools/database` | — | `resources/tools.json#tools.database` | mode declared in operator.json → resources.tools; modes: never \| read \| namespaced-write | — | — | Read or write the product database for verification: seeds, fixtures, is_uat records. |
80
+ | `@tools/fileread` | — | `resources/tools.json#tools.fileread` | mode declared in operator.json → resources.tools; modes: never \| context-aliases | — | — | Read files and directories at the aliases the Context table names, at the frozen head. |
81
+ | `@tools/git` | — | `resources/tools.json#tools.git` | mode declared in operator.json → resources.tools; modes: never \| read \| commit-session-branch \| merge-and-push | — | — | Read and change repository state: heads, branches, worktrees, commits, merges, pushes. |
82
+ | `@tools/http` | — | `resources/tools.json#tools.http` | mode declared in operator.json → resources.tools; modes: never \| probe | — | — | Probe an endpoint: readiness, health, a served route, a GraphQL typename, a status page. |
83
+ | `@tools/imagegen` | — | `resources/tools.json#tools.imagegen` | mode declared in operator.json → resources.tools; modes: never \| judged \| required | — | — | Produce artwork: a digital image from an image model, made to one stated claim. Rendering HTML is the visualize tool, not this one. |
84
+ | `@tools/objectstorage` | — | `resources/tools.json#tools.objectstorage` | mode declared in operator.json → resources.tools; modes: never \| read \| write | — | — | Read or write objects in the content store (MinIO): curriculum, style references, published units. |
85
+ | `@tools/registry` | — | `resources/tools.json#tools.registry` | mode declared in operator.json → resources.tools; modes: never \| read | — | — | Read a package registry: the published Grammar, its version, its files. |
86
+ | `@tools/secrets` | — | `resources/tools.json#tools.secrets` | mode declared in operator.json → resources.tools; modes: never \| resolve-by-name | — | — | Resolve a sealed credential by name at the moment it is used; never read, print or store its value. |
87
+ | `@tools/shell` | — | `resources/tools.json#tools.shell` | mode declared in operator.json → resources.tools; modes: never \| declared-commands | — | — | Run declared commands: gates, builds, proofs, hooks, deployment plans. |
88
+ | `@tools/sourcewrite` | — | `resources/tools.json#tools.sourcewrite` | mode declared in operator.json → resources.tools; modes: never \| declared-write-set | — | — | Write files inside a routed checkout or an authority root. |
89
+ | `@tools/visualize` | — | `resources/tools.json#tools.visualize` | mode declared in operator.json → resources.tools; modes: never \| html | — | — | Render HTML for a person to look at: direction candidates, audit sheets, alternative comparisons, previews. No model grant is involved. |
90
+ | `@tools/websearch` | — | `resources/tools.json#tools.websearch` | mode declared in operator.json → resources.tools; modes: never \| bounded | — | — | Read public web pages to close one named gap in the evidence; results are references with URLs, never authority. |
91
+
92
+ ## Đoạn thân thiện trong một checkout
93
+
94
+ Human-friendly segments inside any checkout alias (@workspaces/fe, @workspaces/be, @workspaces/<project>/<role>), mapped to the exact path. Write the friendly word; the resolver substitutes the path.
95
+
96
+ | Đoạn | Trỏ tới |
97
+ | --- | --- |
98
+ | `husky` | `.husky/ (pre-commit, pre-push)` |
99
+ | `package` | `package.json (scripts, dependencies, the package version)` |
100
+ | `gates` | `package.json#scripts plus the configs it names (eslint.config.*, tsconfig*.json, jest.config.*/vitest.config.*, sonar-project.properties)` |
101
+ | `grammar` | `packages/grammar (the @starci/grammar source inside @workspaces/fe)` |
102
+ | `/branch/session` | `the session branch session/<sessionId> of that checkout, in its own git worktree prepared from the frozen head; the only branch a source-writing operator may commit to` |
103
+ | `/commit/<sha>` | `that checkout at one commit; how a later step names exactly what an earlier step wrote (response.json.commits[])` |
104
+
@@ -0,0 +1,297 @@
1
+ {
2
+ "schemaVersion": 8,
3
+ "note": "Closed registry of reference aliases. An alias reads like the place it names. Static: @workspaces/fe and @workspaces/be (the bound project's routed checkouts), @workspaces/<project>/<role>, @workspaces/{projects,local/routes,ports,device-state}, @grammar/<family>, @knowledge/{ui,grammars,patterns}, @worktrees/{businesses,uat,debts,_templates,sessions/central-runtime}, @remote/{npm,git,ghcr,github-actions,minio}. Dynamic: @dynamic, the current session branch, typed by kind. `<Source>` is the host repository that owns this .claude. A sub-path after a registered alias narrows it; a segment in angle brackets is supplied by the invocation. The registry is a tree: one root per zone, children by path segment, a node with resolvesTo is a definition. Resolution picks the longest registered prefix.",
4
+ "zones": {
5
+ "remote": {
6
+ "en": "Internet. Registries, git remotes, image registries, CI runs, object storage. Read through a network; bound by version, digest, or observed head.",
7
+ "vi": "Internet. Registry, git remote, kho image, run CI, object storage. Đọc qua mạng; bind bằng version, digest hay head quan sát được."
8
+ },
9
+ "grammar": {
10
+ "en": "The @starci/grammar package as the bound app resolves it: the only fact about what a component owns.",
11
+ "vi": "Gói @starci/grammar như app đang resolve: sự thật duy nhất về việc component sở hữu gì."
12
+ },
13
+ "knowledge": {
14
+ "en": "Canonical law in this tree: universal UI law (ui), the family's taste (grammars), code conventions (patterns). Read only; edited by the owner.",
15
+ "vi": "Luật chuẩn trong cây này: luật UI phổ quát (ui), khẩu vị của họ (grammars), quy ước code (patterns). Chỉ đọc; chủ mới sửa."
16
+ },
17
+ "workspaces": {
18
+ "en": "The working area: routed checkouts of the bound project and the declarations, routes, ports, and identity that locate them.",
19
+ "vi": "Vùng làm việc: các checkout đã route của project đang bind, và khai báo, route, port, danh tính để tìm ra chúng."
20
+ },
21
+ "worktrees": {
22
+ "en": "Machine-local authority and evidence outside any checkout: business heads, UAT pairs, debts, templates, the shared runtime owner.",
23
+ "vi": "Thẩm quyền và bằng chứng máy-cục-bộ ngoài mọi checkout: head nghiệp vụ, UAT pair, nợ, khuôn, runtime owner dùng chung."
24
+ },
25
+ "dynamic": {
26
+ "en": "Produced inside the current session by an earlier step and deleted with the session. Never exists before the run.",
27
+ "vi": "Sinh trong phiên hiện tại bởi một bước trước và xoá cùng phiên. Không tồn tại trước lần chạy."
28
+ }
29
+ },
30
+ "segments": {
31
+ "note": "Human-friendly segments inside any checkout alias (@workspaces/fe, @workspaces/be, @workspaces/<project>/<role>), mapped to the exact path. Write the friendly word; the resolver substitutes the path.",
32
+ "husky": ".husky/ (pre-commit, pre-push)",
33
+ "package": "package.json (scripts, dependencies, the package version)",
34
+ "gates": "package.json#scripts plus the configs it names (eslint.config.*, tsconfig*.json, jest.config.*/vitest.config.*, sonar-project.properties)",
35
+ "grammar": "packages/grammar (the @starci/grammar source inside @workspaces/fe)",
36
+ "/branch/session": "the session branch session/<sessionId> of that checkout, in its own git worktree prepared from the frozen head; the only branch a source-writing operator may commit to",
37
+ "/commit/<sha>": "that checkout at one commit; how a later step names exactly what an earlier step wrote (response.json.commits[])"
38
+ },
39
+ "tree": {
40
+ "@workspaces": {
41
+ "params": [
42
+ "project",
43
+ "role"
44
+ ],
45
+ "kind": "checkout",
46
+ "resolvesTo": "<checkout:project/role> (any routed checkout named explicitly, for cross-project reads: @workspaces/nivo/fe)",
47
+ "scheme": "source://<repository>",
48
+ "bind": "fingerprint + sourceHead (git rev-parse HEAD of the checkout)",
49
+ "writers": [],
50
+ "purpose": "A checkout of another project. The bound project's own are @workspaces/fe and @workspaces/be.",
51
+ "fe": {
52
+ "params": [],
53
+ "kind": "checkout",
54
+ "resolvesTo": "<checkout:input.project.id/fe> (diskPath from <Source>/.workspaces/local/routes/<project>/fe/config.json); friendly segments: /husky, /package, /gates, /grammar (see segments)",
55
+ "scheme": "source://<repository>",
56
+ "bind": "fingerprint + sourceHead (git rev-parse HEAD of the checkout)",
57
+ "writers": [
58
+ "frontend.source.apply"
59
+ ],
60
+ "purpose": "The routed frontend checkout of the bound project."
61
+ },
62
+ "be": {
63
+ "params": [],
64
+ "kind": "checkout",
65
+ "resolvesTo": "<checkout:input.project.id/be> (diskPath from <Source>/.workspaces/local/routes/<project>/be/config.json); friendly segments: /husky, /package, /gates (see segments)",
66
+ "scheme": "source://<repository>",
67
+ "bind": "fingerprint + sourceHead (git rev-parse HEAD of the checkout)",
68
+ "writers": [
69
+ "backend.source.apply"
70
+ ],
71
+ "purpose": "The routed backend checkout of the bound project."
72
+ },
73
+ "projects": {
74
+ "params": [],
75
+ "kind": "dir",
76
+ "resolvesTo": "<Source>/.workspaces/projects/<project>/<role>.json",
77
+ "scheme": "workspace://declarations/<project>",
78
+ "bind": "fingerprint",
79
+ "writers": [],
80
+ "purpose": "Portable route declarations, tracked. The only place a route is declared."
81
+ },
82
+ "local": {
83
+ "routes": {
84
+ "params": [],
85
+ "kind": "dir",
86
+ "resolvesTo": "<Source>/.workspaces/local/routes/<project>/<role>/config.json",
87
+ "scheme": "workspace://routes/<project>/<role>",
88
+ "bind": "fingerprint",
89
+ "writers": [
90
+ "workspace.bind"
91
+ ],
92
+ "purpose": "Machine-local hydrated routes; project the declarations onto this disk. Ignored by Git."
93
+ }
94
+ },
95
+ "ports": {
96
+ "params": [],
97
+ "kind": "dir",
98
+ "resolvesTo": "<Source>/.workspaces/ports/<project>.json",
99
+ "scheme": "workspace://ports/<project>",
100
+ "bind": "fingerprint",
101
+ "writers": [],
102
+ "purpose": "Port projection: project offset and application slots. Endpoints are derived, never typed."
103
+ },
104
+ "device-state": {
105
+ "params": [],
106
+ "kind": "file",
107
+ "resolvesTo": "<Source>/.workspaces/device-state.json (sealed keys live in <Source>/.workspaces/local/credentials/*.key.enc and are bound by name, never read)",
108
+ "scheme": "workspace://identity/device",
109
+ "bind": "fingerprint",
110
+ "writers": [],
111
+ "purpose": "Machine identity and the encrypted credential roster reference."
112
+ }
113
+ },
114
+ "@knowledge": {
115
+ "ui": {
116
+ "params": [],
117
+ "kind": "dir",
118
+ "resolvesTo": "<Source>/.claude/knowledge/ui/ (composition/, presentation/, proof/; a sub-path narrows: @knowledge/ui/presentation)",
119
+ "scheme": "knowledge://ui/<group>/<topic>",
120
+ "bind": "fingerprint per file; rule inventory = every `## PREFIX-n` heading in the folder",
121
+ "writers": [],
122
+ "purpose": "Universal UI law: what a tree must contain, which value an app boundary takes, what is only true once rendered."
123
+ },
124
+ "grammars": {
125
+ "params": [],
126
+ "kind": "dir",
127
+ "resolvesTo": "<Source>/.claude/knowledge/grammars/<family>/ (DNA.md generated from the package; idioms.md and playbook.md are the owner's taste; family.md holds the visual DNA and the gap table)",
128
+ "scheme": "knowledge://grammars/<family>/<topic>",
129
+ "bind": "fingerprint per file; DNA.md additionally binds the package version and checkout head it was generated from",
130
+ "writers": [],
131
+ "purpose": "How the family composes: the owner's taste (idioms, playbook) and what exists (DNA). Never the Grammar itself; where a taste row disagrees with @grammar, @grammar is the fact and the row is the finding."
132
+ },
133
+ "patterns": {
134
+ "params": [],
135
+ "kind": "dir",
136
+ "resolvesTo": "<Source>/.claude/knowledge/patterns/ (fe/, be/)",
137
+ "scheme": "knowledge://patterns/<side>/<topic>",
138
+ "bind": "fingerprint per file; rule inventory = every `## PREFIX-n` heading in the folder",
139
+ "writers": [],
140
+ "purpose": "Code conventions counted from the two live sources; a rule cites two real paths."
141
+ }
142
+ },
143
+ "@worktrees": {
144
+ "businesses": {
145
+ "params": [],
146
+ "kind": "dir",
147
+ "resolvesTo": "<Source>/.worktrees/businesses/ (features/<featureId>/model.json; business-registry-v1.json is the head index; objects/sha256/ the content store)",
148
+ "scheme": "business://<featureId>",
149
+ "bind": "content address from business-registry-v1.json featureHeads.<featureId>.head, with authorityStatus",
150
+ "writers": [
151
+ "business.decide"
152
+ ],
153
+ "purpose": "Business promise heads. Its own git worktree; a head binds by content address even before its commit lands."
154
+ },
155
+ "sessions": {
156
+ "params": [],
157
+ "kind": "dir",
158
+ "resolvesTo": "<Source>/.worktrees/sessions/<sessionId>/ (state.json; step-<N>/parallel-<M>/ branches, each with request/ and response/ — see @dynamic; central-runtime/ is the shared runtime owner registry outside any session)",
159
+ "scheme": "session://<sessionId>",
160
+ "bind": "fingerprint per file read",
161
+ "writers": [
162
+ "*"
163
+ ],
164
+ "purpose": "The session container. Operators do not read it directly; they read @dynamic.",
165
+ "central-runtime": {
166
+ "params": [],
167
+ "kind": "file",
168
+ "resolvesTo": "<Source>/.worktrees/sessions/central-runtime/owner.json (generation-<n>-ready.json and logs/ beside it)",
169
+ "scheme": "runtime://owner",
170
+ "bind": "fingerprint + generation",
171
+ "writers": [
172
+ "platform.operate"
173
+ ],
174
+ "purpose": "The shared runtime owner: generation, status, endpoints, health evidence. Callers consume, never own."
175
+ }
176
+ },
177
+ "uat": {
178
+ "params": [],
179
+ "kind": "dir",
180
+ "resolvesTo": "<Source>/.worktrees/uat/<flow>/ (flow.md: cases in order and named assertions; account.json: username, role, credential name of the single shared UAT password sealed at .stacks/<env>/secrets/uat.enc; seed/records.json and seed/expected.json; runs/<runId>/ append-only: result.json, verdicts.json, captures/<case>.png, sheet.png; latest -> the newest run). <case> narrows to one case of the flow",
181
+ "scheme": "uat://<flow>/<case>",
182
+ "bind": "fingerprint of snapshot.json and result.json",
183
+ "writers": [
184
+ "uat.verify"
185
+ ],
186
+ "purpose": "UAT authority per flow: the frozen flow, its dedicated account, its seed, and the append-only history of every run with the commit it verified."
187
+ },
188
+ "debts": {
189
+ "params": [],
190
+ "kind": "dir",
191
+ "resolvesTo": "<Source>/.worktrees/debts/ (be.md, fe.md, per-item files)",
192
+ "scheme": "debt://<file>",
193
+ "bind": "fingerprint per file",
194
+ "writers": [],
195
+ "purpose": "Owner-approved quality debts. A debt without a live approval here is not a debt."
196
+ },
197
+ "_templates": {
198
+ "params": [],
199
+ "kind": "dir",
200
+ "resolvesTo": "<Source>/.worktrees/_templates/ (businesses/, debts/, sessions/, uat/)",
201
+ "scheme": "template://<kind>",
202
+ "bind": "fingerprint per file",
203
+ "writers": [],
204
+ "purpose": "Authority templates for new heads, debts, sessions, and UAT pairs. Consumed, never modified."
205
+ }
206
+ },
207
+ "@grammar": {
208
+ "params": [
209
+ "family"
210
+ ],
211
+ "kind": "checkout",
212
+ "resolvesTo": "the @starci/grammar package as the bound app resolves it (`file:packages/grammar` inside @workspaces/fe today, source 0.4.2; @remote/npm publishes 0.3.0), narrowed to one family <family>: @grammar/core, @grammar/heritage, @grammar/offset-pop; @grammar/common is the shared layer every family imports",
213
+ "scheme": "grammar://<family>@<version>",
214
+ "bind": "package.json version + the resolved location's fingerprint (checkout head for file:, tarball integrity for npm)",
215
+ "writers": [],
216
+ "purpose": "The Grammar as it runs: Common renderers, props, owned relationships, data-contract claims, and the family's own CSS. The only fact about what a component owns."
217
+ },
218
+ "@remote": {
219
+ "npm": {
220
+ "params": [
221
+ "package"
222
+ ],
223
+ "kind": "service",
224
+ "resolvesTo": "the npm registry entry for <package>, e.g. @remote/npm/@starci/grammar@0.3.0",
225
+ "scheme": "npm://<package>@<version>",
226
+ "bind": "version + tarball integrity",
227
+ "writers": [],
228
+ "purpose": "Published packages. A version is the binding; latest never is."
229
+ },
230
+ "git": {
231
+ "params": [
232
+ "project",
233
+ "role"
234
+ ],
235
+ "kind": "service",
236
+ "resolvesTo": "the origin URL in @workspaces/local/routes/<project>/<role> (repository.gitRepository)",
237
+ "scheme": "remote://<repository>/<branch>",
238
+ "bind": "observed remote head (git ls-remote) at invocation time",
239
+ "writers": [
240
+ "git.publish"
241
+ ],
242
+ "purpose": "The publication target; fast-forwardness is decided against this observation."
243
+ },
244
+ "ghcr": {
245
+ "params": [
246
+ "image"
247
+ ],
248
+ "kind": "service",
249
+ "resolvesTo": "ghcr.io/<image>@<digest>",
250
+ "scheme": "oci://ghcr.io/<image>",
251
+ "bind": "digest",
252
+ "writers": [
253
+ "release.deploy"
254
+ ],
255
+ "purpose": "Immutable release images. A tag is never a binding; a digest is."
256
+ },
257
+ "github-actions": {
258
+ "params": [
259
+ "runId"
260
+ ],
261
+ "kind": "service",
262
+ "resolvesTo": "GitHub Actions run <runId> of the routed repository",
263
+ "scheme": "workflow-run://github-actions/<runId>",
264
+ "bind": "run id + conclusion",
265
+ "writers": [],
266
+ "purpose": "CI evidence of a build or rollout, read only."
267
+ },
268
+ "minio": {
269
+ "params": [
270
+ "contentId",
271
+ "locale"
272
+ ],
273
+ "kind": "service",
274
+ "resolvesTo": "MinIO object contents/<contentId>/<locale>.json through the routed runtime",
275
+ "scheme": "content://<contentId>/<locale>",
276
+ "bind": "fingerprint of the fetched object",
277
+ "writers": [
278
+ "content.generate"
279
+ ],
280
+ "purpose": "Authored lesson content as served, not as drafted."
281
+ }
282
+ },
283
+ "@dynamic": {
284
+ "params": [
285
+ "kind"
286
+ ],
287
+ "kind": "dir",
288
+ "resolvesTo": "<Source>/.worktrees/sessions/<sessionId>/step-<N>/parallel-<M>/ — one branch of one step. request/request.json is the gate in (orchestrator writes it); response/ is the agent's: response.json (gate out), response.md and other markdown kinds, data/<name>.json, artifacts/<file>; a nested exchange adds <exchange>/request/ and <exchange>/response/. A kind is passed by explicit path in request.json inputs, from the session root. Dynamic files are passed as kinds (templates/kinds/<kind>), never as aliases. The session folder is created by the orchestrator and deleted when git.publish finishes; a blocked run keeps it for resume",
289
+ "scheme": "step://<sessionId>/<N>/<M>/<path>",
290
+ "bind": "kind contract or schema under templates/kinds; response.json fields is the registry of what a branch produced",
291
+ "writers": [
292
+ "*"
293
+ ],
294
+ "purpose": "Everything produced inside the session and nothing that existed before it. Always dynamic; typed by kind."
295
+ }
296
+ }
297
+ }
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ // The installer for StarCi Skills. The runtime is a tree of files under <repo>/.claude and two
3
+ // bootstrap files at the repo root (CLAUDE.md for Claude Code, AGENTS.md for Codex); nothing here is
4
+ // a framework the tree depends on at run time. The CLI has no dependencies and needs Node 20+.
5
+ //
6
+ // npx @starci/skills init install the tree into ./.claude and write the bootstraps
7
+ // npx @starci/skills update bring an installed tree to this package's version
8
+ // npx @starci/skills doctor run the tree's own validators on the installed copy
9
+ // npx @starci/skills version
10
+ //
11
+ // Every command takes --dir <repo> (default: the current directory). init refuses a non-empty
12
+ // .claude it did not install unless --force; update keeps a file a person changed locally unless
13
+ // --force; neither ever runs a git command.
14
+ import { createHash } from 'node:crypto';
15
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, appendFileSync } from 'node:fs';
16
+ import path from 'node:path';
17
+ import process from 'node:process';
18
+ import { spawnSync } from 'node:child_process';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
22
+ const pkg = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
23
+
24
+ // What an installed tree is made of. Only these paths are copied, hashed and updated; anything else
25
+ // a person adds beside them (a tests/ folder, notes) is theirs and is never touched.
26
+ export const PAYLOAD = [
27
+ 'INDEX.md', 'INDEX.vi.md', 'SKILL.md', 'SKILL.vi.md', 'routing.json',
28
+ 'alias', 'knowledge', 'operators', 'readiness', 'resources', 'scripts', 'templates', 'workflows',
29
+ ];
30
+ const MANIFEST = '.starci-skills.json';
31
+ const SESSIONS_IGNORE = '.worktrees/sessions/';
32
+
33
+ const BOOTSTRAP = `# StarCi agent bootstrap
34
+
35
+ Before planning, reading target source, or running a skill, read
36
+ [\`<Source>/.claude/INDEX.md\`](.claude/INDEX.md) completely and follow its load order.
37
+
38
+ \`<Source>\` is the single host repository that owns this bootstrap and the \`.claude\` runtime. A routed
39
+ repository checkout or Git worktree follows that Source; do not rebind \`<Source>\` to it or expect it to
40
+ contain another \`.claude/INDEX.md\`.
41
+
42
+ This file is only a bootstrap. Do not copy context, brainstorm, compiler, gate or skill rules into it:
43
+ the entry routes, and a rule copied here becomes a second home that nobody remembers to update.
44
+ `;
45
+
46
+ // The validators the tree ships, in the order npm test runs them. --quick keeps the three that
47
+ // finish in seconds; the full doctor also runs the operator self-tests and the script specs.
48
+ const DOCTOR_QUICK = ['validate-routing.mjs', 'validate-alias.mjs', 'validate-operator.mjs'];
49
+ const DOCTOR_FULL = [
50
+ 'validate-routing.mjs', 'validate-resources.mjs', 'validate-knowledge-citations.mjs', 'validate-alias.mjs',
51
+ ['generate-alias-doc.mjs', '--check'], 'validate-operator.mjs', 'validate-workflows.mjs', 'validate-defaults.mjs',
52
+ ['generate-operators-index.mjs', '--check'], 'validate-templates.mjs', 'run-operator-self-tests.mjs',
53
+ ];
54
+
55
+ function parseArgs(argv) {
56
+ const out = { command: argv[0] ?? 'help', dir: process.cwd(), force: false, quick: false, bootstrap: true };
57
+ for (let i = 1; i < argv.length; i += 1) {
58
+ const a = argv[i];
59
+ if (a === '--dir') out.dir = path.resolve(argv[++i] ?? '.');
60
+ else if (a.startsWith('--dir=')) out.dir = path.resolve(a.slice(6));
61
+ else if (a === '--force') out.force = true;
62
+ else if (a === '--quick') out.quick = true;
63
+ else if (a === '--no-bootstrap') out.bootstrap = false;
64
+ else if (a === '-h' || a === '--help') out.command = 'help';
65
+ else throw new Error(`unknown argument ${a}`);
66
+ }
67
+ return out;
68
+ }
69
+
70
+ function walk(root, rel = '') {
71
+ const abs = path.join(root, rel);
72
+ if (!existsSync(abs)) return [];
73
+ if (statSync(abs).isFile()) return [rel];
74
+ const out = [];
75
+ for (const e of readdirSync(abs, { withFileTypes: true })) {
76
+ const next = rel ? `${rel}/${e.name}` : e.name;
77
+ if (e.isDirectory()) out.push(...walk(root, next));
78
+ else out.push(next);
79
+ }
80
+ return out;
81
+ }
82
+ const sha = (file) => createHash('sha256').update(readFileSync(file).toString('utf8').replace(/\r\n/g, '\n')).digest('hex');
83
+ const payloadFiles = (root) => PAYLOAD.flatMap((p) => walk(root, p)).sort();
84
+ const hashTree = (root) => Object.fromEntries(payloadFiles(root).map((rel) => [rel, sha(path.join(root, rel))]));
85
+
86
+ function readManifest(target) {
87
+ const file = path.join(target, MANIFEST);
88
+ return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : null;
89
+ }
90
+ function writeManifest(target, kept = []) {
91
+ const manifest = { name: pkg.name, version: pkg.version, installedAt: new Date().toISOString(), files: hashTree(target) };
92
+ if (kept.length) manifest.keptLocal = kept;
93
+ writeFileSync(path.join(target, MANIFEST), `${JSON.stringify(manifest, null, 2)}\n`);
94
+ return manifest;
95
+ }
96
+
97
+ function copyPayload(target) {
98
+ for (const p of PAYLOAD) {
99
+ const from = path.join(packageRoot, p);
100
+ const to = path.join(target, p);
101
+ if (!existsSync(from)) throw new Error(`package is incomplete: ${p} is missing`);
102
+ if (statSync(from).isDirectory()) { rmSync(to, { recursive: true, force: true }); cpSync(from, to, { recursive: true }); }
103
+ else { mkdirSync(path.dirname(to), { recursive: true }); cpSync(from, to); }
104
+ }
105
+ }
106
+
107
+ function writeBootstraps(repo, log) {
108
+ for (const name of ['CLAUDE.md', 'AGENTS.md']) {
109
+ const file = path.join(repo, name);
110
+ if (!existsSync(file)) { writeFileSync(file, BOOTSTRAP); log(`wrote ${name}`); continue; }
111
+ const current = readFileSync(file, 'utf8');
112
+ if (current.includes('.claude/INDEX.md')) log(`kept ${name} (already routes to .claude/INDEX.md)`);
113
+ else log(`NOTICE ${name} exists and does not route to .claude/INDEX.md; add the bootstrap paragraph yourself`);
114
+ }
115
+ const ignore = path.join(repo, '.gitignore');
116
+ const lines = existsSync(ignore) ? readFileSync(ignore, 'utf8').split(/\r?\n/) : [];
117
+ if (!lines.some((l) => l.trim() === SESSIONS_IGNORE || l.trim() === '.worktrees/' || l.trim() === '.worktrees')) {
118
+ appendFileSync(ignore, `${lines.length && lines.at(-1) !== '' ? '\n' : ''}# StarCi Skills sessions live here and are never committed\n${SESSIONS_IGNORE}\n`);
119
+ log(`added ${SESSIONS_IGNORE} to .gitignore`);
120
+ }
121
+ }
122
+
123
+ export function init(opts, log = console.log) {
124
+ const repo = opts.dir;
125
+ const target = path.join(repo, '.claude');
126
+ if (!existsSync(repo)) throw new Error(`${repo} does not exist`);
127
+ const manifest = readManifest(target);
128
+ if (existsSync(target) && readdirSync(target).length && !manifest && !opts.force) {
129
+ throw new Error(`${target} exists and was not installed by ${pkg.name}; move it away or pass --force to replace the runtime paths inside it`);
130
+ }
131
+ if (manifest) log(`re-installing over ${manifest.name}@${manifest.version} (use "update" to keep local changes)`);
132
+ mkdirSync(target, { recursive: true });
133
+ copyPayload(target);
134
+ const written = writeManifest(target);
135
+ log(`installed ${pkg.name}@${pkg.version} into ${target} (${Object.keys(written.files).length} files)`);
136
+ if (opts.bootstrap) writeBootstraps(repo, log);
137
+ log('next: open the repo with Claude Code or Codex; the bootstrap routes every agent to .claude/INDEX.md');
138
+ return written;
139
+ }
140
+
141
+ export function update(opts, log = console.log) {
142
+ const target = path.join(opts.dir, '.claude');
143
+ const manifest = readManifest(target);
144
+ if (!manifest) throw new Error(`${target} has no ${MANIFEST}; run init first`);
145
+ const before = hashTree(target);
146
+ const locallyChanged = Object.entries(before).filter(([rel, h]) => manifest.files[rel] && manifest.files[rel] !== h).map(([rel]) => rel);
147
+ const locallyAdded = Object.keys(before).filter((rel) => !manifest.files[rel]);
148
+ const saved = Object.fromEntries([...locallyChanged, ...locallyAdded].map((rel) => [rel, readFileSync(path.join(target, rel))]));
149
+ copyPayload(target);
150
+ const kept = [];
151
+ if (!opts.force) {
152
+ for (const [rel, bytes] of Object.entries(saved)) {
153
+ const file = path.join(target, rel);
154
+ mkdirSync(path.dirname(file), { recursive: true });
155
+ writeFileSync(file, bytes);
156
+ kept.push(rel);
157
+ }
158
+ }
159
+ const written = writeManifest(target, kept);
160
+ log(`updated ${manifest.name}@${manifest.version} -> ${pkg.name}@${pkg.version} in ${target}`);
161
+ for (const rel of kept) log(`kept ${rel} (changed locally; pass --force to take the package version)`);
162
+ if (opts.force && (locallyChanged.length || locallyAdded.length)) log(`replaced ${locallyChanged.length + locallyAdded.length} locally changed file(s)`);
163
+ return written;
164
+ }
165
+
166
+ export function doctor(opts, log = console.log) {
167
+ const target = path.join(opts.dir, '.claude');
168
+ if (!existsSync(path.join(target, 'scripts'))) throw new Error(`${target} has no scripts/; run init first`);
169
+ const manifest = readManifest(target);
170
+ if (manifest) {
171
+ const drift = Object.entries(hashTree(target)).filter(([rel, h]) => manifest.files[rel] && manifest.files[rel] !== h).map(([rel]) => rel);
172
+ log(`${manifest.name}@${manifest.version}; ${drift.length} file(s) changed since install${drift.length ? `: ${drift.join(', ')}` : ''}`);
173
+ } else log(`no ${MANIFEST}: validating an unmanaged tree`);
174
+ const steps = opts.quick ? DOCTOR_QUICK : DOCTOR_FULL;
175
+ let failed = 0;
176
+ for (const step of steps) {
177
+ const [script, ...args] = Array.isArray(step) ? step : [step];
178
+ const r = spawnSync(process.execPath, [path.join(target, 'scripts', script), ...args], { cwd: target, encoding: 'utf8' });
179
+ const ok = r.status === 0;
180
+ if (!ok) failed += 1;
181
+ log(`${ok ? 'ok ' : 'FAIL'} ${script}${args.length ? ` ${args.join(' ')}` : ''}${ok ? '' : `\n${(r.stdout + r.stderr).trim()}`}`);
182
+ }
183
+ if (!opts.quick) {
184
+ const specs = readdirSync(path.join(target, 'scripts')).filter((f) => f.endsWith('.spec.mjs')).map((f) => path.join(target, 'scripts', f));
185
+ const r = spawnSync(process.execPath, ['--test', ...specs], { cwd: target, encoding: 'utf8' });
186
+ if (r.status !== 0) failed += 1;
187
+ log(`${r.status === 0 ? 'ok ' : 'FAIL'} node --test scripts/*.spec.mjs (${specs.length} files)${r.status === 0 ? '' : `\n${(r.stdout + r.stderr).trim().split('\n').slice(-30).join('\n')}`}`);
188
+ }
189
+ log(failed ? `doctor: ${failed} check(s) failed` : 'doctor: the installed tree validates');
190
+ return failed;
191
+ }
192
+
193
+ const HELP = `${pkg.name} ${pkg.version}
194
+
195
+ npx ${pkg.name} init [--dir <repo>] [--force] [--no-bootstrap]
196
+ npx ${pkg.name} update [--dir <repo>] [--force]
197
+ npx ${pkg.name} doctor [--dir <repo>] [--quick]
198
+ npx ${pkg.name} version
199
+
200
+ init copies the runtime into <repo>/.claude, writes CLAUDE.md and AGENTS.md when absent, and
201
+ adds .worktrees/sessions/ to .gitignore. Refuses a .claude it did not install unless --force.
202
+ update replaces the runtime paths with this version; a file changed locally is kept and listed
203
+ unless --force. Files outside the runtime paths are never touched.
204
+ doctor runs the tree's own validators on the installed copy and reports local drift.
205
+ `;
206
+
207
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
208
+ try {
209
+ const opts = parseArgs(process.argv.slice(2));
210
+ if (opts.command === 'init') init(opts);
211
+ else if (opts.command === 'update') update(opts);
212
+ else if (opts.command === 'doctor') process.exitCode = doctor(opts) ? 1 : 0;
213
+ else if (opts.command === 'version') console.log(pkg.version);
214
+ else console.log(HELP);
215
+ } catch (err) {
216
+ console.error(`${pkg.name}: ${err.message}`);
217
+ process.exitCode = 1;
218
+ }
219
+ }