@shundoo-ai/dsh-cosmic 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/cordis.patch.yml +5 -5
  2. package/package.json +1 -1
  3. package/skills/cosmic-build/CHANGELOG.md +4 -0
  4. package/skills/cosmic-build/LOCAL-PATCHES.md +91 -40
  5. package/skills/cosmic-build/SKILL.md +46 -13
  6. package/skills/cosmic-build/assets/platform-report-filters/TypedReportFilterFields.java +169 -0
  7. package/skills/cosmic-build/assets/platform-report-filters/platform.patch +98 -0
  8. package/skills/cosmic-build/assets/report-algo-benchmark/ReportAlgoBenchmark.java +48 -0
  9. package/skills/cosmic-build/assets/report-algo-benchmark/ReportBenchmarkLogFactory.java +7 -0
  10. package/skills/cosmic-build/examples/java-rules/CosmicEntryQuery.java +26 -0
  11. package/skills/cosmic-build/examples/java-rules/CosmicReportAggregation.java +35 -0
  12. package/skills/cosmic-build/examples/java-rules/CosmicReportFilters.java +77 -0
  13. package/skills/cosmic-build/examples/java-rules/CosmicTimeAdapter.java +25 -0
  14. package/skills/cosmic-build/examples/java-rules/CosmicTimeAdapterCheck.java +26 -0
  15. package/skills/cosmic-build/knowledge/cosmic/platform/api/algo/GroupbyDataSet.md +47 -0
  16. package/skills/cosmic-build/knowledge/cosmic/platform/api/entity/report/FilterInfo.md +12 -12
  17. package/skills/cosmic-build/knowledge/cosmic/platform/api/entity/report/FilterItemInfo.md +2 -0
  18. package/skills/cosmic-build/knowledge/cosmic/platform/form-plugin.md +2 -4
  19. package/skills/cosmic-build/knowledge/cosmic/platform/java-type-contracts.md +11 -2
  20. package/skills/cosmic-build/knowledge/cosmic/platform/list-plugin.md +18 -14
  21. package/skills/cosmic-build/knowledge/cosmic/platform/operation-plugin.md +4 -4
  22. package/skills/cosmic-build/knowledge/cosmic/platform/reportlistdata-plugin.md +17 -9
  23. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/cross-entity-aggregate-writeback.md +2 -0
  24. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/pre-post-operation.md +15 -7
  25. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-algo.md +24 -68
  26. package/skills/cosmic-build/knowledge/cosmic/platform/workflow-plugin.md +2 -7
  27. package/skills/cosmic-build/references/application-context.md +35 -1
  28. package/skills/cosmic-build/references/common-reference.md +1 -1
  29. package/skills/cosmic-build/references/compile-guide.md +55 -68
  30. package/skills/cosmic-build/references/delivery.md +59 -7
  31. package/skills/cosmic-build/references/execution-contract.md +38 -0
  32. package/skills/cosmic-build/references/form-discovery.md +7 -1
  33. package/skills/cosmic-build/references/java-plugin-delivery.md +32 -162
  34. package/skills/cosmic-build/references/operation-dispatch.md +17 -0
  35. package/skills/cosmic-build/references/plugin-handoff-input.md +131 -0
  36. package/skills/cosmic-build/references/plugin-runtime-routing.md +1 -1
  37. package/skills/cosmic-build/references/report-filter-contract.md +78 -0
  38. package/skills/cosmic-build/references/sdk-inspection.md +23 -0
  39. package/skills/cosmic-build/schemas/data-model-authoring.schema.json +2 -3
  40. package/skills/cosmic-build/scripts/_http_client.py +55 -55
  41. package/skills/cosmic-build/scripts/appconfig_load.py +2 -2
  42. package/skills/cosmic-build/scripts/apply_report_filter_extension.py +39 -0
  43. package/skills/cosmic-build/scripts/bootstrap_cosmic_context.py +37 -2
  44. package/skills/cosmic-build/scripts/compile_plugin_source.py +279 -156
  45. package/skills/cosmic-build/scripts/execution_binding.py +40 -0
  46. package/skills/cosmic-build/scripts/inspect_platform_sdk.py +169 -0
  47. package/skills/cosmic-build/scripts/kd_api.py +23 -22
  48. package/skills/cosmic-build/scripts/kd_auth.py +1 -1
  49. package/skills/cosmic-build/scripts/kd_env_loader.py +19 -10
  50. package/skills/cosmic-build/scripts/kd_token_cache.py +2 -2
  51. package/skills/cosmic-build/scripts/kingscript_sdk_sync.py +350 -0
  52. package/skills/cosmic-build/scripts/kingscript_source_gate.py +11 -8
  53. package/skills/cosmic-build/scripts/platform_api_contract.py +246 -11
  54. package/skills/cosmic-build/scripts/plugin_corpus/build_index.py +403 -0
  55. package/skills/cosmic-build/scripts/plugin_corpus/jvm_classfile.py +281 -0
  56. package/skills/cosmic-build/scripts/plugin_corpus/measure_api_usage.py +446 -0
  57. package/skills/cosmic-build/scripts/plugin_source_gate.py +48 -7
  58. package/skills/cosmic-build/scripts/plugin_target_sdk.py +45 -0
  59. package/skills/cosmic-build/scripts/prepare_plugin_handoff.py +493 -47
  60. package/skills/cosmic-build/scripts/preview_url.py +35 -6
  61. package/skills/cosmic-build/scripts/query_plugin_handoff.py +250 -0
  62. package/skills/cosmic-build/scripts/register_plugins.py +28 -2
  63. package/skills/cosmic-build/scripts/render_output_cards.py +42 -9
  64. package/skills/cosmic-build/scripts/report_algo_benchmark.py +46 -0
  65. package/skills/cosmic-build/scripts/run.py +2 -2
  66. package/skills/cosmic-build/scripts/sync_generated_locale_assets.py +43 -0
  67. package/skills/cosmic-build/scripts/test/fixtures/ReportSdkCheck.java +64 -0
  68. package/skills/cosmic-build/scripts/test/fixtures/java_context_booking_native.json +541 -0
  69. package/skills/cosmic-build/scripts/test/test_add_rule_business_contract.py +85 -14
  70. package/skills/cosmic-build/scripts/test/test_batch5_drift_governance.py +12 -3
  71. package/skills/cosmic-build/scripts/test/test_build_meta_order.py +0 -16
  72. package/skills/cosmic-build/scripts/test/test_cli_continuation.py +87 -0
  73. package/skills/cosmic-build/scripts/test/test_compile_plugin_source.py +224 -3
  74. package/skills/cosmic-build/scripts/test/test_control_authoring.py +123 -4
  75. package/skills/cosmic-build/scripts/test/test_cosmic_sdk_examples.py +141 -0
  76. package/skills/cosmic-build/scripts/test/test_data_model_contract.py +30 -5
  77. package/skills/cosmic-build/scripts/test/test_delivery_stage_boundary.py +2 -10
  78. package/skills/cosmic-build/scripts/test/test_dym_sync_background.py +11 -0
  79. package/skills/cosmic-build/scripts/test/test_dynamic_form_metadata_only_contract.py +59 -1
  80. package/skills/cosmic-build/scripts/test/test_guide_skeleton_contract.py +87 -43
  81. package/skills/cosmic-build/scripts/test/test_inspect_platform_sdk.py +71 -0
  82. package/skills/cosmic-build/scripts/test/test_kd_api.py +67 -19
  83. package/skills/cosmic-build/scripts/test/test_kingscript_sdk_sync.py +221 -0
  84. package/skills/cosmic-build/scripts/test/test_kingscript_source_gate.py +10 -0
  85. package/skills/cosmic-build/scripts/test/test_list_configuration_closure.py +18 -0
  86. package/skills/cosmic-build/scripts/test/test_long_session_regressions.py +116 -0
  87. package/skills/cosmic-build/scripts/test/test_mcp_cli.py +524 -0
  88. package/skills/cosmic-build/scripts/test/test_modeling_input_recovery.py +141 -0
  89. package/skills/cosmic-build/scripts/test/test_open_world_cli_catalog.py +36 -2
  90. package/skills/cosmic-build/scripts/test/test_platform_api_contract.py +161 -1
  91. package/skills/cosmic-build/scripts/test/test_plugin_business_contract.py +91 -0
  92. package/skills/cosmic-build/scripts/test/test_plugin_corpus.py +195 -0
  93. package/skills/cosmic-build/scripts/test/test_plugin_handoff.py +346 -1
  94. package/skills/cosmic-build/scripts/test/test_plugin_target_sdk.py +70 -0
  95. package/skills/cosmic-build/scripts/test/test_preview_url.py +44 -1
  96. package/skills/cosmic-build/scripts/test/test_property_batch.py +22 -0
  97. package/skills/cosmic-build/scripts/test/test_property_input_discovery.py +13 -11
  98. package/skills/cosmic-build/scripts/test/test_query_plugin_handoff.py +160 -0
  99. package/skills/cosmic-build/scripts/test/test_register_plugins.py +31 -1
  100. package/skills/cosmic-build/scripts/test/test_render_output_cards.py +50 -4
  101. package/skills/cosmic-build/scripts/test/test_report_business_contract.py +27 -0
  102. package/skills/cosmic-build/scripts/test/test_report_doc_contract_sync.py +5 -4
  103. package/skills/cosmic-build/scripts/test/test_report_sdk_optimization.py +36 -0
  104. package/skills/cosmic-build/scripts/test/test_rule_batch_evidence.py +1 -1
  105. package/skills/cosmic-build/scripts/test/test_rule_domain_contract.py +20 -0
  106. package/skills/cosmic-build/scripts/test/test_rule_function_formula.py +16 -6
  107. package/skills/cosmic-build/scripts/test/test_skill_entry_contract.py +1 -0
  108. package/skills/cosmic-build/scripts/test/test_test_environment.py +45 -0
  109. package/skills/cosmic-build/scripts/test/test_verify_plugin_loading.py +79 -0
  110. package/skills/cosmic-build/scripts/test_environment.py +49 -0
  111. package/skills/cosmic-build/scripts/verify_plugin_loading.py +71 -0
  112. package/skills/cosmic-build/skills/cosmic-coding-impl/SKILL.md +86 -162
  113. package/skills/cosmic-build/skills/cosmic-coding-script/ATTRIBUTION.md +1 -1
  114. package/skills/cosmic-build/skills/cosmic-coding-script/SKILL.md +45 -14
  115. package/skills/cosmic-build/skills/cosmic-coding-script/references/kwc-controller-authoring.md +6 -0
  116. package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/README.md +29 -19
  117. package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/docs//350/204/232/346/234/254SDK.md +3 -4
  118. package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/indexes/package-index.md +1 -1
  119. package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/strategy.md +27 -18
  120. package/skills/cosmic-build/skills/cosmic-meta-api/SKILL.md +11 -17
  121. package/skills/cosmic-build/skills/cosmic-meta-api/apis/ai_meta.md +1 -1
  122. package/skills/cosmic-build/skills/cosmic-meta-api/apis/app_menu.md +1 -1
  123. package/skills/cosmic-build/skills/cosmic-meta-api/apis/meta_log.md +1 -1
  124. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/control-authoring.json +45 -4
  125. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/form-control-traits.json +1 -1
  126. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/layout-ui.json +18 -0
  127. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/menu-publish.json +8 -2
  128. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/property-batch.json +7 -0
  129. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/property-input-index.json +3 -3
  130. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/report-write-contracts.json +1 -0
  131. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-domain.json +37 -5
  132. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-event-contract.json +24 -3
  133. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/run-build-meta.json +61 -12
  134. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/dropdown-menu.schema.json +69 -0
  135. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/report-write.schema.json +2 -1
  136. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/rule-set.schema.json +1 -0
  137. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/rule-write.schema.json +14 -7
  138. package/skills/cosmic-build/skills/cosmic-meta-api/docs/api-summary.md +2 -2
  139. package/skills/cosmic-build/skills/cosmic-meta-api/modules/app-action/SKILL.md +6 -3
  140. package/skills/cosmic-build/skills/cosmic-meta-api/modules/develop/SKILL.md +1 -2
  141. package/skills/cosmic-build/skills/cosmic-meta-api/modules/export/SKILL.md +5 -6
  142. package/skills/cosmic-build/skills/cosmic-meta-api/modules/init/SKILL.md +13 -36
  143. package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/SKILL.md +8 -9
  144. package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/config.json.example +5 -15
  145. package/skills/cosmic-build/skills/cosmic-meta-api/modules/reset/SKILL.md +6 -6
  146. package/skills/cosmic-build/skills/cosmic-meta-api/modules/usage/SKILL.md +20 -148
  147. package/skills/cosmic-build/skills/cosmic-meta-api/modules/verify/SKILL.md +1 -1
  148. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/build_receipts.py +171 -0
  149. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_apps.py +25 -6
  150. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_controls.py +55 -21
  151. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_fields.py +10 -3
  152. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_formactions.py +63 -6
  153. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_forms.py +59 -2
  154. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_listui.py +8 -0
  155. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_metaops.py +36 -1
  156. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_plugins.py +115 -90
  157. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_properties.py +666 -4
  158. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_rules.py +1415 -87
  159. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/commands.py +6 -1
  160. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/config.py +28 -15
  161. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/execution_errors.py +40 -0
  162. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/formatters.py +32 -5
  163. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/property_policy_contract.py +6 -0
  164. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/report_ops.py +113 -17
  165. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/reset.py +3 -3
  166. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/rule_contract.py +107 -26
  167. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/build_meta_order.py +50 -49
  168. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py +856 -150
  169. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/field_decorator.py +47 -14
  170. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_receipt_resume.py +374 -0
  171. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_cli_failure_contract.py +24 -0
  172. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_creation_identity_boundary.py +4 -2
  173. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_dropdown_menu_contract.py +382 -0
  174. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_existing_form_ui.py +0 -25
  175. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_field_decorator.py +50 -6
  176. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_functional_group_resolution.py +83 -16
  177. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_identity_template_resolution.py +103 -0
  178. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_plugin_contract.py +28 -2
  179. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_readback_derivation.py +22 -0
  180. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_typed_filters.py +65 -0
  181. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_write_closure.py +1041 -15
  182. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_post_build_recovery.py +65 -0
  183. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_verification_evidence.py +17 -0
  184. package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/api-param-checklist.md +1 -1
  185. package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/rule-modeling-guide.md +7 -4
  186. package/skills/cosmic-build/skills/cosmic-meta-modeling/SKILL.md +61 -13
  187. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/app-menu/SKILL.md +8 -0
  188. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/formtemplate/SKILL.md +5 -0
  189. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/formtemplate/dynamic-form-artifact-schema.md +5 -0
  190. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/SKILL.md +21 -9
  191. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-entity-graphs.md +1 -1
  192. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-storage-constraints.md +5 -3
  193. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-ui-composition.md +6 -3
  194. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/creation-recovery.md +13 -0
  195. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/parse-core.md +3 -0
  196. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_contract.py +6 -1
  197. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_emit.py +135 -87
  198. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/field_type_registry.py +11 -1
  199. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/isv_resolver.py +1 -3
  200. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/report_validator.py +29 -0
  201. package/skills/cosmic-build/skills/cosmic-meta-modifier/SKILL.md +4 -2
  202. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/context/SKILL.md +2 -2
  203. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/execute/SKILL.md +1 -1
  204. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/SKILL.md +5 -4
  205. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/operation-write.md +6 -2
  206. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/validation.md +2 -0
  207. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/SKILL.md +20 -5
  208. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/complex-apis.md +1 -1
  209. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/policy-grammar.md +4 -1
  210. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/report-op/SKILL.md +9 -0
  211. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/SKILL.md +61 -4
  212. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/raw-rule-authoring.md +3 -1
  213. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/rule-actions.md +2 -2
  214. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/rule-reference.md +6 -6
  215. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/state.md +1 -1
  216. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/unit/SKILL.md +6 -3
  217. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/verify/usage-guide.md +4 -4
  218. package/skills/cosmic-build/skills/cosmic-meta-modifier/references/list-filter-modification.md +4 -1
  219. package/skills/cosmic-build/skills/cosmic-meta-ui/SKILL.md +9 -1
  220. package/skills/cosmic-build/skills/cosmic-meta-ui/modules/button/SKILL.md +3 -0
  221. package/skills/cosmic-build/skills/mcp-server/SKILL.md +210 -0
  222. package/skills/cosmic-build/skills/mcp-server/scripts/mcp_cli.py +431 -0
  223. package/skills/cosmic-build/skills/openapi-gen/SKILL.md +3 -3
  224. package/skills/cosmic-build/skills/openapi-gen/scripts/api/gen_runner.py +2 -2
  225. package/skills/cosmic-dev-best-practices/references/bill-dev-convention.md +19 -9
  226. package/skills/cosmic-dev-best-practices/references/cosmic-meta-api.md +14 -11
  227. package/skills/cosmic-dev-best-practices/references/design-examples/basedata-design-example.md +1 -1
  228. package/skills/cosmic-dev-best-practices/references/design-examples/bill-design-example.md +1 -1
  229. package/skills/cosmic-dev-best-practices/references/elements/AssistantField.md +1 -1
  230. package/skills/cosmic-dev-best-practices/references/elements/BasedataField.md +2 -2
  231. package/skills/cosmic-dev-best-practices/references/elements/BasedataPropField.md +3 -3
  232. package/skills/cosmic-dev-best-practices/references/elements/CreaterField.md +2 -2
  233. package/skills/cosmic-dev-best-practices/references/elements/CurrencyField.md +2 -2
  234. package/skills/cosmic-dev-best-practices/references/elements/CustomerField.md +2 -2
  235. package/skills/cosmic-dev-best-practices/references/elements/FlexField.md +1 -1
  236. package/skills/cosmic-dev-best-practices/references/elements/MaterielField.md +2 -2
  237. package/skills/cosmic-dev-best-practices/references/elements/OrgField.md +2 -2
  238. package/skills/cosmic-dev-best-practices/references/elements/SupplierField.md +2 -2
  239. package/skills/cosmic-dev-best-practices/references/elements/UnitField.md +1 -1
  240. package/skills/cosmic-dev-best-practices/references/elements/UserField.md +3 -3
  241. package/skills/cosmic-dev-best-practices/references/elements/common-field-property-conventions.md +16 -11
  242. package/skills/cosmic-dev-best-practices/references/layout-control-convention.md +5 -4
  243. package/skills/erp-analysis/references/delivery-contract.md +4 -2
  244. package/skills/erp-analysis/templates/AGENTS.template.md +1 -1
  245. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/.dsh/cosmic/.kd/config.json +0 -21
@@ -0,0 +1,36 @@
1
+ import json
2
+ import os
3
+ import subprocess
4
+ import sys
5
+ from pathlib import Path
6
+ import pytest
7
+
8
+ ROOT = Path(__file__).resolve().parents[2]
9
+ CLASSPATH = os.environ.get("COSMIC_SDK_QUERY_CLASSPATH", "")
10
+ HOME = os.environ.get("COSMIC_SDK_JAVA_HOME", "")
11
+
12
+
13
+ @pytest.mark.skipif(not CLASSPATH or not HOME, reason="target SDK and Java 8 home unavailable")
14
+ def test_native_typed_fields_and_aggregation_use_actual_sdk(tmp_path):
15
+ javac = Path(HOME) / "bin" / ("javac.exe" if os.name == "nt" else "javac")
16
+ java = Path(HOME) / "bin" / ("java.exe" if os.name == "nt" else "java")
17
+ subprocess.run([str(javac), "-source", "8", "-target", "8", "-cp", CLASSPATH, "-d", str(tmp_path),
18
+ str(ROOT / "assets/platform-report-filters/TypedReportFilterFields.java"),
19
+ str(ROOT / "examples/java-rules/CosmicReportAggregation.java"),
20
+ str(ROOT / "scripts/test/fixtures/ReportSdkCheck.java")], check=True, capture_output=True, text=True, timeout=60)
21
+ result = subprocess.run([str(java), "-DclusterName=report-sdk-check", "-Dlogfactory.className=ReportSdkCheck$TestLogFactory",
22
+ "-cp", os.pathsep.join([str(tmp_path), CLASSPATH]), "ReportSdkCheck"], cwd=tmp_path,
23
+ check=True, capture_output=True, text=True, timeout=30)
24
+ assert "report SDK checks passed" in result.stdout
25
+
26
+
27
+ @pytest.mark.skipif(not CLASSPATH or not HOME, reason="target SDK and Java 8 home unavailable")
28
+ def test_benchmark_cli_requires_equal_results_before_reporting_times(tmp_path):
29
+ target = tmp_path / "benchmark.json"
30
+ result = subprocess.run([sys.executable, str(ROOT / "scripts/report_algo_benchmark.py"),
31
+ "--sdk-classpath", CLASSPATH, "--java-home", HOME, "--rows", "1000", "--groups", "10",
32
+ "--iterations", "3", "--output", str(target)], check=True, capture_output=True, text=True, timeout=90)
33
+ data = json.loads(result.stdout)
34
+ assert data == json.loads(target.read_text())
35
+ assert data["status"] == "passed" and data["resultsEqual"] is True and data["databaseQueries"] == 0
36
+ assert data["baselineP50Ms"] > 0 and data["optimizedP95Ms"] > 0
@@ -38,7 +38,7 @@ def test_rule_batch_accepts_atomic_flag_spelling_without_changing_semantics():
38
38
  assert normalized["args"]["onlyEmptyTarget"] is True
39
39
  with patch.object(cmd_rules, "do_ensure_conditional_copy_field_value", return_value={"status": True}) as writer:
40
40
  cmd_rules._execute_rule_set_item({}, "token", "form", normalized)
41
- assert writer.call_args.args[-1] is True
41
+ assert writer.call_args.args[-3] is True
42
42
  item["args"]["onlyEmptyTarget"] = False
43
43
  with pytest.raises(ValueError, match="ARGS_CONFLICT"):
44
44
  cmd_rules._validate_rule_set_request({"rules": [item]})
@@ -31,6 +31,7 @@ def test_rule_domain_contract_publishes_declarative_commands() -> None:
31
31
  assert "ensureConditionalEntryStyle" in document["commands"]
32
32
  assert "ensureConditionalFieldState" in document["commands"]
33
33
  assert "ensureFieldCalculation" in document["commands"]
34
+ assert "ensureTimeDifferenceCalculation" in document["commands"]
34
35
  assert "ensureRuleFunctionFormula" in document["commands"]
35
36
  assert "DateTime" in document["commands"]["ensureRuleFunctionFormula"]["releasedGroups"]
36
37
  assert "ensureRuleSet" in document["commands"]
@@ -69,6 +70,7 @@ def test_cli_and_modifier_route_common_calculation_without_raw_rule_json() -> No
69
70
  cli = CLI.read_text(encoding="utf-8")
70
71
  modifier = MODIFIER.read_text(encoding="utf-8")
71
72
  assert '"ensureFieldCalculation"' in cli
73
+ assert '"ensureTimeDifferenceCalculation"' in cli
72
74
  assert '"ensureRuleFunctionFormula"' in cli
73
75
  assert '"ensureRuleSet"' in cli
74
76
  assert '"ensureConditionalFieldState"' in cli
@@ -81,6 +83,7 @@ def test_cli_and_modifier_route_common_calculation_without_raw_rule_json() -> No
81
83
  assert '"ensureQuantityConversion"' in cli
82
84
  assert '"setSummaryToField"' in cli
83
85
  assert "ensureFieldCalculation --entity" in modifier
86
+ assert "ensureTimeDifferenceCalculation --entity" in modifier
84
87
  assert "function-formulas.md" in RULE_SKILL.read_text()
85
88
  assert "ensureRuleFunctionFormula --app-root" in RULE_SKILL.with_name("function-formulas.md").read_text()
86
89
  assert "ensureConditionalFieldState --entity" in modifier
@@ -98,6 +101,7 @@ def test_rule_commands_publish_the_small_rule_domain_contract() -> None:
98
101
  cli = CLI.read_text(encoding="utf-8")
99
102
  assert '"addRule": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
100
103
  assert '"ensureFieldCalculation": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
104
+ assert '"ensureTimeDifferenceCalculation": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
101
105
  assert '"ensureRuleFunctionFormula": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
102
106
  assert '"ensureConditionalFieldState": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
103
107
  assert '"ensureConditionalEntryStyle": "skills/cosmic-meta-api/contracts/cli/rule-domain.json' in cli
@@ -126,6 +130,7 @@ def test_root_routes_common_rules_directly_to_the_rule_entry() -> None:
126
130
  assert "--project-root" in text
127
131
  assert "data.appRoot" in text
128
132
  assert "ensureFieldCalculation --entity" in text
133
+ assert "ensureTimeDifferenceCalculation --entity" in text
129
134
  assert "ensureConditionalFieldState --entity" in text
130
135
  assert "ensureConditionalClearFields --entity" in text
131
136
  assert "@first" in text
@@ -159,3 +164,18 @@ def test_rule_entity_context_accepts_header_and_entry_business_aliases() -> None
159
164
 
160
165
  assert header["key"] == "demo"
161
166
  assert entry["key"] == "demo_entry"
167
+
168
+
169
+ def test_calculation_scopes_repeated_price_caption_to_the_unique_participating_entity(monkeypatch):
170
+ entities = [{"key": "demo", "type": "BillEntity"}, {"key": "detail", "type": "EntryEntity"},
171
+ {"key": "addon", "type": "SubEntryEntity"}]
172
+ fields = [{"key": "amount", "name": "金额小计", "parentKey": "detail"},
173
+ {"key": "duration", "name": "时长", "parentKey": "detail"},
174
+ {"key": "price", "name": "单价", "parentKey": "detail"},
175
+ {"key": "service_price", "name": "单价", "parentKey": "addon"}]
176
+ monkeypatch.setattr(cmd_rules, "_rule_element_inventory", lambda cfg, token, form_number, category:
177
+ {"status": True, "data": entities if category == "entity" else fields})
178
+ selected, _ = cmd_rules._resolve_rule_entity_context({}, "token", "demo", "entries", ["金额小计", "时长", "单价"])
179
+ assert selected["key"] == "detail"
180
+ with pytest.raises(ValueError, match="AMBIGUOUS"):
181
+ cmd_rules._resolve_rule_entity_context({}, "token", "demo", "entries", ["单价"])
@@ -519,6 +519,7 @@ def test_rule_function_formula_compiles_and_uses_verified_writer(
519
519
  )
520
520
 
521
521
  requested = add_verified.call_args.args[3]
522
+ assert requested["description"] == "来源金额非空时,结果金额 = RemoveZero"
522
523
  assert requested["trueActions"][0]["expression"] == "target = RemoveTailZero(source)"
523
524
  assert requested["preCondition"] == "source <> null"
524
525
  assert requested["falseActions"][0]["expression"] == "target"
@@ -623,11 +624,20 @@ def test_rule_function_formula_adopts_exact_existing_rule(
623
624
  }]}},
624
625
  }
625
626
 
626
- result = cmd_rules.do_ensure_rule_function_formula(
627
- {}, "token", "demo", "header", "target",
628
- {"functionId": "RemoveZero", "args": [{"field": "source"}]},
629
- )
627
+ with mock.patch.object(cmd_rules, "do_update_rule_verified", return_value={
628
+ "status": True, "data": {"ruleId": "rule-id"},
629
+ "verification": {"verified": True, "preservationVerified": True},
630
+ }) as update_verified:
631
+ result = cmd_rules.do_ensure_rule_function_formula(
632
+ {}, "token", "demo", "header", "target",
633
+ {"functionId": "RemoveZero", "args": [{"field": "source"}]},
634
+ )
630
635
 
631
- assert result["data"]["changed"] is False
632
- assert result["writeAttempted"] is False
636
+ assert result["data"]["changed"] is True
637
+ assert result["writeAttempted"] is True
638
+ requested_patch = update_verified.call_args.args[3]
639
+ assert requested_patch == {
640
+ "ruleType": "bizRule", "ruleId": "rule-id",
641
+ "description": "来源金额非空时,结果金额 = RemoveZero",
642
+ }
633
643
  add_verified.assert_not_called()
@@ -70,6 +70,7 @@ def test_rule_hot_path_does_not_rediscover_published_commands_or_delivery_identi
70
70
  for path in entries:
71
71
  text = path.read_text(encoding="utf-8")
72
72
  assert "ensureFieldCalculation --entity" in text
73
+ assert "ensureTimeDifferenceCalculation --entity" in text
73
74
  assert "data.appRoot" in text
74
75
  assert "data.formNumber" in text
75
76
  assert "references/delivery.md" in text
@@ -0,0 +1,45 @@
1
+ import json
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+
7
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
8
+ from test_environment import export_test_environment
9
+
10
+
11
+ def test_export_preserves_target_and_excludes_credentials(tmp_path):
12
+ context = tmp_path / "_runtime" / "context.json"
13
+ context.parent.mkdir()
14
+ context.write_text(json.dumps({
15
+ "appId": "APP", "appCode": "demo", "appName": "Demo",
16
+ "environment": {"baseUrl": "http://127.0.0.1:8080/ierp", "accountId": "123"},
17
+ "cookie": "must-not-export",
18
+ }))
19
+ result = export_test_environment(tmp_path, {
20
+ "baseUrl": "http://127.0.0.1:8080/ierp/", "accountId": "123", "loginUser": "test-user",
21
+ "password": "must-not-export", "appSecret": "must-not-export", "token": "must-not-export",
22
+ }, ["form_a", "form_a", "form_b"], {"form_a": "FORM-ID"}, {
23
+ "form_a": {"formName": "Form A", "previewUrl": "http://127.0.0.1:8080/ierp/?formId=form_a", "cookie": "must-not-export"},
24
+ })
25
+ saved = json.loads(Path(result["path"]).read_text())
26
+ assert saved["baseUrl"] == "http://127.0.0.1:8080/ierp"
27
+ assert saved["accountId"] == "123"
28
+ assert saved["application"]["appId"] == "APP"
29
+ assert saved["forms"] == [{"formNumber": "form_a", "formId": "FORM-ID", "formName": "Form A", "previewUrl": "http://127.0.0.1:8080/ierp/?formId=form_a"}, {"formNumber": "form_b"}]
30
+ assert "must-not-export" not in json.dumps(result)
31
+ assert "authMode" not in saved
32
+
33
+
34
+ @pytest.mark.parametrize("server", [
35
+ {"baseUrl": "https://devops.invalid/", "accountId": "123"},
36
+ {"baseUrl": "http://127.0.0.1:8080/ierp", "accountId": "different"},
37
+ {"baseUrl": "http://user:secret@127.0.0.1:8080/ierp"},
38
+ ])
39
+ def test_export_rejects_changed_environment_or_credential_url(tmp_path, server):
40
+ context = tmp_path / "_runtime" / "context.json"
41
+ context.parent.mkdir()
42
+ context.write_text(json.dumps({"environment": {"baseUrl": "http://127.0.0.1:8080/ierp", "accountId": "123"}}))
43
+ with pytest.raises(ValueError):
44
+ export_test_environment(tmp_path, server, ["form_a"])
45
+ assert not (tmp_path / "_runtime" / "test-environment.json").exists()
@@ -0,0 +1,79 @@
1
+ import hashlib
2
+ import json
3
+ import shutil
4
+ import subprocess
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ import pytest
9
+
10
+ SCRIPTS = Path(__file__).resolve().parents[1]
11
+ sys.path.insert(0, str(SCRIPTS))
12
+ from verify_plugin_loading import verify_loading
13
+
14
+
15
+ @pytest.fixture
16
+ def compiled(tmp_path):
17
+ if not shutil.which("javac"):
18
+ pytest.skip("javac unavailable")
19
+ source = tmp_path / "Report.java"
20
+ source.write_text('package example; public class Report { public String version() { return "current"; } }')
21
+ subprocess.run(["javac", "-source", "8", "-target", "8", "-d", str(tmp_path), str(source)],
22
+ capture_output=True, check=True)
23
+ artifact = tmp_path / "example" / "Report.class"
24
+ deployed = tmp_path / "outputdir" / "example" / "Report.class"
25
+ deployed.parent.mkdir(parents=True)
26
+ shutil.copyfile(artifact, deployed)
27
+ digest = hashlib.sha256(artifact.read_bytes()).hexdigest()
28
+ receipt = {"status": True, "compileSkipped": False, "sourcePath": str(source), "className": "Report",
29
+ "sourceReview": {"sourceHash": hashlib.sha256(source.read_bytes()).hexdigest()},
30
+ "compiledArtifact": {"path": str(artifact), "fqcn": "example.Report", "sha256": digest}}
31
+ trace = {"status": "log-lines-found", "plugin": "example.Report", "traceId": "query-current", "observations": [
32
+ {"pluginMatch": "fully-qualified", "loadedClassSha256": digest}]}
33
+ return receipt, artifact, deployed, trace
34
+
35
+
36
+ def test_artifact_equality_never_implies_jvm_loading(compiled):
37
+ receipt, artifact, deployed, trace = compiled
38
+ result = verify_loading(receipt, artifact, deployed)
39
+ assert result["artifactMatch"] is True and result["runtimeVerified"] is False
40
+ assert result["status"] == "blocked"
41
+ assert verify_loading(receipt, artifact, deployed, trace)["status"] == "passed"
42
+ trace["observations"][0]["loadedClassSha256"] = "0" * 64
43
+ assert verify_loading(receipt, artifact, deployed, trace)["reason"] == "loaded-class-differs"
44
+
45
+
46
+ def test_stale_deployment_and_source_changes_fail(compiled, tmp_path):
47
+ receipt, artifact, deployed, trace = compiled
48
+ source = tmp_path / "old" / "Report.java"
49
+ source.parent.mkdir()
50
+ source.write_text('package example; public class Report { public String version() { return "old"; } }')
51
+ subprocess.run(["javac", "-source", "8", "-target", "8", "-d", str(deployed.parents[1]), str(source)],
52
+ capture_output=True, check=True)
53
+ assert verify_loading(receipt, artifact, deployed, trace)["reason"] == "deployed-class-differs"
54
+ Path(receipt["sourcePath"]).write_text('package example; public class Report {}')
55
+ assert verify_loading(receipt, artifact, deployed, trace)["reason"] == "source-changed-after-compilation"
56
+
57
+
58
+ def test_skipped_compile_unbound_artifact_and_short_logger_do_not_pass(compiled):
59
+ receipt, artifact, deployed, trace = compiled
60
+ trace["observations"][0]["pluginMatch"] = "simple-name-unverified"
61
+ assert verify_loading(receipt, artifact, deployed, trace)["runtimeVerified"] is False
62
+ receipt["compiledArtifact"] = None
63
+ assert verify_loading(receipt, artifact, deployed, trace)["reason"] == "compile-artifact-not-bound"
64
+ receipt["compileSkipped"] = True
65
+ assert verify_loading(receipt, artifact, deployed, trace)["reason"] == "compilation-not-proven"
66
+
67
+
68
+ def test_loading_cli_emits_structured_result_and_nonzero_for_missing_runtime(compiled, tmp_path):
69
+ receipt, artifact, deployed, trace = compiled
70
+ file = tmp_path / "compile.json"
71
+ file.write_text(json.dumps(receipt))
72
+ args = [sys.executable, str(SCRIPTS / "verify_plugin_loading.py"), "--compile-result", str(file),
73
+ "--compiled-class", str(artifact), "--deployed-class", str(deployed)]
74
+ result = subprocess.run(args, capture_output=True, text=True)
75
+ assert result.returncode == 2 and json.loads(result.stdout)["runtimeVerified"] is False
76
+ observation = tmp_path / "trace.json"
77
+ observation.write_text(json.dumps(trace))
78
+ result = subprocess.run([*args, "--runtime-trace", str(observation)], capture_output=True, text=True)
79
+ assert result.returncode == 0 and json.loads(result.stdout)["runtimeVerified"] is True
@@ -0,0 +1,49 @@
1
+ """Export only non-secret target identity for the implementation-to-QA handoff."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from urllib.parse import urlsplit, urlunsplit
6
+
7
+
8
+ def environment_identity(server):
9
+ url = urlsplit(str(server.get("baseUrl") or server.get("base_url") or ""))
10
+ if url.scheme not in ("http", "https") or not url.hostname or url.username or url.password or url.query or url.fragment:
11
+ raise ValueError("Test environment requires a complete HTTP(S) baseUrl without credentials")
12
+ return {
13
+ "baseUrl": urlunsplit((url.scheme.lower(), url.netloc.lower(), url.path.rstrip("/"), "", "")),
14
+ **{key: str(server[key]) for key in ("accountId",) if server.get(key)},
15
+ }
16
+
17
+
18
+ def export_test_environment(app_root, server, form_numbers, form_ids=None, form_links=None):
19
+ root = Path(app_root).resolve()
20
+ context_path = root / "_runtime" / "context.json"
21
+ context = json.loads(context_path.read_text(encoding="utf-8-sig")) if context_path.is_file() else {}
22
+ current = environment_identity(server)
23
+ bound = context.get("environment")
24
+ if bound and any(bound.get(key) and bound[key] != current.get(key) for key in ("baseUrl", "accountId")):
25
+ raise ValueError("Delivery environment differs from the application's bound environment; reconcile the target before delivery")
26
+ handoff = {
27
+ "schemaVersion": "cosmic-test-environment/v1",
28
+ **current,
29
+ "source": "app-build verified target",
30
+ "application": {
31
+ "appRoot": str(root),
32
+ **{key: str(context[key]) for key in ("appCode", "appName", "appId") if context.get(key)},
33
+ },
34
+ "forms": [
35
+ {
36
+ "formNumber": number,
37
+ **({"formId": form_ids[number]} if form_ids and form_ids.get(number) else {}),
38
+ **(
39
+ {key: form_links[number][key] for key in ("formName", "previewUrl", "listUrl") if form_links[number].get(key)}
40
+ if form_links and number in form_links else {}
41
+ ),
42
+ }
43
+ for number in dict.fromkeys(form_numbers)
44
+ ],
45
+ }
46
+ target = root / "_runtime" / "test-environment.json"
47
+ target.parent.mkdir(parents=True, exist_ok=True)
48
+ target.write_text(json.dumps(handoff, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
49
+ return {"path": str(target), "environment": handoff}
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env python3
2
+ """Read-only comparison of compiled/deployed bytes and explicit class-loading evidence."""
3
+
4
+ import argparse
5
+ import hashlib
6
+ import json
7
+ import re
8
+ from pathlib import Path
9
+
10
+ from java_source import stripped
11
+ from plugin_corpus.jvm_classfile import parse_class
12
+
13
+
14
+ def verify_loading(receipt, compiled_class, deployed_class, runtime_trace=None):
15
+ if not isinstance(receipt, dict) or runtime_trace is not None and (
16
+ not isinstance(runtime_trace, dict) or not isinstance(runtime_trace.get("observations"), list)
17
+ or any(not isinstance(item, dict) for item in runtime_trace["observations"])):
18
+ raise ValueError("Expected compile receipt and plugin-trace objects")
19
+ if receipt.get("status") is not True or receipt.get("compileSkipped") is not False:
20
+ return {"status": "blocked", "runtimeVerified": False, "reason": "compilation-not-proven"}
21
+ source = Path(receipt["sourcePath"])
22
+ if hashlib.sha256(source.read_bytes()).hexdigest() != receipt["sourceReview"]["sourceHash"]:
23
+ return {"status": "failed", "runtimeVerified": False, "reason": "source-changed-after-compilation"}
24
+ package = re.search(r"\bpackage\s+([\w.]+)\s*;", stripped(source.read_text(encoding="utf-8-sig")))
25
+ fqcn = (package[1] + "." if package else "") + receipt["className"].rsplit(".", 1)[-1]
26
+ paths = [Path(compiled_class), Path(deployed_class)]
27
+ if any(not path.is_file() for path in paths):
28
+ return {"status": "blocked", "runtimeVerified": False, "reason": "class-file-unavailable", "fqcn": fqcn}
29
+ artifacts = [{"path": str(path.resolve()), "sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
30
+ "fqcn": parse_class(path.read_bytes())["name"].replace("/", ".")} for path in paths]
31
+ if not receipt.get("compiledArtifact"):
32
+ return {"status": "blocked", "runtimeVerified": False, "reason": "compile-artifact-not-bound", "artifacts": artifacts}
33
+ if (receipt["compiledArtifact"].get("fqcn") != fqcn
34
+ or receipt["compiledArtifact"].get("sha256") != artifacts[0]["sha256"]
35
+ or Path(receipt["compiledArtifact"]["path"]).resolve() != paths[0].resolve()):
36
+ return {"status": "failed", "runtimeVerified": False, "reason": "compile-artifact-changed", "artifacts": artifacts}
37
+ if any(item["fqcn"] != fqcn for item in artifacts):
38
+ return {"status": "failed", "runtimeVerified": False, "reason": "class-identity-mismatch", "artifacts": artifacts}
39
+ if artifacts[0]["sha256"] != artifacts[1]["sha256"]:
40
+ return {"status": "failed", "runtimeVerified": False, "reason": "deployed-class-differs", "artifacts": artifacts}
41
+ observed = ([item.get("loadedClassSha256") for item in runtime_trace.get("observations", [])
42
+ if item.get("pluginMatch") == "fully-qualified" and item.get("loadedClassSha256")]
43
+ if runtime_trace and runtime_trace.get("status") == "log-lines-found"
44
+ and runtime_trace.get("plugin") == fqcn and runtime_trace.get("traceId") else [])
45
+ matched = bool(observed) and all(value == artifacts[0]["sha256"] for value in observed)
46
+ return {"status": "passed" if matched else "failed" if observed else "blocked",
47
+ "runtimeVerified": matched, "artifactMatch": True, "fqcn": fqcn, "artifacts": artifacts,
48
+ "reason": "loaded-class-matches" if matched else "loaded-class-differs" if observed else "runtime-loading-evidence-missing",
49
+ "traceId": runtime_trace.get("traceId") if runtime_trace else None,
50
+ "evidenceLimit": "Artifact equality alone does not prove JVM activation. Runtime proof consumes explicit request-scoped loaded-class hashes, never hashes of files merely read after replacement."}
51
+
52
+
53
+ def main():
54
+ parser = argparse.ArgumentParser(description=__doc__)
55
+ parser.add_argument("--compile-result", required=True)
56
+ parser.add_argument("--compiled-class", required=True)
57
+ parser.add_argument("--deployed-class", required=True)
58
+ parser.add_argument("--runtime-trace", help="JSON output of cosmic-e2e-test/scripts/plugin-trace.mjs")
59
+ args = parser.parse_args()
60
+ try:
61
+ result = verify_loading(json.loads(Path(args.compile_result).read_text(encoding="utf-8-sig")),
62
+ args.compiled_class, args.deployed_class,
63
+ json.loads(Path(args.runtime_trace).read_text(encoding="utf-8-sig")) if args.runtime_trace else None)
64
+ except (OSError, ValueError, KeyError, TypeError, AttributeError) as error:
65
+ result = {"status": "blocked", "runtimeVerified": False, "reason": "invalid-loading-evidence", "message": str(error)}
66
+ print(json.dumps(result, ensure_ascii=False))
67
+ return 0 if result["status"] == "passed" else 2
68
+
69
+
70
+ if __name__ == "__main__":
71
+ raise SystemExit(main())