xrefkit 0.6.1__tar.gz → 0.6.2__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 (216) hide show
  1. {xrefkit-0.6.1 → xrefkit-0.6.2}/PKG-INFO +11 -1
  2. {xrefkit-0.6.1 → xrefkit-0.6.2}/README.md +10 -0
  3. {xrefkit-0.6.1 → xrefkit-0.6.2}/pyproject.toml +1 -1
  4. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_artifact_selected_family.py +4 -3
  5. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_brownfield_csharp_structure_definitions.py +5 -3
  6. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_brownfield_file_editing_protocol.py +1 -1
  7. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_business_intake_conversation_definitions.py +5 -4
  8. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_business_intake_definition.py +6 -7
  9. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_catalog_preparation_definition.py +5 -5
  10. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_code_constraint_definition.py +5 -6
  11. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_constraint_derivation_family_definition.py +5 -6
  12. xrefkit-0.6.2/tests/test_constraint_derivation_selected_family.py +103 -0
  13. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_database_batch_definition_migration.py +5 -5
  14. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_design_business_intake_selected_family.py +2 -1
  15. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_design_planning_definition_migration.py +5 -7
  16. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_dotnet_definition_candidate.py +6 -4
  17. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_editorial_family_definition.py +5 -5
  18. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_editorial_intake_definition.py +5 -5
  19. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_editorial_selected_family.py +4 -3
  20. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_final_skilldefinition_batch.py +2 -1
  21. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_flow_selected_family.py +4 -4
  22. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_implementation_flow_definition.py +5 -7
  23. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_knowledge_relations_validator.py +18 -0
  24. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_language_review_definition.py +5 -6
  25. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_mcp_subagent_startup.py +68 -0
  26. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_mcp_subagent_startup_integration.py +8 -3
  27. xrefkit-0.6.2/tests/test_ontology_assessment_validator.py +115 -0
  28. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_os_family_definition.py +5 -5
  29. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_os_knowledge_family_definition.py +5 -5
  30. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_os_selected_family.py +4 -4
  31. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_qa_report_definition.py +5 -11
  32. xrefkit-0.6.2/tests/test_repository_skill_adoption.py +278 -0
  33. xrefkit-0.6.2/tests/test_repository_startup_pack.py +49 -0
  34. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_security_definition_migration.py +5 -9
  35. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_definition_mcp.py +111 -4
  36. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_definition_runtime.py +0 -4
  37. xrefkit-0.6.2/tests/test_skill_release_compatibility.py +313 -0
  38. xrefkit-0.6.2/tests/test_source_analysis_fragments.py +113 -0
  39. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_workflow_family_definition.py +5 -6
  40. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/__init__.py +1 -1
  41. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/audit.py +3 -2
  42. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/catalog.py +117 -25
  43. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/schemas.py +2 -0
  44. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/subagent_startup.py +8 -1
  45. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/packmeta.py +15 -4
  46. xrefkit-0.6.2/xrefkit/repository_skills.py +156 -0
  47. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skillmeta.py +40 -3
  48. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skillrun.py +31 -4
  49. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/xref.py +36 -7
  50. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit.egg-info/PKG-INFO +11 -1
  51. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit.egg-info/SOURCES.txt +6 -0
  52. xrefkit-0.6.1/tests/test_constraint_derivation_selected_family.py +0 -44
  53. {xrefkit-0.6.1 → xrefkit-0.6.2}/LICENSE +0 -0
  54. {xrefkit-0.6.1 → xrefkit-0.6.2}/setup.cfg +0 -0
  55. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_attention_pet.py +0 -0
  56. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_attention_pet_client_protocol.py +0 -0
  57. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_attention_pet_codex_session.py +0 -0
  58. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_attention_pet_fit.py +0 -0
  59. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_boundary_analysis.py +0 -0
  60. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_calibration_lint.py +0 -0
  61. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_check_skill_knowledge_xids.py +0 -0
  62. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_cli.py +0 -0
  63. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_collect_analyzer_sarif.py +0 -0
  64. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_contribution_returns.py +0 -0
  65. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_convert_to_xrefkit_skill.py +0 -0
  66. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_cs_scope_probe.py +0 -0
  67. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_csharp_commonality.py +0 -0
  68. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_csharp_naming_profile.py +0 -0
  69. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_ctx.py +0 -0
  70. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_cutover_readiness.py +0 -0
  71. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_dashboard.py +0 -0
  72. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_decision_trace.py +0 -0
  73. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_embedded_startup_pack.py +0 -0
  74. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_error_policy_audit.py +0 -0
  75. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_error_policy_locator.py +0 -0
  76. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_execution_binding.py +0 -0
  77. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_existing_skill_definition_batch.py +0 -0
  78. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_fm_multiroot.py +0 -0
  79. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_gate.py +0 -0
  80. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_gateway.py +0 -0
  81. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_gateway_mcp.py +0 -0
  82. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_gateway_skill_adapter.py +0 -0
  83. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_gateway_work_items.py +0 -0
  84. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_goal_desired_state.py +0 -0
  85. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_host_precheck.py +0 -0
  86. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_human_evaluation.py +0 -0
  87. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_implementation_review_selected_family.py +0 -0
  88. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_inbound_uploads.py +0 -0
  89. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_instruction_workflow.py +0 -0
  90. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_legacy_migration.py +0 -0
  91. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_mcp_package_routing.py +0 -0
  92. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_mcp_setup.py +0 -0
  93. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_ownership.py +0 -0
  94. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_packmeta.py +0 -0
  95. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_project_quality_baseline.py +0 -0
  96. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_resource_provider.py +0 -0
  97. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_runtime_contracts.py +0 -0
  98. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_sarif_to_locator.py +0 -0
  99. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_definition.py +0 -0
  100. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_definition_governance.py +0 -0
  101. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_edits.py +0 -0
  102. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_maturity_return.py +0 -0
  103. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skill_runtime_audit.py +0 -0
  104. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skillmeta.py +0 -0
  105. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_skills_sync.py +0 -0
  106. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_structure_catalog.py +0 -0
  107. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_subagent_startup.py +0 -0
  108. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_subagent_startup_boundaries.py +0 -0
  109. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_wbs.py +0 -0
  110. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xref.py +0 -0
  111. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xrefkit_instance.py +0 -0
  112. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xrefkit_tools.py +0 -0
  113. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xrefkit_v2_discovery.py +0 -0
  114. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xrefkit_v2_models.py +0 -0
  115. {xrefkit-0.6.1 → xrefkit-0.6.2}/tests/test_xrefkit_v2_pipeline.py +0 -0
  116. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/__main__.py +0 -0
  117. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/__init__.py +0 -0
  118. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/__main__.py +0 -0
  119. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/client.py +0 -0
  120. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/client_protocol.py +0 -0
  121. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/codex_session.py +0 -0
  122. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/evaluator.py +0 -0
  123. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/model.py +0 -0
  124. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/presentation.py +0 -0
  125. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/profiles.py +0 -0
  126. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/scenarios.py +0 -0
  127. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/server.py +0 -0
  128. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/attention_pet/store.py +0 -0
  129. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/boundary_analysis.py +0 -0
  130. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/catalog_cli.py +0 -0
  131. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/cli.py +0 -0
  132. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/contracts.py +0 -0
  133. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/ctx.py +0 -0
  134. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/dashboard.py +0 -0
  135. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/decision_trace.py +0 -0
  136. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/discovery.py +0 -0
  137. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/execution_binding.py +0 -0
  138. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/execution_binding_cli.py +0 -0
  139. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/gate.py +0 -0
  140. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/gateway.py +0 -0
  141. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/goalstate.py +0 -0
  142. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/hashing.py +0 -0
  143. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/host_precheck.py +0 -0
  144. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/import_skill.py +0 -0
  145. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/instance.py +0 -0
  146. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/loaders.py +0 -0
  147. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/__init__.py +0 -0
  148. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/bootstrap.py +0 -0
  149. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/cli.py +0 -0
  150. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/client_cache.py +0 -0
  151. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/client_flow.py +0 -0
  152. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/context_registry.py +0 -0
  153. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/context_token.py +0 -0
  154. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/contracts.py +0 -0
  155. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/contribution_adoption.py +0 -0
  156. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/contribution_returns.py +0 -0
  157. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/dist.py +0 -0
  158. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/gateway.py +0 -0
  159. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/inbound_uploads.py +0 -0
  160. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/knowledge_edits.py +0 -0
  161. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/legacy_migration.py +0 -0
  162. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/ownership.py +0 -0
  163. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/repository.py +0 -0
  164. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/server.py +0 -0
  165. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/setup.py +0 -0
  166. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/skill_edits.py +0 -0
  167. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/skill_maturity.py +0 -0
  168. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp/startup_contract_pack.py +0 -0
  169. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/mcp_tools.py +0 -0
  170. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/__init__.py +0 -0
  171. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/common.py +0 -0
  172. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/effective_bundle.py +0 -0
  173. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/human_evaluation.py +0 -0
  174. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/local_manifest.py +0 -0
  175. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/package_manifest.py +0 -0
  176. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/run_log.py +0 -0
  177. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/server_config.py +0 -0
  178. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/models/skill_definition.py +0 -0
  179. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/operations_cli.py +0 -0
  180. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/ownership.py +0 -0
  181. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/registry.py +0 -0
  182. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resolver.py +0 -0
  183. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resource_provider.py +0 -0
  184. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/attention_pet/client-state.schema.json +0 -0
  185. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/attention_pet/pet.css +0 -0
  186. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/attention_pet/pet.html +0 -0
  187. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/attention_pet/pet.js +0 -0
  188. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/contracts.json +0 -0
  189. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/current.json +0 -0
  190. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json +0 -0
  191. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md +0 -0
  192. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json +0 -0
  193. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md +0 -0
  194. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/model_body.md +0 -0
  195. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/000_agent_entry.md +0 -0
  196. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/011_startup_xref_routing.md +0 -0
  197. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/015_shared_memory_operations.md +0 -0
  198. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/016_uncertainty_protocol.md +0 -0
  199. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/017_base_and_xref_layering.md +0 -0
  200. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/resources/base/startup_sources/053_context_direction_security_guard.md +0 -0
  201. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/runlog.py +0 -0
  202. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skill_definition.py +0 -0
  203. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skill_definition_catalog.py +0 -0
  204. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skill_definition_governance.py +0 -0
  205. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/skills_sync.py +0 -0
  206. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/structure_catalog.py +0 -0
  207. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/subagent_startup.py +0 -0
  208. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/tools/__init__.py +0 -0
  209. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/tools/__main__.py +0 -0
  210. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/v2_cli.py +0 -0
  211. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/wbs.py +0 -0
  212. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit/workspace.py +0 -0
  213. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit.egg-info/dependency_links.txt +0 -0
  214. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit.egg-info/entry_points.txt +0 -0
  215. {xrefkit-0.6.1 → xrefkit-0.6.2}/xrefkit.egg-info/requires.txt +0 -0
  216. {xrefkit-0.6.1 → xrefkit-0.6.2}/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.6.1
3
+ Version: 0.6.2
4
4
  Summary: Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit
5
5
  Author: synthaicode
6
6
  License: MIT License
@@ -186,3 +186,13 @@ XRefKit does not require provider API keys to explore or install the package.
186
186
  Do not commit secrets, API keys, access tokens, `.env` files, or provider
187
187
  credentials. Authenticate external AI tools through their official provider
188
188
  mechanisms.
189
+
190
+ ## Repository Skill adoption and scoped source-analysis knowledge
191
+
192
+ This repository uses the audited canonical Skill sources listed in
193
+ `skills/repository_adoption.json`. Legacy source identities remain aliases;
194
+ external legacy split Skills and YAML Skill Packages remain supported. See
195
+ [SkillDefinition adoption](docs/core/contracts/096_skill_definition_contract.md#xid-E6A19D4B72C3).
196
+ The source-analysis common XID remains stable and routes coherent criteria
197
+ fragments on demand. Narrow tasks avoid unrelated bodies; full reviews retain
198
+ every required axis. No similarity-based knowledge merge or deletion occurs.
@@ -147,3 +147,13 @@ XRefKit does not require provider API keys to explore or install the package.
147
147
  Do not commit secrets, API keys, access tokens, `.env` files, or provider
148
148
  credentials. Authenticate external AI tools through their official provider
149
149
  mechanisms.
150
+
151
+ ## Repository Skill adoption and scoped source-analysis knowledge
152
+
153
+ This repository uses the audited canonical Skill sources listed in
154
+ `skills/repository_adoption.json`. Legacy source identities remain aliases;
155
+ external legacy split Skills and YAML Skill Packages remain supported. See
156
+ [SkillDefinition adoption](docs/core/contracts/096_skill_definition_contract.md#xid-E6A19D4B72C3).
157
+ The source-analysis common XID remains stable and routes coherent criteria
158
+ fragments on demand. Narrow tasks avoid unrelated bodies; full reviews retain
159
+ every required axis. No similarity-based knowledge merge or deletion occurs.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xrefkit"
7
- version = "0.6.1"
7
+ version = "0.6.2"
8
8
  description = "Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -25,9 +27,8 @@ def test_artifact_v1_parse_concrete_metadata_and_legacy(directory, skill_id, xid
25
27
  assert set(metadata["aliases"]) == {body_xid, meta_xid}
26
28
  assert metadata["inputs"] and metadata["outputs"]
27
29
  assert metadata["control_refs"] == []
28
- assert "CAP-" not in definition["method"]
29
- assert "## Reporting Contract" not in definition["method"]
30
- assert "skill_doc: `./SKILL.md`" in (repo / relative.parent / "meta.md").read_text()
30
+ assert_preserved_source_boundary(definition)
31
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
31
32
 
32
33
 
33
34
  def test_artifact_v1_explicit_batch_selection_and_knowledge_resolution():
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  from xrefkit.mcp.catalog import XRefCatalog
@@ -24,9 +26,9 @@ def test_tracked_trio_parse_aliases_metadata_and_legacy_readability():
24
26
  for forbidden in ("capability", "tuning", "responsibility", "execution_mode", "model", "maturity"):
25
27
  assert forbidden not in metadata
26
28
  for common in ("## Reporting Contract", "## Logging", "## Context Direction Guard"):
27
- assert common not in definition["method"]
28
- assert f"<!-- xid: {body_xid} -->" in (repo / "skills" / directory / "SKILL.md").read_text(encoding="utf-8")
29
- assert f"<!-- xid: {meta_xid} -->" in (repo / "skills" / directory / "meta.md").read_text(encoding="utf-8")
29
+ assert_preserved_source_boundary(definition)
30
+ assert_legacy_receipt(repo / 'skills' / directory / 'SKILL.md')
31
+ assert_legacy_receipt(repo / 'skills' / directory / 'meta.md')
30
32
 
31
33
 
32
34
  def test_tracked_trio_combined_catalog_and_knowledge_resolution():
@@ -5,7 +5,7 @@ ROOT = Path(__file__).resolve().parents[1]
5
5
 
6
6
 
7
7
  def test_brownfield_file_editing_protocol_is_in_canonical_and_packaged_skill() -> None:
8
- canonical = (ROOT / "skills" / "brownfield-workflow" / "SKILL.md").read_text(encoding="utf-8")
8
+ canonical = (ROOT / "skills" / "brownfield-workflow" / "SKILL.v1.md").read_text(encoding="utf-8")
9
9
  packaged = (
10
10
  ROOT / "packages" / "xrefkit-skills-brownfield" / "src" / "xrefkit_skills_brownfield"
11
11
  / "skills" / "brownfield_workflow" / "entry.md"
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  from xrefkit.mcp.catalog import XRefCatalog
@@ -21,10 +23,9 @@ def test_business_intake_v1_definitions_parse_aliases_and_preserve_legacy():
21
23
  assert metadata["control_refs"] == []
22
24
  for forbidden in ("capability", "tuning", "responsibility", "execution_mode", "model", "maturity"):
23
25
  assert forbidden not in metadata
24
- assert "## Context Direction Guard" not in definition["method"]
25
- assert "## Reporting Contract" not in definition["method"]
26
- assert f"<!-- xid: {body_xid} -->" in (repo / relative.parent / "SKILL.md").read_text(encoding="utf-8")
27
- assert f"skill_doc: `./SKILL.md`" in (repo / relative.parent / "meta.md").read_text(encoding="utf-8")
26
+ assert_preserved_source_boundary(definition)
27
+ assert_legacy_receipt(repo / relative.parent / 'SKILL.md')
28
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
28
29
 
29
30
 
30
31
  def test_business_intake_v1_explicit_catalog_selection_and_knowledge_resolution():
@@ -1,3 +1,4 @@
1
+ from repository_skill_receipts import assert_legacy_receipt
1
2
  from pathlib import Path
2
3
 
3
4
  from xrefkit.mcp.catalog import XRefCatalog
@@ -43,13 +44,11 @@ def test_business_intake_v1_definitions_parse_select_resolve_and_preserve_legacy
43
44
  assert resolved["unsatisfied_required"] == []
44
45
  assert resolved["needs"][0]["satisfied"] is True
45
46
 
46
- legacy = (directory / "SKILL.md").read_text(encoding="utf-8")
47
- meta = (directory / "meta.md").read_text(encoding="utf-8")
48
- assert f"<!-- xid: {body_xid} -->" in legacy
49
- assert f"<!-- xid: {meta_xid} -->" in meta
50
- assert "skill_doc: `./SKILL.md`" in meta
47
+ assert_legacy_receipt(directory / 'SKILL.md')
48
+ assert_legacy_receipt(directory / 'meta.md')
51
49
 
52
50
  catalog = XRefCatalog.build(repo, skill_definition_paths=paths)
53
- assert {entry.skill_id for entry in catalog.skills if entry.definition_format == "skill_definition_v1"} == {
54
- "business_learning_interview", "business_intake_scoping"
51
+ assert {"business_learning_interview", "business_intake_scoping"} <= {
52
+ entry.skill_id for entry in catalog.skills if entry.definition_format == "skill_definition_v1"
55
53
  }
54
+ assert len(catalog.skills) == 62
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -25,11 +27,9 @@ def test_v1_definitions_parse_with_aliases_and_concrete_metadata(skill_id, folde
25
27
  assert metadata["inputs"] and metadata["outputs"]
26
28
  assert metadata["control_refs"] == []
27
29
  assert not any(key in metadata for key in ("capability", "tuning", "responsibility", "execution_mode", "model", "model_tier", "maturity"))
28
- assert "CAP-" not in definition["method"]
29
- assert "## Reporting Contract" not in definition["method"]
30
- assert "## Required Knowledge (XID)" not in definition["method"]
31
- assert (repo / folder / "SKILL.md").read_text(encoding="utf-8").startswith("<!-- xid: ")
32
- assert (repo / folder / "meta.md").read_text(encoding="utf-8").startswith("<!-- xid: ")
30
+ assert_preserved_source_boundary(definition)
31
+ assert_legacy_receipt(repo / folder / 'SKILL.md')
32
+ assert_legacy_receipt(repo / folder / 'meta.md')
33
33
 
34
34
 
35
35
  def test_explicit_catalog_and_knowledge_resolution_cover_the_trio():
@@ -1,3 +1,4 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
1
2
  from pathlib import Path
2
3
 
3
4
  from xrefkit.mcp.catalog import XRefCatalog
@@ -38,10 +39,8 @@ def test_code_constraint_v1_resolves_selected_knowledge_and_legacy_files_are_unc
38
39
  assert all(need["activation_state"] == "active" for need in result["needs"])
39
40
  assert all(need["satisfied"] is True for need in result["needs"])
40
41
 
41
- meta = (repo / "skills/packs/constraint-derivation/code_constraint_derivation/meta.md").read_text(encoding="utf-8")
42
- legacy = (repo / "skills/packs/constraint-derivation/code_constraint_derivation/SKILL.md").read_text(encoding="utf-8")
43
- assert "skill_doc: `./SKILL.md`" in meta
44
- assert "<!-- xid: D4701BFC6EA4 -->" in meta
45
- assert "<!-- xid: D4701BFC6EA5 -->" in legacy
46
- assert "## Reporting Contract" not in definition["method"]
42
+ from repository_skill_receipts import assert_legacy_receipt
43
+ assert assert_legacy_receipt(repo / "skills/packs/constraint-derivation/code_constraint_derivation/meta.md")["xid"] == "D4701BFC6EA4"
44
+ assert assert_legacy_receipt(repo / "skills/packs/constraint-derivation/code_constraint_derivation/SKILL.md")["xid"] == "D4701BFC6EA5"
45
+ assert_preserved_source_boundary(definition)
47
46
  assert "111D282CA0EA" in definition["metadata"]["control_refs"]
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -24,13 +26,10 @@ def test_constraint_derivation_v1_migration(skill_id, xid, body_xid, meta_xid, s
24
26
  assert metadata["xid"] == xid
25
27
  assert set(metadata["aliases"]) == {body_xid, meta_xid}
26
28
  assert metadata["control_refs"] == ["111D282CA0EA"]
27
- assert "## Reporting Contract" not in definition["method"]
28
- assert "## Required Knowledge (XID)" not in definition["method"]
29
- assert "Context direction guard" not in definition["method"]
29
+ assert_preserved_source_boundary(definition)
30
30
 
31
- legacy = (repo / relative.parent / "SKILL.md").read_bytes()
32
- assert f"<!-- xid: {body_xid} -->".encode() in legacy
33
- assert f"skill_doc: `./SKILL.md`".encode() in (repo / relative.parent / "meta.md").read_bytes()
31
+ assert_legacy_receipt(repo / relative.parent / 'SKILL.md')
32
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
34
33
 
35
34
 
36
35
  def test_constraint_derivation_v1_explicit_selection_and_knowledge_resolution():
@@ -0,0 +1,103 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+
7
+ from xrefkit.mcp.catalog import XRefCatalog
8
+ from xrefkit.skill_definition import load_skill_definition
9
+
10
+
11
+ CASES = [
12
+ ("async_constraint_derivation", "9A4C7E1D2B60", "F6580A1C2346", "F6580A1C2345"),
13
+ ("auth_constraint_derivation", "C8F2A6D1E430", "A7691B2D3457", "A7691B2D3456"),
14
+ ("commonality_derivation", "E7B3C951A2D0", "B87A2C3E4568", "B87A2C3E4567"),
15
+ ("cross_constraint_derivation", "F4A8D2C6B190", "E5812C0D7FB7", "E5812C0D7FB6"),
16
+ ("design_constraint_derivation", "A6D9F3B1C720", "B214C6D8E012", "B214C6D8E011"),
17
+ ]
18
+
19
+
20
+ @pytest.mark.parametrize("skill_id,xid,body_xid,meta_xid", CASES)
21
+ def test_selected_constraint_derivation_v1(skill_id, xid, body_xid, meta_xid):
22
+ repo = Path(__file__).resolve().parents[1]
23
+ relative = Path(f"skills/packs/constraint-derivation/{skill_id}/SKILL.v1.md")
24
+ definition = load_skill_definition(repo / relative)
25
+ metadata = definition["metadata"]
26
+ assert metadata["xid"] == xid
27
+ expected_aliases = {body_xid, meta_xid}
28
+ if skill_id == "async_constraint_derivation":
29
+ expected_aliases.add("F6580A1C2344") # Previously published candidate alias.
30
+ assert set(metadata["aliases"]) == expected_aliases
31
+ assert metadata["control_refs"] == ["111D282CA0EA"]
32
+ assert_preserved_source_boundary(definition)
33
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
34
+
35
+
36
+ def test_selected_constraint_derivation_catalog_and_knowledge_resolution():
37
+ repo = Path(__file__).resolve().parents[1]
38
+ paths = [Path(f"skills/packs/constraint-derivation/{skill}/SKILL.v1.md") for skill, *_ in CASES]
39
+ catalog = XRefCatalog.build(repo, skill_definition_paths=paths)
40
+ entries = {entry.skill_id: entry for entry in catalog.skills if entry.skill_id in {case[0] for case in CASES}}
41
+ assert set(entries) == {case[0] for case in CASES}
42
+ assert all(entry.definition_format == "skill_definition_v1" for entry in entries.values())
43
+ for skill_id, _, _, _ in CASES:
44
+ definition = load_skill_definition(repo / f"skills/packs/constraint-derivation/{skill_id}/SKILL.v1.md")
45
+ need_ids = [need["id"] for need in definition["metadata"]["knowledge_needs"]]
46
+ result = catalog.resolve_skill_knowledge(skill_id, need_ids)
47
+ assert result["unresolved_activation"] == []
48
+ assert result["unsatisfied_required"] == []
49
+
50
+
51
+ def test_async_definition_resolves_actual_legacy_body_identity_after_retirement(tmp_path):
52
+ repo = Path(__file__).resolve().parents[1]
53
+ path = repo / "skills/packs/constraint-derivation/async_constraint_derivation/SKILL.v1.md"
54
+ definition = load_skill_definition(path)
55
+ # A retired split source must resolve through the configured successor.
56
+ successor = tmp_path / "SKILL.v1.md"
57
+ successor.write_bytes(path.read_bytes())
58
+ catalog = XRefCatalog.build(tmp_path, skill_definition_paths=[successor])
59
+ resolved = catalog.get_document_by_xid("F6580A1C2346")
60
+ assert resolved["content_hash"] == definition["content_hash"]
61
+ assert resolved["content"].encode("utf-8") == path.read_bytes()
62
+ assert resolved["xid"] == definition["metadata"]["xid"]
63
+ assert resolved["requested_xid"] == "F6580A1C2346"
64
+ assert resolved["resolved_via"] == "definition_alias"
65
+ cached = catalog.get_document_by_xid("F6580A1C2346", resolved["content_hash"])
66
+ assert cached["cache_status"] == "not_modified"
67
+
68
+
69
+ def test_alias_does_not_replace_present_source_or_hide_conflicts(tmp_path):
70
+ repo = Path(__file__).resolve().parents[1]
71
+ source = repo / "skills/packs/constraint-derivation/async_constraint_derivation"
72
+ successor = tmp_path / "SKILL.v1.md"
73
+ successor.write_bytes((source / "SKILL.v1.md").read_bytes())
74
+ documents = tmp_path / "docs"
75
+ documents.mkdir()
76
+ original = documents / "original.md"
77
+ original.write_bytes(b"<!-- xid: F6580A1C2346 -->\n# External original source\n")
78
+ catalog = XRefCatalog.build(tmp_path, skill_definition_paths=[successor])
79
+ resolved = catalog.get_document_by_xid("F6580A1C2346")
80
+ assert resolved["xid"] == "F6580A1C2346"
81
+ assert "resolved_via" not in resolved
82
+ (documents / "conflicting.md").write_bytes(original.read_bytes())
83
+ conflict = catalog.get_document_by_xid("F6580A1C2346")
84
+ assert conflict["error"] == "xid_conflict"
85
+ assert len(conflict["matches"]) == 2
86
+
87
+
88
+ def test_managed_definition_alias_and_canonical_share_raw_identity(tmp_path):
89
+ repo = Path(__file__).resolve().parents[1]
90
+ source = repo / "skills/packs/constraint-derivation/async_constraint_derivation/SKILL.v1.md"
91
+ directory = tmp_path / "skills" / "async_constraint_derivation"
92
+ directory.mkdir(parents=True)
93
+ successor = directory / "SKILL.v1.md"
94
+ successor.write_bytes(source.read_bytes())
95
+ definition = load_skill_definition(successor)
96
+ catalog = XRefCatalog.build(tmp_path, skill_definition_paths=[successor])
97
+ canonical = catalog.get_document_by_xid(definition["metadata"]["xid"])
98
+ alias = catalog.get_document_by_xid("F6580A1C2346")
99
+ assert canonical["content"].encode("utf-8") == successor.read_bytes()
100
+ assert canonical["content_hash"] == alias["content_hash"] == definition["content_hash"]
101
+ assert canonical["xid"] == alias["xid"]
102
+ cached = catalog.get_document_by_xid(canonical["xid"], alias["content_hash"])
103
+ assert cached["cache_status"] == "not_modified"
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  from xrefkit.mcp.catalog import XRefCatalog
@@ -34,12 +36,10 @@ def test_database_batch_v1_definitions_parse_with_aliases_and_preserve_legacy():
34
36
  assert set(metadata["aliases"]) == {body_xid, meta_xid}
35
37
  assert metadata["control_refs"] == []
36
38
  assert not {"capability", "tuning", "responsibility", "execution_mode", "model", "maturity"} & metadata.keys()
37
- assert "CAP-" not in definition["method"]
38
- assert "Skill operating contract" not in definition["method"]
39
- assert "Context direction guard" not in definition["method"]
39
+ assert_preserved_source_boundary(definition)
40
40
  legacy_dir = repo / relative.parent
41
- assert f"<!-- xid: {body_xid} -->" in (legacy_dir / "SKILL.md").read_text(encoding="utf-8")
42
- assert f"<!-- xid: {meta_xid} -->" in (legacy_dir / "meta.md").read_text(encoding="utf-8")
41
+ assert_legacy_receipt(legacy_dir / 'SKILL.md')
42
+ assert_legacy_receipt(legacy_dir / 'meta.md')
43
43
 
44
44
 
45
45
  def test_database_batch_combined_explicit_catalog_and_knowledge_resolution():
@@ -1,3 +1,4 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
1
2
  from pathlib import Path
2
3
 
3
4
  from xrefkit.mcp.catalog import XRefCatalog
@@ -26,7 +27,7 @@ def test_design_and_business_intake_batch_selects_without_identity_collision():
26
27
 
27
28
  assert len(xids) == len(set(xids))
28
29
  assert set(xids).isdisjoint(aliases)
29
- assert all("CAP-" not in definition["method"] for definition in definitions)
30
+ assert all(assert_preserved_source_boundary(definition) for definition in definitions)
30
31
 
31
32
  catalog = XRefCatalog.build(repo, skill_definition_paths=PATHS)
32
33
  expected = {definition["metadata"]["skill_id"] for definition in definitions}
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -36,7 +38,7 @@ def test_pair_omits_runtime_and_common_control_metadata(case):
36
38
  definition = load_skill_definition(repo / "skills" / skill_id / "SKILL.v1.md")
37
39
  forbidden = {"capability", "tuning", "responsibility", "execution_mode", "model", "maturity"}
38
40
  assert forbidden.isdisjoint(definition["metadata"])
39
- assert "## Reporting Contract" not in definition["method"]
41
+ assert_preserved_source_boundary(definition)
40
42
 
41
43
 
42
44
  def test_pair_is_explicitly_catalog_selected_and_knowledge_resolves():
@@ -63,10 +65,6 @@ def test_pair_is_explicitly_catalog_selected_and_knowledge_resolves():
63
65
  def test_legacy_files_remain_readable_and_unchanged_identity(case):
64
66
  skill_id = case[0]
65
67
  repo = Path(__file__).resolve().parents[1]
66
- body = (repo / "skills" / skill_id / "SKILL.md").read_text(encoding="utf-8")
67
- meta = (repo / "skills" / skill_id / "meta.md").read_text(encoding="utf-8")
68
+ assert_legacy_receipt(repo / 'skills' / skill_id / 'SKILL.md')
69
+ assert_legacy_receipt(repo / 'skills' / skill_id / 'meta.md')
68
70
  expected = next(item for item in CASES if item[0] == skill_id)
69
- assert f"xid-{expected[2]}" in body
70
- assert f"xid-{expected[3]}" in meta
71
- assert f"# Skill: {skill_id}" in body
72
- assert f"# Skill Meta: {skill_id}" in meta
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import shutil
3
3
  from pathlib import Path
4
+ from repository_skill_receipts import assert_preserved_source_boundary
4
5
 
5
6
  import pytest
6
7
 
@@ -12,7 +13,7 @@ from xrefkit.skillmeta import _parse_meta_lines
12
13
 
13
14
  def test_representative_conversion_is_lossless_and_nonactivating(tmp_path):
14
15
  repo = Path(__file__).resolve().parents[1]
15
- source = repo / "skills/dotnet_change_analysis"
16
+ source = repo / "tests/fixtures/legacy_dotnet_skill"
16
17
  dest = tmp_path / "skills/dotnet_change_analysis"
17
18
  shutil.copytree(source, dest)
18
19
  before = {p.name: p.read_bytes() for p in [dest / "SKILL.md", dest / "meta.md"]}
@@ -85,7 +86,8 @@ def test_tracked_v1_definition_resolves_knowledge_and_explicit_selection_is_sing
85
86
  assert definition["metadata"]["xid"] == "9883EF4E8CA9"
86
87
  assert set(definition["metadata"]["aliases"]) == {"D94E3B3A7C11", "1F4A6D20B8E1"}
87
88
  migrated_method = definition["method"].replace("9883EF4E8CA9", "D94E3B3A7C11")
88
- assert migrated_method.splitlines() == candidate["method"].splitlines()
89
+ assert migrated_method.split("## Preserved source obligations", 1)[0].rstrip().splitlines() == candidate["method"].rstrip().splitlines()
90
+ assert_preserved_source_boundary(definition)
89
91
  catalog = XRefCatalog.build(repo, skill_definition_paths=[relative])
90
92
  entries = [entry for entry in catalog.skills if entry.skill_id == "dotnet_change_analysis"]
91
93
  assert len(entries) == 1
@@ -99,5 +101,5 @@ def test_tracked_v1_definition_resolves_knowledge_and_explicit_selection_is_sing
99
101
 
100
102
  def test_legacy_meta_still_points_to_legacy_body():
101
103
  repo = Path(__file__).resolve().parents[1]
102
- meta = (repo / "skills/dotnet_change_analysis/meta.md").read_text(encoding="utf-8")
103
- assert "skill_doc: `./SKILL.md`" in meta
104
+ from repository_skill_receipts import assert_legacy_receipt
105
+ assert_legacy_receipt(repo / "skills/dotnet_change_analysis/meta.md")
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -19,12 +21,10 @@ def test_editorial_v1_migration(skill_id, xid, body_xid, meta_xid):
19
21
  assert definition["metadata"]["xid"] == xid
20
22
  assert set(definition["metadata"]["aliases"]) == {body_xid, meta_xid}
21
23
  assert definition["metadata"]["control_refs"] == []
22
- assert "## Reporting Contract" not in definition["method"]
23
- assert "## Required Knowledge (XID)" not in definition["method"]
24
- assert "Context direction guard" not in definition["method"]
24
+ assert_preserved_source_boundary(definition)
25
25
  assert "human" in definition["method"].lower()
26
- assert f"<!-- xid: {body_xid} -->".encode() in (repo / relative.parent / "SKILL.md").read_bytes()
27
- assert b"skill_doc: `./SKILL.md`" in (repo / relative.parent / "meta.md").read_bytes()
26
+ assert_legacy_receipt(repo / relative.parent / 'SKILL.md')
27
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
28
28
 
29
29
 
30
30
  def test_editorial_v1_explicit_selection_and_knowledge_resolution():
@@ -1,3 +1,4 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
1
2
  from pathlib import Path
2
3
 
3
4
  from xrefkit.mcp.catalog import XRefCatalog
@@ -12,8 +13,7 @@ def test_editorial_intake_v1_aliases_catalog_knowledge_and_legacy_body():
12
13
  assert metadata["xid"] == "7C4E9A2D6F81"
13
14
  assert set(metadata["aliases"]) == {"77F7D4CB9F99", "54437A84B3D0"}
14
15
  assert "capability" not in metadata
15
- assert "## Context Direction Guard" not in definition["method"]
16
- assert "## Reporting Contract" not in definition["method"]
16
+ assert_preserved_source_boundary(definition)
17
17
  catalog = XRefCatalog.build(repo, skill_definition_paths=[relative])
18
18
  entries = [entry for entry in catalog.skills if entry.skill_id == "editorial_intake"]
19
19
  assert len(entries) == 1
@@ -23,6 +23,6 @@ def test_editorial_intake_v1_aliases_catalog_knowledge_and_legacy_body():
23
23
  assert resolved["unresolved_activation"] == []
24
24
  assert resolved["unsatisfied_required"] == []
25
25
  assert all(need["satisfied"] is True for need in resolved["needs"])
26
- legacy = (repo / "skills/packs/editorial-ops/editorial_intake/SKILL.md").read_text(encoding="utf-8")
27
- assert "<!-- xid: 77F7D4CB9F99 -->" in legacy
28
- assert "skill_doc: `./SKILL.md`" in (repo / "skills/packs/editorial-ops/editorial_intake/meta.md").read_text(encoding="utf-8")
26
+ from repository_skill_receipts import assert_legacy_receipt
27
+ assert assert_legacy_receipt(repo / "skills/packs/editorial-ops/editorial_intake/SKILL.md")["xid"] == "77F7D4CB9F99"
28
+ assert_legacy_receipt(repo / "skills/packs/editorial-ops/editorial_intake/meta.md")
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -22,9 +24,8 @@ def test_editorial_v1_parse_aliases_and_legacy(skill_id, xid, body_xid, meta_xid
22
24
  assert metadata["xid"] == xid
23
25
  assert set(metadata["aliases"]) == {body_xid, meta_xid}
24
26
  assert metadata["control_refs"] == []
25
- assert "## Reporting Contract" not in definition["method"]
26
- assert "## Required Knowledge (XID)" not in definition["method"]
27
- assert "skill_doc: `./SKILL.md`" in (repo / relative.parent / "meta.md").read_text()
27
+ assert_preserved_source_boundary(definition)
28
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
28
29
 
29
30
 
30
31
  def test_editorial_v1_explicit_selection_and_knowledge_resolution():
@@ -1,3 +1,4 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
1
2
  from pathlib import Path
2
3
 
3
4
  from xrefkit.mcp.catalog import XRefCatalog
@@ -29,7 +30,7 @@ def test_final_batch_selects_together_without_identity_or_common_control_leaks()
29
30
 
30
31
  assert len(xids) == len(set(xids))
31
32
  assert set(xids).isdisjoint(aliases)
32
- assert all("CAP-" not in definition["method"] for definition in definitions)
33
+ assert all(assert_preserved_source_boundary(definition) for definition in definitions)
33
34
  assert all(
34
35
  "7A2F4C8D1601"
35
36
  not in [xid for need in definition["metadata"]["knowledge_needs"] for xid in need["seed_xids"]]
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -23,10 +25,8 @@ def test_flow_v1_parse_aliases_and_boundaries(skill_id, xid, body_xid, meta_xid)
23
25
  assert metadata["xid"] == xid
24
26
  assert set(metadata["aliases"]) == {body_xid, meta_xid}
25
27
  assert metadata["control_refs"] == []
26
- assert "CAP-" not in definition["method"]
27
- assert "## Reporting Contract" not in definition["method"]
28
- assert "## Required Knowledge (XID)" not in definition["method"]
29
- assert "skill_doc: `./SKILL.md`" in (repo / relative.parent / "meta.md").read_text()
28
+ assert_preserved_source_boundary(definition)
29
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
30
30
 
31
31
 
32
32
  def test_flow_v1_batch_selection_and_knowledge_resolution():
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -43,7 +45,7 @@ def test_flow_definition_omits_runtime_and_common_control_metadata(case) -> None
43
45
  metadata = definition["metadata"]
44
46
  forbidden = {"capability", "tuning", "responsibility", "execution_mode", "model", "maturity"}
45
47
  assert forbidden.isdisjoint(metadata)
46
- assert "## Reporting Contract" not in definition["method"]
48
+ assert_preserved_source_boundary(definition)
47
49
 
48
50
 
49
51
  def test_flow_definitions_are_explicitly_catalog_selected_and_knowledge_resolves() -> None:
@@ -67,9 +69,5 @@ def test_legacy_files_remain_readable_and_retain_original_xids(
67
69
  skill_id: str, xid: str, body_xid: str, meta_xid: str
68
70
  ) -> None:
69
71
  repo = Path(__file__).resolve().parents[1]
70
- body = (repo / "skills" / skill_id / "SKILL.md").read_text(encoding="utf-8")
71
- meta = (repo / "skills" / skill_id / "meta.md").read_text(encoding="utf-8")
72
- assert f"xid-{body_xid}" in body
73
- assert f"xid-{meta_xid}" in meta
74
- assert f"# Skill: {skill_id}" in body
75
- assert f"# Skill Meta: {skill_id}" in meta
72
+ assert_legacy_receipt(repo / 'skills' / skill_id / 'SKILL.md')
73
+ assert_legacy_receipt(repo / 'skills' / skill_id / 'meta.md')
@@ -60,6 +60,24 @@ class KnowledgeRelationsValidatorTests(unittest.TestCase):
60
60
  any("missing from knowledge/000_index.md" in error for error in errors)
61
61
  )
62
62
 
63
+ def test_resolves_relationship_to_repository_contract(self) -> None:
64
+ with tempfile.TemporaryDirectory() as tmp:
65
+ root = Path(tmp)
66
+ self._write(root, "knowledge/000_index.md", "<!-- xid: INDEX -->\n# Index\n- [A](a.md#xid-A)\n")
67
+ self._write(root, "knowledge/a.md", "<!-- xid: A -->\n# A\n\n## Knowledge Relations\n- applies_to: [Contract](../docs/contract.md#xid-CONTRACT)\n")
68
+ self._write(root, "docs/contract.md", "<!-- xid: CONTRACT -->\n# Contract\n")
69
+ self.assertEqual([], VALIDATOR.validate(root))
70
+
71
+ def test_duplicate_contract_owners_are_ambiguous_but_same_file_repeat_is_allowed(self) -> None:
72
+ with tempfile.TemporaryDirectory() as tmp:
73
+ root = Path(tmp)
74
+ self._write(root, "knowledge/000_index.md", "<!-- xid: INDEX -->\n# Index\n- [A](a.md#xid-A)\n")
75
+ self._write(root, "knowledge/a.md", "<!-- xid: A -->\n# A\n\n## Knowledge Relations\n- applies_to: [Contract](../docs/c1.md#xid-CONTRACT)\n")
76
+ self._write(root, "docs/c1.md", "<!-- xid: CONTRACT -->\n# Contract\n<!-- xid: CONTRACT -->\n")
77
+ self.assertEqual([], VALIDATOR.validate(root))
78
+ self._write(root, "docs/c2.md", "<!-- xid: CONTRACT -->\n# Other Contract\n")
79
+ self.assertTrue(any("ambiguous target XID 'CONTRACT'" in e for e in VALIDATOR.validate(root)))
80
+
63
81
  def test_reports_duplicate_primary_titles(self) -> None:
64
82
  with tempfile.TemporaryDirectory() as tmp:
65
83
  root = Path(tmp)
@@ -1,3 +1,5 @@
1
+ from repository_skill_receipts import assert_preserved_source_boundary
2
+ from repository_skill_receipts import assert_legacy_receipt
1
3
  from pathlib import Path
2
4
 
3
5
  import pytest
@@ -32,14 +34,11 @@ def test_language_review_v1_metadata_aliases_boundaries_and_legacy(skill_id, xid
32
34
  "## Check Role",
33
35
  "## Quality Gate",
34
36
  ):
35
- assert common_section not in definition["method"]
37
+ assert_preserved_source_boundary(definition)
36
38
  assert "unknown" in definition["method"]
37
39
  assert "handoff" in definition["method"]
38
- legacy = (repo / relative.parent / "SKILL.md").read_bytes()
39
- assert legacy.startswith(f"<!-- xid: {body_xid} -->".encode())
40
- meta = (repo / relative.parent / "meta.md").read_text(encoding="utf-8")
41
- assert f"<a id=\"xid-{meta_xid}\"></a>" in meta
42
- assert "skill_doc: `./SKILL.md`" in meta
40
+ assert_legacy_receipt(repo / relative.parent / 'SKILL.md')
41
+ assert_legacy_receipt(repo / relative.parent / 'meta.md')
43
42
 
44
43
 
45
44
  def test_language_review_v1_explicit_catalog_selection_and_knowledge_resolution():