fraim 2.0.362-next.4 → 2.0.362

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 (277) hide show
  1. package/dist/registry/scripts/domains/folders.js +55 -0
  2. package/dist/registry/scripts/learning/entry-authoring.js +13 -24
  3. package/dist/registry/scripts/learning/run-publication.js +5 -30
  4. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/aeo-optimization.md +43 -0
  5. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/author-ai-evals.md +33 -0
  6. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/create-ai-agent.md +33 -0
  7. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/create-hub-configured-agent.md +34 -0
  8. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/enable-web-mcp.md +33 -0
  9. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/evaluate-ai-agent.md +32 -0
  10. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/mcp-server-creation.md +35 -0
  11. package/dist/registry/stubs/jobs/ai-employee/ai-engineering/publish-mcp-app.md +28 -0
  12. package/dist/registry/stubs/jobs/ai-employee/bank-compliance/banking-evidence-audit.md +32 -0
  13. package/dist/registry/stubs/jobs/ai-employee/bank-operations/kyc-case-review.md +32 -0
  14. package/dist/registry/stubs/jobs/ai-employee/career/career-networking.md +46 -0
  15. package/dist/registry/stubs/jobs/ai-employee/career/career-spec.md +41 -0
  16. package/dist/registry/stubs/jobs/ai-employee/career/career-trajectory-planning.md +41 -0
  17. package/dist/registry/stubs/jobs/ai-employee/career/job-applications-and-networking.md +40 -0
  18. package/dist/registry/stubs/jobs/ai-employee/career/job-search-strategy-and-application-plan.md +41 -0
  19. package/dist/registry/stubs/jobs/ai-employee/career/offer-negotiation.md +42 -0
  20. package/dist/registry/stubs/jobs/ai-employee/career/pitch-and-interview-prep.md +43 -0
  21. package/dist/registry/stubs/jobs/ai-employee/career/public-profile-updates.md +41 -0
  22. package/dist/registry/stubs/jobs/ai-employee/career/resilience-planning.md +38 -0
  23. package/dist/registry/stubs/jobs/ai-employee/career/resume-creation.md +40 -0
  24. package/dist/registry/stubs/jobs/ai-employee/customer/crm-case-resolution.md +33 -0
  25. package/dist/registry/stubs/jobs/ai-employee/customer/customer-health-review.md +36 -0
  26. package/dist/registry/stubs/jobs/ai-employee/customer/loyalty-program-management.md +35 -0
  27. package/dist/registry/stubs/jobs/ai-employee/customer/support-case-resolution.md +39 -0
  28. package/dist/registry/stubs/jobs/ai-employee/customer/support-playbook-evaluation.md +37 -0
  29. package/dist/registry/stubs/jobs/ai-employee/customer/support-queue-management.md +36 -0
  30. package/dist/registry/stubs/jobs/ai-employee/customer/support-sop-operationalization.md +36 -0
  31. package/dist/registry/stubs/jobs/ai-employee/customer/support-system-operationalization.md +34 -0
  32. package/dist/registry/stubs/jobs/ai-employee/customer/survey-campaign-management.md +36 -0
  33. package/dist/registry/stubs/jobs/ai-employee/customer/update-crm.md +32 -0
  34. package/dist/registry/stubs/jobs/ai-employee/customer/user-survey-management.md +34 -0
  35. package/dist/registry/stubs/jobs/ai-employee/design/brand-creation.md +34 -0
  36. package/dist/registry/stubs/jobs/ai-employee/design/branding-quality-audit.md +32 -0
  37. package/dist/registry/stubs/jobs/ai-employee/design/design-system-creation.md +35 -0
  38. package/dist/registry/stubs/jobs/ai-employee/design/ui-quality-assessment.md +34 -0
  39. package/dist/registry/stubs/jobs/ai-employee/design/user-facing-prototyping.md +31 -0
  40. package/dist/registry/stubs/jobs/ai-employee/design/user-journey-mapping.md +33 -0
  41. package/dist/registry/stubs/jobs/ai-employee/design/ux-research-synthesis.md +33 -0
  42. package/dist/registry/stubs/jobs/ai-employee/design/website-creation.md +32 -0
  43. package/dist/registry/stubs/jobs/ai-employee/dev-ops/cloud-application-deployment.md +35 -0
  44. package/dist/registry/stubs/jobs/ai-employee/dev-ops/cloud-cost-optimization.md +34 -0
  45. package/dist/registry/stubs/jobs/ai-employee/dev-ops/cloud-performance-diagnosis.md +33 -0
  46. package/dist/registry/stubs/jobs/ai-employee/dev-ops/cross-cloud-migration.md +42 -0
  47. package/dist/registry/stubs/jobs/ai-employee/dev-ops/incident-response.md +35 -0
  48. package/dist/registry/stubs/jobs/ai-employee/dev-ops/production-readiness-review.md +31 -0
  49. package/dist/registry/stubs/jobs/ai-employee/dev-ops/reliability-review.md +34 -0
  50. package/dist/registry/stubs/jobs/ai-employee/dev-ops/route-llm-spend-to-cloud-credits.md +36 -0
  51. package/dist/registry/stubs/jobs/ai-employee/dev-ops/run-on-remote-hub.md +30 -0
  52. package/dist/registry/stubs/jobs/ai-employee/dev-ops/set-up-cloud-cost-alerts.md +34 -0
  53. package/dist/registry/stubs/jobs/ai-employee/dev-ops/setup-remote-hub.md +32 -0
  54. package/dist/registry/stubs/jobs/ai-employee/dev-ops/slo-design-and-implementation.md +34 -0
  55. package/dist/registry/stubs/jobs/ai-employee/engineering/application-replication-workflow.md +42 -0
  56. package/dist/registry/stubs/jobs/ai-employee/engineering/code-refactoring.md +35 -0
  57. package/dist/registry/stubs/jobs/ai-employee/engineering/codebase-analysis-and-ideation.md +32 -0
  58. package/dist/registry/stubs/jobs/ai-employee/engineering/create-architecture.md +35 -0
  59. package/dist/registry/stubs/jobs/ai-employee/engineering/data-pipeline-design.md +30 -0
  60. package/dist/registry/stubs/jobs/ai-employee/engineering/data-platform-architecture.md +29 -0
  61. package/dist/registry/stubs/jobs/ai-employee/engineering/data-quality-monitoring.md +29 -0
  62. package/dist/registry/stubs/jobs/ai-employee/engineering/database-schema-design.md +30 -0
  63. package/dist/registry/stubs/jobs/ai-employee/engineering/feature-implementation.md +39 -0
  64. package/dist/registry/stubs/jobs/ai-employee/engineering/github-org-setup.md +32 -0
  65. package/dist/registry/stubs/jobs/ai-employee/engineering/gitlabs-to-github.md +44 -0
  66. package/dist/registry/stubs/jobs/ai-employee/engineering/google-workspace-setup.md +34 -0
  67. package/dist/registry/stubs/jobs/ai-employee/engineering/issue-preparation.md +28 -0
  68. package/dist/registry/stubs/jobs/ai-employee/engineering/large-refactor-plan.md +36 -0
  69. package/dist/registry/stubs/jobs/ai-employee/engineering/mobile-app-development.md +43 -0
  70. package/dist/registry/stubs/jobs/ai-employee/engineering/mobile-app-rejection-response.md +34 -0
  71. package/dist/registry/stubs/jobs/ai-employee/engineering/mobile-app-submission.md +37 -0
  72. package/dist/registry/stubs/jobs/ai-employee/engineering/project-scaffolding.md +39 -0
  73. package/dist/registry/stubs/jobs/ai-employee/engineering/system-migration.md +41 -0
  74. package/dist/registry/stubs/jobs/ai-employee/engineering/technical-design.md +34 -0
  75. package/dist/registry/stubs/jobs/ai-employee/engineering/work-completion.md +29 -0
  76. package/dist/registry/stubs/jobs/ai-employee/engineering/write-dev-docs.md +32 -0
  77. package/dist/registry/stubs/jobs/ai-employee/executive-assistance/analyze-transcript.md +32 -0
  78. package/dist/registry/stubs/jobs/ai-employee/executive-assistance/calendar-triage.md +31 -0
  79. package/dist/registry/stubs/jobs/ai-employee/executive-assistance/chief-of-staff-briefing.md +31 -0
  80. package/dist/registry/stubs/jobs/ai-employee/executive-assistance/executive-assistant.md +31 -0
  81. package/dist/registry/stubs/jobs/ai-employee/executive-assistance/meeting-preparation.md +31 -0
  82. package/dist/registry/stubs/jobs/ai-employee/finance/business-banking-setup.md +29 -0
  83. package/dist/registry/stubs/jobs/ai-employee/finance/cloud-credits-application.md +34 -0
  84. package/dist/registry/stubs/jobs/ai-employee/finance/community-funding-preparation.md +34 -0
  85. package/dist/registry/stubs/jobs/ai-employee/finance/financial-analysis.md +33 -0
  86. package/dist/registry/stubs/jobs/ai-employee/finance/fpa-and-forecasting.md +33 -0
  87. package/dist/registry/stubs/jobs/ai-employee/finance/fundraising-prospect-discovery.md +33 -0
  88. package/dist/registry/stubs/jobs/ai-employee/finance/investor-pitch-preparation.md +40 -0
  89. package/dist/registry/stubs/jobs/ai-employee/finance/invoice-generation.md +35 -0
  90. package/dist/registry/stubs/jobs/ai-employee/finance/monthly-close-review.md +32 -0
  91. package/dist/registry/stubs/jobs/ai-employee/finance/review-funding-preparation.md +33 -0
  92. package/dist/registry/stubs/jobs/ai-employee/finance/tax-strategy-planning.md +33 -0
  93. package/dist/registry/stubs/jobs/ai-employee/fraim/adhoc-prompt.md +33 -0
  94. package/dist/registry/stubs/jobs/ai-employee/fraim/contribute-to-fraim.md +30 -0
  95. package/dist/registry/stubs/jobs/ai-employee/fraim/file-fraim-issue.md +29 -0
  96. package/dist/registry/stubs/jobs/ai-employee/fraim/organizational-learning-synthesis.md +40 -0
  97. package/dist/registry/stubs/jobs/ai-employee/fraim/praise-fraim.md +32 -0
  98. package/dist/registry/stubs/jobs/ai-employee/fraim/share-with-others.md +30 -0
  99. package/dist/registry/stubs/jobs/ai-employee/fraim/sleep-on-learnings.md +41 -0
  100. package/dist/registry/stubs/jobs/ai-employee/fraim/troubleshoot-fraim.md +29 -0
  101. package/dist/registry/stubs/jobs/ai-employee/fraim/video-demo-to-sop.md +35 -0
  102. package/dist/registry/stubs/jobs/ai-employee/go-to-market/ad-performance-analysis.md +32 -0
  103. package/dist/registry/stubs/jobs/ai-employee/go-to-market/aeo-strategy.md +31 -0
  104. package/dist/registry/stubs/jobs/ai-employee/go-to-market/analyze-revenue-system.md +35 -0
  105. package/dist/registry/stubs/jobs/ai-employee/go-to-market/build-gtm-motion.md +37 -0
  106. package/dist/registry/stubs/jobs/ai-employee/go-to-market/build-gtm-stack.md +36 -0
  107. package/dist/registry/stubs/jobs/ai-employee/go-to-market/design-gtm-system.md +34 -0
  108. package/dist/registry/stubs/jobs/ai-employee/go-to-market/developer-advocacy.md +33 -0
  109. package/dist/registry/stubs/jobs/ai-employee/go-to-market/domain-registration-research.md +33 -0
  110. package/dist/registry/stubs/jobs/ai-employee/go-to-market/evangelist-content-development.md +35 -0
  111. package/dist/registry/stubs/jobs/ai-employee/go-to-market/funnel-analysis.md +35 -0
  112. package/dist/registry/stubs/jobs/ai-employee/go-to-market/growth-loop-design.md +35 -0
  113. package/dist/registry/stubs/jobs/ai-employee/go-to-market/linkedin-carousel-from-deck.md +33 -0
  114. package/dist/registry/stubs/jobs/ai-employee/go-to-market/linkedin-company-page-setup.md +32 -0
  115. package/dist/registry/stubs/jobs/ai-employee/go-to-market/marketing-analytics-review.md +34 -0
  116. package/dist/registry/stubs/jobs/ai-employee/go-to-market/marketing-content-creation.md +31 -0
  117. package/dist/registry/stubs/jobs/ai-employee/go-to-market/marketing-strategy-definition.md +35 -0
  118. package/dist/registry/stubs/jobs/ai-employee/go-to-market/notebooklm-content-generation.md +39 -0
  119. package/dist/registry/stubs/jobs/ai-employee/go-to-market/paid-social-strategy.md +34 -0
  120. package/dist/registry/stubs/jobs/ai-employee/go-to-market/plan-gtm-team.md +33 -0
  121. package/dist/registry/stubs/jobs/ai-employee/go-to-market/ppc-campaign-management.md +35 -0
  122. package/dist/registry/stubs/jobs/ai-employee/go-to-market/product-launch-management.md +29 -0
  123. package/dist/registry/stubs/jobs/ai-employee/go-to-market/promo-video-creation.md +33 -0
  124. package/dist/registry/stubs/jobs/ai-employee/go-to-market/seo-strategy.md +34 -0
  125. package/dist/registry/stubs/jobs/ai-employee/go-to-market/social-engagement-campaign.md +31 -0
  126. package/dist/registry/stubs/jobs/ai-employee/go-to-market/thought-leadership-engagement.md +32 -0
  127. package/dist/registry/stubs/jobs/ai-employee/go-to-market/tracking-and-attribution-setup.md +35 -0
  128. package/dist/registry/stubs/jobs/ai-employee/go-to-market/x-account-setup.md +33 -0
  129. package/dist/registry/stubs/jobs/ai-employee/inclusion/ai-fluency-program-design.md +30 -0
  130. package/dist/registry/stubs/jobs/ai-employee/inclusion/ai-governance-for-inclusion.md +33 -0
  131. package/dist/registry/stubs/jobs/ai-employee/inclusion/dei-toolkit-creation.md +31 -0
  132. package/dist/registry/stubs/jobs/ai-employee/inclusion/equity-pattern-analysis.md +31 -0
  133. package/dist/registry/stubs/jobs/ai-employee/inclusion/erg-sop-modernization.md +32 -0
  134. package/dist/registry/stubs/jobs/ai-employee/inclusion/executive-order-dei-impact-analysis.md +33 -0
  135. package/dist/registry/stubs/jobs/ai-employee/inclusion/inclusion-ai-readiness-audit.md +37 -0
  136. package/dist/registry/stubs/jobs/ai-employee/legal/business-annual-report-filing.md +37 -0
  137. package/dist/registry/stubs/jobs/ai-employee/legal/business-tax-registration.md +31 -0
  138. package/dist/registry/stubs/jobs/ai-employee/legal/cap-table-construction.md +31 -0
  139. package/dist/registry/stubs/jobs/ai-employee/legal/contract-review-analysis.md +36 -0
  140. package/dist/registry/stubs/jobs/ai-employee/legal/ein-application.md +31 -0
  141. package/dist/registry/stubs/jobs/ai-employee/legal/employment-structure-decision.md +29 -0
  142. package/dist/registry/stubs/jobs/ai-employee/legal/entity-type-selection.md +31 -0
  143. package/dist/registry/stubs/jobs/ai-employee/legal/founder-and-equity-agreements.md +31 -0
  144. package/dist/registry/stubs/jobs/ai-employee/legal/ip-assignment-agreement-creation.md +29 -0
  145. package/dist/registry/stubs/jobs/ai-employee/legal/nda-creation.md +33 -0
  146. package/dist/registry/stubs/jobs/ai-employee/legal/provisional-patent-application-creation.md +34 -0
  147. package/dist/registry/stubs/jobs/ai-employee/legal/saas-contract-package-creation.md +34 -0
  148. package/dist/registry/stubs/jobs/ai-employee/legal/state-incorporation-filing.md +31 -0
  149. package/dist/registry/stubs/jobs/ai-employee/legal/trademark-registration-management.md +34 -0
  150. package/dist/registry/stubs/jobs/ai-employee/legal/w9-creation.md +37 -0
  151. package/dist/registry/stubs/jobs/ai-employee/management/evolve-employee.md +44 -0
  152. package/dist/registry/stubs/jobs/ai-employee/management/fully-delegate.md +37 -0
  153. package/dist/registry/stubs/jobs/ai-employee/management/generate-productivity-report.md +35 -0
  154. package/dist/registry/stubs/jobs/ai-employee/management/graduate-job.md +24 -0
  155. package/dist/registry/stubs/jobs/ai-employee/management/issue-retrospective.md +30 -0
  156. package/dist/registry/stubs/jobs/ai-employee/management/manager-agreements.md +33 -0
  157. package/dist/registry/stubs/jobs/ai-employee/management/organization-onboarding.md +33 -0
  158. package/dist/registry/stubs/jobs/ai-employee/management/project-onboarding.md +33 -0
  159. package/dist/registry/stubs/jobs/ai-employee/management/send-stakeholder-update.md +31 -0
  160. package/dist/registry/stubs/jobs/ai-employee/people-ops/benefits-analysis-and-enrollment.md +31 -0
  161. package/dist/registry/stubs/jobs/ai-employee/people-ops/hr-business-partner-advisory.md +31 -0
  162. package/dist/registry/stubs/jobs/ai-employee/people-ops/new-hire-onboarding.md +32 -0
  163. package/dist/registry/stubs/jobs/ai-employee/people-ops/payroll-coordination.md +31 -0
  164. package/dist/registry/stubs/jobs/ai-employee/people-ops/performance-review-preparation.md +31 -0
  165. package/dist/registry/stubs/jobs/ai-employee/procurement/equipment-acceptance-and-supplier-retrospective.md +32 -0
  166. package/dist/registry/stubs/jobs/ai-employee/procurement/procurement-intake-and-strategy.md +32 -0
  167. package/dist/registry/stubs/jobs/ai-employee/procurement/procurement-negotiation-prep.md +32 -0
  168. package/dist/registry/stubs/jobs/ai-employee/procurement/proposal-response-evaluation.md +33 -0
  169. package/dist/registry/stubs/jobs/ai-employee/procurement/purchase-approval-and-po-package.md +32 -0
  170. package/dist/registry/stubs/jobs/ai-employee/procurement/rfp-response-preparation.md +30 -0
  171. package/dist/registry/stubs/jobs/ai-employee/procurement/rfx-package-authoring.md +32 -0
  172. package/dist/registry/stubs/jobs/ai-employee/procurement/supplier-discovery-and-qualification.md +32 -0
  173. package/dist/registry/stubs/jobs/ai-employee/procurement/supplier-performance-review.md +32 -0
  174. package/dist/registry/stubs/jobs/ai-employee/product/customer-prospect-discovery.md +42 -0
  175. package/dist/registry/stubs/jobs/ai-employee/product/experiment-tracking.md +30 -0
  176. package/dist/registry/stubs/jobs/ai-employee/product/feature-specification.md +33 -0
  177. package/dist/registry/stubs/jobs/ai-employee/product/independent-implementation-review.md +34 -0
  178. package/dist/registry/stubs/jobs/ai-employee/product/interview-preparation.md +34 -0
  179. package/dist/registry/stubs/jobs/ai-employee/product/mvp-validation-plan.md +30 -0
  180. package/dist/registry/stubs/jobs/ai-employee/product/participant-recruitment.md +38 -0
  181. package/dist/registry/stubs/jobs/ai-employee/product/process-interview-notes.md +42 -0
  182. package/dist/registry/stubs/jobs/ai-employee/product/review-customer-development.md +38 -0
  183. package/dist/registry/stubs/jobs/ai-employee/product/send-newsletter.md +30 -0
  184. package/dist/registry/stubs/jobs/ai-employee/product/send-thank-you-notes.md +30 -0
  185. package/dist/registry/stubs/jobs/ai-employee/product/triage-customer-needs.md +35 -0
  186. package/dist/registry/stubs/jobs/ai-employee/project-management/cross-functional-dependency-management.md +31 -0
  187. package/dist/registry/stubs/jobs/ai-employee/project-management/delivery-governance-review.md +30 -0
  188. package/dist/registry/stubs/jobs/ai-employee/project-management/operational-reporting.md +37 -0
  189. package/dist/registry/stubs/jobs/ai-employee/project-management/project-plan-creation.md +31 -0
  190. package/dist/registry/stubs/jobs/ai-employee/project-management/scrum-sprint-planning.md +33 -0
  191. package/dist/registry/stubs/jobs/ai-employee/project-management/sprint-planning.md +33 -0
  192. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/accessibility-audit.md +33 -0
  193. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/api-testing.md +34 -0
  194. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/codebase-quality-assessment.md +37 -0
  195. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/iterative-quality-improvement.md +37 -0
  196. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/mutation-testing.md +30 -0
  197. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/performance-quality-assessment.md +38 -0
  198. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/stress-test-app-under-load.md +34 -0
  199. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/test-authoring.md +31 -0
  200. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/test-quality-assessment.md +34 -0
  201. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/ui-polish-validation.md +45 -0
  202. package/dist/registry/stubs/jobs/ai-employee/quality-assurance/user-testing-and-bug-bash.md +32 -0
  203. package/dist/registry/stubs/jobs/ai-employee/recruiting/candidate-pipeline-management.md +34 -0
  204. package/dist/registry/stubs/jobs/ai-employee/recruiting/candidate-sourcing-and-ranking.md +35 -0
  205. package/dist/registry/stubs/jobs/ai-employee/recruiting/interview-coordination.md +34 -0
  206. package/dist/registry/stubs/jobs/ai-employee/recruiting/job-posting-and-sourcing.md +32 -0
  207. package/dist/registry/stubs/jobs/ai-employee/recruiting/offer-and-close-management.md +35 -0
  208. package/dist/registry/stubs/jobs/ai-employee/recruiting/role-intake-and-scorecard.md +33 -0
  209. package/dist/registry/stubs/jobs/ai-employee/recruiting/sourcing-funnel-recap.md +35 -0
  210. package/dist/registry/stubs/jobs/ai-employee/sales/account-strategy.md +34 -0
  211. package/dist/registry/stubs/jobs/ai-employee/sales/crm-pipeline-review.md +30 -0
  212. package/dist/registry/stubs/jobs/ai-employee/sales/deal-strategy.md +32 -0
  213. package/dist/registry/stubs/jobs/ai-employee/sales/outbound-sales-strategy.md +34 -0
  214. package/dist/registry/stubs/jobs/ai-employee/sales/proposal-development.md +31 -0
  215. package/dist/registry/stubs/jobs/ai-employee/sales/sales-coaching.md +33 -0
  216. package/dist/registry/stubs/jobs/ai-employee/sales/sales-discovery-preparation.md +33 -0
  217. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-build-automation.md +34 -0
  218. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-build-dashboard.md +35 -0
  219. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-config-deployment.md +35 -0
  220. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-data-management.md +34 -0
  221. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-org-health-check.md +38 -0
  222. package/dist/registry/stubs/jobs/ai-employee/salesforce/sf-user-and-access-management.md +35 -0
  223. package/dist/registry/stubs/jobs/ai-employee/security/compliance-continuous-monitoring.md +31 -0
  224. package/dist/registry/stubs/jobs/ai-employee/security/compliance-policy-authoring.md +31 -0
  225. package/dist/registry/stubs/jobs/ai-employee/security/compliance-questionnaire-response.md +32 -0
  226. package/dist/registry/stubs/jobs/ai-employee/security/compliance-requirements-detection.md +30 -0
  227. package/dist/registry/stubs/jobs/ai-employee/security/compliance-review.md +34 -0
  228. package/dist/registry/stubs/jobs/ai-employee/security/generate-audit-evidence.md +34 -0
  229. package/dist/registry/stubs/jobs/ai-employee/security/regulation-evidence-management.md +33 -0
  230. package/dist/registry/stubs/jobs/ai-employee/security/security-baseline-setup.md +32 -0
  231. package/dist/registry/stubs/jobs/ai-employee/security/security-review.md +32 -0
  232. package/dist/registry/stubs/jobs/ai-employee/security/soc2-evidence-management.md +32 -0
  233. package/dist/registry/stubs/jobs/ai-employee/security/vulnerability-triage-and-remediation.md +33 -0
  234. package/dist/registry/stubs/jobs/ai-employee/strategy/advisor-interview.md +29 -0
  235. package/dist/registry/stubs/jobs/ai-employee/strategy/advisory-board-development.md +31 -0
  236. package/dist/registry/stubs/jobs/ai-employee/strategy/advisory-board-selection.md +29 -0
  237. package/dist/registry/stubs/jobs/ai-employee/strategy/blue-sky-brainstorming.md +33 -0
  238. package/dist/registry/stubs/jobs/ai-employee/strategy/business-idea-validation-and-scoping.md +44 -0
  239. package/dist/registry/stubs/jobs/ai-employee/strategy/business-plan-creation.md +38 -0
  240. package/dist/registry/stubs/jobs/ai-employee/strategy/competitive-analysis.md +36 -0
  241. package/dist/registry/stubs/jobs/ai-employee/strategy/founder-market-fit-analysis.md +40 -0
  242. package/dist/registry/stubs/jobs/ai-employee/strategy/pricing-strategy-definition.md +40 -0
  243. package/dist/registry/stubs/jobs/ai-employee/strategy/problem-statement-crystallization.md +37 -0
  244. package/dist/registry/stubs/jobs/ai-employee/strategy/review-business-strategy.md +37 -0
  245. package/dist/registry/stubs/jobs/ai-employee/travel/travel-disruption-rebooking.md +33 -0
  246. package/dist/registry/stubs/jobs/ai-employee/travel/travel-fare-watch.md +33 -0
  247. package/dist/registry/stubs/jobs/ai-employee/travel/travel-planning.md +32 -0
  248. package/dist/registry/stubs/jobs/ai-manager/fraim/instruction-hygiene-review.md +34 -0
  249. package/dist/registry/stubs/jobs/ai-manager/management/analyze-why-you-messed-up.md +29 -0
  250. package/dist/registry/stubs/jobs/ai-manager/management/author-project-rules.md +31 -0
  251. package/dist/registry/stubs/jobs/ai-manager/management/create-clarity.md +30 -0
  252. package/dist/registry/stubs/jobs/ai-manager/management/explain-it.md +30 -0
  253. package/dist/registry/stubs/jobs/ai-manager/management/follow-your-mentor.md +29 -0
  254. package/dist/registry/stubs/jobs/ai-manager/management/hire-right-ai-for-the-job.md +29 -0
  255. package/dist/registry/stubs/jobs/ai-manager/management/hire-the-right-human-ai-manager.md +29 -0
  256. package/dist/registry/stubs/jobs/ai-manager/management/how-should-i-verify.md +32 -0
  257. package/dist/registry/stubs/jobs/ai-manager/management/need-pov.md +30 -0
  258. package/dist/registry/stubs/jobs/ai-manager/management/recognize-good-work.md +29 -0
  259. package/dist/registry/stubs/jobs/ai-manager/management/refine-core-values.md +29 -0
  260. package/dist/registry/stubs/jobs/ai-manager/management/shape-team.md +30 -0
  261. package/dist/registry/stubs/jobs/ai-manager/management/strong-pov.md +30 -0
  262. package/dist/registry/stubs/jobs/ai-manager/management/weak-pov.md +30 -0
  263. package/dist/registry/stubs/jobs/ai-manager/management/what-should-i-review.md +34 -0
  264. package/dist/src/cli/utils/remote-sync.js +0 -7
  265. package/dist/src/cli/utils/script-sync-utils.js +0 -4
  266. package/dist/src/config/learning-domains.js +12 -19
  267. package/dist/src/core/ai-mentor.js +2 -2
  268. package/dist/src/core/utils/domain-rule-assembler.js +78 -153
  269. package/dist/src/core/utils/include-resolver.js +25 -47
  270. package/dist/src/core/utils/local-registry-resolver.js +0 -51
  271. package/dist/src/local-mcp-server/learning-context-builder.js +36 -33
  272. package/dist/src/local-mcp-server/stdio-server.js +27 -59
  273. package/dist/src/services/mcp-service.js +15 -15
  274. package/dist/src/services/registry-service.js +0 -4
  275. package/package.json +3 -3
  276. package/dist/registry/domains.json +0 -159
  277. package/dist/registry/scripts/domains/catalog.js +0 -112
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CATEGORY_TO_FILETYPE = exports.BRAIN_LEARNING_FILETYPE_TO_REGION = exports.TEAM_CONTEXT_RELATIVE_PATHS = exports.generateLearningEntryId = exports.learningEntryIdLineRegex = exports.learningEntryHeadingRegex = exports.LEARNING_ENTRY_ID_REGEX = exports.LEARNING_PRIORITIES = exports.DEFAULT_THRESHOLD = void 0;
4
4
  exports.storedLearningDomains = storedLearningDomains;
5
+ exports.learningDomainsForWorkspace = learningDomainsForWorkspace;
5
6
  exports.getScoreThreshold = getScoreThreshold;
6
7
  exports.computeEffectiveScore = computeEffectiveScore;
7
8
  exports.getLearningInputHomes = getLearningInputHomes;
@@ -42,12 +43,14 @@ const brand_store_1 = require("../core/brand-store");
42
43
  // cache, which silently returned nothing once that cache stopped existing.
43
44
  const pack_home_2 = require("../cli/utils/pack-home");
44
45
  const learning_domains_1 = require("../config/learning-domains");
46
+ const folders_1 = require("../../registry/scripts/domains/folders");
45
47
  const entry_authoring_1 = require("../../registry/scripts/learning/entry-authoring");
46
- /** Catalog-backed allowlist for existing files, including retired storage identities. */
47
- function storedLearningDomains(effectiveCatalog) {
48
- const configured = effectiveCatalog?.schemaVersion === 2 && effectiveCatalog.domains && typeof effectiveCatalog.domains === 'object'
49
- ? Object.keys(effectiveCatalog.domains).filter(domain => /^[a-z][a-z-]*$/.test(domain) && !['global', 'constructor', 'prototype'].includes(domain)) : [];
50
- return [...new Set([...learning_domains_1.STORED_LEARNING_DOMAINS, ...configured])];
48
+ /** Stored names stay readable; local job folders extend current domains. */
49
+ function storedLearningDomains(effectiveDomains = []) {
50
+ return [...new Set([...learning_domains_1.STORED_LEARNING_DOMAINS, ...effectiveDomains.filter(folders_1.isSafeDomainId)])];
51
+ }
52
+ function learningDomainsForWorkspace(workspaceRoot) {
53
+ return [...new Set([...learning_domains_1.LEARNING_DOMAINS, ...(0, folders_1.discoverJobDomains)((0, path_1.join)(workspaceRoot, 'registry'), (0, project_fraim_paths_1.getUserFraimDirPath)(), (0, path_1.join)((0, project_fraim_paths_1.getWorkspaceFraimDir)(workspaceRoot), 'personalized-employee'), (0, pack_home_2.resolvePackHome)('manager', { migrateLegacy: false }).contentRoot, (0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot)])];
51
54
  }
52
55
  const REPO_LEARNINGS_REL = (0, project_fraim_paths_1.getWorkspaceFraimDisplayPath)('personalized-employee/learnings').replace(/\/$/, '');
53
56
  /**
@@ -546,7 +549,7 @@ const CONTEXT_CATEGORIES = {
546
549
  validated: { ft: 'validated-patterns', label: '(all entries)' },
547
550
  };
548
551
  /** Resolve the files listed in injected context, in delivery order. */
549
- function resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJob, domain, effectiveCatalog) {
552
+ function resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJob, domain, effectiveDomains) {
550
553
  // Domain axis (issue #806) plus the connect/job single-injection contract (issue
551
554
  // #860). Session startup stays broad enough for stable preferences plus L0, while
552
555
  // job contexts add the remaining global categories and may append the current job's
@@ -590,7 +593,7 @@ function resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJo
590
593
  const content = (0, fs_1.readFileSync)(tier.path, 'utf8');
591
594
  const explicitProvenance = /^\*\*(?:Domain|Originating job)\*\*:/m.test(content);
592
595
  if (storageDomain !== 'global' || explicitProvenance)
593
- selected = (0, entry_authoring_1.selectStoredLearningEntries)(content, storageDomain, activeDomain ?? 'global', includeGlobal, effectiveCatalog);
596
+ selected = (0, entry_authoring_1.selectStoredLearningEntries)(content, storageDomain, activeDomain ?? 'global', includeGlobal, effectiveDomains);
594
597
  else if (!includeGlobal)
595
598
  continue;
596
599
  }
@@ -619,7 +622,7 @@ function resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJo
619
622
  for (const key of cats.domain) {
620
623
  if (sessionCats.includes(key))
621
624
  push(domainFiles, key, tiersFor(CONTEXT_CATEGORIES[key].ft), 'global', false);
622
- for (const storageDomain of storedLearningDomains(effectiveCatalog)) {
625
+ for (const storageDomain of storedLearningDomains(effectiveDomains)) {
623
626
  push(domainFiles, key, tiersFor(CONTEXT_CATEGORIES[key].ft, storageDomain), storageDomain);
624
627
  }
625
628
  }
@@ -630,10 +633,10 @@ function resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJo
630
633
  const l1 = collect({ global: l1GlobalCats, domain: l1DomainCats }, (ft, dom) => resolvePersonalLearningFileTiers(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, dom ? `${resolvedUserId}-${dom}-${ft}.md` : `${resolvedUserId}-${ft}.md`), 'manager');
631
634
  return { l2, l1, multiTier, coachPresent };
632
635
  }
633
- function buildLearningContextSection(workspaceRoot, userId, forJob, domain, effectiveCatalog) {
636
+ function buildLearningContextSection(workspaceRoot, userId, forJob, domain, effectiveDomains) {
634
637
  const roots = getLearningRoots(workspaceRoot);
635
638
  const resolvedUserId = resolveLearningUserId(workspaceRoot, userId, roots);
636
- const resolved = resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJob, domain, effectiveCatalog);
639
+ const resolved = resolveContextLearningFiles(workspaceRoot, resolvedUserId, roots, forJob, domain, effectiveDomains);
637
640
  const multiTier = resolved.multiTier;
638
641
  const toListed = (f) => ({
639
642
  displayPath: f.displayPath,
@@ -1068,7 +1071,7 @@ function readLearningEntryTitles(filePath) {
1068
1071
  * manager-coaching entries that field used to hold, so the tile labelled
1069
1072
  * "Manager" reports the level rather than a category.
1070
1073
  */
1071
- function countPreservedLearnings(workspaceRoot, userId, effectiveCatalog) {
1074
+ function countPreservedLearnings(workspaceRoot, userId, effectiveDomains) {
1072
1075
  const roots = getLearningRoots(workspaceRoot);
1073
1076
  const resolvedUserId = resolveLearningUserId(workspaceRoot, userId, roots);
1074
1077
  // Distinct entry titles across every level holding this company family, so a
@@ -1120,7 +1123,7 @@ function countPreservedLearnings(workspaceRoot, userId, effectiveCatalog) {
1120
1123
  let reverseMentoring = coachByLevel.manager + coachByLevel.project;
1121
1124
  // #806: domain-scoped files fold into the same per-level counts so the Brain
1122
1125
  // reconciles with what the loader injects for a job.
1123
- for (const domain of storedLearningDomains(effectiveCatalog)) {
1126
+ for (const domain of storedLearningDomains(effectiveDomains)) {
1124
1127
  for (const ft of ORG_TYPES)
1125
1128
  organization += countOrgFamily(`org-${domain}-${ft}.md`);
1126
1129
  for (const ft of PERSONAL_WORK_TYPES) {
@@ -1331,11 +1334,11 @@ const FILETYPE_TO_CATEGORY = {
1331
1334
  * #806) present in a directory, in a deterministic domain order. Used by the Hub
1332
1335
  * read/count paths so domain learnings appear alongside the flat global files.
1333
1336
  */
1334
- function listDomainLearningFiles(dir, prefix, fileType, effectiveCatalog) {
1337
+ function listDomainLearningFiles(dir, prefix, fileType, effectiveDomains) {
1335
1338
  if (!(0, fs_1.existsSync)(dir))
1336
1339
  return [];
1337
1340
  const out = [];
1338
- for (const domain of storedLearningDomains(effectiveCatalog)) {
1341
+ for (const domain of storedLearningDomains(effectiveDomains)) {
1339
1342
  const fileName = `${prefix}-${domain}-${fileType}.md`;
1340
1343
  if ((0, fs_1.existsSync)((0, path_1.join)(dir, fileName)))
1341
1344
  out.push({ fileName, domain });
@@ -1550,7 +1553,7 @@ function readRejectedProposals(workspaceRoot, userId) {
1550
1553
  // Newest first: the manager is most often checking what they just said no to.
1551
1554
  return out.sort((a, b) => String(b.rejectedAt).localeCompare(String(a.rejectedAt)));
1552
1555
  }
1553
- function readPreservedLearnings(workspaceRoot, userId, scope, level = 'machine', effectiveCatalog) {
1556
+ function readPreservedLearnings(workspaceRoot, userId, scope, level = 'machine', effectiveDomains) {
1554
1557
  const roots = getLearningRoots(workspaceRoot);
1555
1558
  const usageStats = resolveUsageStats();
1556
1559
  // Only the human library reads these observations. An unavailable store must
@@ -1599,8 +1602,8 @@ function readPreservedLearnings(workspaceRoot, userId, scope, level = 'machine',
1599
1602
  out.push(...parseTiers(resolveOrgLearningFileTiers(roots.repoLearningsBase, f), cat));
1600
1603
  // #806: domain-scoped org learnings — union from both locations.
1601
1604
  const allDomainFiles = [
1602
- ...listDomainLearningFiles(roots.repoLearningsBase, 'org', fileType, effectiveCatalog).map((d) => ({ ...d, base: roots.repoLearningsBase })),
1603
- ...listDomainLearningFiles((0, path_1.join)((0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot, 'learnings'), 'org', fileType, effectiveCatalog)
1605
+ ...listDomainLearningFiles(roots.repoLearningsBase, 'org', fileType, effectiveDomains).map((d) => ({ ...d, base: roots.repoLearningsBase })),
1606
+ ...listDomainLearningFiles((0, path_1.join)((0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot, 'learnings'), 'org', fileType, effectiveDomains)
1604
1607
  .map((d) => ({ ...d, base: (0, path_1.join)((0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot, 'learnings') })),
1605
1608
  ];
1606
1609
  const seenDomainFile = new Set();
@@ -1624,7 +1627,7 @@ function readPreservedLearnings(workspaceRoot, userId, scope, level = 'machine',
1624
1627
  const cats = scope === 'reverse' ? ['coaching'] : ['avoid', 'preference', 'repeat'];
1625
1628
  for (const cat of cats) {
1626
1629
  const fileType = exports.CATEGORY_TO_FILETYPE[cat];
1627
- for (const domain of ['global', ...storedLearningDomains(effectiveCatalog)]) {
1630
+ for (const domain of ['global', ...storedLearningDomains(effectiveDomains)]) {
1628
1631
  const domainPart = domain === 'global' ? '' : `-${domain}`;
1629
1632
  for (const storageTier of ['hot', 'cold']) {
1630
1633
  const suffix = storageTier === 'cold' ? COLD_FILE_SUFFIX : '';
@@ -1641,39 +1644,39 @@ function isGlobalDomain(domain) {
1641
1644
  return !domain || domain === 'global';
1642
1645
  }
1643
1646
  /** Normalize a caller-supplied domain to one of the known domains, or 'global'. */
1644
- function normalizeLearningDomain(domain, effectiveCatalog) {
1647
+ function normalizeLearningDomain(domain, effectiveDomains) {
1645
1648
  if (isGlobalDomain(domain))
1646
1649
  return 'global';
1647
- const found = storedLearningDomains(effectiveCatalog).find((d) => d === domain);
1650
+ const found = storedLearningDomains(effectiveDomains).find((d) => d === domain);
1648
1651
  return found ?? 'global';
1649
1652
  }
1650
- function learningFileName(userId, fileType, domain, effectiveCatalog) {
1653
+ function learningFileName(userId, fileType, domain, effectiveDomains) {
1651
1654
  // Issue #1755 / #754: normalize here rather than trusting the caller. The HTTP
1652
1655
  // layer already allowlists the domain, but this function builds a path and a
1653
1656
  // direct caller passing `../../escape` would otherwise write outside the
1654
1657
  // learnings root. Anything not in the known set resolves to the global file.
1655
- const safe = normalizeLearningDomain(domain, effectiveCatalog);
1658
+ const safe = normalizeLearningDomain(domain, effectiveDomains);
1656
1659
  return safe === 'global' ? `${userId}-${fileType}.md` : `${userId}-${safe}-${fileType}.md`;
1657
1660
  }
1658
- function resolveLearningFilePath(workspaceRoot, userId, ref, effectiveCatalog) {
1661
+ function resolveLearningFilePath(workspaceRoot, userId, ref, effectiveDomains) {
1659
1662
  const roots = getLearningRoots(workspaceRoot);
1660
1663
  const fileType = exports.CATEGORY_TO_FILETYPE[ref.category];
1661
1664
  if (ref.scope === 'org') {
1662
1665
  // Write org entries to the org pack home — same location share-with-others uses.
1663
1666
  // The Hub read path already merges pack home + repo-local, so edits land where
1664
1667
  // the agent reads them without needing a repo commit.
1665
- return (0, path_1.join)((0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot, 'learnings', learningFileName('org', fileType, ref.domain, effectiveCatalog));
1668
+ return (0, path_1.join)((0, pack_home_2.resolvePackHome)('org', { migrateLegacy: false }).contentRoot, 'learnings', learningFileName('org', fileType, ref.domain, effectiveDomains));
1666
1669
  }
1667
1670
  const resolvedUserId = resolveLearningUserId(workspaceRoot, userId, roots);
1668
1671
  // Issue #1070: for the 'machine' level use the configured manager home.
1669
1672
  const base = ref.level === 'project' ? roots.repoLearningsBase : roots.managerHomeBase;
1670
- return (0, path_1.join)(base, learningFileName(resolvedUserId, fileType, ref.domain, effectiveCatalog));
1673
+ return (0, path_1.join)(base, learningFileName(resolvedUserId, fileType, ref.domain, effectiveDomains));
1671
1674
  }
1672
1675
  function titleCaseFromFileType(fileType) {
1673
1676
  return fileType.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
1674
1677
  }
1675
- function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, effectiveCatalog) {
1676
- const filePath = resolveLearningFilePath(workspaceRoot, userId, ref, effectiveCatalog);
1678
+ function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, effectiveDomains) {
1679
+ const filePath = resolveLearningFilePath(workspaceRoot, userId, ref, effectiveDomains);
1677
1680
  const existing = (0, fs_1.existsSync)(filePath) ? (0, fs_1.readFileSync)(filePath, 'utf8') : '';
1678
1681
  const nl = existing.includes('\r\n') ? '\r\n' : '\n';
1679
1682
  const lines = existing.length ? existing.split(/\r?\n/) : [];
@@ -1687,9 +1690,9 @@ function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, e
1687
1690
  };
1688
1691
  const metadataLine = /^\*\*(Id|Score|Last seen|Recurrences|Technical trace|Users|First recorded|First synthesized|Originating job|Sources|Domain|Domain basis|Domain history)\*\*:/i;
1689
1692
  const setManagerDomain = (metadata, domain) => {
1690
- const version = effectiveCatalog?.mapVersion ?? learning_domains_1.LEARNING_DOMAIN_MAP_VERSION;
1693
+ const version = learning_domains_1.LEARNING_DOMAIN_MAP_VERSION;
1691
1694
  if (!Number.isInteger(version) || version < 1)
1692
- throw new Error('Cannot record a learning domain decision: restore the domain catalog first.');
1695
+ throw new Error('Cannot record a learning domain decision: check the stored provenance version.');
1693
1696
  const oldDomain = metadata.find(line => /^\*\*Domain\*\*:/i.test(line.trim()))?.trim().replace(/^\*\*Domain\*\*:\s*/i, '');
1694
1697
  const oldBasis = metadata.find(line => /^\*\*Domain basis\*\*:/i.test(line.trim()))?.trim().replace(/^\*\*Domain basis\*\*:\s*/i, '');
1695
1698
  const retained = metadata.filter(line => !/^\*\*(Domain|Domain basis)\*\*:/i.test(line.trim()));
@@ -1702,7 +1705,7 @@ function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, e
1702
1705
  const sev = (payload.severity || 'P-MED');
1703
1706
  const title = (payload.title || '').trim() || 'Untitled learning';
1704
1707
  const suppliedLines = String(payload.body || '').trim().split(/\r?\n/);
1705
- const addDomain = normalizeLearningDomain(ref.domain, effectiveCatalog);
1708
+ const addDomain = normalizeLearningDomain(ref.domain, effectiveDomains);
1706
1709
  const metadata = setManagerDomain(suppliedLines.filter(line => metadataLine.test(line.trim())), addDomain);
1707
1710
  const body = suppliedLines.filter(line => !metadataLine.test(line.trim())).join(nl).trim();
1708
1711
  const block = [`#### [${sev}] ${title}`, '', ...metadata, '', body, '', '---'].join(nl);
@@ -1755,7 +1758,7 @@ function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, e
1755
1758
  }
1756
1759
  const originalBody = lines.slice(start + 1, end).filter(line => line.trim() !== '---' && !metadataLine.test(line.trim()) && !/^(First|Last) synthesized:/i.test(line.trim())).join(nl).trim();
1757
1760
  const body = payload.body === undefined ? originalBody : String(payload.body).split(/\r?\n/).filter(line => !metadataLine.test(line.trim())).join(nl).trim();
1758
- const targetDomain = payload.targetDomain === undefined ? undefined : normalizeLearningDomain(payload.targetDomain, effectiveCatalog);
1761
+ const targetDomain = payload.targetDomain === undefined ? undefined : normalizeLearningDomain(payload.targetDomain, effectiveDomains);
1759
1762
  // A normal prose edit is not authority to reclassify an ambiguous legacy entry.
1760
1763
  // An explicit choice records a manager decision even when its filename is unchanged.
1761
1764
  const updatedMeta = targetDomain !== undefined && targetDomain === payload.targetDomain ? setManagerDomain(meta, targetDomain) : meta;
@@ -1764,8 +1767,8 @@ function applyLearningEntryChange(workspaceRoot, userId, ref, action, payload, e
1764
1767
  // IS the filename. Cut the rebuilt block from the source file and append it to the
1765
1768
  // destination, so the entry keeps its id, score and history rather than being
1766
1769
  // re-created as a new entry with no past.
1767
- if (targetDomain !== undefined && targetDomain !== normalizeLearningDomain(ref.domain, effectiveCatalog)) {
1768
- const destPath = resolveLearningFilePath(workspaceRoot, userId, { ...ref, domain: targetDomain }, effectiveCatalog);
1770
+ if (targetDomain !== undefined && targetDomain !== normalizeLearningDomain(ref.domain, effectiveDomains)) {
1771
+ const destPath = resolveLearningFilePath(workspaceRoot, userId, { ...ref, domain: targetDomain }, effectiveDomains);
1769
1772
  const destExisting = (0, fs_1.existsSync)(destPath) ? (0, fs_1.readFileSync)(destPath, 'utf8') : '';
1770
1773
  const destNl = destExisting.includes('\r\n') ? '\r\n' : nl;
1771
1774
  const fileTypeForHeader = exports.CATEGORY_TO_FILETYPE[ref.category];
@@ -81,7 +81,7 @@ const usage_collector_js_1 = require("./usage-collector.js");
81
81
  const otlp_metrics_receiver_js_1 = require("./otlp-metrics-receiver.js");
82
82
  const token_adapter_registry_js_1 = require("./token-adapter-registry.js");
83
83
  const learning_context_builder_js_1 = require("./learning-context-builder.js");
84
- const catalog_1 = require("../../registry/scripts/domains/catalog");
84
+ const folders_1 = require("../../registry/scripts/domains/folders");
85
85
  const skill_include_dedup_js_1 = require("./skill-include-dedup.js");
86
86
  const git_utils_1 = require("../core/utils/git-utils");
87
87
  /**
@@ -1820,7 +1820,7 @@ class FraimLocalMCPServer {
1820
1820
  // request, authorizes dependent catalog, include and rule reads. Keep it
1821
1821
  // request-local so a later rejected reconnect cannot change another call.
1822
1822
  if (toolName === 'fraim_connect') {
1823
- const connectedSessionId = response.result?.structuredContent?.sessionId ?? response.result?.sessionId;
1823
+ const connectedSessionId = response.result?._meta?.sessionId ?? response.result?.sessionId;
1824
1824
  if (typeof connectedSessionId === 'string' && connectedSessionId.trim())
1825
1825
  requestSessionId = connectedSessionId;
1826
1826
  }
@@ -1903,13 +1903,11 @@ class FraimLocalMCPServer {
1903
1903
  finalizedResponse.result.content[0].text = responseText;
1904
1904
  }
1905
1905
  }
1906
- let catalogRead;
1907
1906
  // 4. After get_fraim_job succeeds, inject learning context with job-focus frame.
1908
1907
  if (toolName === 'get_fraim_job' && !finalizedResponse.error) {
1909
1908
  const text = finalizedResponse.result?.content?.[0]?.text;
1910
1909
  if (typeof text === 'string') {
1911
- catalogRead = (0, domain_rule_assembler_1.withRuleDeliveryTimeout)(resolver.resolveFile('domains.json', { includeMetadata: false }));
1912
- finalizedResponse.result.content[0].text = await this.appendJobContext(text, args.job, requestSessionId, requestId, catalogRead);
1910
+ finalizedResponse.result.content[0].text = await this.appendJobContext(text, args.job, requestSessionId, requestId);
1913
1911
  }
1914
1912
  // Issue #1345: forward executionMode from get_fraim_job response to Hub so
1915
1913
  // the chip reads from run data (no local file read, no separate endpoint needed).
@@ -1925,23 +1923,17 @@ class FraimLocalMCPServer {
1925
1923
  }
1926
1924
  }
1927
1925
  }
1928
- finalizedResponse = await this.addRuleDelivery(request, finalizedResponse, requestSessionId, catalogRead);
1926
+ finalizedResponse = await this.addRuleDelivery(request, finalizedResponse, requestSessionId);
1929
1927
  return this.processResponseWithHydration(finalizedResponse, requestSessionId);
1930
1928
  }
1931
1929
  /** Keep context delivery and offer attribution together for local and remote jobs. */
1932
- async appendJobContext(text, jobName, requestSessionId, requestId, catalogRead) {
1930
+ async appendJobContext(text, jobName, requestSessionId, requestId) {
1933
1931
  const userEmail = this.ensureEngine().getUserEmail();
1934
1932
  const workspaceRoot = this.findProjectRoot() || process.cwd();
1935
- let effectiveCatalog;
1936
- try {
1937
- const source = await (catalogRead ?? (0, domain_rule_assembler_1.withRuleDeliveryTimeout)(this.getRegistryResolver(requestSessionId).resolveFile('domains.json', { includeMetadata: false })));
1938
- effectiveCatalog = JSON.parse(source.content);
1939
- }
1940
- catch { /* Rule delivery returns the source warning; retain available global learning. */ }
1941
1933
  if (!userEmail)
1942
1934
  return text;
1943
- const jobDomain = effectiveCatalog ? await this.resolveJobDomainForJob(jobName, requestSessionId, effectiveCatalog) : null;
1944
- const learningSection = (0, learning_context_builder_js_1.buildLearningContextSection)(workspaceRoot, userEmail, true, jobDomain, effectiveCatalog);
1935
+ const jobDomain = await this.resolveJobDomainForJob(jobName, requestSessionId);
1936
+ const learningSection = (0, learning_context_builder_js_1.buildLearningContextSection)(workspaceRoot, userEmail, true, jobDomain, (0, learning_context_builder_js_1.learningDomainsForWorkspace)(workspaceRoot));
1945
1937
  const teamContextSection = (0, learning_context_builder_js_1.buildTeamContextSection)(workspaceRoot, true);
1946
1938
  if (learningSection || teamContextSection) {
1947
1939
  text += `\n\n---` + learningSection + teamContextSection;
@@ -1956,7 +1948,7 @@ class FraimLocalMCPServer {
1956
1948
  * context must never break a job response, and an unknown job never guesses a
1957
1949
  * wrong domain.
1958
1950
  */
1959
- async resolveJobDomainForJob(jobName, requestSessionId, effectiveCatalog) {
1951
+ async resolveJobDomainForJob(jobName, requestSessionId) {
1960
1952
  try {
1961
1953
  const resolver = this.getRegistryResolver(requestSessionId);
1962
1954
  if (!resolver)
@@ -1964,9 +1956,7 @@ class FraimLocalMCPServer {
1964
1956
  const registryPath = await resolver.findRegistryPath('jobs', jobName);
1965
1957
  if (!registryPath)
1966
1958
  return null;
1967
- const catalog = effectiveCatalog ?? JSON.parse((await (0, domain_rule_assembler_1.withRuleDeliveryTimeout)(resolver.resolveFile('domains.json', { includeMetadata: false }))).content);
1968
- const selected = (0, catalog_1.selectCatalogDomain)(catalog, registryPath);
1969
- return selected.selection === 'mapped' && selected.domain !== 'global' ? selected.domain : null;
1959
+ return (0, folders_1.jobDomainFromRegistryPath)(registryPath);
1970
1960
  }
1971
1961
  catch {
1972
1962
  return null;
@@ -2003,51 +1993,32 @@ class FraimLocalMCPServer {
2003
1993
  }
2004
1994
  return errors;
2005
1995
  }
2006
- async addRuleDelivery(request, response, sessionId, catalogRead) {
1996
+ async addRuleDelivery(request, response, sessionId) {
2007
1997
  if (response.error || response.result?.isError || response.result?.personaLock || !response.result)
2008
1998
  return response;
2009
1999
  const tool = request.params?.name;
2010
2000
  const args = request.params?.arguments || {};
2011
2001
  let jobPath = null;
2012
2002
  if (tool === 'get_fraim_job' || tool === 'seekMentoring') {
2003
+ if (tool === 'seekMentoring' && !(args.status === 'starting' && args.requestInstructions === true))
2004
+ return response;
2013
2005
  const context = await this.getMentor(sessionId).getRuleDeliveryContext(args.job || args.jobName);
2014
2006
  if (!context)
2015
2007
  return response;
2016
2008
  jobPath = context.jobPath;
2017
- if (tool === 'seekMentoring' && !(args.status === 'starting' &&
2018
- (args.currentPhase === 'starting' || args.currentPhase === context.initialPhase || args.requestInstructions === true)))
2019
- return response;
2020
2009
  }
2021
2010
  else if (tool !== 'fraim_connect')
2022
2011
  return response;
2023
- // Reuse authenticated connect policy only as the remote fallback. The
2024
- // ordinary resolver still checks every effective local/overlay source first.
2025
- const remoteFiles = new Map();
2026
- if (tool === 'fraim_connect') {
2027
- const prior = response.result.structuredContent?.ruleAssembly;
2028
- const block = Number.isInteger(prior?.contentBlockIndex) && prior.contentBlockIndex >= 0
2029
- ? response.result.content?.[prior.contentBlockIndex] : undefined;
2030
- const artifact = Array.isArray(prior?.artifacts) && prior.artifacts.length === 1 ? prior.artifacts[0] : undefined;
2031
- const prefix = '## Applicable rules\n\n### rules/constitution.md\n\n';
2032
- if (prior?.complete === true && prior.selection === 'connect' && prior.domain === 'global'
2033
- && Array.isArray(prior.warnings) && prior.warnings.length === 0
2034
- && artifact?.path === 'rules/constitution.md' && block?.type === 'text'
2035
- && typeof block.text === 'string' && block.text.startsWith(prefix)) {
2036
- const body = block.text.slice(prefix.length);
2037
- if ((0, crypto_1.createHash)('sha256').update(body).digest('hex') === artifact?.hash)
2038
- remoteFiles.set(artifact.path, body);
2039
- }
2040
- }
2041
- const resolver = this.getRegistryResolver(sessionId, remoteFiles);
2042
- const result = (0, domain_rule_assembler_1.attachRuleAssembly)(response.result, await (0, domain_rule_assembler_1.assembleDomainRules)({ jobPath,
2043
- resolveFile: path => path === 'domains.json' && catalogRead ? catalogRead : resolver.resolveFile(path, { includeMetadata: false, stripMcpHeader: true }) }));
2044
- const metadata = result.structuredContent?.ruleAssembly;
2045
- for (const warning of metadata?.warnings ?? []) {
2012
+ const resolver = this.getRegistryResolver(sessionId);
2013
+ const assembly = await (0, domain_rule_assembler_1.assembleDomainRules)({ jobPath,
2014
+ resolveFile: path => resolver.resolveFile(path, { includeMetadata: false, stripMcpHeader: true }) });
2015
+ const result = (0, domain_rule_assembler_1.appendRuleInstructions)(response.result, assembly);
2016
+ for (const warning of assembly.metadata.warnings) {
2046
2017
  this.logError('Rule delivery warning: ' + JSON.stringify(warning));
2047
2018
  }
2048
2019
  return { ...response, result };
2049
2020
  }
2050
- async finalizeLocalToolTextResponse(request, requestSessionId, requestId, text, catalogRead) {
2021
+ async finalizeLocalToolTextResponse(request, requestSessionId, requestId, text) {
2051
2022
  const response = {
2052
2023
  jsonrpc: '2.0',
2053
2024
  id: request.id,
@@ -2055,7 +2026,7 @@ class FraimLocalMCPServer {
2055
2026
  content: [{ type: 'text', text }]
2056
2027
  }
2057
2028
  };
2058
- const withRules = await this.addRuleDelivery(request, response, requestSessionId, catalogRead);
2029
+ const withRules = await this.addRuleDelivery(request, response, requestSessionId);
2059
2030
  const withResolvedIncludes = await this.resolveIncludesInResponse(withRules, requestSessionId, requestId);
2060
2031
  return this.processResponseWithHydration(withResolvedIncludes, requestSessionId);
2061
2032
  }
@@ -2201,7 +2172,7 @@ class FraimLocalMCPServer {
2201
2172
  /**
2202
2173
  * Initialize the LocalRegistryResolver for override resolution
2203
2174
  */
2204
- getRegistryResolver(requestSessionId, remoteFiles) {
2175
+ getRegistryResolver(requestSessionId) {
2205
2176
  const projectRoot = this.findProjectRoot();
2206
2177
  this.log(`🔍 getRegistryResolver: projectRoot = ${projectRoot}`);
2207
2178
  // Determine effective FRAIM dir using shadow semantics
@@ -2228,8 +2199,6 @@ class FraimLocalMCPServer {
2228
2199
  orgCacheRoot: (0, pack_home_1.resolvePackHome)('org', { migrateLegacy: false }).contentRoot,
2229
2200
  shouldFilter: (content) => this.isStub(content),
2230
2201
  remoteContentResolver: async (path) => {
2231
- if (remoteFiles?.has(path))
2232
- return remoteFiles.get(path);
2233
2202
  // Fetch parent content from remote for inheritance
2234
2203
  this.log(`🔄 Remote content resolver: fetching ${path}`);
2235
2204
  this.log(`🔄 Fetching raw file content: ${path}`);
@@ -2988,7 +2957,7 @@ class FraimLocalMCPServer {
2988
2957
  return acceptedResponse;
2989
2958
  const acceptedReceipt = this.persistAcceptedReceipt(args, requestSessionId, tutoringResponse, request.id);
2990
2959
  const phaseStartWarning = this.acceptPhaseTracking(args, requestSessionId, tutoringResponse.nextPhase, !!acceptedReceipt);
2991
- acceptedResponse.result.structuredContent = { ...acceptedResponse.result.structuredContent,
2960
+ acceptedResponse.result._meta = { ...acceptedResponse.result._meta,
2992
2961
  phaseAccepted: true, nextPhase: tutoringResponse.nextPhase, outcome: tutoringResponse.outcome,
2993
2962
  workflowDigest: tutoringResponse.workflowDigest, ...(acceptedReceipt ? { acceptedReceipt } : {}) };
2994
2963
  if (phaseStartWarning && acceptedResponse.result?.content?.[0]) {
@@ -3026,9 +2995,8 @@ class FraimLocalMCPServer {
3026
2995
  responseText = `${mentor.getCompactPhaseAuthority()}\n\n${responseText}`;
3027
2996
  responseText += `\n\n---\n\n**Job ID:** \`${jobId}\`\n\n**This job has phases.** Use \`seekMentoring\` with the jobId above to get phase-specific instructions.`;
3028
2997
  }
3029
- const catalogRead = (0, domain_rule_assembler_1.withRuleDeliveryTimeout)(this.getRegistryResolver(requestSessionId).resolveFile('domains.json', { includeMetadata: false }));
3030
- responseText = await this.appendJobContext(responseText, name, requestSessionId, requestId, catalogRead);
3031
- return await this.finalizeLocalToolTextResponse(request, requestSessionId, requestId, responseText, catalogRead);
2998
+ responseText = await this.appendJobContext(responseText, name, requestSessionId, requestId);
2999
+ return await this.finalizeLocalToolTextResponse(request, requestSessionId, requestId, responseText);
3032
3000
  }
3033
3001
  }
3034
3002
  catch (error) {
@@ -3126,8 +3094,8 @@ class FraimLocalMCPServer {
3126
3094
  // Reconcile remote fallback against the same persisted local instance.
3127
3095
  // Only the remote's explicit accepted result can consume a start.
3128
3096
  if (toolName === 'seekMentoring' && !processedResponse.error && !processedResponse.result?.isError
3129
- && response.result?.structuredContent?.phaseAccepted === true) {
3130
- const metadata = response.result.structuredContent;
3097
+ && response.result?._meta?.phaseAccepted === true) {
3098
+ const metadata = response.result._meta;
3131
3099
  let acceptedReceipt;
3132
3100
  if (metadata.acceptedReceipt) {
3133
3101
  const remote = metadata.acceptedReceipt;
@@ -3146,7 +3114,7 @@ class FraimLocalMCPServer {
3146
3114
  catch (error) {
3147
3115
  return { jsonrpc: '2.0', id: request.id, result: { isError: true, content: [{ type: 'text', text: `Phase acceptance failed: ${error.message}` }] } };
3148
3116
  }
3149
- processedResponse.result.structuredContent = { ...processedResponse.result.structuredContent, ...(acceptedReceipt ? { acceptedReceipt } : {}) };
3117
+ processedResponse.result._meta = { ...processedResponse.result._meta, ...(acceptedReceipt ? { acceptedReceipt } : {}) };
3150
3118
  }
3151
3119
  const textBlock = processedResponse.result?.content?.find((item) => item.type === 'text');
3152
3120
  if (textBlock) {
@@ -3385,7 +3353,7 @@ class FraimLocalMCPServer {
3385
3353
  const requestSessionId = this.extractSessionIdFromRequest(request);
3386
3354
  if (toolName && requestSessionId) {
3387
3355
  const success = !response.error && !response.result?.isError;
3388
- let acceptedPhaseResponse = success && response.result?.structuredContent?.phaseAccepted === true;
3356
+ let acceptedPhaseResponse = success && response.result?._meta?.phaseAccepted === true;
3389
3357
  this.log(`📊 Collecting usage: ${toolName} (session: ${requestSessionId}, success: ${success})`);
3390
3358
  if (!this.repoInfo) {
3391
3359
  this.detectRepoInfo();
@@ -238,12 +238,12 @@ class McpService {
238
238
  case 'get_fraim_job':
239
239
  if (!args.job)
240
240
  throw new Error('Argument "job" is required for get_fraim_job');
241
- return await this.handleGetJob(args.job, context.apiKey, context.userId);
241
+ return await this.handleGetJob(args.job, context.apiKey, context.userId, !!context.localMcpVersion && context.localMcpVersion !== 'unknown');
242
242
  case 'seekMentoring':
243
243
  if (!args.jobName || !args.issueNumber || !args.currentPhase || !args.status) {
244
244
  throw new Error('Arguments "jobName", "issueNumber", "currentPhase", and "status" are required for seekMentoring');
245
245
  }
246
- return await this.handleSeekMentoring(args, context.userId);
246
+ return await this.handleSeekMentoring(args, context.userId, !!context.localMcpVersion && context.localMcpVersion !== 'unknown');
247
247
  case 'list_fraim_jobs':
248
248
  return await this.handleListJobs();
249
249
  case 'file_fraim_github_issue':
@@ -327,7 +327,7 @@ class McpService {
327
327
  throw new Error(`Failed to read file: ${error.message}`);
328
328
  }
329
329
  }
330
- async handleGetJob(jobName, apiKey, userId) {
330
+ async handleGetJob(jobName, apiKey, userId, localProxy = false) {
331
331
  let effectiveUserId = userId;
332
332
  if (!effectiveUserId && apiKey) {
333
333
  try {
@@ -424,7 +424,7 @@ class McpService {
424
424
  }
425
425
  return this.addRuleDelivery({
426
426
  content: [{ type: 'text', text: response }]
427
- }, jobName);
427
+ }, jobName, undefined, localProxy);
428
428
  }
429
429
  async handleListJobs() {
430
430
  const jobs = Array.from(this.registryService.getFileIndex().values()).filter((f) => f.type === 'job' && !f.isStub);
@@ -577,7 +577,7 @@ class McpService {
577
577
  type: 'text',
578
578
  text: lines.join('\n')
579
579
  }],
580
- structuredContent: {
580
+ _meta: {
581
581
  sessionId,
582
582
  userId: session.userId,
583
583
  agent: session.agent,
@@ -585,7 +585,7 @@ class McpService {
585
585
  repo: session.repo
586
586
  },
587
587
  sessionId: sessionId
588
- });
588
+ }, undefined, undefined, isLocalProxyCall);
589
589
  }
590
590
  validateIssueTrackingConfig(issueTracking) {
591
591
  if (!issueTracking.provider) {
@@ -705,7 +705,7 @@ class McpService {
705
705
  }
706
706
  };
707
707
  }
708
- async handleSeekMentoring(args, userId) {
708
+ async handleSeekMentoring(args, userId, localProxy = false) {
709
709
  const restoringInstructions = args.status === 'starting' && args.requestInstructions === true;
710
710
  const personaLock = await this.maybeBuildPersonaLockResponse(args.jobName, userId, undefined, args.status === 'starting' && !restoringInstructions);
711
711
  if (personaLock) {
@@ -900,8 +900,8 @@ class McpService {
900
900
  type: 'text',
901
901
  text: trackingWarning + phaseStartWarning + result.message
902
902
  }],
903
- structuredContent: { phaseAccepted: true, nextPhase: result.nextPhase, phaseStartWarning }
904
- }, args.jobName, args);
903
+ _meta: { phaseAccepted: true, nextPhase: result.nextPhase, phaseStartWarning }
904
+ }, args.jobName, args, localProxy);
905
905
  if (!finalized.isError && !restoringInstructions && result.outcome && result.workflowDigest && sessionId) {
906
906
  // Remote-only execution has no trusted Hub binding. The executing local
907
907
  // proxy verifies this envelope and supplies its own launch binding.
@@ -912,25 +912,25 @@ class McpService {
912
912
  executionEpoch: sessionId, phaseId: args.currentPhase, requestedStatus: args.status,
913
913
  outcome: result.outcome.kind, ...(result.nextPhase ? { nextPhase: result.nextPhase } : {}), verifiedEvidenceRefs: [],
914
914
  };
915
- finalized.structuredContent = { ...finalized.structuredContent, acceptedReceipt, outcome: result.outcome, workflowDigest: result.workflowDigest };
915
+ finalized._meta = { ...finalized._meta, acceptedReceipt, outcome: result.outcome, workflowDigest: result.workflowDigest };
916
916
  }
917
917
  return finalized;
918
918
  }
919
- async addRuleDelivery(response, jobName, phaseArgs) {
920
- if (response.isError || response.personaLock)
919
+ async addRuleDelivery(response, jobName, phaseArgs, localProxy = false) {
920
+ if (localProxy || response.isError || response.personaLock)
921
+ return response;
922
+ if (phaseArgs && !(phaseArgs.status === 'starting' && phaseArgs.requestInstructions === true))
921
923
  return response;
922
924
  const context = jobName ? await this.aiMentor.getRuleDeliveryContext(jobName) : null;
923
925
  if (jobName && !context)
924
926
  return response;
925
- if (phaseArgs && !(phaseArgs.status === 'starting' && (phaseArgs.currentPhase === 'starting' || phaseArgs.currentPhase === context?.initialPhase || phaseArgs.requestInstructions === true)))
926
- return response;
927
927
  const assembly = await (0, domain_rule_assembler_1.assembleDomainRules)({ jobPath: context?.jobPath, resolveFile: async (path) => {
928
928
  const content = await this.registryService.getFile(path);
929
929
  if (content === null)
930
930
  throw new Error(`Rule source unavailable: ${path}`);
931
931
  return { content, source: 'remote', personalized: false, inherited: false };
932
932
  } });
933
- const result = (0, domain_rule_assembler_1.attachRuleAssembly)(response, assembly);
933
+ const result = (0, domain_rule_assembler_1.appendRuleInstructions)(response, assembly);
934
934
  for (const warning of assembly.metadata.warnings) {
935
935
  console.warn('Rule delivery warning:', JSON.stringify(warning));
936
936
  }
@@ -308,10 +308,6 @@ class RegistryService {
308
308
  }
309
309
  getSyncBundle() {
310
310
  const files = [];
311
- const domainCatalog = (0, path_1.join)(this.registryPath, 'domains.json');
312
- if ((0, fs_1.existsSync)(domainCatalog)) {
313
- files.push({ path: 'domains.json', content: (0, fs_1.readFileSync)(domainCatalog, 'utf8'), type: 'config' });
314
- }
315
311
  const allFiles = Array.from(this.fileIndex.values());
316
312
  // 1. Add job STUBS (not full jobs) from registry/stubs/jobs
317
313
  const jobStubs = allFiles.filter(f => f.type === 'job' && f.path.includes('stubs/jobs/'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.362-next.4",
3
+ "version": "2.0.362",
4
4
  "description": "FRAIM core CLI and MCP package.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -9,8 +9,8 @@
9
9
  "files": [
10
10
  "dist/registry/scripts/artifact-paths.js",
11
11
  "dist/registry/scripts/learning-usage/local-runtime.js",
12
- "dist/registry/domains.json",
13
- "dist/registry/scripts/domains/catalog.js",
12
+ "dist/registry/stubs/jobs/",
13
+ "dist/registry/scripts/domains/folders.js",
14
14
  "dist/registry/scripts/learning/entry-format.js",
15
15
  "dist/registry/scripts/learning/completion-state.js",
16
16
  "dist/registry/scripts/learning/corpus-audit.js",