xrefkit 0.7.5__tar.gz → 0.7.7__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.5/xrefkit.egg-info → xrefkit-0.7.7}/PKG-INFO +1 -1
- {xrefkit-0.7.5 → xrefkit-0.7.7}/pyproject.toml +1 -1
- xrefkit-0.7.7/tests/test_governance_host.py +248 -0
- xrefkit-0.7.7/tests/test_package_skill_run.py +101 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/__init__.py +1 -1
- xrefkit-0.7.7/xrefkit/governance_host.py +378 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/operations_cli.py +1 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skillrun.py +66 -15
- {xrefkit-0.7.5 → xrefkit-0.7.7/xrefkit.egg-info}/PKG-INFO +1 -1
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit.egg-info/SOURCES.txt +3 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/LICENSE +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/README.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/setup.cfg +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_artifact_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_attention_pet.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_attention_pet_client_protocol.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_attention_pet_codex_session.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_attention_pet_fit.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_azure_connection.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_azure_import.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_azure_recovery.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_azure_update_candidate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_azure_writer.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_boundary_analysis.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_brownfield_csharp_structure_definitions.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_brownfield_file_editing_protocol.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_business_intake_conversation_definitions.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_business_intake_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_calibration_lint.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_catalog_preparation_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_check_skill_knowledge_xids.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_ci_workflow_invariants.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_code_constraint_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_collect_analyzer_sarif.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_compact_skill_logs.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_constraint_derivation_family_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_constraint_derivation_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_contribution_adoption_bytes.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_contribution_returns.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_convert_to_xrefkit_skill.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_cs_scope_probe.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_csharp_commonality.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_csharp_naming_profile.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_ctx.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_cutover_readiness.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_dashboard.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_database_batch_definition_migration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_decision_trace.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_design_business_intake_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_design_planning_definition_migration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_dotnet_definition_candidate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_editorial_family_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_editorial_intake_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_editorial_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_embedded_startup_pack.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_error_policy_audit.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_error_policy_locator.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_execution_binding.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_existing_skill_definition_batch.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_final_skilldefinition_batch.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_flow_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_fm_multiroot.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_gate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_gateway.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_gateway_mcp.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_gateway_skill_adapter.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_gateway_work_items.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_goal_desired_state.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_governance_entry.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_host_precheck.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_human_evaluation.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_implementation_flow_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_implementation_review_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_inbound_uploads.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_instruction_workflow.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_knowledge_relations_validator.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_language_review_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_legacy_guidance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_legacy_migration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_legacy_resources.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_mcp_package_routing.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_mcp_setup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_mcp_subagent_startup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_mcp_subagent_startup_integration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_ontology_assessment_validator.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_os_family_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_os_knowledge_family_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_os_selected_family.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_ownership.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_packaged_native_governance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_packmeta.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_plan_markdown.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_plan_observation.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_project_management_materialization.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_project_quality_baseline.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_qa_report_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_reporting_profiles.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_reporting_quality.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_repository_skill_adoption.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_repository_startup_pack.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_resource_provider.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_runtime_contracts.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_sarif_to_locator.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_security_definition_migration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_site_release_metadata.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_definition_governance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_definition_mcp.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_definition_runtime.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_edits.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_maturity_return.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_release_compatibility.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skill_runtime_audit.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skillmeta.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_skills_sync.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_source_analysis_fragments.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_structure_catalog.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_subagent_startup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_subagent_startup_boundaries.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_wbs.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_work_management.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_work_packages.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_workflow_family_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xref.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xrefkit_instance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xrefkit_tools.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xrefkit_v2_discovery.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xrefkit_v2_models.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/tests/test_xrefkit_v2_pipeline.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/__main__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/__init__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/__main__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/client.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/client_protocol.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/codex_session.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/evaluator.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/model.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/presentation.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/profiles.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/scenarios.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/server.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/attention_pet/store.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/azure_connection.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/azure_import.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/azure_recovery.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/azure_update_candidate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/azure_writer.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/boundary_analysis.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/catalog_cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/contracts.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/ctx.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/dashboard.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/decision_trace.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/discovery.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/execution_binding.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/execution_binding_cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/gate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/gateway.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/goalstate.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/governance_entry.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/governance_entry_cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/hashing.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/host_precheck.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/import_skill.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/instance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/loaders.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/__init__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/audit.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/bootstrap.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/catalog.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/client_cache.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/client_flow.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/context_registry.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/context_token.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/contracts.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/contribution_adoption.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/contribution_returns.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/dist.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/gateway.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/governed_overlays.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/inbound_uploads.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/knowledge_edits.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/legacy_guidance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/legacy_migration.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/legacy_resources.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/ownership.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/repository.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/schemas.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/server.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/setup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/skill_edits.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/skill_maturity.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/startup_contract_pack.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/subagent_startup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp/update_gate_intake.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/mcp_tools.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/__init__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/common.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/effective_bundle.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/human_evaluation.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/local_manifest.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/package_manifest.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/run_log.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/server_config.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/models/skill_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/ownership.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/packmeta.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/plan_markdown.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/plan_observation.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/registry.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/reporting.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/reporting_profiles.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/repository_skills.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resolver.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resource_provider.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/attention_pet/client-state.schema.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/attention_pet/pet.css +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/attention_pet/pet.html +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/attention_pet/pet.js +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/contracts.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/current.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/model_body.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/000_agent_entry.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/011_startup_xref_routing.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/015_shared_memory_operations.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/016_uncertainty_protocol.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/017_base_and_xref_layering.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/053_context_direction_security_guard.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/base/startup_sources/yomiyasu_LICENSE.txt +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/docs/guides/062_legacy_flow_skill_migration_guide.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/knowledge/operations/130_legacy_flow_skill_migration_rules.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/knowledge/organization/160_context_direction_guard_rules.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/skills/os/legacy_flow_skill_migration/SKILL.v1.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/skills/os/legacy_flow_skill_migration/references/legacy_flow_skill_migration_template.md +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/skills/repository_adoption.json +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/resources/migration/tools/migrate_legacy_flow_skill.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/runlog.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skill_definition.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skill_definition_catalog.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skill_definition_governance.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skillmeta.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/skills_sync.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/structure_catalog.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/subagent_startup.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/tools/__init__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/tools/__main__.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/v2_cli.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/wbs.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/work_management.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/work_management_view.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/workspace.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit/xref.py +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit.egg-info/dependency_links.txt +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit.egg-info/entry_points.txt +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit.egg-info/requires.txt +0 -0
- {xrefkit-0.7.5 → xrefkit-0.7.7}/xrefkit.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Local host integration checks use simulated subprocess/UI, never real approval."""
|
|
2
|
+
import copy
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import subprocess
|
|
6
|
+
from types import SimpleNamespace
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from test_governance_entry import case, host_receipt, HOST_KEY
|
|
11
|
+
from test_subagent_startup import startup
|
|
12
|
+
from xrefkit.governance_entry import digest, validate_result
|
|
13
|
+
from xrefkit.mcp.contribution_adoption import HmacHumanApprovalVerifier
|
|
14
|
+
from xrefkit import governance_host as host
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def local(case, monkeypatch):
|
|
19
|
+
root, packet, _ = case
|
|
20
|
+
packet_file = root / "work/packet.json"
|
|
21
|
+
packet_file.write_text(json.dumps(packet))
|
|
22
|
+
receipt = host_receipt(root, packet)
|
|
23
|
+
receipt_file = root / "work/receipt.json"
|
|
24
|
+
receipt_file.write_text(json.dumps(receipt))
|
|
25
|
+
state_file = root / "authority.dpapi"
|
|
26
|
+
state = {"schema": "xrefkit.local_host_authority/v1", "root": str(root),
|
|
27
|
+
"packet_hash": packet["packet_hash"], "receipt_hash": digest(receipt),
|
|
28
|
+
"host_secret": HOST_KEY, "applied": False}
|
|
29
|
+
monkeypatch.setattr(host, "_load_state", lambda path: copy.deepcopy(state))
|
|
30
|
+
monkeypatch.setattr(host, "_save_state", lambda path, value, **kwargs: state.update(value))
|
|
31
|
+
return root, packet, packet_file, receipt_file, state_file, state
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_native_decline_never_applies_or_issues_human_secret(local, monkeypatch):
|
|
35
|
+
root, _, packet, receipt, state_file, state = local
|
|
36
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: False)
|
|
37
|
+
result = host.apply_local(root, packet, receipt, state_file, root / "work/reflection.json")
|
|
38
|
+
assert result["status"] == "human_declined_no_application"
|
|
39
|
+
assert not (root / "knowledge/item.md").exists()
|
|
40
|
+
assert "human_secret" not in state and not state["applied"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_native_action_applies_with_separate_keys_and_stale_replay_refuses(local, monkeypatch):
|
|
44
|
+
root, _, packet, receipt, state_file, state = local
|
|
45
|
+
observed = []
|
|
46
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: observed.append(args) or True)
|
|
47
|
+
result = host.apply_local(root, packet, receipt, state_file, root / "work/reflection.json")
|
|
48
|
+
assert result["runtime_activation"] == "not_performed"
|
|
49
|
+
assert observed[0][0] == "knowledge/item.md" and "+# New" in observed[0][2]
|
|
50
|
+
assert state["human_secret"] != state["host_secret"]
|
|
51
|
+
assert (root / "knowledge/item.md").read_bytes() == (root / "work/candidate.md").read_bytes()
|
|
52
|
+
with pytest.raises(ValueError, match="unapplied dispatch"):
|
|
53
|
+
host.apply_local(root, packet, receipt, state_file, root / "work/replay.json")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.mark.parametrize("mutation", ["candidate", "target"])
|
|
57
|
+
def test_change_during_dialog_refuses_even_after_ui_accepts(local, monkeypatch, mutation):
|
|
58
|
+
root, _, packet, receipt, state_file, state = local
|
|
59
|
+
def change(*args):
|
|
60
|
+
path = root / ("work/candidate.md" if mutation == "candidate" else "knowledge/item.md")
|
|
61
|
+
path.parent.mkdir(exist_ok=True)
|
|
62
|
+
path.write_text("external change")
|
|
63
|
+
return True
|
|
64
|
+
monkeypatch.setattr(host, "_review_dialog", change)
|
|
65
|
+
with pytest.raises(ValueError, match="changed"):
|
|
66
|
+
host.apply_local(root, packet, receipt, state_file, root / "work/reflection.json")
|
|
67
|
+
assert not state["applied"]
|
|
68
|
+
if mutation == "target":
|
|
69
|
+
assert (root / "knowledge/item.md").read_text() == "external change"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@pytest.mark.parametrize("field", ["packet_hash", "receipt_hash", "root"])
|
|
73
|
+
def test_wrong_dispatch_state_rejected_before_dialog(local, monkeypatch, field):
|
|
74
|
+
root, _, packet, receipt, state_file, state = local
|
|
75
|
+
state[field] = "wrong"
|
|
76
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: pytest.fail("UI must not open"))
|
|
77
|
+
with pytest.raises(ValueError, match="does not match"):
|
|
78
|
+
host.apply_local(root, packet, receipt, state_file, root / "work/reflection.json")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_failed_gate_cannot_be_human_approved(local, monkeypatch):
|
|
82
|
+
root, packet, packet_file, receipt_file, state_file, state = local
|
|
83
|
+
receipt = host_receipt(root, packet, failed=True)
|
|
84
|
+
receipt_file.write_text(json.dumps(receipt))
|
|
85
|
+
state["receipt_hash"] = digest(receipt)
|
|
86
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: pytest.fail("UI must not open"))
|
|
87
|
+
with pytest.raises(ValueError, match="failed or unknown"):
|
|
88
|
+
host.apply_local(root, packet_file, receipt_file, state_file, root / "work/reflection.json")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_tampered_signature_refused_even_with_matching_receipt_digest(local, monkeypatch):
|
|
92
|
+
root, _, packet, receipt_file, state_file, state = local
|
|
93
|
+
receipt = json.loads(receipt_file.read_text())
|
|
94
|
+
receipt["signature"] = "wrong"
|
|
95
|
+
receipt_file.write_text(json.dumps(receipt))
|
|
96
|
+
state["receipt_hash"] = digest(receipt)
|
|
97
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: pytest.fail("UI must not open"))
|
|
98
|
+
with pytest.raises(ValueError, match="signature"):
|
|
99
|
+
host.apply_local(root, packet, receipt_file, state_file, root / "work/reflection.json")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_evidence_destination_cannot_overwrite_packet(local, monkeypatch):
|
|
103
|
+
root, _, packet, receipt, state_file, _ = local
|
|
104
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: pytest.fail("UI must not open"))
|
|
105
|
+
with pytest.raises(ValueError, match="overwrite"):
|
|
106
|
+
host.apply_local(root, packet, receipt, state_file, packet)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.parametrize("events", [[], [{"type": "thread.started", "thread_id": "x"}],
|
|
110
|
+
[{"type": "thread.started", "thread_id": "x"}, {"type": "turn.failed"}],
|
|
111
|
+
[{"type": "thread.started", "thread_id": "x"}, {"type": "turn.completed"}, {"type": "turn.completed"}]])
|
|
112
|
+
def test_missing_or_failed_terminal_events_are_not_execution(tmp_path, events):
|
|
113
|
+
path = tmp_path / "events.jsonl"
|
|
114
|
+
path.write_text("\n".join(json.dumps(event) for event in events))
|
|
115
|
+
with pytest.raises(ValueError):
|
|
116
|
+
host._completed_session(path)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_valid_single_completion(tmp_path):
|
|
120
|
+
path = tmp_path / "events.jsonl"
|
|
121
|
+
path.write_text('{"type":"thread.started","thread_id":"actual-session"}\n{"type":"turn.completed"}\n')
|
|
122
|
+
assert host._completed_session(path) == "actual-session"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_authority_never_inherited_by_child(monkeypatch):
|
|
126
|
+
monkeypatch.setenv("XREFKIT_GOVERNANCE_HOST_SECRET", "private")
|
|
127
|
+
monkeypatch.setenv("XREFKIT_GOVERNANCE_HUMAN_SECRET", "private")
|
|
128
|
+
monkeypatch.setenv("XREFKIT_CONTRIBUTION_APPROVAL_SECRET", "private")
|
|
129
|
+
env = host._child_environment()
|
|
130
|
+
assert not any(key.startswith("XREFKIT_GOVERNANCE_") for key in env)
|
|
131
|
+
assert "XREFKIT_CONTRIBUTION_APPROVAL_SECRET" not in env
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_child_open_refusal_never_dispatches(case, monkeypatch):
|
|
135
|
+
root, packet, _ = case
|
|
136
|
+
source = root / "work/packet.json"
|
|
137
|
+
source.write_text(json.dumps(packet))
|
|
138
|
+
binary = root / "codex.exe"
|
|
139
|
+
binary.write_bytes(b"test fixture, never executable")
|
|
140
|
+
monkeypatch.setattr(host.subprocess, "run", lambda *args, **kwargs:
|
|
141
|
+
SimpleNamespace(returncode=2, stdout='{"ok":false}'))
|
|
142
|
+
monkeypatch.setattr(host.subprocess, "Popen", lambda *args, **kwargs: pytest.fail("must not dispatch"))
|
|
143
|
+
with pytest.raises(ValueError, match="Skill run refused"):
|
|
144
|
+
host.dispatch_local(root, source, binary, root / "work/dispatch")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_process_failure_never_generates_host_authority(case, monkeypatch):
|
|
148
|
+
root, packet, _ = case
|
|
149
|
+
source = root / "work/packet.json"
|
|
150
|
+
source.write_text(json.dumps(packet))
|
|
151
|
+
binary = root / "codex.exe"
|
|
152
|
+
binary.write_bytes(b"test fixture, never executable")
|
|
153
|
+
monkeypatch.setattr(host.subprocess, "run", lambda *args, **kwargs:
|
|
154
|
+
SimpleNamespace(returncode=0, stdout='{"ok":true,"run_id":"opened"}'))
|
|
155
|
+
process = SimpleNamespace(returncode=7, pid=123, communicate=lambda *args, **kwargs: None)
|
|
156
|
+
monkeypatch.setattr(host.subprocess, "Popen", lambda *args, **kwargs: process)
|
|
157
|
+
monkeypatch.setattr(host.secrets, "token_hex", lambda *args: pytest.fail("key must not be generated"))
|
|
158
|
+
with pytest.raises(ValueError, match="process failed"):
|
|
159
|
+
host.dispatch_local(root, source, binary, root / "work/dispatch")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_no_cli_automatic_approval_option():
|
|
163
|
+
with pytest.raises(SystemExit) as exc:
|
|
164
|
+
host.main(["--root", ".", "apply", "--packet", "a", "--receipt", "b",
|
|
165
|
+
"--authority-state", "c", "--out", "d", "--yes"])
|
|
166
|
+
assert exc.value.code == 2
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def test_applied_but_authority_save_failure_carries_reflection(local, monkeypatch):
|
|
170
|
+
root, _, packet, receipt, state_file, _ = local
|
|
171
|
+
monkeypatch.setattr(host, "_review_dialog", lambda *args: True)
|
|
172
|
+
def fail_save(*args, **kwargs):
|
|
173
|
+
raise OSError("simulated authority disk failure")
|
|
174
|
+
monkeypatch.setattr(host, "_save_state", fail_save)
|
|
175
|
+
with pytest.raises(host.AppliedEvidenceError) as exc:
|
|
176
|
+
host.apply_local(root, packet, receipt, state_file, root / "work/reflection.json")
|
|
177
|
+
assert (root / "knowledge/item.md").read_bytes() == (root / "work/candidate.md").read_bytes()
|
|
178
|
+
assert exc.value.reflection["target"]["path"] == "knowledge/item.md"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def test_cli_distinguishes_applied_evidence_failure(monkeypatch, capsys):
|
|
182
|
+
reflection = {"target": {"path": "skills/example/SKILL.v1.md", "sha256": "observed-hash"}}
|
|
183
|
+
def failed(*args):
|
|
184
|
+
raise host.AppliedEvidenceError(reflection)
|
|
185
|
+
monkeypatch.setattr(host, "apply_local", failed)
|
|
186
|
+
code = host.main(["--root", ".", "apply", "--packet", "a", "--receipt", "b",
|
|
187
|
+
"--authority-state", "c", "--out", "d"])
|
|
188
|
+
assert code == 3
|
|
189
|
+
assert "observed-hash" in capsys.readouterr().out
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@pytest.mark.parametrize("invalid_run", [None, "identity", "escalated"])
|
|
193
|
+
def test_dispatch_attests_only_actual_opened_run_and_completed_output(case, monkeypatch, invalid_run):
|
|
194
|
+
root, packet, _ = case
|
|
195
|
+
source = root / "work/packet.json"
|
|
196
|
+
source.write_text(json.dumps(packet))
|
|
197
|
+
binary = root / "codex.exe"
|
|
198
|
+
binary.write_bytes(b"test fixture, never executable")
|
|
199
|
+
host_receipt(root, packet) # Test-only prepared body/closed log.
|
|
200
|
+
out = root / "work/dispatch"
|
|
201
|
+
state = {}
|
|
202
|
+
child_path = None
|
|
203
|
+
def open_run(argv, **kwargs):
|
|
204
|
+
nonlocal child_path
|
|
205
|
+
child_path = Path(argv[argv.index("--out") + 1])
|
|
206
|
+
assert child_path.name.endswith("_skill_run_shared_asset_update_gate.md")
|
|
207
|
+
text = (root / "work/child.md").read_text().replace("work/analysis.md", "work/dispatch/analysis.json")
|
|
208
|
+
child_path.write_text(text)
|
|
209
|
+
return SimpleNamespace(returncode=0, stdout='{"ok":true,"run_id":"child-test-run"}')
|
|
210
|
+
def launch(argv, **kwargs):
|
|
211
|
+
def communicate(prompt, **options):
|
|
212
|
+
assert b"Do not open another run" in prompt
|
|
213
|
+
(out / "analysis.json").write_bytes((root / "work/analysis.md").read_bytes())
|
|
214
|
+
Path(argv[argv.index("--output-last-message") + 1]).write_text("Analysis complete")
|
|
215
|
+
kwargs["stdout"].write(b'{"type":"thread.started","thread_id":"simulated-session"}\n{"type":"turn.completed"}\n')
|
|
216
|
+
if invalid_run == "identity":
|
|
217
|
+
child_path.write_text(child_path.read_text().replace("child-test-run", "replaced-run"))
|
|
218
|
+
elif invalid_run == "escalated":
|
|
219
|
+
child_path.write_text(child_path.read_text().replace(
|
|
220
|
+
"## Closure Gate\n- status: `done`", "## Closure Gate\n- status: `escalated`"))
|
|
221
|
+
return SimpleNamespace(returncode=0, pid=123, communicate=communicate)
|
|
222
|
+
monkeypatch.setattr(host.subprocess, "run", open_run)
|
|
223
|
+
monkeypatch.setattr(host.subprocess, "Popen", launch)
|
|
224
|
+
monkeypatch.setattr(host, "_state_path", lambda execution_id: root / "authority.dpapi")
|
|
225
|
+
monkeypatch.setattr(host, "_save_state", lambda path, value, **kwargs: state.update(value))
|
|
226
|
+
if invalid_run:
|
|
227
|
+
expected = "host-opened child identity" if invalid_run == "identity" else "completed child Skill run"
|
|
228
|
+
with pytest.raises(ValueError, match=expected):
|
|
229
|
+
host.dispatch_local(root, source, binary, out)
|
|
230
|
+
assert not state and not (out / "receipt.json").exists()
|
|
231
|
+
else:
|
|
232
|
+
result = host.dispatch_local(root, source, binary, out)
|
|
233
|
+
receipt = json.loads(Path(result["receipt"]).read_text())
|
|
234
|
+
verifier = HmacHumanApprovalVerifier(state["host_secret"])
|
|
235
|
+
assert validate_result(root, packet, receipt, verifier)["packet_hash"] == packet["packet_hash"]
|
|
236
|
+
provenance = json.loads((out / "dispatch.json").read_text())
|
|
237
|
+
verifier.verify_event(provenance["event"], provenance["signature"])
|
|
238
|
+
assert provenance["event"]["thread_id"] == "simulated-session"
|
|
239
|
+
assert state["host_secret"] not in (out / "receipt.json").read_text()
|
|
240
|
+
assert not (root / "knowledge/item.md").exists()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@pytest.mark.skipif(host.os.name != "nt", reason="Windows operator adapter")
|
|
244
|
+
def test_windows_dpapi_roundtrip():
|
|
245
|
+
disposable = b"non-secret disposable integration test"
|
|
246
|
+
ciphertext = host._protect(disposable)
|
|
247
|
+
assert ciphertext != disposable
|
|
248
|
+
assert host._protect(ciphertext, decrypt=True) == disposable
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@pytest.mark.parametrize(
|
|
5
|
+
("module", "reference", "xid"),
|
|
6
|
+
[
|
|
7
|
+
("xrefkit_skills_csharp", "xrefkit.skills.csharp::csharp.review", "xid-skill-csharp-review"),
|
|
8
|
+
("xrefkit_skills_brownfield", "xrefkit.skills.brownfield::brownfield.workflow", "xid-skill-brownfield-workflow"),
|
|
9
|
+
("xrefkit_skills_batch_regression", "xrefkit.skills.batch_regression::batch.impact_regression", "xid-skill-batch-impact-regression"),
|
|
10
|
+
],
|
|
11
|
+
)
|
|
12
|
+
def test_installed_package_run_binds_over_mcp(tmp_path, module, reference, xid):
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
import tempfile
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
pytest.importorskip(module)
|
|
21
|
+
anyio = pytest.importorskip("anyio")
|
|
22
|
+
pytest.importorskip("mcp")
|
|
23
|
+
from mcp.client.session import ClientSession
|
|
24
|
+
from mcp.client.stdio import StdioServerParameters, stdio_client
|
|
25
|
+
|
|
26
|
+
repo = Path(__file__).resolve().parents[1]
|
|
27
|
+
cli = [sys.executable, "-m", "xrefkit"]
|
|
28
|
+
|
|
29
|
+
env = {**os.environ, "PYTHONPATH": str(repo)}
|
|
30
|
+
|
|
31
|
+
def run_cli(*args):
|
|
32
|
+
return subprocess.check_output(
|
|
33
|
+
cli + list(args), cwd=tmp_path, env=env, encoding="utf-8"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
args = [
|
|
37
|
+
"skill", "run",
|
|
38
|
+
"--package-skill", reference,
|
|
39
|
+
"--task", "Verify package run startup and MCP binding",
|
|
40
|
+
"--capability", "integration verification", "--tuning", "XRefKit package startup",
|
|
41
|
+
"--responsibility", "Verify run creation and correlation",
|
|
42
|
+
"--execution-mode", "subagent_required", "--json",
|
|
43
|
+
]
|
|
44
|
+
run = json.loads(run_cli(*args))
|
|
45
|
+
assert run["skill_id"] == reference.split("::")[1]
|
|
46
|
+
log_path = Path(run["run_log"])
|
|
47
|
+
assert log_path.is_relative_to(tmp_path)
|
|
48
|
+
assert Path(run["skill_doc"]).is_file()
|
|
49
|
+
log = log_path.read_text(encoding="utf-8")
|
|
50
|
+
assert "maturity: `unassessed`" in log
|
|
51
|
+
assert f"package_skill_xid: `{xid}`" in log
|
|
52
|
+
assert "package_skill_sha256:" in log
|
|
53
|
+
|
|
54
|
+
rejected = subprocess.run(
|
|
55
|
+
cli + [arg for arg in args if arg not in {"--capability", "integration verification"}],
|
|
56
|
+
cwd=tmp_path, env=env, capture_output=True, encoding="utf-8",
|
|
57
|
+
)
|
|
58
|
+
assert rejected.returncode == 1
|
|
59
|
+
assert json.loads(rejected.stdout)["run_id"] is None
|
|
60
|
+
|
|
61
|
+
async def scenario():
|
|
62
|
+
server = StdioServerParameters(
|
|
63
|
+
command=sys.executable,
|
|
64
|
+
args=[
|
|
65
|
+
"-m", "xrefkit.mcp.server", "--repo", str(repo),
|
|
66
|
+
"--audit-log", str(tmp_path / "mcp-audit.jsonl"),
|
|
67
|
+
],
|
|
68
|
+
cwd=str(repo),
|
|
69
|
+
)
|
|
70
|
+
with tempfile.TemporaryFile(mode="w+", encoding="utf-8") as stderr:
|
|
71
|
+
async with stdio_client(server, errlog=stderr) as (read, write):
|
|
72
|
+
async with ClientSession(read, write) as session:
|
|
73
|
+
await session.initialize()
|
|
74
|
+
startup = await session.call_tool("get_startup_context", {})
|
|
75
|
+
assert not startup.isError, startup.content
|
|
76
|
+
binding = await session.call_tool(
|
|
77
|
+
"bind_skill_run",
|
|
78
|
+
{"run_id": run["run_id"], "skill_id": run["skill_id"]},
|
|
79
|
+
)
|
|
80
|
+
assert not binding.isError, binding.content
|
|
81
|
+
bound = binding.structuredContent
|
|
82
|
+
assert bound["run_id"] == run["run_id"]
|
|
83
|
+
assert bound["skill_id"] == run["skill_id"]
|
|
84
|
+
assert "xrefkit skill correlate" in bound["client_record_command"]
|
|
85
|
+
run_cli(
|
|
86
|
+
"skill", "correlate", "--log", str(log_path),
|
|
87
|
+
"--run-id", bound["run_id"],
|
|
88
|
+
"--mcp-session-id", bound["mcp_session_id"],
|
|
89
|
+
"--repository-fingerprint", bound["repository_fingerprint"],
|
|
90
|
+
)
|
|
91
|
+
assert bound["mcp_session_id"] in log_path.read_text(encoding="utf-8")
|
|
92
|
+
requirements = await session.call_tool(
|
|
93
|
+
"get_skill_requirements", {"skill_id": run["skill_id"]}
|
|
94
|
+
)
|
|
95
|
+
assert not requirements.isError, requirements.content
|
|
96
|
+
assert not requirements.structuredContent["missing"]
|
|
97
|
+
skill = await session.call_tool("get_skill", {"skill_id": run["skill_id"]})
|
|
98
|
+
assert not skill.isError, skill.content
|
|
99
|
+
assert skill.structuredContent["skill_id"] == run["skill_id"]
|
|
100
|
+
|
|
101
|
+
anyio.run(scenario)
|