xrefkit 0.7.7__tar.gz → 0.7.8__tar.gz

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 (264) hide show
  1. {xrefkit-0.7.7/xrefkit.egg-info → xrefkit-0.7.8}/PKG-INFO +1 -1
  2. {xrefkit-0.7.7 → xrefkit-0.7.8}/pyproject.toml +1 -1
  3. xrefkit-0.7.8/tests/test_package_knowledge_resolution.py +166 -0
  4. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_package_skill_run.py +29 -0
  5. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/__init__.py +1 -1
  6. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/catalog.py +113 -7
  7. {xrefkit-0.7.7 → xrefkit-0.7.8/xrefkit.egg-info}/PKG-INFO +1 -1
  8. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit.egg-info/SOURCES.txt +1 -0
  9. {xrefkit-0.7.7 → xrefkit-0.7.8}/LICENSE +0 -0
  10. {xrefkit-0.7.7 → xrefkit-0.7.8}/README.md +0 -0
  11. {xrefkit-0.7.7 → xrefkit-0.7.8}/setup.cfg +0 -0
  12. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_artifact_selected_family.py +0 -0
  13. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_attention_pet.py +0 -0
  14. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_attention_pet_client_protocol.py +0 -0
  15. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_attention_pet_codex_session.py +0 -0
  16. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_attention_pet_fit.py +0 -0
  17. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_azure_connection.py +0 -0
  18. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_azure_import.py +0 -0
  19. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_azure_recovery.py +0 -0
  20. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_azure_update_candidate.py +0 -0
  21. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_azure_writer.py +0 -0
  22. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_boundary_analysis.py +0 -0
  23. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_brownfield_csharp_structure_definitions.py +0 -0
  24. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_brownfield_file_editing_protocol.py +0 -0
  25. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_business_intake_conversation_definitions.py +0 -0
  26. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_business_intake_definition.py +0 -0
  27. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_calibration_lint.py +0 -0
  28. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_catalog_preparation_definition.py +0 -0
  29. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_check_skill_knowledge_xids.py +0 -0
  30. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_ci_workflow_invariants.py +0 -0
  31. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_cli.py +0 -0
  32. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_code_constraint_definition.py +0 -0
  33. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_collect_analyzer_sarif.py +0 -0
  34. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_compact_skill_logs.py +0 -0
  35. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_constraint_derivation_family_definition.py +0 -0
  36. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_constraint_derivation_selected_family.py +0 -0
  37. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_contribution_adoption_bytes.py +0 -0
  38. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_contribution_returns.py +0 -0
  39. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_convert_to_xrefkit_skill.py +0 -0
  40. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_cs_scope_probe.py +0 -0
  41. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_csharp_commonality.py +0 -0
  42. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_csharp_naming_profile.py +0 -0
  43. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_ctx.py +0 -0
  44. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_cutover_readiness.py +0 -0
  45. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_dashboard.py +0 -0
  46. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_database_batch_definition_migration.py +0 -0
  47. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_decision_trace.py +0 -0
  48. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_design_business_intake_selected_family.py +0 -0
  49. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_design_planning_definition_migration.py +0 -0
  50. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_dotnet_definition_candidate.py +0 -0
  51. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_editorial_family_definition.py +0 -0
  52. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_editorial_intake_definition.py +0 -0
  53. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_editorial_selected_family.py +0 -0
  54. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_embedded_startup_pack.py +0 -0
  55. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_error_policy_audit.py +0 -0
  56. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_error_policy_locator.py +0 -0
  57. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_execution_binding.py +0 -0
  58. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_existing_skill_definition_batch.py +0 -0
  59. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_final_skilldefinition_batch.py +0 -0
  60. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_flow_selected_family.py +0 -0
  61. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_fm_multiroot.py +0 -0
  62. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_gate.py +0 -0
  63. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_gateway.py +0 -0
  64. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_gateway_mcp.py +0 -0
  65. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_gateway_skill_adapter.py +0 -0
  66. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_gateway_work_items.py +0 -0
  67. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_goal_desired_state.py +0 -0
  68. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_governance_entry.py +0 -0
  69. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_governance_host.py +0 -0
  70. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_host_precheck.py +0 -0
  71. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_human_evaluation.py +0 -0
  72. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_implementation_flow_definition.py +0 -0
  73. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_implementation_review_selected_family.py +0 -0
  74. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_inbound_uploads.py +0 -0
  75. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_instruction_workflow.py +0 -0
  76. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_knowledge_relations_validator.py +0 -0
  77. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_language_review_definition.py +0 -0
  78. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_legacy_guidance.py +0 -0
  79. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_legacy_migration.py +0 -0
  80. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_legacy_resources.py +0 -0
  81. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_mcp_package_routing.py +0 -0
  82. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_mcp_setup.py +0 -0
  83. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_mcp_subagent_startup.py +0 -0
  84. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_mcp_subagent_startup_integration.py +0 -0
  85. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_ontology_assessment_validator.py +0 -0
  86. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_os_family_definition.py +0 -0
  87. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_os_knowledge_family_definition.py +0 -0
  88. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_os_selected_family.py +0 -0
  89. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_ownership.py +0 -0
  90. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_packaged_native_governance.py +0 -0
  91. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_packmeta.py +0 -0
  92. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_plan_markdown.py +0 -0
  93. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_plan_observation.py +0 -0
  94. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_project_management_materialization.py +0 -0
  95. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_project_quality_baseline.py +0 -0
  96. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_qa_report_definition.py +0 -0
  97. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_reporting_profiles.py +0 -0
  98. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_reporting_quality.py +0 -0
  99. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_repository_skill_adoption.py +0 -0
  100. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_repository_startup_pack.py +0 -0
  101. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_resource_provider.py +0 -0
  102. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_runtime_contracts.py +0 -0
  103. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_sarif_to_locator.py +0 -0
  104. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_security_definition_migration.py +0 -0
  105. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_site_release_metadata.py +0 -0
  106. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_definition.py +0 -0
  107. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_definition_governance.py +0 -0
  108. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_definition_mcp.py +0 -0
  109. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_definition_runtime.py +0 -0
  110. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_edits.py +0 -0
  111. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_maturity_return.py +0 -0
  112. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_release_compatibility.py +0 -0
  113. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skill_runtime_audit.py +0 -0
  114. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skillmeta.py +0 -0
  115. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_skills_sync.py +0 -0
  116. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_source_analysis_fragments.py +0 -0
  117. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_structure_catalog.py +0 -0
  118. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_subagent_startup.py +0 -0
  119. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_subagent_startup_boundaries.py +0 -0
  120. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_wbs.py +0 -0
  121. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_work_management.py +0 -0
  122. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_work_packages.py +0 -0
  123. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_workflow_family_definition.py +0 -0
  124. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xref.py +0 -0
  125. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xrefkit_instance.py +0 -0
  126. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xrefkit_tools.py +0 -0
  127. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xrefkit_v2_discovery.py +0 -0
  128. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xrefkit_v2_models.py +0 -0
  129. {xrefkit-0.7.7 → xrefkit-0.7.8}/tests/test_xrefkit_v2_pipeline.py +0 -0
  130. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/__main__.py +0 -0
  131. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/__init__.py +0 -0
  132. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/__main__.py +0 -0
  133. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/client.py +0 -0
  134. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/client_protocol.py +0 -0
  135. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/codex_session.py +0 -0
  136. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/evaluator.py +0 -0
  137. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/model.py +0 -0
  138. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/presentation.py +0 -0
  139. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/profiles.py +0 -0
  140. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/scenarios.py +0 -0
  141. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/server.py +0 -0
  142. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/attention_pet/store.py +0 -0
  143. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/azure_connection.py +0 -0
  144. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/azure_import.py +0 -0
  145. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/azure_recovery.py +0 -0
  146. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/azure_update_candidate.py +0 -0
  147. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/azure_writer.py +0 -0
  148. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/boundary_analysis.py +0 -0
  149. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/catalog_cli.py +0 -0
  150. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/cli.py +0 -0
  151. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/contracts.py +0 -0
  152. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/ctx.py +0 -0
  153. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/dashboard.py +0 -0
  154. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/decision_trace.py +0 -0
  155. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/discovery.py +0 -0
  156. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/execution_binding.py +0 -0
  157. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/execution_binding_cli.py +0 -0
  158. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/gate.py +0 -0
  159. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/gateway.py +0 -0
  160. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/goalstate.py +0 -0
  161. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/governance_entry.py +0 -0
  162. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/governance_entry_cli.py +0 -0
  163. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/governance_host.py +0 -0
  164. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/hashing.py +0 -0
  165. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/host_precheck.py +0 -0
  166. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/import_skill.py +0 -0
  167. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/instance.py +0 -0
  168. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/loaders.py +0 -0
  169. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/__init__.py +0 -0
  170. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/audit.py +0 -0
  171. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/bootstrap.py +0 -0
  172. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/cli.py +0 -0
  173. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/client_cache.py +0 -0
  174. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/client_flow.py +0 -0
  175. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/context_registry.py +0 -0
  176. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/context_token.py +0 -0
  177. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/contracts.py +0 -0
  178. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/contribution_adoption.py +0 -0
  179. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/contribution_returns.py +0 -0
  180. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/dist.py +0 -0
  181. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/gateway.py +0 -0
  182. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/governed_overlays.py +0 -0
  183. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/inbound_uploads.py +0 -0
  184. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/knowledge_edits.py +0 -0
  185. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/legacy_guidance.py +0 -0
  186. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/legacy_migration.py +0 -0
  187. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/legacy_resources.py +0 -0
  188. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/ownership.py +0 -0
  189. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/repository.py +0 -0
  190. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/schemas.py +0 -0
  191. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/server.py +0 -0
  192. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/setup.py +0 -0
  193. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/skill_edits.py +0 -0
  194. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/skill_maturity.py +0 -0
  195. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/startup_contract_pack.py +0 -0
  196. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/subagent_startup.py +0 -0
  197. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp/update_gate_intake.py +0 -0
  198. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/mcp_tools.py +0 -0
  199. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/__init__.py +0 -0
  200. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/common.py +0 -0
  201. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/effective_bundle.py +0 -0
  202. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/human_evaluation.py +0 -0
  203. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/local_manifest.py +0 -0
  204. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/package_manifest.py +0 -0
  205. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/run_log.py +0 -0
  206. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/server_config.py +0 -0
  207. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/models/skill_definition.py +0 -0
  208. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/operations_cli.py +0 -0
  209. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/ownership.py +0 -0
  210. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/packmeta.py +0 -0
  211. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/plan_markdown.py +0 -0
  212. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/plan_observation.py +0 -0
  213. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/registry.py +0 -0
  214. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/reporting.py +0 -0
  215. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/reporting_profiles.py +0 -0
  216. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/repository_skills.py +0 -0
  217. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resolver.py +0 -0
  218. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resource_provider.py +0 -0
  219. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/attention_pet/client-state.schema.json +0 -0
  220. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/attention_pet/pet.css +0 -0
  221. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/attention_pet/pet.html +0 -0
  222. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/attention_pet/pet.js +0 -0
  223. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/contracts.json +0 -0
  224. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/current.json +0 -0
  225. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json +0 -0
  226. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md +0 -0
  227. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json +0 -0
  228. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md +0 -0
  229. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/model_body.md +0 -0
  230. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/000_agent_entry.md +0 -0
  231. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/011_startup_xref_routing.md +0 -0
  232. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/015_shared_memory_operations.md +0 -0
  233. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/016_uncertainty_protocol.md +0 -0
  234. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/017_base_and_xref_layering.md +0 -0
  235. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/053_context_direction_security_guard.md +0 -0
  236. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/base/startup_sources/yomiyasu_LICENSE.txt +0 -0
  237. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/docs/guides/062_legacy_flow_skill_migration_guide.md +0 -0
  238. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/knowledge/operations/130_legacy_flow_skill_migration_rules.md +0 -0
  239. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/knowledge/organization/160_context_direction_guard_rules.md +0 -0
  240. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/skills/os/legacy_flow_skill_migration/SKILL.v1.md +0 -0
  241. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/skills/os/legacy_flow_skill_migration/references/legacy_flow_skill_migration_template.md +0 -0
  242. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/skills/repository_adoption.json +0 -0
  243. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/resources/migration/tools/migrate_legacy_flow_skill.py +0 -0
  244. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/runlog.py +0 -0
  245. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skill_definition.py +0 -0
  246. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skill_definition_catalog.py +0 -0
  247. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skill_definition_governance.py +0 -0
  248. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skillmeta.py +0 -0
  249. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skillrun.py +0 -0
  250. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/skills_sync.py +0 -0
  251. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/structure_catalog.py +0 -0
  252. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/subagent_startup.py +0 -0
  253. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/tools/__init__.py +0 -0
  254. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/tools/__main__.py +0 -0
  255. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/v2_cli.py +0 -0
  256. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/wbs.py +0 -0
  257. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/work_management.py +0 -0
  258. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/work_management_view.py +0 -0
  259. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/workspace.py +0 -0
  260. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit/xref.py +0 -0
  261. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit.egg-info/dependency_links.txt +0 -0
  262. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit.egg-info/entry_points.txt +0 -0
  263. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit.egg-info/requires.txt +0 -0
  264. {xrefkit-0.7.7 → xrefkit-0.7.8}/xrefkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xrefkit
3
- Version: 0.7.7
3
+ Version: 0.7.8
4
4
  Summary: Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit
5
5
  Author: synthaicode
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xrefkit"
7
- version = "0.7.7"
7
+ version = "0.7.8"
8
8
  description = "Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -0,0 +1,166 @@
1
+ from dataclasses import replace
2
+
3
+ import pytest
4
+
5
+ from xrefkit.discovery import DiscoveredSkillPackage
6
+ from xrefkit.loaders import load_package_manifest
7
+ from xrefkit.mcp.catalog import XRefCatalog
8
+
9
+
10
+ def package_catalog(tmp_path, asset_path="knowledge/rules.md"):
11
+ import yaml
12
+ package_root = tmp_path / "package"
13
+ package_root.mkdir()
14
+ (package_root / "knowledge").mkdir()
15
+ (package_root / "knowledge/rules.md").write_text("# Package rules\n\nRequired rules.\n")
16
+ (package_root / "method.md").write_text("# Method\n")
17
+ manifest = package_root / "package_manifest.yaml"
18
+ manifest.write_text(yaml.safe_dump({
19
+ "package_id": "example.rules", "package_type": "skill_package", "version": "1.0.0",
20
+ "requires": {"xrefkit_core": ">=2.0.0 <3.0.0"},
21
+ "provides": {
22
+ "skills": [{"id": "example.review", "xid": "xid-skill-example", "path": "method.md"}],
23
+ "knowledge": [{"id": "rules", "xid": "xid-knowledge-rules", "path": asset_path}],
24
+ },
25
+ "contract": {},
26
+ }))
27
+ package = DiscoveredSkillPackage("example", package_root, manifest, load_package_manifest(manifest))
28
+ repo = tmp_path / "repo"
29
+ repo.mkdir()
30
+ return replace(XRefCatalog.build(repo), discovered_packages=(package,))
31
+
32
+
33
+ def test_manifest_identity_resolves_without_inline_xid(tmp_path):
34
+ catalog = package_catalog(tmp_path)
35
+ document = catalog.get_document_by_xid("xid-knowledge-rules")
36
+ assert document["content"] == catalog.expand_knowledge("xid-knowledge-rules")["content"]
37
+ assert document["xid"] == "xid-knowledge-rules"
38
+ assert catalog.search_knowledge_catalog("Required rules")[0]["xid"] == "xid-knowledge-rules"
39
+ cached = catalog.get_document_by_xid("xid-knowledge-rules", document["content_hash"])
40
+ assert cached["content_hash"] == document["content_hash"]
41
+ assert cached["content_omitted"] == document["cache_policy"]["cache_recommended"]
42
+
43
+
44
+ def test_duplicate_package_xid_refuses_selection(tmp_path):
45
+ catalog = package_catalog(tmp_path)
46
+ catalog = replace(catalog, discovered_packages=catalog.discovered_packages * 2)
47
+ assert catalog.get_document_by_xid("xid-knowledge-rules")["error"] == "xid_conflict"
48
+ with pytest.raises(ValueError, match="knowledge xid conflict"):
49
+ catalog.expand_knowledge("xid-knowledge-rules")
50
+
51
+
52
+ def test_package_path_cannot_escape_root(tmp_path):
53
+ catalog = package_catalog(tmp_path, "../outside.md")
54
+ with pytest.raises(ValueError, match="escapes root"):
55
+ catalog.get_document_by_xid("xid-knowledge-rules")
56
+
57
+
58
+ def installed_catalog(tmp_path, monkeypatch):
59
+ """Simulate entry-point installation, then use the real package discovery loader."""
60
+ import yaml
61
+ from types import SimpleNamespace
62
+ from xrefkit import discovery
63
+ catalog = package_catalog(tmp_path)
64
+ package = catalog.discovered_packages[0]
65
+ root = package.package_root
66
+ manifest = yaml.safe_load(package.manifest_path.read_text())
67
+ manifest["provides"]["skills"][0]["path"] = "method.skill.yaml"
68
+ manifest["provides"]["skills"][0]["required_knowledge"] = ["xid-knowledge-rules"]
69
+ manifest["provides"]["review_axes"] = [{"id": "axis", "xid": "xid-axis-rules", "path": "axis.yaml"}]
70
+ manifest["provides"]["schemas"] = [{"id": "schema", "xid": "xid-schema-rules", "path": "schema.json"}]
71
+ package.manifest_path.write_text(yaml.safe_dump(manifest))
72
+ (root / "method.skill.yaml").write_text(yaml.safe_dump({
73
+ "skill_id": "example.review", "xid": "xid-skill-example",
74
+ "entry": {"xid": "xid-entry-example", "path": "method.md", "load_policy": "required_inline"},
75
+ "required_outputs": ["report"], "required_knowledge": ["xid-knowledge-rules"],
76
+ "review_axes": ["xid-axis-rules"], "schemas": ["xid-schema-rules"],
77
+ "must_not": [], "extension_policy": {},
78
+ }))
79
+ (root / "axis.yaml").write_text("axis_id: example\nxid: xid-axis-rules\nchecks: []\n")
80
+ (root / "schema.json").write_text('{"type":"object"}\n')
81
+ ep = SimpleNamespace(name="example", load=lambda: lambda: root)
82
+ monkeypatch.setattr(discovery, "_select_entry_points", lambda group: [ep])
83
+ return XRefCatalog.build(catalog.repo_root, discover_packages=True)
84
+
85
+
86
+ def test_discovered_required_knowledge_is_resolved_and_all_declared_assets_are_fetchable(tmp_path, monkeypatch):
87
+ catalog = installed_catalog(tmp_path, monkeypatch)
88
+ skill = catalog.get_skill("example.review")
89
+ assert skill["required_knowledge"] == [{"xid": "xid-knowledge-rules", "required": True, "reason": "package declaration"}]
90
+ resolved = catalog.resolve_skill_knowledge("example.review")
91
+ assert not resolved["unsatisfied_required"]
92
+ assert resolved["slots"][0]["bind"] == "xid-knowledge-rules"
93
+ assert resolved["slots"][0]["required"] is True and resolved["slots"][0]["satisfied"] is True
94
+ for xid in ("xid-knowledge-rules", "xid-axis-rules", "xid-schema-rules", "xid-entry-example", "xid-skill-example"):
95
+ assert catalog.get_document_by_xid(xid)["content"]
96
+ assert catalog.expand_knowledge("xid-knowledge-rules")["content"].startswith("# Package rules")
97
+
98
+
99
+ def test_undeclared_file_is_not_exposed_and_absent_need_remains_unsatisfied(tmp_path, monkeypatch):
100
+ catalog = installed_catalog(tmp_path, monkeypatch)
101
+ package = catalog.discovered_packages[0]
102
+ (package.package_root / "secret.md").write_text("<!-- xid: ABCDEF123456 -->\n# Never declared")
103
+ with pytest.raises(KeyError):
104
+ catalog.get_document_by_xid("ABCDEF123456")
105
+ package.manifest.provides.knowledge.clear()
106
+ resolved = catalog.resolve_skill_knowledge("example.review")
107
+ assert resolved["unsatisfied_required"] == ["xid-knowledge-rules"]
108
+ assert resolved["slots"][0]["candidates"] == []
109
+ with pytest.raises(KeyError):
110
+ catalog.expand_knowledge("xid-knowledge-rules")
111
+
112
+
113
+ def test_live_asset_changes_invalidate_catalog_and_document_cache(tmp_path, monkeypatch):
114
+ catalog = installed_catalog(tmp_path, monkeypatch)
115
+ path = catalog.discovered_packages[0].package_root / "axis.yaml"
116
+ before = catalog.catalog_version
117
+ document = catalog.get_document_by_xid("xid-axis-rules")
118
+ path.write_text(path.read_text() + "summary: revised\n")
119
+ current = catalog.get_document_by_xid("xid-axis-rules", document["content_hash"])
120
+ assert not current["content_omitted"]
121
+ assert current["content_hash"] != document["content_hash"]
122
+ assert catalog.catalog_version != before
123
+
124
+
125
+ def test_duplicate_knowledge_cannot_silently_satisfy_required_slot(tmp_path, monkeypatch):
126
+ catalog = installed_catalog(tmp_path, monkeypatch)
127
+ (catalog.repo_root / "knowledge").mkdir()
128
+ (catalog.repo_root / "knowledge/local.md").write_text("<!-- xid: xid-knowledge-rules -->\n# Conflicting local rules")
129
+ with pytest.raises(ValueError, match="knowledge xid conflict"):
130
+ catalog.resolve_skill_knowledge("example.review")
131
+
132
+
133
+ @pytest.mark.parametrize("relative", ["../outside.md", "/absolute.md", "C:/absolute.md", "knowledge/../rules.md", "knowledge\\rules.md"])
134
+ def test_nonportable_or_escaping_declarations_refused(tmp_path, relative):
135
+ catalog = package_catalog(tmp_path, relative)
136
+ with pytest.raises(ValueError, match="package asset escapes root"):
137
+ catalog.get_document_by_xid("xid-knowledge-rules")
138
+
139
+
140
+ def test_symlink_escape_is_not_exposed(tmp_path):
141
+ catalog = package_catalog(tmp_path)
142
+ outside = tmp_path / "outside.md"
143
+ outside.write_text("private outside content")
144
+ inside = catalog.discovered_packages[0].package_root / "knowledge/rules.md"
145
+ inside.unlink()
146
+ try:
147
+ inside.symlink_to(outside)
148
+ except OSError:
149
+ pytest.skip("symlink creation not available")
150
+ with pytest.raises(ValueError, match="escapes root"):
151
+ catalog.get_document_by_xid("xid-knowledge-rules")
152
+
153
+
154
+ def test_package_cannot_shadow_embedded_startup_identity(tmp_path):
155
+ catalog = package_catalog(tmp_path)
156
+ catalog.discovered_packages[0].manifest.provides.knowledge[0].xid = "0B5C58B5E5B2"
157
+ with pytest.raises(ValueError, match="core startup XID"):
158
+ catalog.get_document_by_xid("0B5C58B5E5B2")
159
+
160
+
161
+ def test_inline_identity_mismatch_refused(tmp_path):
162
+ catalog = package_catalog(tmp_path)
163
+ path = catalog.discovered_packages[0].package_root / "knowledge/rules.md"
164
+ path.write_text("<!-- xid: ABCDEF123456 -->\n# Wrong identity")
165
+ with pytest.raises(ValueError, match="identity does not match"):
166
+ catalog.expand_knowledge("xid-knowledge-rules")
@@ -18,6 +18,13 @@ def test_installed_package_run_binds_over_mcp(tmp_path, module, reference, xid):
18
18
  from pathlib import Path
19
19
 
20
20
  pytest.importorskip(module)
21
+ from xrefkit.discovery import discover_skill_packages
22
+ package_id = reference.split("::")[0]
23
+ package = next(item for item in discover_skill_packages() if item.package_id == package_id)
24
+ package_knowledge_xids = [asset.xid for asset in package.manifest.provides.knowledge]
25
+ package_reference_xids = [asset.xid for asset in (
26
+ *package.manifest.provides.review_axes, *package.manifest.provides.schemas
27
+ )]
21
28
  anyio = pytest.importorskip("anyio")
22
29
  pytest.importorskip("mcp")
23
30
  from mcp.client.session import ClientSession
@@ -94,8 +101,30 @@ def test_installed_package_run_binds_over_mcp(tmp_path, module, reference, xid):
94
101
  )
95
102
  assert not requirements.isError, requirements.content
96
103
  assert not requirements.structuredContent["missing"]
104
+ for xid in package_knowledge_xids:
105
+ document = await session.call_tool("get_document_by_xid", {"xid": xid})
106
+ assert not document.isError, document.content
107
+ expanded = await session.call_tool("expand_knowledge", {"xid": xid})
108
+ assert not expanded.isError, expanded.content
109
+ assert expanded.structuredContent["content"]
110
+
97
111
  skill = await session.call_tool("get_skill", {"skill_id": run["skill_id"]})
98
112
  assert not skill.isError, skill.content
99
113
  assert skill.structuredContent["skill_id"] == run["skill_id"]
114
+ for asset_xid in package_reference_xids:
115
+ document = await session.call_tool("get_document_by_xid", {"xid": asset_xid})
116
+ assert not document.isError, document.content
117
+ assert document.structuredContent["content"]
118
+ resolved = await session.call_tool(
119
+ "resolve_skill_knowledge", {"skill_id": run["skill_id"]}
120
+ )
121
+ assert not resolved.isError, resolved.content
122
+ required_xids = {need["xid"] for need in skill.structuredContent["required_knowledge"]}
123
+ assert required_xids <= {slot["bind"] for slot in resolved.structuredContent["slots"]}
124
+ for slot in resolved.structuredContent["slots"]:
125
+ if slot["bind"] in package_knowledge_xids:
126
+ assert slot["satisfied"]
127
+ if not slot["satisfied"]:
128
+ assert slot["slot"] in resolved.structuredContent["unsatisfied_required"]
100
129
 
101
130
  anyio.run(scenario)
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.7.7"
5
+ __version__ = "0.7.8"
@@ -5,8 +5,9 @@ import io
5
5
  import json
6
6
  import re
7
7
  import zipfile
8
+ from collections.abc import Iterator
8
9
  from dataclasses import dataclass, replace
9
- from pathlib import Path
10
+ from pathlib import Path, PurePosixPath, PureWindowsPath
10
11
 
11
12
  from .contracts import builtin_tool_contracts
12
13
  from .legacy_migration import migration_context
@@ -683,14 +684,63 @@ class XRefCatalog:
683
684
  for entry in self.skills
684
685
  ]
685
686
  + [
686
- f"{package.package_id}{package.version}"
687
- for package in self.discovered_packages
687
+ f"{package.package_id}{package.version}{xid}{stable_hash(read_text(path))}"
688
+ for package, xid, path, _kind in self._package_assets()
688
689
  ]
689
690
  + [tool.tool_id + tool.version for tool in self.tools]
690
691
  + ([self.ownership.content_hash] if self.ownership else [])
691
692
  )
692
693
  return stable_hash(version_basis)[:16]
693
694
 
695
+ def _package_assets(self) -> Iterator[tuple[DiscoveredSkillPackage, str, Path, str]]:
696
+ """Resolve only manifest-declared assets and split Skill references."""
697
+ for package in self.discovered_packages:
698
+ root = package.package_root.resolve()
699
+ seen = set()
700
+ provides = package.manifest.provides
701
+ groups = {
702
+ "knowledge": provides.knowledge,
703
+ "fragment": provides.fragments,
704
+ "review_axis": provides.review_axes,
705
+ "schema": provides.schemas,
706
+ "template": provides.templates,
707
+ "skill": provides.skills,
708
+ }
709
+ for kind, assets in groups.items():
710
+ for asset in assets:
711
+ path = _package_asset_path(root, asset.path)
712
+ if _embedded_startup_document(asset.xid) is not None:
713
+ raise ValueError(f"package asset conflicts with core startup XID: {asset.xid}")
714
+ key = (asset.xid, path)
715
+ if key not in seen:
716
+ seen.add(key)
717
+ yield package, asset.xid, path, kind
718
+ if kind == "skill" and path.suffix.lower() != ".md":
719
+ skill = load_package_skill_definition(path)
720
+ if skill.xid != asset.xid or skill.skill_id != asset.id:
721
+ raise ValueError("package Skill identity does not match manifest")
722
+ for fragment in [skill.entry, *skill.required_fragments, *skill.branches]:
723
+ target = _package_asset_path(root, fragment.path)
724
+ if _embedded_startup_document(fragment.xid) is not None:
725
+ raise ValueError(f"package fragment conflicts with core startup XID: {fragment.xid}")
726
+ key = (fragment.xid, target)
727
+ if key not in seen:
728
+ seen.add(key)
729
+ yield package, fragment.xid, target, "fragment"
730
+
731
+ def _package_document(self, package: DiscoveredSkillPackage, xid: str, path: Path, text: str) -> XRefDocument:
732
+ if path.suffix.lower() == ".md" and first_xid(text) and first_xid(text) != xid:
733
+ raise ValueError(f"package document identity does not match manifest: {xid}")
734
+ return XRefDocument(
735
+ xid=xid,
736
+ title=first_heading(text, path.stem),
737
+ path=f"package:{package.package_id}/{path.relative_to(package.package_root.resolve()).as_posix()}",
738
+ summary=first_paragraph(text),
739
+ content=text,
740
+ links=markdown_xid_link_targets(text),
741
+ content_hash=stable_hash(text),
742
+ )
743
+
694
744
  def _scan_knowledge(self) -> list[tuple[KnowledgeCatalogEntry, str]]:
695
745
  """One consistent read per file: entry hash and body come from the
696
746
  same text, so they can never disagree."""
@@ -714,6 +764,17 @@ class XRefCatalog:
714
764
  text = read_text(path)
715
765
  if first_xid(text) not in known:
716
766
  entries.append((_knowledge_entry(builtin_root, None, path, text), text))
767
+ for package, xid, path, kind in self._package_assets():
768
+ if kind != "knowledge":
769
+ continue
770
+ text = read_text(path)
771
+ entry = _knowledge_entry(package.package_root.resolve(), None, path, text)
772
+ document = self._package_document(package, xid, path, text)
773
+ entries.append((replace(
774
+ entry, xid=xid, path=document.path, missing=[],
775
+ zone_metadata={"source": "installed_skill_package", "package_id": package.package_id,
776
+ "package_version": package.version},
777
+ ), text))
717
778
  return entries
718
779
 
719
780
  def get_repository_identity(self) -> dict[str, str]:
@@ -742,6 +803,7 @@ class XRefCatalog:
742
803
  def build_knowledge_context(self, query: str, limit: int = 5) -> dict:
743
804
  scanned = self._scan_knowledge()
744
805
  ranked = _rank_entries(query, [entry for entry, _text in scanned])[:limit]
806
+ _require_unique_knowledge([entry for entry, _ in scanned])
745
807
  by_xid = {entry.xid: (entry, text) for entry, text in scanned}
746
808
  expanded: list[dict] = []
747
809
  missing: list[dict] = []
@@ -899,6 +961,7 @@ class XRefCatalog:
899
961
  """
900
962
  entry = self._skill_by_id(skill_id)
901
963
  knowledge = self.knowledge
964
+ _require_unique_knowledge(knowledge)
902
965
  by_xid = {item.xid: item for item in knowledge}
903
966
  if entry.definition_format == "skill_definition_v1":
904
967
  needs = entry.knowledge_slots
@@ -1234,6 +1297,18 @@ class XRefCatalog:
1234
1297
  for local_xid, path in local_knowledge_files(self.repo_root)
1235
1298
  if local_xid == xid
1236
1299
  )
1300
+ package_documents = {}
1301
+ for package, asset_xid, path, _kind in self._package_assets():
1302
+ if asset_xid == xid:
1303
+ text = read_text(path)
1304
+ matches.append((path, text))
1305
+ package_documents[path] = self._package_document(package, xid, path, text)
1306
+ if package_documents:
1307
+ # Installed packages cannot shadow a core migration document merely
1308
+ # because the consumer repository does not contain that document.
1309
+ builtin_root = Path(__file__).resolve().parents[1] / "resources" / "migration"
1310
+ if self.repo_root != builtin_root and builtin_root.is_dir():
1311
+ matches.extend(_managed_markdown_matches_by_xid(builtin_root, None, xid))
1237
1312
  # An active local edit is an explicit overlay of its source document.
1238
1313
  # Suppress only the corresponding source path; unrelated documents
1239
1314
  # declaring the same XID remain a conflict.
@@ -1277,12 +1352,19 @@ class XRefCatalog:
1277
1352
  "xid": xid,
1278
1353
  "message": "multiple catalog-visible documents declare this XID; refusing path-order selection",
1279
1354
  "matches": [
1280
- _document_conflict_match(self.repo_root, self.ownership, path, text)
1355
+ ({"source": "installed_skill_package",
1356
+ "content_hash": package_documents[path].content_hash}
1357
+ if path in package_documents else
1358
+ _document_conflict_match(self.repo_root, self.ownership, path, text))
1281
1359
  for path, text in matches
1282
1360
  ],
1283
1361
  }
1284
1362
  if len(matches) == 1:
1285
1363
  path, text = matches[0]
1364
+ if path in package_documents:
1365
+ return _conditional_document_response(
1366
+ package_documents[path], known_version, self.repository_fingerprint,
1367
+ )
1286
1368
  for entry in (self.skills if self.skill_definition_paths else []):
1287
1369
  if (entry.definition_format == "skill_definition_v1"
1288
1370
  and entry.package_id is None
@@ -1638,6 +1720,27 @@ def _knowledge_entry(
1638
1720
  )
1639
1721
 
1640
1722
 
1723
+ def _package_asset_path(root: Path, relative: str) -> Path:
1724
+ """Manifest paths are portable relative allowlist entries, never glob roots."""
1725
+ portable = PurePosixPath(relative)
1726
+ if ("\\" in relative or ":" in relative or portable.is_absolute()
1727
+ or PureWindowsPath(relative).drive or ".." in portable.parts
1728
+ or portable.as_posix() != relative):
1729
+ raise ValueError(f"package asset escapes root or is not a portable relative path: {relative}")
1730
+ path = (root / relative).resolve()
1731
+ if not path.is_relative_to(root):
1732
+ raise ValueError(f"package asset escapes root: {relative}")
1733
+ return path
1734
+
1735
+
1736
+ def _require_unique_knowledge(entries: list[KnowledgeCatalogEntry]) -> None:
1737
+ seen: set[str] = set()
1738
+ for entry in entries:
1739
+ if entry.xid in seen:
1740
+ raise ValueError(f"knowledge xid conflict: {entry.xid} appears in multiple catalog-visible knowledge entries")
1741
+ seen.add(entry.xid)
1742
+
1743
+
1641
1744
  def _external_knowledge_entry(root: Path, path: Path, text: str) -> KnowledgeCatalogEntry:
1642
1745
  xid = first_xid(text)
1643
1746
  if not xid:
@@ -2400,14 +2503,16 @@ def _build_package_skills(package: DiscoveredSkillPackage) -> list[SkillCatalogE
2400
2503
  )
2401
2504
  continue
2402
2505
  skill = load_package_skill_definition(skill_path)
2403
- entry_path = package.package_root / skill.entry.path
2506
+ if skill.xid != provided.xid or skill.skill_id != provided.id:
2507
+ raise ValueError("package Skill identity does not match manifest")
2508
+ entry_path = _package_asset_path(package_root, skill.entry.path)
2404
2509
  entry_text = read_text(entry_path) if entry_path.exists() else ""
2405
2510
  summary = first_paragraph(entry_text) or f"Package Skill {skill.skill_id}"
2406
2511
  rel_skill = skill_path.relative_to(package_root).as_posix()
2407
2512
  rel_entry = skill.entry.path.replace("\\", "/")
2408
2513
  required_knowledge = [
2409
2514
  {"xid": xid, "required": True, "reason": "package declaration"}
2410
- for xid in skill.required_knowledge
2515
+ for xid in dict.fromkeys([*provided.required_knowledge, *skill.required_knowledge])
2411
2516
  ]
2412
2517
  entries.append(
2413
2518
  SkillCatalogEntry(
@@ -2443,7 +2548,8 @@ def _build_package_skills(package: DiscoveredSkillPackage) -> list[SkillCatalogE
2443
2548
  ),
2444
2549
  responsibility=skill.role or "package Skill execution",
2445
2550
  preconditions=[],
2446
- knowledge_slots=[],
2551
+ knowledge_slots=[{"slot": need["xid"], "bind": need["xid"], "required": True, "min": 1}
2552
+ for need in required_knowledge],
2447
2553
  missing=[],
2448
2554
  zone_metadata={
2449
2555
  "source": "installed_skill_package",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xrefkit
3
- Version: 0.7.7
3
+ Version: 0.7.8
4
4
  Summary: Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit
5
5
  Author: synthaicode
6
6
  License: MIT License
@@ -79,6 +79,7 @@ tests/test_os_family_definition.py
79
79
  tests/test_os_knowledge_family_definition.py
80
80
  tests/test_os_selected_family.py
81
81
  tests/test_ownership.py
82
+ tests/test_package_knowledge_resolution.py
82
83
  tests/test_package_skill_run.py
83
84
  tests/test_packaged_native_governance.py
84
85
  tests/test_packmeta.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes