xrefkit 0.7.7__tar.gz → 0.7.9__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.9}/PKG-INFO +1 -1
  2. {xrefkit-0.7.7 → xrefkit-0.7.9}/pyproject.toml +1 -1
  3. xrefkit-0.7.9/tests/test_package_knowledge_resolution.py +193 -0
  4. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_package_skill_run.py +29 -0
  5. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/__init__.py +1 -1
  6. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/catalog.py +120 -7
  7. {xrefkit-0.7.7 → xrefkit-0.7.9/xrefkit.egg-info}/PKG-INFO +1 -1
  8. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit.egg-info/SOURCES.txt +1 -0
  9. {xrefkit-0.7.7 → xrefkit-0.7.9}/LICENSE +0 -0
  10. {xrefkit-0.7.7 → xrefkit-0.7.9}/README.md +0 -0
  11. {xrefkit-0.7.7 → xrefkit-0.7.9}/setup.cfg +0 -0
  12. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_artifact_selected_family.py +0 -0
  13. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_attention_pet.py +0 -0
  14. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_attention_pet_client_protocol.py +0 -0
  15. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_attention_pet_codex_session.py +0 -0
  16. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_attention_pet_fit.py +0 -0
  17. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_azure_connection.py +0 -0
  18. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_azure_import.py +0 -0
  19. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_azure_recovery.py +0 -0
  20. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_azure_update_candidate.py +0 -0
  21. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_azure_writer.py +0 -0
  22. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_boundary_analysis.py +0 -0
  23. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_brownfield_csharp_structure_definitions.py +0 -0
  24. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_brownfield_file_editing_protocol.py +0 -0
  25. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_business_intake_conversation_definitions.py +0 -0
  26. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_business_intake_definition.py +0 -0
  27. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_calibration_lint.py +0 -0
  28. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_catalog_preparation_definition.py +0 -0
  29. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_check_skill_knowledge_xids.py +0 -0
  30. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_ci_workflow_invariants.py +0 -0
  31. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_cli.py +0 -0
  32. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_code_constraint_definition.py +0 -0
  33. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_collect_analyzer_sarif.py +0 -0
  34. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_compact_skill_logs.py +0 -0
  35. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_constraint_derivation_family_definition.py +0 -0
  36. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_constraint_derivation_selected_family.py +0 -0
  37. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_contribution_adoption_bytes.py +0 -0
  38. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_contribution_returns.py +0 -0
  39. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_convert_to_xrefkit_skill.py +0 -0
  40. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_cs_scope_probe.py +0 -0
  41. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_csharp_commonality.py +0 -0
  42. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_csharp_naming_profile.py +0 -0
  43. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_ctx.py +0 -0
  44. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_cutover_readiness.py +0 -0
  45. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_dashboard.py +0 -0
  46. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_database_batch_definition_migration.py +0 -0
  47. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_decision_trace.py +0 -0
  48. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_design_business_intake_selected_family.py +0 -0
  49. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_design_planning_definition_migration.py +0 -0
  50. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_dotnet_definition_candidate.py +0 -0
  51. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_editorial_family_definition.py +0 -0
  52. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_editorial_intake_definition.py +0 -0
  53. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_editorial_selected_family.py +0 -0
  54. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_embedded_startup_pack.py +0 -0
  55. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_error_policy_audit.py +0 -0
  56. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_error_policy_locator.py +0 -0
  57. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_execution_binding.py +0 -0
  58. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_existing_skill_definition_batch.py +0 -0
  59. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_final_skilldefinition_batch.py +0 -0
  60. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_flow_selected_family.py +0 -0
  61. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_fm_multiroot.py +0 -0
  62. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_gate.py +0 -0
  63. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_gateway.py +0 -0
  64. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_gateway_mcp.py +0 -0
  65. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_gateway_skill_adapter.py +0 -0
  66. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_gateway_work_items.py +0 -0
  67. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_goal_desired_state.py +0 -0
  68. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_governance_entry.py +0 -0
  69. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_governance_host.py +0 -0
  70. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_host_precheck.py +0 -0
  71. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_human_evaluation.py +0 -0
  72. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_implementation_flow_definition.py +0 -0
  73. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_implementation_review_selected_family.py +0 -0
  74. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_inbound_uploads.py +0 -0
  75. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_instruction_workflow.py +0 -0
  76. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_knowledge_relations_validator.py +0 -0
  77. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_language_review_definition.py +0 -0
  78. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_legacy_guidance.py +0 -0
  79. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_legacy_migration.py +0 -0
  80. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_legacy_resources.py +0 -0
  81. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_mcp_package_routing.py +0 -0
  82. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_mcp_setup.py +0 -0
  83. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_mcp_subagent_startup.py +0 -0
  84. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_mcp_subagent_startup_integration.py +0 -0
  85. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_ontology_assessment_validator.py +0 -0
  86. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_os_family_definition.py +0 -0
  87. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_os_knowledge_family_definition.py +0 -0
  88. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_os_selected_family.py +0 -0
  89. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_ownership.py +0 -0
  90. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_packaged_native_governance.py +0 -0
  91. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_packmeta.py +0 -0
  92. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_plan_markdown.py +0 -0
  93. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_plan_observation.py +0 -0
  94. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_project_management_materialization.py +0 -0
  95. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_project_quality_baseline.py +0 -0
  96. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_qa_report_definition.py +0 -0
  97. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_reporting_profiles.py +0 -0
  98. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_reporting_quality.py +0 -0
  99. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_repository_skill_adoption.py +0 -0
  100. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_repository_startup_pack.py +0 -0
  101. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_resource_provider.py +0 -0
  102. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_runtime_contracts.py +0 -0
  103. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_sarif_to_locator.py +0 -0
  104. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_security_definition_migration.py +0 -0
  105. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_site_release_metadata.py +0 -0
  106. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_definition.py +0 -0
  107. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_definition_governance.py +0 -0
  108. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_definition_mcp.py +0 -0
  109. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_definition_runtime.py +0 -0
  110. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_edits.py +0 -0
  111. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_maturity_return.py +0 -0
  112. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_release_compatibility.py +0 -0
  113. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skill_runtime_audit.py +0 -0
  114. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skillmeta.py +0 -0
  115. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_skills_sync.py +0 -0
  116. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_source_analysis_fragments.py +0 -0
  117. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_structure_catalog.py +0 -0
  118. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_subagent_startup.py +0 -0
  119. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_subagent_startup_boundaries.py +0 -0
  120. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_wbs.py +0 -0
  121. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_work_management.py +0 -0
  122. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_work_packages.py +0 -0
  123. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_workflow_family_definition.py +0 -0
  124. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xref.py +0 -0
  125. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xrefkit_instance.py +0 -0
  126. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xrefkit_tools.py +0 -0
  127. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xrefkit_v2_discovery.py +0 -0
  128. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xrefkit_v2_models.py +0 -0
  129. {xrefkit-0.7.7 → xrefkit-0.7.9}/tests/test_xrefkit_v2_pipeline.py +0 -0
  130. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/__main__.py +0 -0
  131. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/__init__.py +0 -0
  132. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/__main__.py +0 -0
  133. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/client.py +0 -0
  134. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/client_protocol.py +0 -0
  135. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/codex_session.py +0 -0
  136. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/evaluator.py +0 -0
  137. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/model.py +0 -0
  138. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/presentation.py +0 -0
  139. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/profiles.py +0 -0
  140. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/scenarios.py +0 -0
  141. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/server.py +0 -0
  142. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/attention_pet/store.py +0 -0
  143. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/azure_connection.py +0 -0
  144. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/azure_import.py +0 -0
  145. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/azure_recovery.py +0 -0
  146. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/azure_update_candidate.py +0 -0
  147. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/azure_writer.py +0 -0
  148. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/boundary_analysis.py +0 -0
  149. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/catalog_cli.py +0 -0
  150. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/cli.py +0 -0
  151. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/contracts.py +0 -0
  152. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/ctx.py +0 -0
  153. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/dashboard.py +0 -0
  154. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/decision_trace.py +0 -0
  155. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/discovery.py +0 -0
  156. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/execution_binding.py +0 -0
  157. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/execution_binding_cli.py +0 -0
  158. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/gate.py +0 -0
  159. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/gateway.py +0 -0
  160. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/goalstate.py +0 -0
  161. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/governance_entry.py +0 -0
  162. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/governance_entry_cli.py +0 -0
  163. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/governance_host.py +0 -0
  164. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/hashing.py +0 -0
  165. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/host_precheck.py +0 -0
  166. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/import_skill.py +0 -0
  167. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/instance.py +0 -0
  168. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/loaders.py +0 -0
  169. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/__init__.py +0 -0
  170. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/audit.py +0 -0
  171. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/bootstrap.py +0 -0
  172. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/cli.py +0 -0
  173. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/client_cache.py +0 -0
  174. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/client_flow.py +0 -0
  175. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/context_registry.py +0 -0
  176. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/context_token.py +0 -0
  177. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/contracts.py +0 -0
  178. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/contribution_adoption.py +0 -0
  179. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/contribution_returns.py +0 -0
  180. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/dist.py +0 -0
  181. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/gateway.py +0 -0
  182. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/governed_overlays.py +0 -0
  183. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/inbound_uploads.py +0 -0
  184. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/knowledge_edits.py +0 -0
  185. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/legacy_guidance.py +0 -0
  186. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/legacy_migration.py +0 -0
  187. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/legacy_resources.py +0 -0
  188. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/ownership.py +0 -0
  189. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/repository.py +0 -0
  190. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/schemas.py +0 -0
  191. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/server.py +0 -0
  192. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/setup.py +0 -0
  193. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/skill_edits.py +0 -0
  194. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/skill_maturity.py +0 -0
  195. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/startup_contract_pack.py +0 -0
  196. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/subagent_startup.py +0 -0
  197. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp/update_gate_intake.py +0 -0
  198. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/mcp_tools.py +0 -0
  199. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/__init__.py +0 -0
  200. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/common.py +0 -0
  201. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/effective_bundle.py +0 -0
  202. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/human_evaluation.py +0 -0
  203. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/local_manifest.py +0 -0
  204. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/package_manifest.py +0 -0
  205. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/run_log.py +0 -0
  206. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/server_config.py +0 -0
  207. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/models/skill_definition.py +0 -0
  208. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/operations_cli.py +0 -0
  209. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/ownership.py +0 -0
  210. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/packmeta.py +0 -0
  211. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/plan_markdown.py +0 -0
  212. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/plan_observation.py +0 -0
  213. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/registry.py +0 -0
  214. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/reporting.py +0 -0
  215. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/reporting_profiles.py +0 -0
  216. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/repository_skills.py +0 -0
  217. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resolver.py +0 -0
  218. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resource_provider.py +0 -0
  219. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/attention_pet/client-state.schema.json +0 -0
  220. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/attention_pet/pet.css +0 -0
  221. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/attention_pet/pet.html +0 -0
  222. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/attention_pet/pet.js +0 -0
  223. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/contracts.json +0 -0
  224. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/current.json +0 -0
  225. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json +0 -0
  226. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md +0 -0
  227. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json +0 -0
  228. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md +0 -0
  229. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/model_body.md +0 -0
  230. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/000_agent_entry.md +0 -0
  231. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/011_startup_xref_routing.md +0 -0
  232. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/015_shared_memory_operations.md +0 -0
  233. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/016_uncertainty_protocol.md +0 -0
  234. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/017_base_and_xref_layering.md +0 -0
  235. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/053_context_direction_security_guard.md +0 -0
  236. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/base/startup_sources/yomiyasu_LICENSE.txt +0 -0
  237. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/migration/docs/guides/062_legacy_flow_skill_migration_guide.md +0 -0
  238. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/migration/knowledge/operations/130_legacy_flow_skill_migration_rules.md +0 -0
  239. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/migration/knowledge/organization/160_context_direction_guard_rules.md +0 -0
  240. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/migration/skills/os/legacy_flow_skill_migration/SKILL.v1.md +0 -0
  241. {xrefkit-0.7.7 → xrefkit-0.7.9}/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.9}/xrefkit/resources/migration/skills/repository_adoption.json +0 -0
  243. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/resources/migration/tools/migrate_legacy_flow_skill.py +0 -0
  244. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/runlog.py +0 -0
  245. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skill_definition.py +0 -0
  246. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skill_definition_catalog.py +0 -0
  247. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skill_definition_governance.py +0 -0
  248. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skillmeta.py +0 -0
  249. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skillrun.py +0 -0
  250. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/skills_sync.py +0 -0
  251. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/structure_catalog.py +0 -0
  252. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/subagent_startup.py +0 -0
  253. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/tools/__init__.py +0 -0
  254. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/tools/__main__.py +0 -0
  255. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/v2_cli.py +0 -0
  256. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/wbs.py +0 -0
  257. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/work_management.py +0 -0
  258. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/work_management_view.py +0 -0
  259. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/workspace.py +0 -0
  260. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit/xref.py +0 -0
  261. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit.egg-info/dependency_links.txt +0 -0
  262. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit.egg-info/entry_points.txt +0 -0
  263. {xrefkit-0.7.7 → xrefkit-0.7.9}/xrefkit.egg-info/requires.txt +0 -0
  264. {xrefkit-0.7.7 → xrefkit-0.7.9}/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.9
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.9"
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,193 @@
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")
167
+
168
+
169
+ @pytest.mark.parametrize(("declared", "inline", "accepted"), [
170
+ ("xid-7A2F4C8D1401", "7A2F4C8D1401", True),
171
+ ("7A2F4C8D1401", "xid-7A2F4C8D1401", True),
172
+ ("xid-7A2F4C8D1401", "7A2F4C8D1402", False),
173
+ ("xid-knowledge-rules", "knowledge-rules", False),
174
+ ("xid-7A2F4C8D1401-extra", "7A2F4C8D1401", False),
175
+ ])
176
+ def test_native_hex_inline_identity_compatibility(tmp_path, declared, inline, accepted):
177
+ catalog = package_catalog(tmp_path)
178
+ package = catalog.discovered_packages[0]
179
+ package.manifest.provides.knowledge[0].xid = declared
180
+ (package.package_root / "knowledge/rules.md").write_text(f"<!-- xid: {inline} -->\n# Rules")
181
+ if accepted:
182
+ assert catalog.get_document_by_xid(declared)["xid"] == declared
183
+ assert catalog.expand_knowledge(declared)["content"]
184
+ else:
185
+ with pytest.raises(ValueError, match="identity does not match"):
186
+ catalog.get_document_by_xid(declared)
187
+
188
+
189
+ def test_prefixed_native_startup_identity_cannot_shadow_core(tmp_path):
190
+ catalog = package_catalog(tmp_path)
191
+ catalog.discovered_packages[0].manifest.provides.knowledge[0].xid = "xid-0B5C58B5E5B2"
192
+ with pytest.raises(ValueError, match="core startup XID"):
193
+ catalog.get_document_by_xid("xid-0B5C58B5E5B2")
@@ -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.9"
@@ -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,64 @@ 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(_native_xid_identity(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(_native_xid_identity(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
+ document_xid = first_xid(text) if path.suffix.lower() == ".md" else None
733
+ if document_xid and _native_xid_identity(document_xid) != _native_xid_identity(xid):
734
+ raise ValueError(f"package document identity does not match manifest: {xid}")
735
+ return XRefDocument(
736
+ xid=xid,
737
+ title=first_heading(text, path.stem),
738
+ path=f"package:{package.package_id}/{path.relative_to(package.package_root.resolve()).as_posix()}",
739
+ summary=first_paragraph(text),
740
+ content=text,
741
+ links=markdown_xid_link_targets(text),
742
+ content_hash=stable_hash(text),
743
+ )
744
+
694
745
  def _scan_knowledge(self) -> list[tuple[KnowledgeCatalogEntry, str]]:
695
746
  """One consistent read per file: entry hash and body come from the
696
747
  same text, so they can never disagree."""
@@ -714,6 +765,17 @@ class XRefCatalog:
714
765
  text = read_text(path)
715
766
  if first_xid(text) not in known:
716
767
  entries.append((_knowledge_entry(builtin_root, None, path, text), text))
768
+ for package, xid, path, kind in self._package_assets():
769
+ if kind != "knowledge":
770
+ continue
771
+ text = read_text(path)
772
+ entry = _knowledge_entry(package.package_root.resolve(), None, path, text)
773
+ document = self._package_document(package, xid, path, text)
774
+ entries.append((replace(
775
+ entry, xid=xid, path=document.path, missing=[],
776
+ zone_metadata={"source": "installed_skill_package", "package_id": package.package_id,
777
+ "package_version": package.version},
778
+ ), text))
717
779
  return entries
718
780
 
719
781
  def get_repository_identity(self) -> dict[str, str]:
@@ -742,6 +804,7 @@ class XRefCatalog:
742
804
  def build_knowledge_context(self, query: str, limit: int = 5) -> dict:
743
805
  scanned = self._scan_knowledge()
744
806
  ranked = _rank_entries(query, [entry for entry, _text in scanned])[:limit]
807
+ _require_unique_knowledge([entry for entry, _ in scanned])
745
808
  by_xid = {entry.xid: (entry, text) for entry, text in scanned}
746
809
  expanded: list[dict] = []
747
810
  missing: list[dict] = []
@@ -899,6 +962,7 @@ class XRefCatalog:
899
962
  """
900
963
  entry = self._skill_by_id(skill_id)
901
964
  knowledge = self.knowledge
965
+ _require_unique_knowledge(knowledge)
902
966
  by_xid = {item.xid: item for item in knowledge}
903
967
  if entry.definition_format == "skill_definition_v1":
904
968
  needs = entry.knowledge_slots
@@ -1234,6 +1298,18 @@ class XRefCatalog:
1234
1298
  for local_xid, path in local_knowledge_files(self.repo_root)
1235
1299
  if local_xid == xid
1236
1300
  )
1301
+ package_documents = {}
1302
+ for package, asset_xid, path, _kind in self._package_assets():
1303
+ if asset_xid == xid:
1304
+ text = read_text(path)
1305
+ matches.append((path, text))
1306
+ package_documents[path] = self._package_document(package, xid, path, text)
1307
+ if package_documents:
1308
+ # Installed packages cannot shadow a core migration document merely
1309
+ # because the consumer repository does not contain that document.
1310
+ builtin_root = Path(__file__).resolve().parents[1] / "resources" / "migration"
1311
+ if self.repo_root != builtin_root and builtin_root.is_dir():
1312
+ matches.extend(_managed_markdown_matches_by_xid(builtin_root, None, xid))
1237
1313
  # An active local edit is an explicit overlay of its source document.
1238
1314
  # Suppress only the corresponding source path; unrelated documents
1239
1315
  # declaring the same XID remain a conflict.
@@ -1277,12 +1353,19 @@ class XRefCatalog:
1277
1353
  "xid": xid,
1278
1354
  "message": "multiple catalog-visible documents declare this XID; refusing path-order selection",
1279
1355
  "matches": [
1280
- _document_conflict_match(self.repo_root, self.ownership, path, text)
1356
+ ({"source": "installed_skill_package",
1357
+ "content_hash": package_documents[path].content_hash}
1358
+ if path in package_documents else
1359
+ _document_conflict_match(self.repo_root, self.ownership, path, text))
1281
1360
  for path, text in matches
1282
1361
  ],
1283
1362
  }
1284
1363
  if len(matches) == 1:
1285
1364
  path, text = matches[0]
1365
+ if path in package_documents:
1366
+ return _conditional_document_response(
1367
+ package_documents[path], known_version, self.repository_fingerprint,
1368
+ )
1286
1369
  for entry in (self.skills if self.skill_definition_paths else []):
1287
1370
  if (entry.definition_format == "skill_definition_v1"
1288
1371
  and entry.package_id is None
@@ -1638,6 +1721,33 @@ def _knowledge_entry(
1638
1721
  )
1639
1722
 
1640
1723
 
1724
+ def _native_xid_identity(xid: str) -> str:
1725
+ """Accept the legacy anchor prefix only for native 12-digit hex XIDs."""
1726
+ match = re.fullmatch(r"(?:xid-)?([0-9A-F]{12})", xid)
1727
+ return match.group(1) if match else xid
1728
+
1729
+
1730
+ def _package_asset_path(root: Path, relative: str) -> Path:
1731
+ """Manifest paths are portable relative allowlist entries, never glob roots."""
1732
+ portable = PurePosixPath(relative)
1733
+ if ("\\" in relative or ":" in relative or portable.is_absolute()
1734
+ or PureWindowsPath(relative).drive or ".." in portable.parts
1735
+ or portable.as_posix() != relative):
1736
+ raise ValueError(f"package asset escapes root or is not a portable relative path: {relative}")
1737
+ path = (root / relative).resolve()
1738
+ if not path.is_relative_to(root):
1739
+ raise ValueError(f"package asset escapes root: {relative}")
1740
+ return path
1741
+
1742
+
1743
+ def _require_unique_knowledge(entries: list[KnowledgeCatalogEntry]) -> None:
1744
+ seen: set[str] = set()
1745
+ for entry in entries:
1746
+ if entry.xid in seen:
1747
+ raise ValueError(f"knowledge xid conflict: {entry.xid} appears in multiple catalog-visible knowledge entries")
1748
+ seen.add(entry.xid)
1749
+
1750
+
1641
1751
  def _external_knowledge_entry(root: Path, path: Path, text: str) -> KnowledgeCatalogEntry:
1642
1752
  xid = first_xid(text)
1643
1753
  if not xid:
@@ -2400,14 +2510,16 @@ def _build_package_skills(package: DiscoveredSkillPackage) -> list[SkillCatalogE
2400
2510
  )
2401
2511
  continue
2402
2512
  skill = load_package_skill_definition(skill_path)
2403
- entry_path = package.package_root / skill.entry.path
2513
+ if skill.xid != provided.xid or skill.skill_id != provided.id:
2514
+ raise ValueError("package Skill identity does not match manifest")
2515
+ entry_path = _package_asset_path(package_root, skill.entry.path)
2404
2516
  entry_text = read_text(entry_path) if entry_path.exists() else ""
2405
2517
  summary = first_paragraph(entry_text) or f"Package Skill {skill.skill_id}"
2406
2518
  rel_skill = skill_path.relative_to(package_root).as_posix()
2407
2519
  rel_entry = skill.entry.path.replace("\\", "/")
2408
2520
  required_knowledge = [
2409
2521
  {"xid": xid, "required": True, "reason": "package declaration"}
2410
- for xid in skill.required_knowledge
2522
+ for xid in dict.fromkeys([*provided.required_knowledge, *skill.required_knowledge])
2411
2523
  ]
2412
2524
  entries.append(
2413
2525
  SkillCatalogEntry(
@@ -2443,7 +2555,8 @@ def _build_package_skills(package: DiscoveredSkillPackage) -> list[SkillCatalogE
2443
2555
  ),
2444
2556
  responsibility=skill.role or "package Skill execution",
2445
2557
  preconditions=[],
2446
- knowledge_slots=[],
2558
+ knowledge_slots=[{"slot": need["xid"], "bind": need["xid"], "required": True, "min": 1}
2559
+ for need in required_knowledge],
2447
2560
  missing=[],
2448
2561
  zone_metadata={
2449
2562
  "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.9
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