create-yss-spec 3.5.2 → 3.5.3

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 (438) hide show
  1. package/package.json +1 -1
  2. package/src/template/asset-runtime.js +3 -1
  3. package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
  4. package/template/.agents/skills/codebase-design/SKILL.md +4 -0
  5. package/template/{.codex/skills/improve-codebase-architecture/SKILL.md → .agents/skills/codebase-design/references/architecture-audit.md} +3 -9
  6. package/template/.agents/skills/frontend-commit/SKILL.md +4 -93
  7. package/template/.agents/skills/git-commit-core/SKILL.md +18 -0
  8. package/template/.agents/skills/java-backend-commit/SKILL.md +4 -96
  9. package/template/.agents/skills/llm-wiki/SKILL.md +12 -13
  10. package/template/.agents/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  11. package/template/.agents/skills/llm-wiki/references/compile.md +21 -114
  12. package/template/.agents/skills/llm-wiki/references/ingest.md +8 -33
  13. package/template/.agents/skills/llm-wiki/references/lint.md +9 -46
  14. package/template/.agents/skills/llm-wiki/references/query.md +9 -18
  15. package/template/.agents/skills/llm-wiki/references/schema.md +56 -29
  16. package/template/.agents/skills/llm-wiki/references/transactions.md +48 -0
  17. package/template/.agents/skills/llm-wiki/references/writing.md +4 -4
  18. package/template/.agents/skills/llm-wiki/scripts/advise.mjs +46 -58
  19. package/template/.agents/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  20. package/template/.agents/skills/llm-wiki/scripts/core.mjs +262 -0
  21. package/template/.agents/skills/llm-wiki/scripts/extract.mjs +35 -18
  22. package/template/.agents/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  23. package/template/.agents/skills/llm-wiki/scripts/feedback.mjs +51 -0
  24. package/template/.agents/skills/llm-wiki/scripts/inventory.mjs +43 -171
  25. package/template/.agents/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  26. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  27. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  28. package/template/.agents/skills/llm-wiki/scripts/migrate.mjs +51 -0
  29. package/template/.agents/skills/llm-wiki/scripts/query.mjs +149 -0
  30. package/template/.agents/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  31. package/template/.agents/skills/llm-wiki/scripts/sources.mjs +166 -0
  32. package/template/.agents/skills/llm-wiki/scripts/transaction.mjs +384 -0
  33. package/template/.agents/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  34. package/template/.agents/skills/prototype/LOGIC.md +1 -1
  35. package/template/.agents/skills/prototype/SKILL.md +5 -19
  36. package/template/.agents/skills/setup-matt-pocock-skills/SKILL.md +3 -3
  37. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  38. package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  39. package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  40. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +8 -8
  41. package/template/.agents/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  42. package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  43. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
  44. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  45. package/template/.agents/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
  46. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +1 -1
  47. package/template/.agents/skills/yss-research/SKILL.md +4 -0
  48. package/template/.codex/skills/codebase-design/SKILL.md +4 -0
  49. package/template/{.pi/skills/improve-codebase-architecture/SKILL.md → .codex/skills/codebase-design/references/architecture-audit.md} +3 -9
  50. package/template/.codex/skills/frontend-commit/SKILL.md +4 -93
  51. package/template/.codex/skills/git-commit-core/SKILL.md +18 -0
  52. package/template/.codex/skills/java-backend-commit/SKILL.md +4 -96
  53. package/template/.codex/skills/llm-wiki/SKILL.md +12 -13
  54. package/template/.codex/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  55. package/template/.codex/skills/llm-wiki/references/compile.md +21 -114
  56. package/template/.codex/skills/llm-wiki/references/ingest.md +8 -33
  57. package/template/.codex/skills/llm-wiki/references/lint.md +9 -46
  58. package/template/.codex/skills/llm-wiki/references/query.md +9 -18
  59. package/template/.codex/skills/llm-wiki/references/schema.md +56 -29
  60. package/template/.codex/skills/llm-wiki/references/transactions.md +48 -0
  61. package/template/.codex/skills/llm-wiki/references/writing.md +4 -4
  62. package/template/.codex/skills/llm-wiki/scripts/advise.mjs +46 -58
  63. package/template/.codex/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  64. package/template/.codex/skills/llm-wiki/scripts/core.mjs +262 -0
  65. package/template/.codex/skills/llm-wiki/scripts/extract.mjs +35 -18
  66. package/template/.codex/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  67. package/template/.codex/skills/llm-wiki/scripts/feedback.mjs +51 -0
  68. package/template/.codex/skills/llm-wiki/scripts/inventory.mjs +43 -171
  69. package/template/.codex/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  70. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  71. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  72. package/template/.codex/skills/llm-wiki/scripts/migrate.mjs +51 -0
  73. package/template/.codex/skills/llm-wiki/scripts/query.mjs +149 -0
  74. package/template/.codex/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  75. package/template/.codex/skills/llm-wiki/scripts/sources.mjs +166 -0
  76. package/template/.codex/skills/llm-wiki/scripts/transaction.mjs +384 -0
  77. package/template/.codex/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  78. package/template/.codex/skills/prototype/LOGIC.md +1 -1
  79. package/template/.codex/skills/prototype/SKILL.md +5 -19
  80. package/template/.codex/skills/setup-matt-pocock-skills/SKILL.md +3 -3
  81. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  82. package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  83. package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  84. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +8 -8
  85. package/template/.codex/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  86. package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  87. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
  88. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  89. package/template/.codex/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
  90. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +1 -1
  91. package/template/.codex/skills/yss-research/SKILL.md +4 -0
  92. package/template/.cursor/skills/codebase-design/SKILL.md +4 -0
  93. package/template/.cursor/skills/{improve-codebase-architecture/SKILL.md → codebase-design/references/architecture-audit.md} +3 -9
  94. package/template/.cursor/skills/frontend-commit/SKILL.md +4 -93
  95. package/template/.cursor/skills/git-commit-core/SKILL.md +18 -0
  96. package/template/.cursor/skills/java-backend-commit/SKILL.md +4 -96
  97. package/template/.cursor/skills/llm-wiki/SKILL.md +12 -13
  98. package/template/.cursor/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  99. package/template/.cursor/skills/llm-wiki/references/compile.md +21 -114
  100. package/template/.cursor/skills/llm-wiki/references/ingest.md +8 -33
  101. package/template/.cursor/skills/llm-wiki/references/lint.md +9 -46
  102. package/template/.cursor/skills/llm-wiki/references/query.md +9 -18
  103. package/template/.cursor/skills/llm-wiki/references/schema.md +56 -29
  104. package/template/.cursor/skills/llm-wiki/references/transactions.md +48 -0
  105. package/template/.cursor/skills/llm-wiki/references/writing.md +4 -4
  106. package/template/.cursor/skills/llm-wiki/scripts/advise.mjs +46 -58
  107. package/template/.cursor/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  108. package/template/.cursor/skills/llm-wiki/scripts/core.mjs +262 -0
  109. package/template/.cursor/skills/llm-wiki/scripts/extract.mjs +35 -18
  110. package/template/.cursor/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  111. package/template/.cursor/skills/llm-wiki/scripts/feedback.mjs +51 -0
  112. package/template/.cursor/skills/llm-wiki/scripts/inventory.mjs +43 -171
  113. package/template/.cursor/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  114. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  115. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  116. package/template/.cursor/skills/llm-wiki/scripts/migrate.mjs +51 -0
  117. package/template/.cursor/skills/llm-wiki/scripts/query.mjs +149 -0
  118. package/template/.cursor/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  119. package/template/.cursor/skills/llm-wiki/scripts/sources.mjs +166 -0
  120. package/template/.cursor/skills/llm-wiki/scripts/transaction.mjs +384 -0
  121. package/template/.cursor/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  122. package/template/.cursor/skills/prototype/LOGIC.md +1 -1
  123. package/template/.cursor/skills/prototype/SKILL.md +5 -19
  124. package/template/.cursor/skills/setup-matt-pocock-skills/SKILL.md +3 -3
  125. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  126. package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  127. package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  128. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +8 -8
  129. package/template/.cursor/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  130. package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  131. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
  132. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  133. package/template/.cursor/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
  134. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +1 -1
  135. package/template/.cursor/skills/yss-research/SKILL.md +4 -0
  136. package/template/.pi/skills/codebase-design/SKILL.md +4 -0
  137. package/template/{.agents/skills/improve-codebase-architecture/SKILL.md → .pi/skills/codebase-design/references/architecture-audit.md} +3 -9
  138. package/template/.pi/skills/frontend-commit/SKILL.md +4 -93
  139. package/template/.pi/skills/git-commit-core/SKILL.md +18 -0
  140. package/template/.pi/skills/java-backend-commit/SKILL.md +4 -96
  141. package/template/.pi/skills/llm-wiki/SKILL.md +12 -13
  142. package/template/.pi/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  143. package/template/.pi/skills/llm-wiki/references/compile.md +21 -114
  144. package/template/.pi/skills/llm-wiki/references/ingest.md +8 -33
  145. package/template/.pi/skills/llm-wiki/references/lint.md +9 -46
  146. package/template/.pi/skills/llm-wiki/references/query.md +9 -18
  147. package/template/.pi/skills/llm-wiki/references/schema.md +56 -29
  148. package/template/.pi/skills/llm-wiki/references/transactions.md +48 -0
  149. package/template/.pi/skills/llm-wiki/references/writing.md +4 -4
  150. package/template/.pi/skills/llm-wiki/scripts/advise.mjs +46 -58
  151. package/template/.pi/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  152. package/template/.pi/skills/llm-wiki/scripts/core.mjs +262 -0
  153. package/template/.pi/skills/llm-wiki/scripts/extract.mjs +35 -18
  154. package/template/.pi/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  155. package/template/.pi/skills/llm-wiki/scripts/feedback.mjs +51 -0
  156. package/template/.pi/skills/llm-wiki/scripts/inventory.mjs +43 -171
  157. package/template/.pi/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  158. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  159. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  160. package/template/.pi/skills/llm-wiki/scripts/migrate.mjs +51 -0
  161. package/template/.pi/skills/llm-wiki/scripts/query.mjs +149 -0
  162. package/template/.pi/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  163. package/template/.pi/skills/llm-wiki/scripts/sources.mjs +166 -0
  164. package/template/.pi/skills/llm-wiki/scripts/transaction.mjs +384 -0
  165. package/template/.pi/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  166. package/template/.pi/skills/prototype/LOGIC.md +1 -1
  167. package/template/.pi/skills/prototype/SKILL.md +5 -19
  168. package/template/.pi/skills/setup-matt-pocock-skills/SKILL.md +3 -3
  169. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  170. package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  171. package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  172. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +8 -8
  173. package/template/.pi/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  174. package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  175. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
  176. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  177. package/template/.pi/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
  178. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +1 -1
  179. package/template/.pi/skills/yss-research/SKILL.md +4 -0
  180. package/template/.template-spec/agents/README.md +1 -1
  181. package/template/.template-spec/agents/digital-human-roles.yaml +1 -1
  182. package/template/.template-spec/agents/skill-migrations.md +15 -0
  183. package/template/.template-spec/agents/yss-skill-registry.yaml +10 -29
  184. package/template/.template-spec/architecture/README.md +3 -34
  185. package/template/.template-spec/plan/templates/competitive-analysis-template.md +2 -2
  186. package/template/.template-spec/process/contract-reading.md +24 -0
  187. package/template/.template-spec/process/lifecycle-registry-baseline.json +3 -1
  188. package/template/.template-spec/process/lifecycle-registry.yaml +6 -0
  189. package/template/.template-spec/process/research-completion.md +23 -0
  190. package/template/.template-spec/process/schemas/digital-human-task-package.schema.json +202 -12
  191. package/template/.template-spec/process/schemas/frontend-implementation-evidence.schema.json +7 -15
  192. package/template/.template-spec/process/subagent-collaboration.md +8 -0
  193. package/template/.template-spec/process/templates/frontend-implementation-verification-template.yaml +15 -1
  194. package/template/AGENTS.md +1 -1
  195. package/template/CONTEXT.md +5 -1
  196. package/template/README.md +12 -24
  197. package/template/scripts/contract +5 -5
  198. package/template/scripts/lib/contract-views.mjs +57 -2
  199. package/template/scripts/lib/execution-evidence.mjs +51 -0
  200. package/template/scripts/lib/harness-execution-scope.mjs +1 -1
  201. package/template/scripts/lib/implementation-contract-compiler.mjs +2 -0
  202. package/template/scripts/lib/lifecycle-context-query.mjs +15 -3
  203. package/template/scripts/lib/lifecycle-status.mjs +32 -6
  204. package/template/scripts/lib/lifecycle-transition.mjs +19 -1
  205. package/template/scripts/lib/maintenance-research.mjs +63 -0
  206. package/template/scripts/lib/read-only-intake.mjs +132 -0
  207. package/template/scripts/lib/skill-registry.mjs +2 -1
  208. package/template/scripts/lib/skill-supply-chain.mjs +4 -0
  209. package/template/scripts/lib/slice-task-package.mjs +1 -1
  210. package/template/scripts/lib/task-package.mjs +9 -2
  211. package/template/scripts/lifecycle-status +2 -2
  212. package/template/scripts/prepare-read-only-intake +16 -0
  213. package/template/scripts/run-read-only-intake +14 -0
  214. package/template/scripts/verify-digital-human-task-package +2 -2
  215. package/template/scripts/verify-frontend-implementation-evidence +24 -1
  216. package/template/scripts/verify-maintenance-research +13 -0
  217. package/template/skills-lock.json +19 -76
  218. package/template.manifest.json +118 -29
  219. package/template.snapshot.json +5 -6
  220. package/template/.agents/skills/grill-with-docs/SKILL.md +0 -20
  221. package/template/.agents/skills/grill-with-docs/agents/openai.yaml +0 -5
  222. package/template/.agents/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  223. package/template/.agents/skills/prototype/UI.md +0 -112
  224. package/template/.agents/skills/setup-matt-pocock-skills/domain.md +0 -37
  225. package/template/.agents/skills/to-questionnaire/SKILL.md +0 -55
  226. package/template/.agents/skills/to-questionnaire/agents/openai.yaml +0 -5
  227. package/template/.agents/skills/wait-what/SKILL.md +0 -7
  228. package/template/.agents/skills/wait-what/agents/openai.yaml +0 -5
  229. package/template/.codex/skills/data-analytics/.app.json +0 -84
  230. package/template/.codex/skills/data-analytics/.codex-plugin/plugin.json +0 -66
  231. package/template/.codex/skills/data-analytics/.mcp.json +0 -30
  232. package/template/.codex/skills/data-analytics/AGENTS.md +0 -20
  233. package/template/.codex/skills/data-analytics/DEPENDENCIES.MD +0 -27
  234. package/template/.codex/skills/data-analytics/README.md +0 -60
  235. package/template/.codex/skills/data-analytics/__yss_dotfile__.gitignore +0 -2
  236. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html +0 -16
  237. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part001 +0 -1
  238. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part002 +0 -1
  239. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part003 +0 -1
  240. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part004 +0 -1
  241. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part005 +0 -1
  242. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part006 +0 -1
  243. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html +0 -16
  244. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part001 +0 -1
  245. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part002 +0 -1
  246. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part003 +0 -1
  247. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part004 +0 -1
  248. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part005 +0 -1
  249. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part006 +0 -1
  250. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part007 +0 -1
  251. package/template/.codex/skills/data-analytics/assets/datascience-small.svg +0 -5
  252. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html +0 -16
  253. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part001 +0 -1
  254. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part002 +0 -1
  255. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part003 +0 -1
  256. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part004 +0 -1
  257. package/template/.codex/skills/data-analytics/assets/datascience.png +0 -0
  258. package/template/.codex/skills/data-analytics/assets/datascience.svg +0 -10
  259. package/template/.codex/skills/data-analytics/mcp/server.cjs +0 -2964
  260. package/template/.codex/skills/data-analytics/package-lock.json +0 -3048
  261. package/template/.codex/skills/data-analytics/package.json +0 -43
  262. package/template/.codex/skills/data-analytics/scripts/normalize-widget-assets.mjs +0 -75
  263. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +0 -137
  264. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/agents/openai.yaml +0 -6
  265. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/references/quality-checks.md +0 -29
  266. package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +0 -148
  267. package/template/.codex/skills/data-analytics/skills/build-dashboard/agents/openai.yaml +0 -6
  268. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/bi-platform-dashboard.md +0 -18
  269. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/html-dashboard.md +0 -24
  270. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/mcp-artifact-dashboard.md +0 -71
  271. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/streamlit-dashboard.md +0 -85
  272. package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +0 -207
  273. package/template/.codex/skills/data-analytics/skills/build-report/agents/openai.yaml +0 -6
  274. package/template/.codex/skills/data-analytics/skills/build-report/assets/executive-report-shell.html +0 -70
  275. package/template/.codex/skills/data-analytics/skills/build-report/assets/technical-report-shell.html +0 -66
  276. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/SKILL.md +0 -108
  277. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/agents/openai.yaml +0 -6
  278. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/__init__.py +0 -1
  279. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/cli.py +0 -52
  280. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/constants.py +0 -61
  281. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/docx_writer.py +0 -362
  282. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/html_parser.py +0 -829
  283. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/model.py +0 -30
  284. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/plan.py +0 -127
  285. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/quality.py +0 -374
  286. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/rendering.py +0 -613
  287. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/table_utils.py +0 -54
  288. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/utils.py +0 -16
  289. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc_plan.py +0 -9
  290. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/tests/test_delivery_plan.py +0 -45
  291. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/SKILL.md +0 -77
  292. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/agents/openai.yaml +0 -6
  293. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/scripts/report_to_google_slides.py +0 -2379
  294. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/SKILL.md +0 -88
  295. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/agents/openai.yaml +0 -6
  296. package/template/.codex/skills/data-analytics/skills/build-report/specifications/executive-report.md +0 -97
  297. package/template/.codex/skills/data-analytics/skills/build-report/specifications/mcp-app-report.md +0 -59
  298. package/template/.codex/skills/data-analytics/skills/build-report/specifications/technical-report.md +0 -75
  299. package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +0 -103
  300. package/template/.codex/skills/data-analytics/skills/design-kpis/agents/openai.yaml +0 -6
  301. package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +0 -68
  302. package/template/.codex/skills/data-analytics/skills/gather-business-context/agents/openai.yaml +0 -6
  303. package/template/.codex/skills/data-analytics/skills/index/SKILL.md +0 -251
  304. package/template/.codex/skills/data-analytics/skills/index/agents/openai.yaml +0 -6
  305. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +0 -131
  306. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/agents/openai.yaml +0 -6
  307. package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +0 -141
  308. package/template/.codex/skills/data-analytics/skills/kpi-reporting/agents/openai.yaml +0 -6
  309. package/template/.codex/skills/data-analytics/skills/kpi-reporting/references/report-templates.md +0 -32
  310. package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +0 -106
  311. package/template/.codex/skills/data-analytics/skills/market-sizing/agents/openai.yaml +0 -6
  312. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +0 -130
  313. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/agents/openai.yaml +0 -6
  314. package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +0 -141
  315. package/template/.codex/skills/data-analytics/skills/product-business-analysis/agents/openai.yaml +0 -6
  316. package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +0 -178
  317. package/template/.codex/skills/data-analytics/skills/spreadsheets/agents/openai.yaml +0 -9
  318. package/template/.codex/skills/data-analytics/skills/spreadsheets/assets/file-spreadsheet.png +0 -0
  319. package/template/.codex/skills/data-analytics/skills/spreadsheets/charts.md +0 -31
  320. package/template/.codex/skills/data-analytics/skills/spreadsheets/references/artifact_tool_api.md +0 -466
  321. package/template/.codex/skills/data-analytics/skills/spreadsheets/style_guidelines.md +0 -99
  322. package/template/.codex/skills/data-analytics/skills/user-context/SKILL.md +0 -197
  323. package/template/.codex/skills/data-analytics/skills/user-context/agents/openai.yaml +0 -6
  324. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/automation-config.md +0 -26
  325. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/source-category-config.json +0 -51
  326. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/user-context-config.md +0 -66
  327. package/template/.codex/skills/data-analytics/skills/user-context/references/automation.md +0 -69
  328. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-examples.md +0 -204
  329. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-state-template.json +0 -87
  330. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding.md +0 -497
  331. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/connector-playbook.md +0 -74
  332. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/setup.md +0 -65
  333. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/skill-template.md +0 -160
  334. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/source-intake.md +0 -75
  335. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/weekly-polling-automation.md +0 -96
  336. package/template/.codex/skills/data-analytics/skills/user-context/references/source-category-runtime.md +0 -263
  337. package/template/.codex/skills/data-analytics/skills/user-context/scripts/data_analytics_preflight.py +0 -1462
  338. package/template/.codex/skills/data-analytics/skills/user-context/scripts/init_user_context_state.py +0 -128
  339. package/template/.codex/skills/data-analytics/skills/user-context/scripts/reset_user_context_state.py +0 -101
  340. package/template/.codex/skills/data-analytics/skills/user-context/scripts/validate_user_context_preflight.py +0 -499
  341. package/template/.codex/skills/data-analytics/skills/user-context/tests/test_state_helpers.py +0 -978
  342. package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +0 -126
  343. package/template/.codex/skills/data-analytics/skills/validate-data/agents/openai.yaml +0 -6
  344. package/template/.codex/skills/data-analytics/skills/validate-data/references/validation-methods.md +0 -70
  345. package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +0 -157
  346. package/template/.codex/skills/data-analytics/skills/visualize-data/agents/openai.yaml +0 -6
  347. package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md +0 -774
  348. package/template/.codex/skills/data-analytics/src/DESIGN.md +0 -222
  349. package/template/.codex/skills/data-analytics/src/analytics-app/App.tsx +0 -3666
  350. package/template/.codex/skills/data-analytics/src/analytics-app/analytics-layout.test.mjs +0 -136
  351. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartFrame.tsx +0 -54
  352. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartLegend.tsx +0 -96
  353. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartRenderer.tsx +0 -1647
  354. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartTooltip.tsx +0 -245
  355. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-app-helpers.tsx +0 -462
  356. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-capabilities.ts +0 -107
  357. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-compatibility.ts +0 -164
  358. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-contract.ts +0 -192
  359. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-theme.ts +0 -203
  360. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-tokens.css +0 -619
  361. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-transforms.ts +0 -402
  362. package/template/.codex/skills/data-analytics/src/analytics-app/fonts/SystemSansVariableVF.woff2 +0 -0
  363. package/template/.codex/skills/data-analytics/src/analytics-app/imageExport.ts +0 -370
  364. package/template/.codex/skills/data-analytics/src/analytics-app/layout/AnalyticsLayoutCanvas.tsx +0 -536
  365. package/template/.codex/skills/data-analytics/src/analytics-app/layout/RichMarkdown.tsx +0 -681
  366. package/template/.codex/skills/data-analytics/src/analytics-app/layout/analyticsLayoutCore.ts +0 -164
  367. package/template/.codex/skills/data-analytics/src/analytics-app/main.tsx +0 -21
  368. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/chart_contract.py +0 -472
  369. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/check_analytics_app_runtime_links.py +0 -75
  370. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/design_contract.py +0 -142
  371. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/package_utils.py +0 -142
  372. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/tests/test_package_utils.py +0 -377
  373. package/template/.codex/skills/data-analytics/src/analytics-app/styles.css +0 -3468
  374. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.d.ts +0 -44
  375. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.jsx +0 -639
  376. package/template/.codex/skills/data-analytics/src/analytics-app/tables/data-table.css +0 -327
  377. package/template/.codex/skills/data-analytics/src/analytics-app/tokens.css +0 -225
  378. package/template/.codex/skills/data-analytics/src/analytics-app/types.ts +0 -204
  379. package/template/.codex/skills/data-analytics/src/analytics-app-core.md +0 -85
  380. package/template/.codex/skills/data-analytics/src/codex-style-contract.md +0 -30
  381. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.html +0 -12
  382. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.jsx +0 -1008
  383. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.css +0 -2117
  384. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.html +0 -122
  385. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.js +0 -3588
  386. package/template/.codex/skills/data-analytics/src/datascience-table-widget.css +0 -483
  387. package/template/.codex/skills/data-analytics/src/datascience-table-widget.html +0 -32
  388. package/template/.codex/skills/data-analytics/src/datascience-table-widget.js +0 -333
  389. package/template/.codex/skills/data-analytics/src/mcp-host.js +0 -153
  390. package/template/.codex/skills/data-analytics/src/recharts-config.js +0 -315
  391. package/template/.codex/skills/data-analytics/src/recharts-renderer.jsx +0 -294
  392. package/template/.codex/skills/data-analytics/src/sql-source-view.css +0 -33
  393. package/template/.codex/skills/data-analytics/src/sql-source-view.js +0 -157
  394. package/template/.codex/skills/data-analytics/src/styles/codex-theme.css +0 -121
  395. package/template/.codex/skills/data-analytics/src/table-renderer.jsx +0 -28
  396. package/template/.codex/skills/data-analytics/tests/chart-transforms.test.mjs +0 -87
  397. package/template/.codex/skills/data-analytics/tests/funnel-smoke.html +0 -105
  398. package/template/.codex/skills/data-analytics/tests/inline-widget-compare.html +0 -233
  399. package/template/.codex/skills/data-analytics/tests/mcp-server.test.mjs +0 -1500
  400. package/template/.codex/skills/data-analytics/tests/native-style-contract.test.mjs +0 -219
  401. package/template/.codex/skills/data-analytics/tests/recharts-config.test.mjs +0 -144
  402. package/template/.codex/skills/data-analytics/tests/recharts-renderer.test.mjs +0 -11
  403. package/template/.codex/skills/data-analytics/tests/rich-markdown.test.mjs +0 -54
  404. package/template/.codex/skills/data-analytics/tests/widget-render-harness.html +0 -321
  405. package/template/.codex/skills/data-analytics/tsconfig.json +0 -19
  406. package/template/.codex/skills/data-analytics/vite.config.ts +0 -46
  407. package/template/.codex/skills/grill-with-docs/SKILL.md +0 -20
  408. package/template/.codex/skills/grill-with-docs/agents/openai.yaml +0 -5
  409. package/template/.codex/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  410. package/template/.codex/skills/prototype/UI.md +0 -112
  411. package/template/.codex/skills/setup-matt-pocock-skills/domain.md +0 -37
  412. package/template/.codex/skills/to-questionnaire/SKILL.md +0 -55
  413. package/template/.codex/skills/to-questionnaire/agents/openai.yaml +0 -5
  414. package/template/.codex/skills/wait-what/SKILL.md +0 -7
  415. package/template/.codex/skills/wait-what/agents/openai.yaml +0 -5
  416. package/template/.cursor/skills/grill-with-docs/SKILL.md +0 -20
  417. package/template/.cursor/skills/grill-with-docs/agents/openai.yaml +0 -5
  418. package/template/.cursor/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  419. package/template/.cursor/skills/prototype/UI.md +0 -112
  420. package/template/.cursor/skills/setup-matt-pocock-skills/domain.md +0 -37
  421. package/template/.cursor/skills/to-questionnaire/SKILL.md +0 -55
  422. package/template/.cursor/skills/to-questionnaire/agents/openai.yaml +0 -5
  423. package/template/.cursor/skills/wait-what/SKILL.md +0 -7
  424. package/template/.cursor/skills/wait-what/agents/openai.yaml +0 -5
  425. package/template/.pi/skills/grill-with-docs/SKILL.md +0 -20
  426. package/template/.pi/skills/grill-with-docs/agents/openai.yaml +0 -5
  427. package/template/.pi/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  428. package/template/.pi/skills/prototype/UI.md +0 -112
  429. package/template/.pi/skills/setup-matt-pocock-skills/domain.md +0 -37
  430. package/template/.pi/skills/to-questionnaire/SKILL.md +0 -55
  431. package/template/.pi/skills/to-questionnaire/agents/openai.yaml +0 -5
  432. package/template/.pi/skills/wait-what/SKILL.md +0 -7
  433. package/template/.pi/skills/wait-what/agents/openai.yaml +0 -5
  434. package/template/.template-spec/agents/domain.md +0 -31
  435. /package/template/.agents/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  436. /package/template/.codex/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  437. /package/template/.cursor/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  438. /package/template/.pi/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
@@ -1,978 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import importlib.util
4
- import json
5
- import shutil
6
- import subprocess
7
- import sys
8
- import tempfile
9
- import unittest
10
- from pathlib import Path
11
-
12
- SKILL_ROOT = Path(__file__).resolve().parents[1]
13
- SCRIPT_DIR = SKILL_ROOT / "scripts"
14
- PLUGIN_ROOT = SKILL_ROOT.parents[1]
15
- ONBOARDING_REFERENCE = SKILL_ROOT / "references/onboarding.md"
16
- SOURCE_RUNTIME_REFERENCE = SKILL_ROOT / "references/source-category-runtime.md"
17
- AUTOMATION_REFERENCE = SKILL_ROOT / "references/automation.md"
18
- SOURCE_CATEGORY_CONFIG = SKILL_ROOT / "plugin-author-config/source-category-config.json"
19
- APP_MANIFEST = PLUGIN_ROOT / ".app.json"
20
- SEMANTIC_LAYER_SETUP_REFERENCE = SKILL_ROOT / "references/semantic-layer/setup.md"
21
- SEMANTIC_LAYER_SOURCE_INTAKE_REFERENCE = SKILL_ROOT / "references/semantic-layer/source-intake.md"
22
- SEMANTIC_LAYER_SKILL_TEMPLATE_REFERENCE = SKILL_ROOT / "references/semantic-layer/skill-template.md"
23
- SEMANTIC_LAYER_WEEKLY_POLLING_REFERENCE = (
24
- SKILL_ROOT / "references/semantic-layer/weekly-polling-automation.md"
25
- )
26
- HERO_SKILLS = (
27
- PLUGIN_ROOT / "skills/metric-diagnostics/SKILL.md",
28
- PLUGIN_ROOT / "skills/product-business-analysis/SKILL.md",
29
- PLUGIN_ROOT / "skills/kpi-reporting/SKILL.md",
30
- )
31
- PREFLIGHT_SPEC = importlib.util.spec_from_file_location(
32
- "data_analytics_preflight",
33
- SCRIPT_DIR / "data_analytics_preflight.py",
34
- )
35
- assert PREFLIGHT_SPEC and PREFLIGHT_SPEC.loader
36
- PREFLIGHT_MODULE = importlib.util.module_from_spec(PREFLIGHT_SPEC)
37
- PREFLIGHT_SPEC.loader.exec_module(PREFLIGHT_MODULE)
38
-
39
- # Representative host_available_plugin_catalog fixture for plugin-first routing.
40
- LIVE_INSTALLABLE_PLUGIN_CANDIDATES = [
41
- {
42
- "id": "databricks@openai-curated",
43
- "name": "databricks",
44
- "tool_type": "plugin",
45
- "has_skills": True,
46
- "app_connector_ids": ["templated_apps_Databricks"],
47
- },
48
- {
49
- "id": "bigquery@openai-curated",
50
- "name": "bigquery",
51
- "tool_type": "plugin",
52
- "has_skills": True,
53
- "app_connector_ids": ["connector_7c3f2c8cdbf64bb0b183ff52f527a06e"],
54
- },
55
- {
56
- "id": "snowflake@openai-curated",
57
- "name": "snowflake",
58
- "tool_type": "plugin",
59
- "has_skills": True,
60
- "app_connector_ids": ["templated_apps_Snowflake"],
61
- },
62
- {
63
- "id": "outlook-calendar@openai-curated",
64
- "name": "outlook-calendar",
65
- "tool_type": "plugin",
66
- "has_skills": True,
67
- "app_connector_ids": ["connector_e6a7394682e24467ac68c60696f275a4"],
68
- },
69
- {
70
- "id": "outlook-email@openai-curated",
71
- "name": "outlook-email",
72
- "tool_type": "plugin",
73
- "has_skills": True,
74
- "app_connector_ids": ["connector_4aaab2856305417b993eca9a216aaf6e"],
75
- },
76
- {
77
- "id": "sharepoint@openai-curated",
78
- "name": "sharepoint",
79
- "tool_type": "plugin",
80
- "has_skills": True,
81
- "app_connector_ids": ["connector_1e4f6a44acf14e3ca1d96672f8c945bc"],
82
- },
83
- {
84
- "id": "slack@openai-curated",
85
- "name": "slack",
86
- "tool_type": "plugin",
87
- "has_skills": True,
88
- "app_connector_ids": ["REPLACE_WITH_SLACK_APP_OR_CONNECTOR_ID"],
89
- },
90
- {
91
- "id": "teams@openai-curated",
92
- "name": "teams",
93
- "tool_type": "plugin",
94
- "has_skills": True,
95
- "app_connector_ids": ["connector_246af0940da3457da0e751171dc1ce60"],
96
- },
97
- {
98
- "id": "thoughtspot@openai-curated",
99
- "name": "thoughtspot",
100
- "tool_type": "plugin",
101
- "has_skills": True,
102
- "app_connector_ids": ["REPLACE_WITH_THOUGHTSPOT_APP_OR_CONNECTOR_ID"],
103
- },
104
- {
105
- "id": "omni-analytics@openai-curated",
106
- "name": "omni-analytics",
107
- "tool_type": "plugin",
108
- "has_skills": True,
109
- "app_connector_ids": ["REPLACE_WITH_OMNI_ANALYTICS_APP_OR_CONNECTOR_ID"],
110
- },
111
- {
112
- "id": "metabase@openai-curated",
113
- "name": "metabase",
114
- "tool_type": "plugin",
115
- "has_skills": True,
116
- "app_connector_ids": ["templated_apps_Metabase"],
117
- },
118
- {
119
- "id": "amplitude@openai-curated",
120
- "name": "amplitude",
121
- "tool_type": "plugin",
122
- "has_skills": True,
123
- "app_connector_ids": ["REPLACE_WITH_AMPLITUDE_APP_OR_CONNECTOR_ID"],
124
- },
125
- {
126
- "id": "mixpanel@openai-curated",
127
- "name": "mixpanel",
128
- "tool_type": "plugin",
129
- "has_skills": True,
130
- "app_connector_ids": ["REPLACE_WITH_MIXPANEL_APP_OR_CONNECTOR_ID"],
131
- },
132
- {
133
- "id": "hex@openai-curated",
134
- "name": "hex",
135
- "tool_type": "plugin",
136
- "has_skills": True,
137
- "app_connector_ids": ["REPLACE_WITH_HEX_APP_OR_CONNECTOR_ID"],
138
- },
139
- {
140
- "id": "deepnote@openai-curated",
141
- "name": "deepnote",
142
- "tool_type": "plugin",
143
- "has_skills": True,
144
- "app_connector_ids": ["REPLACE_WITH_DEEPNOTE_APP_OR_CONNECTOR_ID"],
145
- },
146
- ]
147
- SESSION_ENABLED_PLUGIN_CANDIDATES = [
148
- {"id": "github@openai-curated", "name": "github", "tool_type": "plugin"},
149
- {"id": "gmail@openai-curated", "name": "gmail", "tool_type": "plugin"},
150
- {"id": "google-calendar@openai-curated", "name": "google-calendar", "tool_type": "plugin"},
151
- {"id": "google-drive@openai-curated", "name": "google-drive", "tool_type": "plugin"},
152
- {"id": "notion@openai-curated", "name": "notion", "tool_type": "plugin"},
153
- ]
154
-
155
-
156
- class DataAnalyticsStateHelperTests(unittest.TestCase):
157
- def setUp(self) -> None:
158
- self._tmp = tempfile.TemporaryDirectory(
159
- prefix="data-analytics-user-context-tests-",
160
- dir="/private/tmp",
161
- )
162
- self.tmp_path = Path(self._tmp.name)
163
- self.state_dir = self.tmp_path / "state"
164
- self.maxDiff = None
165
-
166
- def tearDown(self) -> None:
167
- self._tmp.cleanup()
168
-
169
- def run_json(self, args: list[str], *, expect: int = 0) -> dict:
170
- proc = subprocess.run(args, text=True, capture_output=True)
171
- self.assertEqual(
172
- proc.returncode,
173
- expect,
174
- msg=f"command failed: {' '.join(args)}\nSTDOUT:\n{proc.stdout}\nSTDERR:\n{proc.stderr}",
175
- )
176
- return json.loads(proc.stdout)
177
-
178
- def preflight(self, *extra: str, state_dir: Path | None = None) -> dict:
179
- return self.run_json(
180
- [
181
- sys.executable,
182
- str(SCRIPT_DIR / "data_analytics_preflight.py"),
183
- "--workflow",
184
- "metric-diagnostics",
185
- "--state-dir",
186
- str(state_dir or self.state_dir),
187
- *extra,
188
- ]
189
- )
190
-
191
- def write_state(
192
- self,
193
- *,
194
- user_context: str | None = None,
195
- onboarding_state: dict | None = None,
196
- state_dir: Path | None = None,
197
- ) -> Path:
198
- target = state_dir or self.state_dir
199
- target.mkdir(parents=True, exist_ok=True)
200
- if user_context is not None:
201
- (target / "user-context.md").write_text(user_context, encoding="utf-8")
202
- if onboarding_state is not None:
203
- (target / "onboarding-state.json").write_text(
204
- json.dumps(onboarding_state),
205
- encoding="utf-8",
206
- )
207
- return target
208
-
209
- def active_core_categories(self) -> dict[str, dict[str, str]]:
210
- return {
211
- "structured_data": {"status": "active", "preferred": "Databricks"},
212
- "team_communication": {"status": "active", "preferred": "Slack"},
213
- "company_docs": {"status": "active", "preferred": "Google Drive"},
214
- }
215
-
216
- def source_category_config(self) -> dict:
217
- return json.loads(SOURCE_CATEGORY_CONFIG.read_text(encoding="utf-8"))["categories"]
218
-
219
- def test_missing_preflight_returns_setup_obligation_context_gap_and_empty_hero_prompt(
220
- self,
221
- ) -> None:
222
- payload = self.preflight(state_dir=self.tmp_path / "missing")
223
- self.assertTrue(payload["read_only"])
224
- self.assertEqual(payload["state"]["user_context_status"], "missing")
225
- self.assertEqual(payload["state"]["onboarding_state_status"], "missing")
226
- self.assertTrue(payload["current_skill_experience"]["intro_eligible"])
227
- obligation = payload["control"]["final_obligations"][0]
228
- self.assertEqual(obligation["id"], "offer_data_analytics_onboarding_next_step")
229
- self.assertIn("## Data Analytics Setup Required", obligation["template"])
230
- self.assertEqual(payload["control"]["conditional_guidance"][0]["id"], "context_gap_note")
231
- self.assertEqual(payload["context"]["hero_prompt_candidates"], [])
232
- self.assertIsNone(payload["context"]["primary_hero_prompt"])
233
- self.assertEqual(
234
- payload["context"]["connector_setup_summary"]["needs_attention"][0]["status"],
235
- "needs_confirmation",
236
- )
237
-
238
- def test_direct_and_guided_modes_suppress_ordinary_setup_obligation(self) -> None:
239
- direct_payload = self.preflight("--request-mode", "direct_onboarding_status")
240
- guided_payload = self.preflight("--request-mode", "guided_onboarding_workflow")
241
- self.assertEqual(direct_payload["control"]["final_obligations"], [])
242
- self.assertEqual(guided_payload["control"]["final_obligations"], [])
243
- self.assertEqual(direct_payload["control"]["conditional_guidance"], [])
244
- self.assertEqual(guided_payload["control"]["conditional_guidance"], [])
245
- self.assertEqual(guided_payload["current_skill_experience"]["cta_owner"], "onboarding")
246
-
247
- def test_legacy_verified_connector_status_maps_to_active_try_on_use(self) -> None:
248
- self.assertEqual(
249
- PREFLIGHT_MODULE.source_status({"status": "connected"}),
250
- "active",
251
- )
252
- self.assertEqual(PREFLIGHT_MODULE.source_status({"status": "manual"}), "active")
253
- self.assertEqual(
254
- PREFLIGHT_MODULE.source_status({"status": "selected_needs_auth"}),
255
- "needs_confirmation",
256
- )
257
- self.assertEqual(PREFLIGHT_MODULE.source_status({"status": "choose_source"}), "needs_confirmation")
258
-
259
- def test_configured_plugin_routes_are_manifest_backed_and_add_google_calendar(
260
- self,
261
- ) -> None:
262
- categories = self.source_category_config()
263
- self.assertEqual(categories["team_communication"]["preferred_plugins"], ["Slack", "Teams"])
264
- self.assertEqual(
265
- categories["company_docs"]["preferred_plugins"],
266
- ["Google Drive", "SharePoint", "Notion"],
267
- )
268
- self.assertEqual(
269
- categories["email_context"]["preferred_plugins"],
270
- ["Gmail", "Outlook Email"],
271
- )
272
- self.assertEqual(
273
- categories["calendar_context"]["preferred_plugins"],
274
- ["Google Calendar", "Outlook Calendar"],
275
- )
276
- self.assertNotIn("preferred_apps", categories["calendar_context"])
277
- self.assertEqual(categories["code_repository"]["preferred_plugins"], ["GitHub"])
278
- app_manifest = json.loads(APP_MANIFEST.read_text(encoding="utf-8"))
279
- self.assertEqual(
280
- app_manifest["apps"]["google_calendar"]["id"],
281
- "connector_947e0d954944416db111db556030eea6",
282
- )
283
- self.assertEqual(
284
- PREFLIGHT_MODULE.load_app_connector_ids()["googlecalendar"],
285
- "connector_947e0d954944416db111db556030eea6",
286
- )
287
-
288
- def test_live_install_listing_fixture_matches_every_installable_data_analytics_plugin(
289
- self,
290
- ) -> None:
291
- matches = PREFLIGHT_MODULE.match_installable_plugin_candidates(
292
- self.source_category_config(),
293
- {"tools": LIVE_INSTALLABLE_PLUGIN_CANDIDATES},
294
- )
295
- self.assertEqual(
296
- {
297
- category_id: [entry["preferred_plugin"] for entry in entries]
298
- for category_id, entries in matches.items()
299
- },
300
- {
301
- "structured_data": ["Databricks", "BigQuery", "Snowflake"],
302
- "team_communication": ["Slack", "Teams"],
303
- "company_docs": ["SharePoint"],
304
- "dashboards_bi": ["ThoughtSpot", "Omni Analytics", "Metabase"],
305
- "behavior_signals": ["Amplitude", "Mixpanel"],
306
- "notebook_lab": ["Hex", "Deepnote"],
307
- "email_context": ["Outlook Email"],
308
- "calendar_context": ["Outlook Calendar"],
309
- },
310
- )
311
-
312
- def test_configured_plugins_match_installable_or_enabled_plugin_surfaces(self) -> None:
313
- categories = self.source_category_config()
314
- matches = PREFLIGHT_MODULE.match_installable_plugin_candidates(
315
- categories,
316
- [*LIVE_INSTALLABLE_PLUGIN_CANDIDATES, *SESSION_ENABLED_PLUGIN_CANDIDATES],
317
- )
318
- self.assertEqual(
319
- {
320
- category_id: [entry["preferred_plugin"] for entry in entries]
321
- for category_id, entries in matches.items()
322
- },
323
- {
324
- category_id: metadata["preferred_plugins"]
325
- for category_id, metadata in categories.items()
326
- if metadata.get("preferred_plugins")
327
- },
328
- )
329
-
330
- def test_plugin_candidate_matching_uses_connector_id_when_slug_changes(self) -> None:
331
- matches = PREFLIGHT_MODULE.match_installable_plugin_candidates(
332
- self.source_category_config(),
333
- [
334
- {
335
- "id": "renamed-plugin@openai-curated",
336
- "name": "renamed-plugin",
337
- "tool_type": "plugin",
338
- "app_connector_ids": ["REPLACE_WITH_SLACK_APP_OR_CONNECTOR_ID"],
339
- }
340
- ],
341
- )
342
- slack_match = matches["team_communication"][0]
343
- self.assertEqual(slack_match["preferred_plugin"], "Slack")
344
- self.assertEqual(slack_match["match_reasons"], ["app_connector_id"])
345
-
346
- def test_plugin_candidate_matching_ignores_description_only_category_similarity(self) -> None:
347
- matches = PREFLIGHT_MODULE.match_installable_plugin_candidates(
348
- self.source_category_config(),
349
- [
350
- {
351
- "id": "broad-search@openai-curated",
352
- "name": "broad-search",
353
- "display_name": "Broad Search",
354
- "description": "Indexes Slack and Teams for team communication.",
355
- "tool_type": "plugin",
356
- "has_skills": True,
357
- }
358
- ],
359
- )
360
- self.assertNotIn("team_communication", matches)
361
-
362
- def test_preflight_exposes_plugin_setup_before_connector_fallback(self) -> None:
363
- payload = self.preflight(state_dir=self.tmp_path / "missing")
364
- confirmation = payload["context"]["connector_confirmation"]
365
- slack = confirmation["team_communication"]
366
- self.assertEqual(slack["setup_action"], "run_plugin_first_source_setup")
367
- self.assertEqual(
368
- slack["fallback_setup_action"],
369
- "ask_user_to_choose_or_confirm_source",
370
- )
371
- self.assertEqual(slack["plugin_preference_order"], ["Slack", "Teams"])
372
- self.assertEqual(
373
- slack["setup_recovery"]["candidate_lookup"],
374
- "host_available_plugin_catalog",
375
- )
376
- self.assertEqual(
377
- slack["setup_recovery"]["install_request"],
378
- "host_authorized_plugin_install",
379
- )
380
- calendar = confirmation["calendar_context"]
381
- self.assertEqual(
382
- calendar["plugin_preference_order"],
383
- ["Google Calendar", "Outlook Calendar"],
384
- )
385
- self.assertIn(
386
- "team_communication",
387
- {
388
- entry["id"]
389
- for entry in payload["context"]["connector_setup_summary"][
390
- "plugin_setup_opportunities"
391
- ]
392
- },
393
- )
394
-
395
- def test_preflight_keeps_onboarding_state_provenance_without_raw_state_echo(self) -> None:
396
- self.write_state(onboarding_state={"status": "active", "connector_confirmation": {}})
397
- payload = self.preflight()
398
- onboarding_state = payload["files"]["onboarding_state"]
399
- self.assertEqual(onboarding_state["status"], "present")
400
- self.assertFalse(onboarding_state["omitted"])
401
- self.assertNotIn("content", onboarding_state)
402
- self.assertNotIn("data", onboarding_state)
403
- self.assertNotIn(
404
- "setup_recovery",
405
- payload["context"]["connector_setup_summary"]["needs_attention"][0],
406
- )
407
- self.assertIn(
408
- "setup_recovery",
409
- payload["context"]["connector_confirmation"]["structured_data"],
410
- )
411
-
412
- def test_connector_inventory_classifies_routes_without_eager_reads(self) -> None:
413
- self.write_state(
414
- onboarding_state={
415
- "status": "active",
416
- "connector_inventory": {
417
- "active_apps": ["Slack"],
418
- "available_apps": ["Databricks"],
419
- },
420
- }
421
- )
422
- payload = self.preflight("--request-mode", "direct_onboarding_status")
423
- confirmation = payload["context"]["connector_confirmation"]
424
-
425
- self.assertEqual(confirmation["structured_data"]["status"], "needs_confirmation")
426
- self.assertEqual(confirmation["structured_data"]["candidates"], ["Databricks"])
427
- self.assertEqual(confirmation["team_communication"]["status"], "needs_confirmation")
428
- self.assertEqual(confirmation["team_communication"]["candidates"], ["Slack"])
429
- self.assertEqual(confirmation["company_docs"]["status"], "missing")
430
- self.assertFalse(confirmation["structured_data"]["eager_read"])
431
- self.assertEqual(
432
- confirmation["structured_data"]["workflow_time_behavior"],
433
- "attempt_actual_reads_only_when_a_workflow_needs_the_source",
434
- )
435
-
436
- def test_helper_skills_apply_to_app_fallback_but_not_active_plugin_routes(self) -> None:
437
- source_config = {
438
- "team_communication": {
439
- "label": "Team communication",
440
- "preferred_plugins": ["slack"],
441
- "preferred_apps": ["Slack"],
442
- "relevant_skills": [{"app": "Slack", "skill": "slack-helper"}],
443
- }
444
- }
445
- connector_fallback = PREFLIGHT_MODULE.normalized_connector_confirmation(
446
- source_config,
447
- {
448
- "connector_confirmation": {
449
- "categories": {
450
- "team_communication": {
451
- "status": "active",
452
- "preferred": "Slack",
453
- "source_kind": "connector",
454
- }
455
- }
456
- }
457
- },
458
- )["team_communication"]
459
- self.assertEqual(connector_fallback["setup_action"], "run_plugin_first_source_setup")
460
- self.assertEqual(connector_fallback["fallback_setup_action"], "none_try_on_use")
461
- self.assertEqual(connector_fallback["helper_skills_apply_when"], ["app", "connector"])
462
-
463
- plugin_route = PREFLIGHT_MODULE.normalized_connector_confirmation(
464
- source_config,
465
- {
466
- "connector_confirmation": {
467
- "categories": {
468
- "team_communication": {
469
- "status": "active",
470
- "preferred": "slack",
471
- "source_kind": "plugin",
472
- "plugin_install_evidence": "plugin_in_available_plugins",
473
- "skill_surface_evidence": "plugin_skills_visible",
474
- }
475
- }
476
- }
477
- },
478
- )["team_communication"]
479
- self.assertEqual(plugin_route["setup_action"], "none_try_on_use")
480
- self.assertNotIn("fallback_setup_action", plugin_route)
481
- self.assertNotIn("setup_recovery", plugin_route)
482
- self.assertNotIn("helper_skills", plugin_route)
483
-
484
- def test_validator_rejects_preferred_plugin_without_manifest_dependency(self) -> None:
485
- plugin_copy = self.tmp_path / "data-analytics"
486
- shutil.copytree(PLUGIN_ROOT, plugin_copy)
487
- config_path = plugin_copy / "skills/user-context/plugin-author-config/source-category-config.json"
488
- config = json.loads(config_path.read_text(encoding="utf-8"))
489
- config["categories"]["calendar_context"]["preferred_plugins"].append("missing-calendar")
490
- config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
491
- proc = subprocess.run(
492
- [
493
- sys.executable,
494
- str(SCRIPT_DIR / "validate_user_context_preflight.py"),
495
- str(plugin_copy),
496
- "--plugin-id",
497
- "data-analytics",
498
- ],
499
- text=True,
500
- capture_output=True,
501
- )
502
- self.assertNotEqual(proc.returncode, 0)
503
- self.assertIn(
504
- "preferred plugin missing-calendar must be declared in .app.json",
505
- proc.stderr,
506
- )
507
-
508
- def test_validator_rejects_preferred_app_without_manifest_dependency(self) -> None:
509
- plugin_copy = self.tmp_path / "data-analytics"
510
- shutil.copytree(PLUGIN_ROOT, plugin_copy)
511
- config_path = plugin_copy / "skills/user-context/plugin-author-config/source-category-config.json"
512
- config = json.loads(config_path.read_text(encoding="utf-8"))
513
- config["categories"]["calendar_context"]["preferred_apps"] = ["Missing Calendar"]
514
- config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
515
- proc = subprocess.run(
516
- [
517
- sys.executable,
518
- str(SCRIPT_DIR / "validate_user_context_preflight.py"),
519
- str(plugin_copy),
520
- "--plugin-id",
521
- "data-analytics",
522
- ],
523
- text=True,
524
- capture_output=True,
525
- )
526
- self.assertNotEqual(proc.returncode, 0)
527
- self.assertIn(
528
- "preferred app Missing Calendar must be declared in .app.json",
529
- proc.stderr,
530
- )
531
-
532
- def test_validator_rejects_saved_context_heading_in_author_config(self) -> None:
533
- plugin_copy = self.tmp_path / "data-analytics"
534
- shutil.copytree(PLUGIN_ROOT, plugin_copy)
535
- config_path = plugin_copy / "skills/user-context/plugin-author-config/user-context-config.md"
536
- config = config_path.read_text(encoding="utf-8")
537
- config_path.write_text(
538
- config.replace(
539
- "# Semantic Layers\n\n",
540
- "# Semantic Layers\n\n## Saved Links And Context\n\n",
541
- 1,
542
- ),
543
- encoding="utf-8",
544
- )
545
- proc = subprocess.run(
546
- [
547
- sys.executable,
548
- str(SCRIPT_DIR / "validate_user_context_preflight.py"),
549
- str(plugin_copy),
550
- "--plugin-id",
551
- "data-analytics",
552
- ],
553
- text=True,
554
- capture_output=True,
555
- )
556
- self.assertNotEqual(proc.returncode, 0)
557
- self.assertIn("default user context must not contain: ## Saved Links And Context", proc.stderr)
558
-
559
- def test_selected_source_needs_confirmation_stays_unresolved_until_user_resolves_it(
560
- self,
561
- ) -> None:
562
- self.write_state(
563
- user_context="""# Data Analytics Source Routing Preferences
564
-
565
- Store durable Data Analytics source-routing choices explicitly selected for future use.
566
-
567
- ## structured_data
568
-
569
- - Prefer:
570
- - Avoid:
571
-
572
- # Semantic Layers
573
-
574
- status: not provided
575
- """,
576
- onboarding_state={
577
- "status": "active",
578
- "orientation": {"status": "shown"},
579
- "connector_confirmation": {
580
- "structured_data": {
581
- "status": "needs_confirmation",
582
- "preferred": "Databricks",
583
- },
584
- "team_communication": {"status": "active", "preferred": "Slack"},
585
- "company_docs": {"status": "active", "preferred": "Google Drive"},
586
- },
587
- },
588
- )
589
- payload = self.preflight()
590
- summary = payload["context"]["connector_setup_summary"]
591
- self.assertEqual(payload["context"]["user_context"]["semantic_layer_count"], 0)
592
- self.assertFalse(summary["core_complete"])
593
- self.assertEqual(summary["next_action"]["category_id"], "structured_data")
594
- self.assertEqual(
595
- summary["next_action"]["setup_action"],
596
- "run_plugin_first_source_setup",
597
- )
598
- self.assertEqual(summary["needs_attention"][0]["status"], "needs_confirmation")
599
- self.assertNotIn(
600
- "structured_data",
601
- {entry["id"] for entry in summary["ready"]},
602
- )
603
- self.assertEqual(
604
- payload["control"]["final_obligations"][0]["id"],
605
- "complete_data_analytics_core_onboarding",
606
- )
607
-
608
- def test_unacknowledged_deferred_core_sources_reopen_as_needs_confirmation(self) -> None:
609
- self.write_state(
610
- onboarding_state={
611
- "status": "active",
612
- "orientation": {"status": "shown"},
613
- "connector_confirmation": {
614
- "status": "completed",
615
- "structured_data": {"status": "deferred"},
616
- "team_communication": {"status": "deferred"},
617
- "company_docs": {"status": "active", "preferred": "Google Drive"},
618
- },
619
- }
620
- )
621
- payload = self.preflight("--request-mode", "direct_onboarding_status")
622
- confirmation = payload["context"]["connector_confirmation"]
623
- summary = payload["context"]["connector_setup_summary"]
624
- self.assertEqual(confirmation["structured_data"]["status"], "needs_confirmation")
625
- self.assertEqual(confirmation["structured_data"]["recorded_status"], "deferred")
626
- self.assertEqual(
627
- confirmation["structured_data"]["setup_note"],
628
- "core_source_requires_explicit_user_resolution_before_fallback",
629
- )
630
- self.assertEqual(confirmation["team_communication"]["status"], "needs_confirmation")
631
- self.assertFalse(summary["core_complete"])
632
- self.assertEqual(
633
- summary["unresolved_core_ids"],
634
- ["structured_data", "team_communication"],
635
- )
636
- self.assertEqual(
637
- [entry["id"] for entry in summary["needs_attention"][:2]],
638
- ["structured_data", "team_communication"],
639
- )
640
- self.assertEqual(summary["next_action"]["category_id"], "structured_data")
641
- self.assertEqual(
642
- payload["control"]["onboarding_progress"]["task_list"][1]["status"],
643
- "in_progress",
644
- )
645
-
646
- def test_connector_confirmation_status_without_core_categories_stays_pending(self) -> None:
647
- self.write_state(
648
- onboarding_state={
649
- "status": "active",
650
- "orientation": {"status": "shown"},
651
- "connector_confirmation": {"status": "completed"},
652
- }
653
- )
654
- payload = self.preflight("--request-mode", "direct_onboarding_status")
655
- summary = payload["context"]["connector_setup_summary"]
656
- self.assertEqual(summary["classification_status"], "pending")
657
- self.assertFalse(summary["core_complete"])
658
- self.assertEqual(
659
- payload["control"]["onboarding_progress"]["task_list"][1]["status"],
660
- "in_progress",
661
- )
662
-
663
- def test_explicit_core_source_defer_counts_as_recorded_known_gap(self) -> None:
664
- self.write_state(
665
- onboarding_state={
666
- "status": "active",
667
- "connector_confirmation": {
668
- "structured_data": {"status": "deferred", "resolution": "user_deferred"},
669
- "team_communication": {
670
- "status": "deferred",
671
- "resolution": "user_continued_with_known_gap",
672
- },
673
- "company_docs": {"status": "active", "preferred": "Google Drive"},
674
- },
675
- }
676
- )
677
- payload = self.preflight("--request-mode", "direct_onboarding_status")
678
- confirmation = payload["context"]["connector_confirmation"]
679
- summary = payload["context"]["connector_setup_summary"]
680
- self.assertEqual(confirmation["structured_data"]["status"], "deferred")
681
- self.assertEqual(confirmation["structured_data"]["resolution"], "user_deferred")
682
- self.assertTrue(summary["core_complete"])
683
- self.assertEqual(summary["unresolved_core_ids"], [])
684
- self.assertEqual(
685
- {entry["id"] for entry in summary["fallback_or_closed"]},
686
- {"structured_data", "team_communication"},
687
- )
688
-
689
- def test_core_onboarding_complete_requires_active_or_explicit_fallback_sources(self) -> None:
690
- self.write_state(
691
- onboarding_state={
692
- "status": "active",
693
- "orientation": {"status": "shown"},
694
- "connector_confirmation": {
695
- **self.active_core_categories(),
696
- },
697
- "semantic_layer_setup": {"status": "created"},
698
- "semantic_layer_refresh": {"status": "declined"},
699
- }
700
- )
701
- payload = self.preflight("--request-mode", "direct_onboarding_status")
702
- progress = payload["control"]["onboarding_progress"]
703
- task_statuses = {item["id"]: item["status"] for item in progress["task_list"]}
704
- self.assertTrue(progress["core_onboarding"]["complete"])
705
- self.assertEqual(task_statuses["source_setup_confirmation"], "completed")
706
- self.assertEqual(task_statuses["semantic_layer_setup"], "completed")
707
- self.assertEqual(task_statuses["hero_prompt"], "in_progress")
708
-
709
- def test_core_onboarding_complete_allows_semantic_layer_skip_without_refresh(self) -> None:
710
- self.write_state(
711
- onboarding_state={
712
- "status": "active",
713
- "orientation": {"status": "shown"},
714
- "connector_confirmation": {
715
- "status": "completed",
716
- **self.active_core_categories(),
717
- },
718
- "semantic_layer_setup": {"status": "skipped"},
719
- }
720
- )
721
- payload = self.preflight("--request-mode", "direct_onboarding_status")
722
- progress = payload["control"]["onboarding_progress"]
723
- task_statuses = {item["id"]: item["status"] for item in progress["task_list"]}
724
- self.assertTrue(progress["core_onboarding"]["complete"])
725
- self.assertEqual(task_statuses["semantic_layer_setup"], "completed")
726
- self.assertEqual(task_statuses["hero_prompt"], "in_progress")
727
-
728
- def test_active_core_incomplete_returns_single_reminder_with_next_action(self) -> None:
729
- self.write_state(
730
- user_context="""# Data Analytics Source Routing Preferences
731
-
732
- Store durable Data Analytics source-routing choices explicitly selected for future use.
733
-
734
- ## structured_data
735
-
736
- - Prefer:
737
- - Avoid:
738
-
739
- # Semantic Layers
740
-
741
- status: not provided
742
- """,
743
- onboarding_state={"status": "active", "orientation": {"status": "shown"}},
744
- )
745
- payload = self.preflight()
746
- obligation = payload["control"]["final_obligations"][0]
747
- self.assertEqual(obligation["id"], "complete_data_analytics_core_onboarding")
748
- self.assertEqual(obligation["next_action"]["id"], "confirm_analytics_sources")
749
- self.assertIn("**Next Step**", obligation["template"])
750
- self.assertIn("Reply `continue onboarding`", obligation["template"])
751
- self.assertEqual(len(payload["control"]["final_obligations"]), 1)
752
-
753
- def test_complete_and_quiet_onboarding_suppress_auto_obligations(self) -> None:
754
- for status in ("complete", "quiet"):
755
- with self.subTest(status=status):
756
- state_dir = self.tmp_path / status
757
- self.write_state(onboarding_state={"status": status}, state_dir=state_dir)
758
- payload = self.preflight(state_dir=state_dir)
759
- self.assertEqual(payload["control"]["final_obligations"], [])
760
-
761
- def test_semantic_layer_registry_and_hero_prompt_candidates_come_from_context(
762
- self,
763
- ) -> None:
764
- self.write_state(
765
- user_context="""# Data Analytics Source Routing Preferences
766
-
767
- Store durable Data Analytics source-routing choices explicitly selected for future use.
768
-
769
- ## structured_data
770
-
771
- - Prefer: Databricks
772
- - Avoid: Snowflake
773
-
774
- # Semantic Layers
775
-
776
- - Area: API
777
- - Skill Name: api-semantic-layer
778
- - Skill Path: /tmp/api-semantic-layer
779
- - Source Inventory Path: /tmp/api-semantic-layer/references/source-inventory.md
780
- - Last Updated: 2026-05-29
781
- """,
782
- onboarding_state={"status": "active", "semantic_layer_setup": {"area": "API"}},
783
- )
784
- payload = self.preflight()
785
- self.assertNotIn("user_context_markdown", payload["context"])
786
- self.assertNotIn("content", payload["files"]["user_context"])
787
- self.assertTrue(payload["context"]["user_context"]["normalization_complete"])
788
- self.assertEqual(payload["context"]["semantic_layers"][0]["area"], "API")
789
- self.assertEqual(payload["context"]["source_preferences"]["structured_data"], {
790
- "preferred": ["Databricks"],
791
- "avoid": ["Snowflake"],
792
- })
793
- self.assertEqual(len(payload["context"]["hero_prompt_candidates"]), 1)
794
- self.assertEqual(payload["context"]["primary_hero_prompt"]["skill"], "product-business-analysis")
795
- self.assertEqual(
796
- payload["context"]["primary_hero_prompt"]["label"],
797
- "Build a decision-ready report",
798
- )
799
- self.assertEqual(
800
- payload["context"]["primary_hero_prompt"]["prompt"],
801
- (
802
- "Build a decision-ready report for API: explain what is happening, "
803
- "identify the main drivers, recommend where the team should focus next, "
804
- "and include sources, caveats, and useful charts."
805
- ),
806
- )
807
- self.assertEqual(payload["context"]["extra_hero_prompt_candidates"], [])
808
-
809
- def test_large_user_context_renders_source_preferences_and_requested_section(self) -> None:
810
- self.write_state(
811
- user_context="""# Data Analytics Source Routing Preferences
812
-
813
- Store durable Data Analytics source-routing choices explicitly selected for future use.
814
-
815
- ## structured_data
816
-
817
- - Prefer: Databricks
818
- - Avoid: Snowflake
819
-
820
- ## company_docs
821
-
822
- - Prefer: Google Drive
823
- - Avoid:
824
-
825
- # Semantic Layers
826
-
827
- """ + ("x" * 2048),
828
- )
829
- payload = self.preflight(
830
- "--max-context-bytes",
831
- "80",
832
- "--section",
833
- "Data Analytics Source Routing Preferences",
834
- )
835
- self.assertNotIn("user_context_markdown", payload["context"])
836
- self.assertNotIn("content", payload["files"]["user_context"])
837
- self.assertTrue(payload["files"]["user_context"]["omitted"])
838
- self.assertEqual(payload["files"]["user_context"]["sections"][0]["status"], "present")
839
- self.assertTrue(payload["context"]["user_context"]["normalization_complete"])
840
- self.assertEqual(
841
- payload["context"]["source_preferences"],
842
- {
843
- "structured_data": {
844
- "preferred": ["Databricks"],
845
- "avoid": ["Snowflake"],
846
- },
847
- "company_docs": {"preferred": ["Google Drive"]},
848
- },
849
- )
850
- self.assertEqual(
851
- payload["context"]["user_context"]["source_routing_preferences"],
852
- payload["context"]["source_preferences"],
853
- )
854
-
855
- def test_reset_moves_active_state_files(self) -> None:
856
- self.state_dir.mkdir(parents=True)
857
- user_context_path = self.state_dir / "user-context.md"
858
- onboarding_state_path = self.state_dir / "onboarding-state.json"
859
- user_context_path.write_text("# Context\n", encoding="utf-8")
860
- onboarding_state_path.write_text(json.dumps({"status": "active"}), encoding="utf-8")
861
- backup_dir = self.tmp_path / "backup"
862
- proc = subprocess.run(
863
- [
864
- sys.executable,
865
- str(SCRIPT_DIR / "reset_user_context_state.py"),
866
- "--state-dir",
867
- str(self.state_dir),
868
- "--backup-dir",
869
- str(backup_dir),
870
- ],
871
- text=True,
872
- capture_output=True,
873
- )
874
- self.assertEqual(proc.returncode, 0, msg=proc.stderr)
875
- self.assertFalse(user_context_path.exists())
876
- self.assertFalse(onboarding_state_path.exists())
877
- self.assertTrue((backup_dir / "user-context.md").exists())
878
- self.assertTrue((backup_dir / "onboarding-state.json").exists())
879
-
880
- def test_initializer_creates_user_context_and_onboarding_state(self) -> None:
881
- proc = subprocess.run(
882
- [
883
- sys.executable,
884
- str(SCRIPT_DIR / "init_user_context_state.py"),
885
- "--state-dir",
886
- str(self.state_dir),
887
- ],
888
- text=True,
889
- capture_output=True,
890
- )
891
- self.assertEqual(proc.returncode, 0, msg=proc.stderr)
892
- user_context = (self.state_dir / "user-context.md").read_text(encoding="utf-8")
893
- self.assertNotIn("# Data Analytics User Context Config", user_context)
894
- self.assertNotIn("- Priority:", user_context)
895
- self.assertNotIn("- Use When:", user_context)
896
- self.assertIn(
897
- "Store durable Data Analytics source-routing choices explicitly selected for future use.",
898
- user_context,
899
- )
900
- self.assertEqual(user_context.count("## "), 9)
901
- self.assertEqual(user_context.count("- Prefer:"), 9)
902
- self.assertEqual(user_context.count("- Avoid:"), 9)
903
- self.assertEqual(user_context.count("status: not provided"), 1)
904
- onboarding_state = json.loads((self.state_dir / "onboarding-state.json").read_text())
905
- self.assertEqual(onboarding_state["status"], "active")
906
- self.assertNotIn("connector_inventory", onboarding_state)
907
- self.assertNotIn("seed_sources", onboarding_state["semantic_layer_setup"])
908
- self.assertEqual(onboarding_state["semantic_layer_setup"]["seed_source_count"], 0)
909
- self.assertIn("hero_prompt_choice", onboarding_state)
910
- self.assertIn("skill_experience", onboarding_state)
911
-
912
- def test_onboarding_contract_mentions_active_sources_and_one_first_hero_prompt(
913
- self,
914
- ) -> None:
915
- onboarding_text = ONBOARDING_REFERENCE.read_text(encoding="utf-8")
916
- source_runtime_text = SOURCE_RUNTIME_REFERENCE.read_text(encoding="utf-8")
917
- automation_text = AUTOMATION_REFERENCE.read_text(encoding="utf-8")
918
- self.assertIn("Check Main Analytics Sources", onboarding_text)
919
- self.assertIn("Resolve Source Questions", onboarding_text)
920
- self.assertIn("transition without a proof read", onboarding_text)
921
- self.assertIn("Set Up Data Context", onboarding_text)
922
- self.assertIn("Codex gets better at data work", onboarding_text)
923
- self.assertIn("Send anything you would point a new analyst to", onboarding_text)
924
- self.assertIn("Reply with any starting points, or say `skip for now`", onboarding_text)
925
- self.assertIn("Do not: require the user to name a product or business area up front", onboarding_text)
926
- self.assertNotIn("smallest useful seed", onboarding_text)
927
- self.assertNotIn("first semantic layer", onboarding_text)
928
- self.assertNotIn("main source categories", onboarding_text)
929
- self.assertIn("Show one strong prompt first", onboarding_text)
930
- self.assertIn("Do not: show three hero prompts initially", onboarding_text)
931
- self.assertIn("write the prompt you would rather try instead", onboarding_text)
932
- self.assertIn("`skip` to finish onboarding", onboarding_text)
933
- self.assertIn("Step 5, `complete_or_quiet`, when the user skips or defers", onboarding_text)
934
- self.assertIn("`needs_confirmation`", source_runtime_text)
935
- self.assertIn("Do not run a proof query during onboarding", source_runtime_text)
936
- self.assertIn("Do not mark setup complete", automation_text)
937
- for hero_skill in HERO_SKILLS:
938
- text = hero_skill.read_text(encoding="utf-8")
939
- self.assertIn("data-analytics:user-context", text)
940
-
941
- def test_semantic_layer_setup_uses_lightweight_generated_skills_and_source_checkpoint(
942
- self,
943
- ) -> None:
944
- setup_text = SEMANTIC_LAYER_SETUP_REFERENCE.read_text(encoding="utf-8")
945
- source_intake_text = SEMANTIC_LAYER_SOURCE_INTAKE_REFERENCE.read_text(encoding="utf-8")
946
- template_text = SEMANTIC_LAYER_SKILL_TEMPLATE_REFERENCE.read_text(encoding="utf-8")
947
- weekly_polling_text = SEMANTIC_LAYER_WEEKLY_POLLING_REFERENCE.read_text(
948
- encoding="utf-8"
949
- )
950
- self.assertIn("source-use checkpoint", setup_text)
951
- self.assertIn("rejected or lower-confidence candidates", setup_text)
952
- self.assertIn("Infer expected source lanes", setup_text)
953
- self.assertIn("nearby but not exact", setup_text)
954
- self.assertIn("authoritative data documentation", setup_text)
955
- self.assertIn("source-backed semantic-layer skills", setup_text)
956
- self.assertIn("user-trusted canonical data skills", setup_text)
957
- self.assertIn("treat that as authoritative data documentation", setup_text)
958
- self.assertIn("authoritative data documentation", weekly_polling_text)
959
- self.assertIn("source-backed semantic-layer skills", weekly_polling_text)
960
- self.assertIn("user-trusted canonical data skills", weekly_polling_text)
961
- self.assertIn("Infer useful source families", source_intake_text)
962
- self.assertIn("do not treat ambient app availability as user approval", source_intake_text)
963
- self.assertIn("Send anything you would point a new analyst to", source_intake_text)
964
- self.assertIn("Reply with any starting points, or say `skip for now`", source_intake_text)
965
- self.assertIn("## Start Here", template_text)
966
- self.assertIn("## References", template_text)
967
- self.assertIn("Answering Rules", template_text)
968
- self.assertIn("## Quick Reference", template_text)
969
- self.assertIn("## Entity Clarification", template_text)
970
- self.assertIn("## Standard Filters And Dimensions", template_text)
971
- self.assertIn("evidence.md`: detailed provenance, only when the layer needs separate evidence tracking", template_text)
972
- self.assertIn("Do not put setup-time policy or full evidence procedures", template_text)
973
- self.assertNotIn("### Source Order", template_text)
974
- self.assertNotIn("### Evidence Standard", template_text)
975
-
976
-
977
- if __name__ == "__main__":
978
- unittest.main()