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