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