@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,146 @@
1
+ // frontend.direction.decide's own law over one branch, on top of the shared step check: the intent and the
2
+ // change level agree; the selection policy and the approval agree; the receipt names exactly one
3
+ // selected candidate, falsifies every candidate it formed, and rejects the others by name; a refine
4
+ // forms no structural candidate and consults no external reference; more than one candidate is
5
+ // rendered; and COVERAGE-1 holds, meaning the coverage enumerates every action, region, state and
6
+ // responsive branch the UI contract declares.
7
+ import { existsSync } from 'node:fs';
8
+ import { readFile } from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ import process from 'node:process';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { validateStep } from '../../scripts/validate-step.mjs';
13
+ import { tableUnder } from '../../scripts/validate-response.mjs';
14
+
15
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
16
+ const empty = (v) => v === undefined || v === null || v === '' || v === '—';
17
+ const list = (v) => (Array.isArray(v) ? v : empty(v) ? [] : [v]);
18
+
19
+ // COVERAGE-1 (knowledge/ui/composition): a decided direction enumerates what a later operator has to
20
+ // exercise. Every element the UI contract declares is covered, every pending path settles, every
21
+ // meaning has its own carrier, and every responsive branch has one owner.
22
+ export function coverageErrors(coverage, declared, at) {
23
+ const errors = [];
24
+ const need = (kind) => declared.filter((d) => d.kind === kind).map((d) => d.element);
25
+ const actions = need('action');
26
+ if (actions.length) {
27
+ if ((coverage.actions ?? []).length === 0) errors.push(`${at}: COVERAGE-1: actions must enumerate every declared action`);
28
+ const covered = (coverage.actions ?? []).map((a) => a.action);
29
+ for (const action of actions) if (!covered.includes(action)) errors.push(`${at}: COVERAGE-1: action is not covered: ${action}`);
30
+ for (const entry of coverage.actions ?? []) for (const p of entry.pendingPaths ?? []) if (!p.settlement) errors.push(`${at}: COVERAGE-1: pending path without a settlement: ${entry.action}`);
31
+ }
32
+ const regions = need('region');
33
+ if (regions.length) {
34
+ if ((coverage.regions ?? []).length === 0) errors.push(`${at}: COVERAGE-1: regions must enumerate every declared region`);
35
+ const covered = (coverage.regions ?? []).map((r) => r.region);
36
+ for (const region of regions) if (!covered.includes(region)) errors.push(`${at}: COVERAGE-1: region is not covered: ${region}`);
37
+ for (const region of covered) if (!regions.includes(region)) errors.push(`${at}: COVERAGE-1: coverage names a region the UI contract does not declare: ${region}`);
38
+ }
39
+ const states = need('state');
40
+ if (states.length) {
41
+ if ((coverage.states ?? []).length === 0) errors.push(`${at}: COVERAGE-1: states must enumerate every named meaning`);
42
+ const covered = (coverage.states ?? []).map((s) => s.meaning);
43
+ for (const state of states) if (!covered.includes(state)) errors.push(`${at}: COVERAGE-1: state is not covered: ${state}`);
44
+ const carriers = (coverage.states ?? []).map((s) => s.carrier);
45
+ if (new Set(carriers).size !== carriers.length) errors.push(`${at}: COVERAGE-1: two meanings share one carrier`);
46
+ }
47
+ const responsive = need('responsive');
48
+ if (responsive.length) {
49
+ if ((coverage.responsive ?? []).length === 0) errors.push(`${at}: COVERAGE-1: responsive must enumerate every responsive branch`);
50
+ const covered = (coverage.responsive ?? []).map((b) => b.branch);
51
+ for (const branch of responsive) if (!covered.includes(branch)) errors.push(`${at}: COVERAGE-1: responsive branch is not covered: ${branch}`);
52
+ if (new Set(covered).size !== covered.length) errors.push(`${at}: COVERAGE-1: a responsive branch is named twice, so it has more than one owner`);
53
+ }
54
+ return errors;
55
+ }
56
+
57
+ export async function validateDirectionStep(branchDir, root = ROOT) {
58
+ const base = await validateStep(root, branchDir);
59
+ const errors = [...base.errors];
60
+ const { response, requirements = {}, present = new Set() } = base;
61
+ if (!response || response.operatorId !== 'frontend.direction.decide') return { errors };
62
+ const has = (f) => existsSync(path.join(branchDir, f));
63
+ const read = (f) => readFile(path.join(branchDir, f), 'utf8');
64
+
65
+ const intent = requirements.intent ?? 'modify';
66
+ const changeLevel = requirements.changeLevel;
67
+ const candidates = Number(requirements.candidates ?? 1);
68
+ const preview = requirements.preview ?? 'no';
69
+ const policy = requirements.selectionPolicy ?? 'automatic';
70
+ const approval = empty(requirements.approval) ? null : requirements.approval;
71
+ const references = list(requirements.references);
72
+
73
+ if (intent === 'create' && changeLevel !== 'new') errors.push('request.json: intent create requires changeLevel new');
74
+ if (changeLevel === 'new' && intent !== 'create') errors.push('request.json: changeLevel new requires intent create');
75
+ if (!(candidates >= 1 && candidates <= 3)) errors.push(`request.json: candidates must be 1, 2 or 3, not ${requirements.candidates}`);
76
+ if (policy === 'automatic' && approval !== null) errors.push('request.json: approval is bound under automatic policy; supplying both hides which one decided');
77
+
78
+ const artifacts = new Set(list(response.fields?.candidates));
79
+ if (response.status === 'done') {
80
+ if (candidates > 1 && artifacts.size === 0) errors.push('response/response.json: more than one candidate was formed but none was rendered');
81
+ if (preview === 'yes' && artifacts.size === 0) errors.push('response/response.json: preview was asked for but no candidate page was rendered');
82
+ if (candidates === 1 && preview === 'no' && artifacts.size > 0) errors.push('response/response.json: one candidate under no preview renders no page');
83
+ }
84
+
85
+ let coverage = null;
86
+ if (present.has('ui-coverage') && has('response/data/coverage.json')) {
87
+ try { coverage = JSON.parse(await read('response/data/coverage.json')); } catch { coverage = null; }
88
+ } else if (response.status === 'done') errors.push('response/data/coverage.json: a done branch needs the coverage enumeration');
89
+
90
+ if (present.has('frontend-direction-decision') && has('response/response.md')) {
91
+ const text = await read('response/response.md');
92
+ const at = 'response/response.md';
93
+ const decision = Object.fromEntries((tableUnder(text, '## Decision') ?? []).map(([k, v]) => [k, v]));
94
+ if (!empty(requirements.target) && decision.Target !== requirements.target) errors.push(`${at}: Target differs from the request`);
95
+ if (decision.Intent !== intent) errors.push(`${at}: Intent ${decision.Intent} differs from the request's ${intent}`);
96
+ if (decision['Change level'] !== changeLevel) errors.push(`${at}: Change level ${decision['Change level']} differs from the request's ${changeLevel}`);
97
+ if (!empty(requirements.ownerCeiling) && decision['Owner ceiling'] !== requirements.ownerCeiling) errors.push(`${at}: Owner ceiling differs from the request`);
98
+ if (decision['Selection policy'] !== policy) errors.push(`${at}: Selection policy ${decision['Selection policy']} differs from the request's ${policy}`);
99
+ if (changeLevel === 'refine' && decision.Classification !== 'locked-refine') errors.push(`${at}: a refine is classified locked-refine, not ${decision.Classification}`);
100
+ if (changeLevel !== 'refine' && decision.Classification === 'locked-refine') errors.push(`${at}: locked-refine requires change level refine`);
101
+
102
+ // Exactly one candidate is selected, every candidate formed is falsified, and every candidate
103
+ // that was not selected is rejected by name.
104
+ const attacks = tableUnder(text, '## Falsification') ?? [];
105
+ const formed = new Set(attacks.map((r) => r[1]));
106
+ const rejected = new Set((tableUnder(text, '## Why not the others') ?? []).map((r) => r[0]));
107
+ const selected = decision['Selected candidate'];
108
+ if (response.status === 'done') {
109
+ if (empty(selected)) errors.push(`${at}: a decided direction names one selected candidate`);
110
+ else if (!formed.has(selected)) errors.push(`${at}: the selected candidate ${selected} carries no falsification row`);
111
+ if (formed.size !== candidates) errors.push(`${at}: Falsification covers ${formed.size} candidates, the request asked for ${candidates}`);
112
+ for (const candidate of formed) {
113
+ if (candidate === selected) continue;
114
+ if (!rejected.has(candidate)) errors.push(`${at}: candidate ${candidate} was not selected and is not rejected by name`);
115
+ }
116
+ if (rejected.has(selected)) errors.push(`${at}: the selected candidate ${selected} is also listed under Why not the others`);
117
+ for (const [, candidate, verdict] of attacks) {
118
+ if (candidate === selected && verdict === 'fails') errors.push(`${at}: the selected candidate ${selected} fails an attack, so the direction is not decided`);
119
+ }
120
+ }
121
+ if (policy === 'approval-required' && response.status === 'done') {
122
+ if (approval === null) errors.push('response/response.json: approval-required with no approval cannot end done; DIRECTION_CHOICE_REQUIRED terminates here');
123
+ else if (approval !== selected) errors.push(`${at}: the receipt selects ${selected} but approval names ${approval}`);
124
+ }
125
+
126
+ // A refine moves elements inside the approved structure and consults no external reference.
127
+ const refs = tableUnder(text, '## References') ?? [];
128
+ if (changeLevel === 'refine' && refs.length) errors.push(`${at}: a refine works from the family idioms alone, so References carries no row`);
129
+ if (references.length && refs.length === 0) errors.push(`${at}: the person supplied references and none of them is recorded`);
130
+ const contract = (tableUnder(text, '## UI contract') ?? []).map(([element, kind]) => ({ element, kind }));
131
+ if (coverage) {
132
+ errors.push(...coverageErrors(coverage, contract, 'response/data/coverage.json'));
133
+ if (!empty(decision['Direction id']) && coverage.directionId !== decision['Direction id']) {
134
+ errors.push(`response/data/coverage.json: directionId ${coverage.directionId} differs from the receipt's ${decision['Direction id']}`);
135
+ }
136
+ }
137
+ }
138
+ return { errors };
139
+ }
140
+
141
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
142
+ const target = process.argv[2];
143
+ if (!target) { process.stderr.write('usage: node validate.mjs <session>/step-N/parallel-M\n'); process.exit(2); }
144
+ const { errors } = await validateDirectionStep(path.resolve(target));
145
+ if (errors.length) { process.stderr.write(`${errors.join('\n')}\n`); process.exitCode = 1; } else process.stdout.write('valid frontend.direction.decide branch\n');
146
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "schemaVersion": 9,
3
+ "note": "Stop codes frontend.presentation.resolve emits. Same entry shape as operators/errors.json, scope implicit. Shared codes (INVALID_INPUT, SOURCE_DRIFT, NO_PROGRESS) come from operators/errors.json. OWNER_CONFLICT and UNKNOWN_RULE are defined here and also emitted by frontend.source.apply and frontend.surface.audit; they belong in operators/errors.json with a scope list.",
4
+ "codes": {
5
+ "KNOWLEDGE_UNBOUND": {
6
+ "domain": "knowledge",
7
+ "disposition": "terminate",
8
+ "meaning": {
9
+ "en": "A presentation property is present in the tree and no knowledge topic is bound for it.",
10
+ "vi": "Một thuộc tính trình bày có trong cây mà không topic kiến thức nào được bind cho nó."
11
+ },
12
+ "resume": {
13
+ "en": "Bind the missing topic.",
14
+ "vi": "Bind topic còn thiếu."
15
+ }
16
+ },
17
+ "RULE_MISSING": {
18
+ "domain": "knowledge",
19
+ "disposition": "terminate",
20
+ "meaning": {
21
+ "en": "No published case matches the observed condition on a node.",
22
+ "vi": "Không case nào đã publish khớp điều kiện quan sát được trên một node."
23
+ },
24
+ "resume": {
25
+ "en": "The knowledge owner publishes the case, and the tree is resolved again.",
26
+ "vi": "Chủ knowledge publish case, rồi cây được resolve lại."
27
+ }
28
+ },
29
+ "GRAMMAR_UNPUBLISHED": {
30
+ "domain": "grammar",
31
+ "disposition": "terminate",
32
+ "meaning": {
33
+ "en": "The Grammar package is unpublished or the bound fingerprint is stale.",
34
+ "vi": "Gói Grammar chưa publish hoặc fingerprint đã bind là cũ."
35
+ },
36
+ "resume": {
37
+ "en": "A person publishes the exact Grammar package.",
38
+ "vi": "Người publish đúng gói Grammar."
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "schemaVersion": 9,
3
+ "id": "frontend.presentation.resolve",
4
+ "domain": "frontend",
5
+ "job": "Resolve every application-owned presentation property on one already-composed tree to exactly one published rule, emit its class and verifiable contract claim, and stop at the smallest owning gap instead of inventing a value.",
6
+ "package": "operator.md",
7
+ "errors": "errors.json",
8
+ "validator": "validate.mjs",
9
+ "selfTest": "self-test.mjs",
10
+ "resources": {
11
+ "profile": "luna",
12
+ "grammarBound": true,
13
+ "tools": {
14
+ "@tools/fileread": "context-aliases",
15
+ "@tools/git": "read",
16
+ "@tools/registry": "read"
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,142 @@
1
+ # frontend.presentation.resolve
2
+
3
+ ## Job
4
+
5
+ Resolve every application-owned presentation property on one already-composed tree to exactly one
6
+ published rule, emit its class and its verifiable contract claim, and stop at the smallest owning gap
7
+ instead of inventing a value.
8
+
9
+ ## Structure arrives decided
10
+
11
+ Structure, element order, Grammar component selection, copy, data and behaviour arrive decided, and
12
+ so does the owner ceiling: it is carried by the direction this branch resolves, never re-declared
13
+ here. This operator only answers, for each node the application owns, which value each presentation
14
+ property takes and which rule authorizes it. It changes nothing about what the tree renders.
15
+
16
+ ## No fabricated rule
17
+
18
+ A rule exists only if the bound knowledge topic publishes its identifier, and that inventory is
19
+ frozen for the whole run. An emitted identifier absent from the inventory is `UNKNOWN_RULE`. A class
20
+ that contradicts its identifier is rejected: the rule number is an ordinal on the value scale, so
21
+ `GAP-5` renders `gap-6` and `PADDING-5` renders `p-6`, and writing the ordinal as the step is the
22
+ defect this check exists to catch. When no published case matches the observed condition the run
23
+ stops with `RULE_MISSING` naming that node; it does not choose a nearby value, round to the closest
24
+ step, or copy a neighbouring node. The operator never edits knowledge: a missing case goes back to
25
+ the knowledge owner, and the same tree is resolved again once the case is published.
26
+
27
+ ## Grammar is read as published, and consulted first
28
+
29
+ The owned relationships come from the published package's own data-contract claims, never from
30
+ Grammar source. A property a component already owns resolves to that component, emits no application
31
+ class, and names the rule the component satisfies; that ordering makes reimplementation impossible
32
+ rather than merely discouraged. An application class that reimplements an owned relationship,
33
+ overrides Grammar anatomy or sits off the closed scale is removed with its own row, per node and
34
+ never silently.
35
+
36
+ ## A forbidden class is removed, not ruled
37
+
38
+ When the only case that names an application class states a condition the node does not meet (an
39
+ accent foreground that `SURFACE-4` allows solely inside a raised band, written on an unraised row),
40
+ the property is not missing a rule: the rule has answered, and the answer is no. The class is removed
41
+ in the removal step, the property falls back to what the node inherits, and the removal is recorded
42
+ with the case that refused it. `RULE_MISSING` is reserved for a property no published case addresses
43
+ at all.
44
+
45
+ ## A missing public path is a gap, not a stop
46
+
47
+ When Common exposes no public path for a relationship the application legitimately needs, the node
48
+ keeps its application class and the branch records a row under `## Gaps` naming the node, the
49
+ property and the missing path. The branch does not stop: a recorded workaround is visible to the
50
+ family owner and to the next audit, while a stop here would only trade one silent value for a
51
+ blocked chain.
52
+
53
+ ## The contract is a claim, not a verdict
54
+
55
+ Every application-owned node publishes the identifiers it claims. `data-contract` records which
56
+ rules a node claims to satisfy and never asserts that the node passes; the claim exists so a later
57
+ audit can contradict it, and one rule stays selectable as `[data-contract~="GAP-4"]`. With emission
58
+ off the tree carries nothing and the receipt alone holds the claims.
59
+
60
+ ## The loop is counted
61
+
62
+ An audit that sends its findings back here starts another round, and a round that repeats itself is
63
+ not progress. The number of audit receipts this session has fed back is counted at the gate, and a
64
+ run beyond `maxRounds` stops with `NO_PROGRESS` rather than resolving the same tree a third time.
65
+
66
+ ## Boundary
67
+
68
+ Context is read-only. The operator writes only `response/` of its own branch: the resolution receipt,
69
+ the inventory and the resolved tree. It does not change DOM structure, element order, Grammar
70
+ component selection, copy or behaviour, write a class for a property a Grammar component already
71
+ owns, reach into Grammar anatomy with a selector or a passed class, edit knowledge, publish Grammar,
72
+ write product source, or record a verdict, score or pass claim on any node.
73
+
74
+ ## Context
75
+
76
+ | Alias | Bind | Required |
77
+ | --- | --- | --- |
78
+ | `@knowledge/ui/presentation` | the closed rule inventory read at its fingerprint; the only source of valid identifiers | yes |
79
+ | `@grammar/core` | the published package's owned relationships, read as published and never from Grammar source | yes |
80
+ | `@workspaces/fe` | the routed checkout the composed tree belongs to, read at the frozen head | yes |
81
+
82
+ ## Inputs
83
+
84
+ | Kind | From | Required |
85
+ | --- | --- | --- |
86
+ | `frontend-direction-decision` | `frontend.direction.decide`, the intent and the owner ceiling this resolution works inside; never a source of presentation values | yes |
87
+ | `frontend-surface-audit` | `frontend.surface.audit`, the findings that opened this round; present only when this is a loop | no |
88
+
89
+ ## Requirements
90
+
91
+ | Field | Type | Default | Ask |
92
+ | --- | --- | --- | --- |
93
+ | `maxRounds` | number | 2 | How many audit-to-resolve rounds this surface may take before the loop is called off |
94
+ | `contractEmission` | choice | on | `on` writes the claim token list onto the tree, `off` leaves the receipt as the record |
95
+ | `resume` | token | null | The blocked branch's token when re-entering after a stop |
96
+
97
+ ## Steps
98
+
99
+ | # | Step | Params | Reads | Writes | Stops with |
100
+ | --- | --- | --- | --- | --- | --- |
101
+ | 1 | Validate the gate and resume, and count the audit rounds | `resume`, `maxRounds` | `request/request.json`, input `frontend-surface-audit` when this is a loop, @workspaces/fe at the frozen head | — | `INVALID_INPUT`, `SOURCE_DRIFT`, `NO_PROGRESS` |
102
+ | 2 | Bind the authority | — | @knowledge/ui/presentation (every topic with its fingerprint and rule inventory), @grammar/core (the published package's owned relationships), @workspaces/fe (the routed head and the frozen tree), input `frontend-direction-decision`, @tools/git, @tools/registry | — | `KNOWLEDGE_UNBOUND`, `GRAMMAR_UNPUBLISHED` |
103
+ | 3 | Walk the tree once under the owner ceiling the direction carries | — | @workspaces/fe (the frozen tree, in document order), input `frontend-direction-decision` | — | `OWNER_CONFLICT` |
104
+ | 4 | Determine the owner of every present property | — | @grammar/core (the owned relationships), @workspaces/fe (the properties the node presently carries) | `response/data/inventory.json` | — |
105
+ | 5 | Select one presentation rule per remaining application-owned property | — | @knowledge/ui/presentation (the cases the bound topic publishes) | — | `RULE_MISSING` |
106
+ | 6 | Classify a missing public path as a Grammar gap | — | @grammar/core (the relationship under question), @knowledge/ui/presentation (the capability-gap marking) | — | — |
107
+ | 7 | Remove what the tree should not carry | — | @workspaces/fe (the application classes on the node), @grammar/core (Grammar anatomy and the closed scale) | — | — |
108
+ | 8 | Emit the contract claims onto the application-owned nodes | `contractEmission` | @knowledge/ui/presentation (the frozen rule inventory) | — | `UNKNOWN_RULE` |
109
+ | 9 | Emit | — | everything above | `response/artifacts/<target>.resolved.tsx`, `response/data/inventory.json`, `response/response.md`, `response/response.json` | — |
110
+
111
+ The walk visits every node in document order and records a stable node path; a node outside the
112
+ ceiling the direction carries is observed and never mutated. Steps 4 to 8 run per node, so a single
113
+ tree yields one decision per node and property. The receipt authorizes a later audit to measure the
114
+ rendered result against the claims; it proves nothing about how the tree renders.
115
+
116
+ ## Outputs
117
+
118
+ | Kind | File | Type | Required |
119
+ | --- | --- | --- | --- |
120
+ | `frontend-presentation-resolution` | `response/response.md` | md | yes |
121
+ | `inventory` | `response/data/inventory.json` | data | yes |
122
+ | `resolved-tree` | `response/artifacts/<target>.resolved.tsx` | artifact | yes |
123
+
124
+ ## Stops
125
+
126
+ | Code | Disposition |
127
+ | --- | --- |
128
+ | `INVALID_INPUT` | terminate |
129
+ | `SOURCE_DRIFT` | terminate |
130
+ | `OWNER_CONFLICT` | terminate |
131
+ | `KNOWLEDGE_UNBOUND` | terminate |
132
+ | `UNKNOWN_RULE` | terminate |
133
+ | `RULE_MISSING` | terminate |
134
+ | `GRAMMAR_UNPUBLISHED` | terminate |
135
+ | `NO_PROGRESS` | terminate |
136
+
137
+ ## Next
138
+
139
+ | When | Operator |
140
+ | --- | --- |
141
+ | the tree is resolved and its values must be written into product source | `frontend.source.apply` |
142
+ | a gap needs a family component before the next round, so a person publishes it and the same tree is resolved again | `frontend.presentation.resolve` |
@@ -0,0 +1,140 @@
1
+ # frontend.presentation.resolve
2
+
3
+ ## Việc
4
+
5
+ Resolve mọi thuộc tính trình bày do ứng dụng sở hữu trên một cây đã compose sẵn về đúng một luật đã
6
+ publish, phát ra class và lời khai contract kiểm chứng được của nó, và dừng ở khoảng trống có chủ nhỏ
7
+ nhất thay vì bịa ra một giá trị.
8
+
9
+ ## Cấu trúc đến nơi là đã quyết xong
10
+
11
+ Cấu trúc, thứ tự phần tử, việc chọn component Grammar, chữ, dữ liệu và hành vi đến nơi là đã quyết
12
+ xong, và trần owner cũng vậy: nó do chính cái hướng mà nhánh này resolve mang theo, không bao giờ
13
+ được khai lại ở đây. Operator này chỉ trả lời, cho từng node ứng dụng sở hữu, mỗi thuộc tính trình
14
+ bày nhận giá trị nào và luật nào uỷ quyền cho giá trị ấy. Nó không đổi gì về thứ cây render ra.
15
+
16
+ ## Không có luật bịa
17
+
18
+ Một luật chỉ tồn tại khi topic kiến thức được bind publish đúng identifier của nó, và kho luật ấy
19
+ đóng băng suốt lần chạy. Một identifier phát ra mà không có trong kho là `UNKNOWN_RULE`. Một class
20
+ chỏi với identifier của nó bị từ chối: số hiệu luật là số thứ tự trên thang giá trị, nên `GAP-5`
21
+ render ra `gap-6` và `PADDING-5` render ra `p-6`, và viết số thứ tự thành bước thang chính là lỗi mà
22
+ phép kiểm này sinh ra để bắt. Khi không case nào đã publish khớp điều kiện quan sát được, lần chạy
23
+ dừng với `RULE_MISSING` gọi tên đúng node đó; nó không chọn giá trị gần, không làm tròn về bước gần
24
+ nhất, không chép của node bên cạnh. Operator không bao giờ sửa knowledge: case còn thiếu được trả về
25
+ cho chủ knowledge, và chính cây ấy được resolve lại sau khi case được publish.
26
+
27
+ ## Grammar đọc ở bản đã publish, và được hỏi trước
28
+
29
+ Các quan hệ đã sở hữu lấy từ chính lời khai data-contract của gói đã publish, không bao giờ lấy từ
30
+ source của Grammar. Một thuộc tính mà component đã sở hữu sẽ resolve về component ấy, không phát class
31
+ ứng dụng nào, và gọi tên luật mà component thoả; thứ tự đó làm việc hiện thực lại thành bất khả thi
32
+ chứ không chỉ là điều bị khuyên can. Một class ứng dụng hiện thực lại quan hệ đã có chủ, đè lên giải
33
+ phẫu Grammar hay nằm ngoài thang đóng sẽ bị bỏ kèm một dòng ghi của chính nó, theo từng node và không
34
+ bao giờ im lặng.
35
+
36
+ ## Class bị cấm thì gỡ, không phải thiếu rule
37
+
38
+ Khi case duy nhất gọi tên một class của ứng dụng nêu điều kiện mà node không thoả (foreground accent
39
+ mà `SURFACE-4` chỉ cho phép trong một dải raised, lại viết lên một hàng không raised), thuộc tính đó
40
+ không thiếu rule: rule đã trả lời, và câu trả lời là không. Class bị gỡ ở bước gỡ bỏ, thuộc tính rơi
41
+ về giá trị node kế thừa, và việc gỡ được ghi kèm case đã từ chối nó. `RULE_MISSING` chỉ dành cho thuộc
42
+ tính không case nào đã publish nhắc tới.
43
+
44
+ ## Thiếu đường công khai là một khoảng trống, không phải một lần dừng
45
+
46
+ Khi Common không mở đường công khai nào cho một quan hệ mà ứng dụng cần một cách chính đáng, node giữ
47
+ lại class ứng dụng của nó và nhánh ghi một dòng vào `## Gaps` gọi tên node, thuộc tính và đường còn
48
+ thiếu. Nhánh không dừng: một cách chữa cháy có ghi sổ thì chủ họ và lượt audit sau đều thấy, còn dừng
49
+ ở đây chỉ đổi một giá trị im lặng lấy một chuỗi bị chặn.
50
+
51
+ ## Contract là lời khai, không phải phán quyết
52
+
53
+ Mọi node do ứng dụng sở hữu đều công bố các identifier nó khai. `data-contract` ghi lại node khai
54
+ thoả những luật nào và không bao giờ khẳng định node đó pass; lời khai tồn tại để một lượt audit sau
55
+ có thể phản bác, và một luật vẫn chọn được trực tiếp bằng `[data-contract~="GAP-4"]`. Khi tắt chế độ
56
+ phát, cây không mang gì và một mình biên nhận giữ lời khai.
57
+
58
+ ## Vòng lặp được đếm
59
+
60
+ Một lượt audit gửi phát hiện ngược về đây là mở thêm một vòng, và một vòng lặp lại chính nó thì không
61
+ phải tiến triển. Số biên nhận audit mà phiên này đã đẩy ngược về được đếm ngay ở gate, và một lần
62
+ chạy vượt `maxRounds` sẽ dừng với `NO_PROGRESS` thay vì resolve cùng một cây tới lần thứ ba.
63
+
64
+ ## Ranh giới
65
+
66
+ Context chỉ đọc. Operator chỉ ghi `response/` của nhánh mình: biên nhận resolution, bản kiểm kê và
67
+ cây đã resolve. Nó không đổi cấu trúc DOM, thứ tự phần tử, việc chọn component Grammar, chữ hay hành
68
+ vi, không viết class cho thuộc tính mà một component Grammar đã sở hữu, không thò tay vào giải phẫu
69
+ Grammar bằng selector hay class truyền vào, không sửa knowledge, không publish Grammar, không ghi
70
+ source sản phẩm, và không ghi phán quyết, điểm số hay tuyên bố pass lên bất kỳ node nào.
71
+
72
+ ## Context
73
+
74
+ | Alias | Bind | Bắt buộc |
75
+ | --- | --- | --- |
76
+ | `@knowledge/ui/presentation` | kho luật đóng, đọc ở fingerprint của nó; nguồn duy nhất của identifier hợp lệ | có |
77
+ | `@grammar/core` | các quan hệ đã sở hữu của gói đã publish, đọc ở bản publish chứ không bao giờ từ source Grammar | có |
78
+ | `@workspaces/fe` | checkout được route mà cây đã compose thuộc về, đọc ở head đóng băng | có |
79
+
80
+ ## Đầu vào
81
+
82
+ | Kind | Từ đâu | Bắt buộc |
83
+ | --- | --- | --- |
84
+ | `frontend-direction-decision` | `frontend.direction.decide`, ý đồ và trần owner mà lượt resolve này làm việc bên trong; không bao giờ là nguồn giá trị trình bày | có |
85
+ | `frontend-surface-audit` | `frontend.surface.audit`, các phát hiện mở ra vòng này; chỉ có mặt khi đây là một vòng lặp | không |
86
+
87
+ ## Yêu cầu
88
+
89
+ | Field | Kiểu | Mặc định | Hỏi |
90
+ | --- | --- | --- | --- |
91
+ | `maxRounds` | number | 2 | Bề mặt này được đi bao nhiêu vòng audit rồi resolve trước khi gọi dừng vòng lặp |
92
+ | `contractEmission` | choice | on | `on` ghi danh sách token lời khai lên cây, `off` để một mình biên nhận làm bằng |
93
+ | `resume` | token | null | Token của nhánh bị chặn khi vào lại sau một mã dừng |
94
+
95
+ ## Các bước
96
+
97
+ | # | Bước | Tham số | Đọc | Ghi | Dừng với |
98
+ | --- | --- | --- | --- | --- | --- |
99
+ | 1 | Kiểm gate, chạy lại, và đếm số vòng audit | `resume`, `maxRounds` | `request/request.json`, đầu vào `frontend-surface-audit` khi đây là vòng lặp, @workspaces/fe ở head đóng băng | — | `INVALID_INPUT`, `SOURCE_DRIFT`, `NO_PROGRESS` |
100
+ | 2 | Bind thẩm quyền | — | @knowledge/ui/presentation (mọi topic kèm fingerprint và kho luật), @grammar/core (các quan hệ đã sở hữu của gói đã publish), @workspaces/fe (head được route và cây đã đóng băng), đầu vào `frontend-direction-decision`, @tools/git, @tools/registry | — | `KNOWLEDGE_UNBOUND`, `GRAMMAR_UNPUBLISHED` |
101
+ | 3 | Đi hết cây một lượt dưới trần owner mà hướng mang theo | — | @workspaces/fe (cây đóng băng, theo thứ tự tài liệu), đầu vào `frontend-direction-decision` | — | `OWNER_CONFLICT` |
102
+ | 4 | Xác định chủ của từng thuộc tính đang có | — | @grammar/core (các quan hệ đã sở hữu), @workspaces/fe (thuộc tính node đang mang) | `response/data/inventory.json` | — |
103
+ | 5 | Chọn một luật trình bày cho mỗi thuộc tính ứng dụng còn sở hữu | — | @knowledge/ui/presentation (các case topic được bind publish) | — | `RULE_MISSING` |
104
+ | 6 | Xếp một đường công khai còn thiếu thành khoảng trống Grammar | — | @grammar/core (quan hệ đang xét), @knowledge/ui/presentation (dấu khoảng trống năng lực) | — | — |
105
+ | 7 | Bỏ những gì cây không nên mang | — | @workspaces/fe (class ứng dụng trên node), @grammar/core (giải phẫu Grammar và thang đóng) | — | — |
106
+ | 8 | Phát lời khai contract lên các node do ứng dụng sở hữu | `contractEmission` | @knowledge/ui/presentation (kho luật đã đóng băng) | — | `UNKNOWN_RULE` |
107
+ | 9 | Phát | — | mọi thứ ở trên | `response/artifacts/<target>.resolved.tsx`, `response/data/inventory.json`, `response/response.md`, `response/response.json` | — |
108
+
109
+ Lượt đi thăm mọi node theo thứ tự tài liệu và ghi một node path ổn định; node nằm ngoài trần mà hướng
110
+ mang theo thì chỉ quan sát chứ không bao giờ bị sửa. Bước 4 đến 8 chạy theo từng node, nên một cây cho
111
+ đúng một quyết định cho mỗi cặp node và thuộc tính. Biên nhận uỷ quyền cho một lượt audit sau đo kết
112
+ quả render đối chiếu với lời khai; nó không chứng minh gì về việc cây render ra sao.
113
+
114
+ ## Đầu ra
115
+
116
+ | Kind | File | Kiểu | Bắt buộc |
117
+ | --- | --- | --- | --- |
118
+ | `frontend-presentation-resolution` | `response/response.md` | md | có |
119
+ | `inventory` | `response/data/inventory.json` | data | có |
120
+ | `resolved-tree` | `response/artifacts/<target>.resolved.tsx` | artifact | có |
121
+
122
+ ## Dừng
123
+
124
+ | Code | Xử lý |
125
+ | --- | --- |
126
+ | `INVALID_INPUT` | terminate |
127
+ | `SOURCE_DRIFT` | terminate |
128
+ | `OWNER_CONFLICT` | terminate |
129
+ | `KNOWLEDGE_UNBOUND` | terminate |
130
+ | `UNKNOWN_RULE` | terminate |
131
+ | `RULE_MISSING` | terminate |
132
+ | `GRAMMAR_UNPUBLISHED` | terminate |
133
+ | `NO_PROGRESS` | terminate |
134
+
135
+ ## Kế tiếp
136
+
137
+ | Khi | Operator |
138
+ | --- | --- |
139
+ | cây đã resolve và các giá trị của nó phải được ghi vào source sản phẩm | `frontend.source.apply` |
140
+ | một khoảng trống cần component của họ trước vòng sau, nên một người publish nó rồi chính cây ấy được resolve lại | `frontend.presentation.resolve` |