hap-cli 0.8.30__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (436) hide show
  1. {hap_cli-0.8.30 → hap_cli-0.9.0}/PKG-INFO +31 -21
  2. {hap_cli-0.8.30/hap_cli → hap_cli-0.9.0}/README.md +30 -20
  3. hap_cli-0.9.0/app_live_tests/fixtures/__init__.py +1 -0
  4. hap_cli-0.9.0/app_live_tests/fixtures/feedback_scenario.py +256 -0
  5. hap_cli-0.9.0/app_live_tests/smoke.py +4618 -0
  6. {hap_cli-0.8.30 → hap_cli-0.9.0/hap_cli}/README.md +30 -20
  7. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/README_CN.md +34 -20
  8. hap_cli-0.9.0/hap_cli/__init__.py +68 -0
  9. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/__main__.py +1 -1
  10. hap_cli-0.8.30/hap_cli/hap_cli.py → hap_cli-0.9.0/hap_cli/_entry.py +80 -0
  11. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/app_cmd.py +188 -14
  12. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/attachment_cmd.py +20 -3
  13. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/auth_cmd.py +6 -6
  14. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/calendar_cmd.py +55 -7
  15. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/chart_cmd.py +55 -14
  16. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/chat_cmd.py +11 -15
  17. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/chatbot_cmd.py +20 -7
  18. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/config_cmd.py +5 -6
  19. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/contact_cmd.py +103 -7
  20. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/department_cmd.py +2 -2
  21. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/group_cmd.py +43 -2
  22. hap_cli-0.9.0/hap_cli/commands/guide_cmd.py +57 -0
  23. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/instance_cmd.py +315 -35
  24. hap_cli-0.9.0/hap_cli/commands/node_cmd.py +1494 -0
  25. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/optionset_cmd.py +2 -1
  26. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/page_cmd.py +123 -27
  27. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/post_cmd.py +41 -13
  28. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/record_cmd.py +246 -18
  29. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/role_cmd.py +3 -2
  30. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/v3_registry.py +140 -8
  31. hap_cli-0.9.0/hap_cli/commands/workflow_cmd.py +788 -0
  32. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/worksheet_cmd.py +674 -54
  33. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/context.py +8 -2
  34. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/action_spec_adapter.py +102 -9
  35. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app.py +490 -34
  36. hap_cli-0.9.0/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +11 -0
  37. hap_cli-0.9.0/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +66 -0
  38. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/charts.py +4 -6
  39. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/config.py +6 -4
  40. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/fields.py +3 -9
  41. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/hap.py +2 -2
  42. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/steps.py +12 -43
  43. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/store.py +5 -7
  44. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/workflow_dsl.py +3 -13
  45. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/attachment.py +80 -11
  46. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/auth.py +21 -3
  47. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/calendar_mod.py +163 -7
  48. hap_cli-0.9.0/hap_cli/core/chart.py +679 -0
  49. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/chat.py +134 -1
  50. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/chatbot.py +80 -8
  51. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/cli_access.py +35 -12
  52. hap_cli-0.9.0/hap_cli/core/condition_dsl.py +946 -0
  53. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/contact.py +77 -0
  54. {hap_cli-0.8.30/hap_cli/core/app_creator/_hapmeta → hap_cli-0.9.0/hap_cli/core}/control_type_codes.py +15 -0
  55. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/department.py +14 -2
  56. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/editspec/field.schema.json +52 -4
  57. hap_cli-0.9.0/hap_cli/core/editor/fieldlower.py +226 -0
  58. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/jsonschema_mini.py +38 -4
  59. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/ops.py +149 -3
  60. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/reader.py +33 -3
  61. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/field_normalizer.py +133 -20
  62. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/field_spec_adapter.py +48 -12
  63. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/filter_translator.py +107 -3
  64. hap_cli-0.9.0/hap_cli/core/filter_v3.py +218 -0
  65. hap_cli-0.9.0/hap_cli/core/flow_node.py +2558 -0
  66. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/global_meta.py +15 -0
  67. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/group.py +35 -4
  68. hap_cli-0.9.0/hap_cli/core/guide.py +350 -0
  69. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/instance.py +799 -98
  70. hap_cli-0.9.0/hap_cli/core/layout_check.py +355 -0
  71. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/logger.py +36 -1
  72. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/optionset.py +11 -4
  73. hap_cli-0.9.0/hap_cli/core/page.py +713 -0
  74. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/post.py +38 -7
  75. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/record.py +830 -33
  76. hap_cli-0.9.0/hap_cli/core/record_defaults.py +1041 -0
  77. hap_cli-0.9.0/hap_cli/core/record_form_checks.py +286 -0
  78. hap_cli-0.9.0/hap_cli/core/record_lookups.py +199 -0
  79. hap_cli-0.9.0/hap_cli/core/record_rules.py +1483 -0
  80. hap_cli-0.9.0/hap_cli/core/relation_scope.py +569 -0
  81. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/role.py +50 -6
  82. hap_cli-0.9.0/hap_cli/core/rule_spec_adapter.py +116 -0
  83. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/session.py +133 -6
  84. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/update.py +12 -6
  85. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/upload.py +111 -8
  86. hap_cli-0.9.0/hap_cli/core/v3/dispatcher.py +926 -0
  87. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/view_spec_adapter.py +316 -23
  88. hap_cli-0.9.0/hap_cli/core/workflow.py +1292 -0
  89. hap_cli-0.9.0/hap_cli/core/workflow_node_dsl.py +5055 -0
  90. hap_cli-0.9.0/hap_cli/core/worksheet.py +3406 -0
  91. hap_cli-0.9.0/hap_cli/core/worksheet_form.py +71 -0
  92. hap_cli-0.9.0/hap_cli/core/worksheet_reference.py +283 -0
  93. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/worksheet_templates.py +152 -16
  94. hap_cli-0.9.0/hap_cli/guide/en/approval.md +354 -0
  95. hap_cli-0.9.0/hap_cli/guide/en/chart.md +308 -0
  96. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/en/messages.md +9 -3
  97. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/en/overview.md +17 -11
  98. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/en/post.md +14 -2
  99. hap_cli-0.9.0/hap_cli/guide/en/record.md +1144 -0
  100. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/en/setup.md +10 -0
  101. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/en/skills.md +13 -5
  102. hap_cli-0.9.0/hap_cli/guide/en/workflow.md +1161 -0
  103. hap_cli-0.9.0/hap_cli/guide/en/worksheet.md +661 -0
  104. hap_cli-0.9.0/hap_cli/guide/index.json +103 -0
  105. hap_cli-0.9.0/hap_cli/guide/zh-Hans/approval.md +314 -0
  106. hap_cli-0.9.0/hap_cli/guide/zh-Hans/chart.md +262 -0
  107. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/zh-Hans/messages.md +9 -3
  108. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/zh-Hans/overview.md +14 -10
  109. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/zh-Hans/post.md +14 -2
  110. hap_cli-0.9.0/hap_cli/guide/zh-Hans/record.md +1017 -0
  111. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/zh-Hans/setup.md +10 -0
  112. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/guide/zh-Hans/skills.md +13 -5
  113. hap_cli-0.9.0/hap_cli/guide/zh-Hans/workflow.md +1037 -0
  114. hap_cli-0.9.0/hap_cli/guide/zh-Hans/worksheet.md +583 -0
  115. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/i18n.py +18 -0
  116. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/locale/messages.json +2566 -276
  117. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/conftest.py +22 -1
  118. hap_cli-0.9.0/hap_cli/tests/test_action_mdpublic_parity.py +289 -0
  119. hap_cli-0.9.0/hap_cli/tests/test_advanced_setting_guard.py +514 -0
  120. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_app_export_usage.py +1 -1
  121. hap_cli-0.9.0/hap_cli/tests/test_app_light_color.py +42 -0
  122. hap_cli-0.9.0/hap_cli/tests/test_app_section_name.py +97 -0
  123. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_approval_submit_fill_cli.py +1 -1
  124. hap_cli-0.9.0/hap_cli/tests/test_approval_wire.py +259 -0
  125. hap_cli-0.9.0/hap_cli/tests/test_atomic_write.py +202 -0
  126. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_attachment_share.py +1 -1
  127. hap_cli-0.9.0/hap_cli/tests/test_batch_add_atomic.py +381 -0
  128. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_bug_036430.py +1 -1
  129. hap_cli-0.9.0/hap_cli/tests/test_calendar_date_range.py +51 -0
  130. hap_cli-0.9.0/hap_cli/tests/test_calendar_discussion_cli.py +89 -0
  131. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_chart.py +73 -10
  132. hap_cli-0.9.0/hap_cli/tests/test_chart_filter_merge.py +200 -0
  133. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_chat_attachment_send.py +11 -5
  134. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_chat_recall_cli.py +14 -12
  135. hap_cli-0.9.0/hap_cli/tests/test_chat_send_socket.py +122 -0
  136. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_cli_access.py +2 -2
  137. hap_cli-0.9.0/hap_cli/tests/test_coded_responses.py +152 -0
  138. hap_cli-0.9.0/hap_cli/tests/test_condition_dsl.py +451 -0
  139. hap_cli-0.9.0/hap_cli/tests/test_condition_dsl_entries.py +239 -0
  140. hap_cli-0.9.0/hap_cli/tests/test_condition_dsl_readback.py +131 -0
  141. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_config_cmd.py +1 -1
  142. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_core.py +859 -77
  143. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_destructive_confirm_cli.py +6 -1
  144. hap_cli-0.9.0/hap_cli/tests/test_dsl_existing_node_refs.py +372 -0
  145. hap_cli-0.9.0/hap_cli/tests/test_dsl_multi_record_guard.py +444 -0
  146. hap_cli-0.9.0/hap_cli/tests/test_engine_core_parity.py +121 -0
  147. hap_cli-0.9.0/hap_cli/tests/test_fb_arg_consistency.py +236 -0
  148. hap_cli-0.9.0/hap_cli/tests/test_fb_bidirectional.py +155 -0
  149. hap_cli-0.9.0/hap_cli/tests/test_fb_discussion_mentions.py +227 -0
  150. hap_cli-0.9.0/hap_cli/tests/test_fb_entry_module.py +122 -0
  151. hap_cli-0.9.0/hap_cli/tests/test_fb_field_record_ref.py +380 -0
  152. hap_cli-0.9.0/hap_cli/tests/test_fb_http_error_body.py +85 -0
  153. hap_cli-0.9.0/hap_cli/tests/test_fb_json_anywhere.py +123 -0
  154. hap_cli-0.9.0/hap_cli/tests/test_fb_json_file_arg.py +65 -0
  155. hap_cli-0.9.0/hap_cli/tests/test_fb_layout_check.py +206 -0
  156. hap_cli-0.9.0/hap_cli/tests/test_fb_node_get_detail.py +188 -0
  157. hap_cli-0.9.0/hap_cli/tests/test_fb_node_summary.py +226 -0
  158. hap_cli-0.9.0/hap_cli/tests/test_fb_post_cursor.py +119 -0
  159. hap_cli-0.9.0/hap_cli/tests/test_fb_publish_reasons.py +193 -0
  160. hap_cli-0.9.0/hap_cli/tests/test_fb_replicate_workflow.py +587 -0
  161. hap_cli-0.9.0/hap_cli/tests/test_fb_save_fields_shape.py +167 -0
  162. hap_cli-0.9.0/hap_cli/tests/test_fb_subgroups.py +73 -0
  163. hap_cli-0.9.0/hap_cli/tests/test_fb_subtable_read.py +281 -0
  164. hap_cli-0.9.0/hap_cli/tests/test_fb_worksheet_references.py +262 -0
  165. hap_cli-0.9.0/hap_cli/tests/test_fb_worksheet_visibility.py +133 -0
  166. hap_cli-0.9.0/hap_cli/tests/test_fb_worksheet_workflows.py +159 -0
  167. hap_cli-0.9.0/hap_cli/tests/test_fields_mdpublic_parity.py +287 -0
  168. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_full_e2e.py +2 -2
  169. hap_cli-0.9.0/hap_cli/tests/test_g1_chart_parity.py +200 -0
  170. hap_cli-0.9.0/hap_cli/tests/test_g1_record_parity.py +206 -0
  171. hap_cli-0.9.0/hap_cli/tests/test_g1_upload_parity.py +163 -0
  172. hap_cli-0.9.0/hap_cli/tests/test_g1_worksheet_parity.py +237 -0
  173. hap_cli-0.9.0/hap_cli/tests/test_g2_coverage_parity.py +484 -0
  174. hap_cli-0.9.0/hap_cli/tests/test_g3_workflow_parity.py +348 -0
  175. hap_cli-0.9.0/hap_cli/tests/test_g4_approval_parity.py +403 -0
  176. hap_cli-0.9.0/hap_cli/tests/test_g5_low_frequency_parity.py +500 -0
  177. hap_cli-0.9.0/hap_cli/tests/test_g6_advanced_fields.py +460 -0
  178. hap_cli-0.9.0/hap_cli/tests/test_g6_fields_roundtrip.py +102 -0
  179. hap_cli-0.9.0/hap_cli/tests/test_g7_misc_gaps.py +342 -0
  180. hap_cli-0.9.0/hap_cli/tests/test_g7b_permanent_delete.py +348 -0
  181. hap_cli-0.9.0/hap_cli/tests/test_g8_filter_operator.py +305 -0
  182. hap_cli-0.9.0/hap_cli/tests/test_g8b_pivot_operators.py +106 -0
  183. hap_cli-0.9.0/hap_cli/tests/test_g8c_empty_filter_and_help_truth.py +329 -0
  184. hap_cli-0.9.0/hap_cli/tests/test_g9_appid_resolve.py +166 -0
  185. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_global_meta.py +1 -1
  186. hap_cli-0.9.0/hap_cli/tests/test_guide.py +364 -0
  187. hap_cli-0.9.0/hap_cli/tests/test_guide_sections.py +322 -0
  188. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_i18n.py +8 -8
  189. hap_cli-0.9.0/hap_cli/tests/test_inner_flow_batch_add.py +151 -0
  190. hap_cli-0.9.0/hap_cli/tests/test_instance_envelope.py +127 -0
  191. hap_cli-0.9.0/hap_cli/tests/test_instance_history_cli.py +89 -0
  192. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_misc.py +8 -4
  193. hap_cli-0.9.0/hap_cli/tests/test_jsonschema_mini_copy.py +84 -0
  194. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_multi_profile.py +1 -1
  195. hap_cli-0.9.0/hap_cli/tests/test_noninteractive_confirm.py +153 -0
  196. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +1 -1
  197. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_org_id_cli.py +1 -1
  198. hap_cli-0.9.0/hap_cli/tests/test_page_filters_group_read.py +243 -0
  199. hap_cli-0.9.0/hap_cli/tests/test_page_filters_group_update.py +290 -0
  200. hap_cli-0.9.0/hap_cli/tests/test_page_save_page_id.py +76 -0
  201. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_post_scope_cli.py +1 -1
  202. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +1 -1
  203. hap_cli-0.9.0/hap_cli/tests/test_record_business_rules.py +999 -0
  204. hap_cli-0.9.0/hap_cli/tests/test_record_defaults.py +723 -0
  205. hap_cli-0.9.0/hap_cli/tests/test_record_doc_id_hidden.py +199 -0
  206. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_record_field_alias.py +1 -1
  207. hap_cli-0.9.0/hap_cli/tests/test_record_form_checks.py +355 -0
  208. hap_cli-0.9.0/hap_cli/tests/test_record_run_action.py +345 -0
  209. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_record_v3_semantic_cli.py +1 -1
  210. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_record_write_fixes.py +8 -5
  211. hap_cli-0.9.0/hap_cli/tests/test_relation_scope.py +440 -0
  212. hap_cli-0.9.0/hap_cli/tests/test_rmw_mdpublic_parity.py +183 -0
  213. hap_cli-0.9.0/hap_cli/tests/test_role_app_scope.py +101 -0
  214. hap_cli-0.9.0/hap_cli/tests/test_rule_filters_and_field_warning.py +199 -0
  215. hap_cli-0.9.0/hap_cli/tests/test_save_action_silent_drop.py +66 -0
  216. hap_cli-0.9.0/hap_cli/tests/test_save_rule_spec.py +274 -0
  217. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_semantic_types_registry.py +1 -1
  218. hap_cli-0.9.0/hap_cli/tests/test_subtable_mdpublic_parity.py +82 -0
  219. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_update.py +3 -3
  220. hap_cli-0.9.0/hap_cli/tests/test_upload_mdpublic_parity.py +105 -0
  221. hap_cli-0.9.0/hap_cli/tests/test_v3_bool_flags.py +195 -0
  222. hap_cli-0.9.0/hap_cli/tests/test_v3_response_format_json.py +276 -0
  223. hap_cli-0.9.0/hap_cli/tests/test_view_mdpublic_parity.py +197 -0
  224. hap_cli-0.9.0/hap_cli/tests/test_wf_config_keys.py +153 -0
  225. hap_cli-0.9.0/hap_cli/tests/test_wf_inner_scope.py +155 -0
  226. hap_cli-0.9.0/hap_cli/tests/test_wf_json_file_arg.py +86 -0
  227. hap_cli-0.9.0/hap_cli/tests/test_wf_node_delete_missing.py +98 -0
  228. hap_cli-0.9.0/hap_cli/tests/test_wf_save_action_dsl_fields.py +184 -0
  229. hap_cli-0.9.0/hap_cli/tests/test_wf_structure_listing.py +79 -0
  230. hap_cli-0.9.0/hap_cli/tests/test_wf_trigger_outcome.py +72 -0
  231. hap_cli-0.9.0/hap_cli/tests/test_wf_trigger_preserve.py +99 -0
  232. hap_cli-0.9.0/hap_cli/tests/test_wo4_result_handling.py +184 -0
  233. hap_cli-0.9.0/hap_cli/tests/test_workflow_code_node.py +324 -0
  234. hap_cli-0.9.0/hap_cli/tests/test_workflow_condition_field_types.py +360 -0
  235. hap_cli-0.9.0/hap_cli/tests/test_workflow_condition_slots.py +180 -0
  236. hap_cli-0.9.0/hap_cli/tests/test_workflow_delete_cascade.py +137 -0
  237. hap_cli-0.9.0/hap_cli/tests/test_workflow_lifecycle_wire.py +179 -0
  238. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_workflow_list_cli.py +1 -1
  239. hap_cli-0.9.0/hap_cli/tests/test_workflow_node_wire.py +349 -0
  240. hap_cli-0.9.0/hap_cli/tests/test_workflow_publish_inner.py +349 -0
  241. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_workflow_v3_semantic_cli.py +29 -12
  242. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_worksheet_crud_cli.py +1 -1
  243. hap_cli-0.9.0/hap_cli/tests/test_worksheet_filter_read.py +203 -0
  244. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_worksheet_switch.py +19 -7
  245. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +24 -6
  246. hap_cli-0.9.0/hap_cli/utils/atomic_write.py +97 -0
  247. hap_cli-0.9.0/hap_cli/utils/confirm.py +60 -0
  248. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/utils/formatting.py +38 -0
  249. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/utils/options.py +41 -0
  250. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli.egg-info/PKG-INFO +31 -21
  251. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli.egg-info/SOURCES.txt +116 -1
  252. hap_cli-0.9.0/hap_cli.egg-info/entry_points.txt +2 -0
  253. {hap_cli-0.8.30 → hap_cli-0.9.0}/setup.py +1 -1
  254. hap_cli-0.8.30/app_live_tests/smoke.py +0 -575
  255. hap_cli-0.8.30/hap_cli/__init__.py +0 -3
  256. hap_cli-0.8.30/hap_cli/commands/guide_cmd.py +0 -36
  257. hap_cli-0.8.30/hap_cli/commands/node_cmd.py +0 -730
  258. hap_cli-0.8.30/hap_cli/commands/workflow_cmd.py +0 -419
  259. hap_cli-0.8.30/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -734
  260. hap_cli-0.8.30/hap_cli/core/chart.py +0 -276
  261. hap_cli-0.8.30/hap_cli/core/control_type_codes.py +0 -210
  262. hap_cli-0.8.30/hap_cli/core/editor/fieldlower.py +0 -66
  263. hap_cli-0.8.30/hap_cli/core/flow_node.py +0 -1331
  264. hap_cli-0.8.30/hap_cli/core/guide.py +0 -176
  265. hap_cli-0.8.30/hap_cli/core/page.py +0 -367
  266. hap_cli-0.8.30/hap_cli/core/v3/dispatcher.py +0 -516
  267. hap_cli-0.8.30/hap_cli/core/workflow.py +0 -704
  268. hap_cli-0.8.30/hap_cli/core/workflow_node_dsl.py +0 -2607
  269. hap_cli-0.8.30/hap_cli/core/worksheet.py +0 -1930
  270. hap_cli-0.8.30/hap_cli/guide/en/approval.md +0 -118
  271. hap_cli-0.8.30/hap_cli/guide/en/chart.md +0 -150
  272. hap_cli-0.8.30/hap_cli/guide/en/record.md +0 -455
  273. hap_cli-0.8.30/hap_cli/guide/index.json +0 -60
  274. hap_cli-0.8.30/hap_cli/guide/zh-Hans/approval.md +0 -105
  275. hap_cli-0.8.30/hap_cli/guide/zh-Hans/chart.md +0 -133
  276. hap_cli-0.8.30/hap_cli/guide/zh-Hans/record.md +0 -430
  277. hap_cli-0.8.30/hap_cli/tests/test_guide.py +0 -173
  278. hap_cli-0.8.30/hap_cli/tests/test_instance_history_cli.py +0 -34
  279. hap_cli-0.8.30/hap_cli.egg-info/entry_points.txt +0 -2
  280. {hap_cli-0.8.30 → hap_cli-0.9.0}/MANIFEST.in +0 -0
  281. {hap_cli-0.8.30 → hap_cli-0.9.0}/app_live_tests/__init__.py +0 -0
  282. {hap_cli-0.8.30 → hap_cli-0.9.0}/app_live_tests/__main__.py +0 -0
  283. {hap_cli-0.8.30 → hap_cli-0.9.0}/app_live_tests/config.py +0 -0
  284. {hap_cli-0.8.30 → hap_cli-0.9.0}/app_live_tests/harness.py +0 -0
  285. {hap_cli-0.8.30 → hap_cli-0.9.0}/app_live_tests/state.py +0 -0
  286. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/__init__.py +0 -0
  287. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/app_creator_cmd.py +0 -0
  288. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/app_editor_cmd.py +0 -0
  289. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/icon_cmd.py +0 -0
  290. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/region_cmd.py +0 -0
  291. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/update_cmd.py +0 -0
  292. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/commands/upload_cmd.py +0 -0
  293. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/__init__.py +0 -0
  294. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/__init__.py +0 -0
  295. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
  296. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/cleanup.py +0 -0
  297. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/compiler.py +0 -0
  298. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/design/design.schema.json +0 -0
  299. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/errors.py +0 -0
  300. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
  301. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/executor.py +0 -0
  302. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/merge.py +0 -0
  303. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/recording/__init__.py +0 -0
  304. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/recording/console.py +0 -0
  305. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
  306. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/recording/mirror.py +0 -0
  307. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/recording/report.py +0 -0
  308. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/schema.py +0 -0
  309. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
  310. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/__init__.py +0 -0
  311. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/cli.py +0 -0
  312. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/executor.py +0 -0
  313. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
  314. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
  315. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
  316. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
  317. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/seed/template.py +0 -0
  318. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/selftest.py +0 -0
  319. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/smoke.py +0 -0
  320. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/app_creator/validate.py +0 -0
  321. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/__init__.py +0 -0
  322. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
  323. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
  324. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/apply.py +0 -0
  325. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/componentlower.py +0 -0
  326. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/editspec/component.schema.json +0 -0
  327. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/editspec/custom-action.schema.json +0 -0
  328. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/editspec/envelope.schema.json +0 -0
  329. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/editspec.py +0 -0
  330. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/errors.py +0 -0
  331. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/models.py +0 -0
  332. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/editor/planner.py +0 -0
  333. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/icon_index.py +0 -0
  334. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/response_crypto.py +0 -0
  335. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/role_perm_builder.py +0 -0
  336. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/token_crypto.py +0 -0
  337. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/v3/__init__.py +0 -0
  338. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/v3/render.py +0 -0
  339. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/core/v3/schema.py +0 -0
  340. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/locale/__init__.py +0 -0
  341. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/locale/messages.schema.json +0 -0
  342. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/__init__.py +0 -0
  343. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_app_creator.py +0 -0
  344. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_app_editor.py +0 -0
  345. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_auth_prerelease.py +0 -0
  346. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_bug_036750.py +0 -0
  347. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_content_language.py +0 -0
  348. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_control_lookup_guard.py +0 -0
  349. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration.py +0 -0
  350. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_approval.py +0 -0
  351. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_approval_actions.py +0 -0
  352. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_calendar.py +0 -0
  353. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_destructive.py +0 -0
  354. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_post.py +0 -0
  355. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_social.py +0 -0
  356. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_v3.py +0 -0
  357. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_workflow.py +0 -0
  358. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  359. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_member_relation_array_wrap.py +0 -0
  360. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_no_workflow_unsupported.py +0 -0
  361. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_org_id_docs.py +0 -0
  362. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_parameter_conventions.py +0 -0
  363. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  364. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_select_add_option.py +0 -0
  365. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_select_rejects_relation_value.py +0 -0
  366. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_update_mode.py +0 -0
  367. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_upload_allow_down.py +0 -0
  368. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_upload_host_resolution.py +0 -0
  369. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  370. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  371. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  372. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_v3_session.py +0 -0
  373. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  374. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_workflow_envelope_errors.py +0 -0
  375. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_workflow_read_write_keys.py +0 -0
  376. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/tests/test_worksheet_create_section.py +0 -0
  377. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/utils/__init__.py +0 -0
  378. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli/utils/parameter_mapping.py +0 -0
  379. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli.egg-info/dependency_links.txt +0 -0
  380. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli.egg-info/requires.txt +0 -0
  381. {hap_cli-0.8.30 → hap_cli-0.9.0}/hap_cli.egg-info/top_level.txt +0 -0
  382. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/__init__.py +0 -0
  383. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/__main__.py +0 -0
  384. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/_wftest.py +0 -0
  385. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/charts.py +0 -0
  386. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/cleanup.py +0 -0
  387. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/compiler.py +0 -0
  388. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/config.py +0 -0
  389. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/errors.py +0 -0
  390. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/executor.py +0 -0
  391. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/fields.py +0 -0
  392. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/hap.py +0 -0
  393. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/recording/__init__.py +0 -0
  394. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/recording/console.py +0 -0
  395. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/recording/jsonl.py +0 -0
  396. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/recording/mirror.py +0 -0
  397. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/recording/report.py +0 -0
  398. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/schema.py +0 -0
  399. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/seed/__init__.py +0 -0
  400. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/seed/cli.py +0 -0
  401. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/seed/executor.py +0 -0
  402. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/seed/template.py +0 -0
  403. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/selftest.py +0 -0
  404. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/smoke.py +0 -0
  405. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/step.py +0 -0
  406. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/steps.py +0 -0
  407. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/store.py +0 -0
  408. {hap_cli-0.8.30 → hap_cli-0.9.0}/live_tests/workflow_dsl.py +0 -0
  409. {hap_cli-0.8.30 → hap_cli-0.9.0}/setup.cfg +0 -0
  410. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/INDEX.json +0 -0
  411. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  412. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  413. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/create_optionset.yaml +0 -0
  414. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/create_role.yaml +0 -0
  415. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  416. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/delete_record.yaml +0 -0
  417. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/delete_role.yaml +0 -0
  418. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  419. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_app_info.yaml +0 -0
  420. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  421. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  422. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  423. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_details.yaml +0 -0
  424. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  425. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_list.yaml +0 -0
  426. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  427. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  428. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  429. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  430. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_regions.yaml +0 -0
  431. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_role_details.yaml +0 -0
  432. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/get_role_list.yaml +0 -0
  433. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  434. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  435. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  436. {hap_cli-0.8.30 → hap_cli-0.9.0}/sources/v3-api-schema/update_optionset.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hap-cli
3
- Version: 0.8.30
3
+ Version: 0.9.0
4
4
  Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
@@ -131,7 +131,9 @@ hap worksheet record list WORKSHEET_ID --page-size 10
131
131
  hap --json worksheet record list WORKSHEET_ID
132
132
  ```
133
133
 
134
- Every command supports `--json` for machine-readable output.
134
+ Every command supports `--json` for machine-readable output. It can go
135
+ before or after the command: `hap --json post list` and `hap post list --json`
136
+ do the same thing.
135
137
 
136
138
  ---
137
139
 
@@ -164,9 +166,9 @@ discover every subcommand.
164
166
  | `app select APP_ID` / `app unselect` | Manage the default app used when `--app-id` is omitted |
165
167
  | `app create-section / edit-section / delete-section` | Section management |
166
168
  | `app sort-sections / sort-worksheets` | Reorder sections / a section's worksheets |
167
- | `app create-item` | Batch-create empty worksheets / custom pages |
168
169
  | `app backup / export / exports / backup-logs` | Backup & export |
169
- | `app usage / logs` | Statistics and operation logs |
170
+ | `app usage / logs / log-archives` | Statistics, operation logs and their archives |
171
+ | `app trash` | What was deleted from an application, and by whom |
170
172
  | `app role …` | Role CRUD, permissions, members, leave-all, applications |
171
173
  | `app optionset …` | Option set CRUD and cross-app moves |
172
174
  | `app knowledge list / search` | Vector knowledge bases |
@@ -175,24 +177,30 @@ discover every subcommand.
175
177
 
176
178
  | Command | Description |
177
179
  |---|---|
178
- | `worksheet list / info / fields / field-types` | Discover structure |
179
- | `worksheet create / update / copy / delete` | Worksheet lifecycle |
180
+ | `worksheet list / info / fields / field-types` | Discover structure (`info --with-form --with-views` pulls the layout and views in the same call) |
181
+ | `worksheet list --workflows / --without-workflows` | See which worksheets have automation, and which have none |
182
+ | `worksheet references` | What else points at a worksheet — fields in other sheets, and workflow steps |
183
+ | `worksheet create / update / copy / delete` | Worksheet lifecycle (`update --visibility` hides a sheet from the app navigation) |
184
+ | `worksheet pair-relation` | Make a relation field point both ways (`--repair` fixes one paired by hand) |
185
+ | `worksheet add-fields / update-fields` | Append fields, or replace the whole field layout |
186
+ | `worksheet mount-subtable` | Embed an existing worksheet as a sub-table |
180
187
  | `worksheet rules / save-rule` | Business rules |
181
- | `worksheet switches / edit-switch` | Feature switches |
188
+ | `worksheet switches / switch-types / edit-switch / batch-edit-switch` | Feature switches |
182
189
  | `worksheet form-settings / save-form-settings` | Form submission settings |
183
190
  | `worksheet custom-actions / create-custom-action / delete-custom-action` | Custom action buttons |
184
- | `worksheet create-chart` | Build a statistics chart on a worksheet |
185
- | `worksheet view list / info / create / copy / delete / sort` | View management |
191
+ | `worksheet chart list / get / create / update / delete` | Statistics charts on a worksheet |
192
+ | `worksheet view list / info / create / copy / delete / sort` | View management (`list --deleted` is the recycle bin; a spec can group a table, restrict its columns, or name a plugin) |
186
193
 
187
194
  ### worksheet record — record CRUD
188
195
 
189
196
  | Command | Description |
190
197
  |---|---|
191
198
  | `worksheet record list / get` | Query and read |
192
- | `worksheet record create / update / delete` | Single-row CRUD |
193
- | `worksheet record batch-create / batch-update` | Bulk operations (main-site path; relation/sub-table cells persist) |
199
+ | `worksheet record create / update / delete` | Single-row CRUD (`update --lock` / `--unlock` locks a record against edits) |
200
+ | `worksheet record batch-create / batch-update` | Bulk operations (relation/sub-table cells persist; `batch-create --single-request` writes them all in one call) |
194
201
  | `worksheet record relations / share-link` | Linked records and share URLs |
195
- | `worksheet record discussions / add-discussion / delete-discussion` | Discussion threads |
202
+ | `worksheet record run-action` | Press a custom action button on one or more records (`--button` by name or ID, `--row-ids` comma-separated or repeated) |
203
+ | `worksheet record discussions / add-discussion / delete-discussion` | Discussion threads (mention people with `--at-all` / `--at`) |
196
204
  | `worksheet record logs` | Per-record change log |
197
205
  | `worksheet record pivot / bottom-stats` | Aggregations and summary rows |
198
206
 
@@ -200,13 +208,12 @@ discover every subcommand.
200
208
 
201
209
  | Command | Description |
202
210
  |---|---|
203
- | `workflow list / get / structure / history / groups / stats` | Inspect |
204
- | `workflow create / update / copy / move / delete` | Lifecycle |
211
+ | `workflow list / get / structure / history / groups / stats / pbp-parameters` | Inspect (`list --kind` filters by trigger) |
212
+ | `workflow create / update / copy / move / delete / restore / purge` | Lifecycle (delete is the recycle bin; restore and purge are the way out) |
205
213
  | `workflow publish / rollback` | Versioning |
206
214
  | `workflow trigger / trigger-pbp` | Manual trigger |
207
215
  | `workflow config-get / config-set` | Global config |
208
- | `workflow create-approval / update-approval / delete-approval` | Approval blocks |
209
- | `workflow node …` | Node CRUD, batch-add / batch-update / batch-delete (and `*-approval` variants), test-code / test-webhook / test-ai, controls, types, code templates |
216
+ | `workflow node …` | Node CRUD, batch-add, save-action / save-search / save-get-more, test-code / test-webhook / test-ai, controls, types, code templates |
210
217
 
211
218
  > Always run `hap workflow structure PROCESS_ID` before computing insertion
212
219
  > points, branch IDs, or approval block IDs. Don't fabricate node / block /
@@ -216,9 +223,9 @@ discover every subcommand.
216
223
 
217
224
  | Command | Description |
218
225
  |---|---|
219
- | `approval todo / todo-count / todo-filters / archived` | Pending and archived |
220
- | `approval get / get-by-row / list-by-row / work-item / operations / op-history / history / history-detail` | Read instance state |
221
- | `approval approve / reject / submit / sign / forward / urge` | Act on a task |
226
+ | `approval todo / todo-count / done-count / todo-filters / archived` | Pending, finished and archived |
227
+ | `approval get / work-item / operations / op-history / history / history-detail` | Read instance state |
228
+ | `approval approve / reject / submit / sign / forward / transfer / undo-approval / urge` | Act on a task (signature, attachments and the next step's approvers included) |
222
229
  | `approval revoke / terminate / restart / retry` | Lifecycle |
223
230
  | `approval batch / retry-batch / end-batch` | Bulk variants |
224
231
  | `approval list-types` | Enum reference |
@@ -239,6 +246,7 @@ discover every subcommand.
239
246
  | `contact search / resolve` | Find members by keyword / name / email / phone |
240
247
  | `contact friends / friend-requests` | Address book |
241
248
  | `contact add-friend / accept-friend / reject-friend / ignore-friend / remove-friend` | Friend management |
249
+ | `contact org-roles / org-role-members` | Organization roles and who holds them |
242
250
 
243
251
  ### department — directory
244
252
 
@@ -264,6 +272,7 @@ discover every subcommand.
264
272
  | `calendar list / get / create / update / delete` | Event lifecycle |
265
273
  | `calendar categories` | Built-in categories |
266
274
  | `calendar add-member / remove-member` | Membership |
275
+ | `calendar add-discussion` | Comment on an event (attachments supported; mention people with `--at-all` / `--at`) |
267
276
 
268
277
  ### chat — chat & messaging
269
278
 
@@ -280,6 +289,7 @@ discover every subcommand.
280
289
 
281
290
  | Command | Description |
282
291
  |---|---|
292
+ | `group list` | List open groups you have joined (`--org-id`, `--keywords`, and pagination options) |
283
293
  | `group info GROUP_ID` | Group metadata |
284
294
  | `group create` | Create a new group (`--name`, `--org-id`, optional `--member`) |
285
295
  | `group add-member` | Add one or more members (`--group-id`, `--account-id`) |
@@ -302,7 +312,7 @@ discover every subcommand.
302
312
 
303
313
  | Command | Description |
304
314
  |---|---|
305
- | `attachment share ADDRESS` | Create a link to a stored file that you can pass on (`--hours`, default 48) |
315
+ | `attachment share [ADDRESS]` | Create a link to a stored file that you can pass on (`--hours`, default 48; `--file-id` to share by attachment id, `--short` for a landing page instead of the storage address) |
306
316
 
307
317
  > ADDRESS is the file's link — one that has already stopped working is fine, paste it as-is — or just the path part of it. The file itself does not expire, only the link does, so a dead link can always be revived.
308
318
 
@@ -310,7 +320,7 @@ discover every subcommand.
310
320
 
311
321
  | Command | Description |
312
322
  |---|---|
313
- | `guide` | Built-in usage guide: what this version can do, and the value formats that are easy to get wrong (`hap guide <topic>` for detail) |
323
+ | `guide` | Built-in usage guide: what this version can do, and the value formats that are easy to get wrong. `hap guide` lists the topics, `hap guide <topic>` what one covers section by section, `hap guide <topic> <number or name>` one section |
314
324
 
315
325
  ### upload — file upload
316
326
 
@@ -102,7 +102,9 @@ hap worksheet record list WORKSHEET_ID --page-size 10
102
102
  hap --json worksheet record list WORKSHEET_ID
103
103
  ```
104
104
 
105
- Every command supports `--json` for machine-readable output.
105
+ Every command supports `--json` for machine-readable output. It can go
106
+ before or after the command: `hap --json post list` and `hap post list --json`
107
+ do the same thing.
106
108
 
107
109
  ---
108
110
 
@@ -135,9 +137,9 @@ discover every subcommand.
135
137
  | `app select APP_ID` / `app unselect` | Manage the default app used when `--app-id` is omitted |
136
138
  | `app create-section / edit-section / delete-section` | Section management |
137
139
  | `app sort-sections / sort-worksheets` | Reorder sections / a section's worksheets |
138
- | `app create-item` | Batch-create empty worksheets / custom pages |
139
140
  | `app backup / export / exports / backup-logs` | Backup & export |
140
- | `app usage / logs` | Statistics and operation logs |
141
+ | `app usage / logs / log-archives` | Statistics, operation logs and their archives |
142
+ | `app trash` | What was deleted from an application, and by whom |
141
143
  | `app role …` | Role CRUD, permissions, members, leave-all, applications |
142
144
  | `app optionset …` | Option set CRUD and cross-app moves |
143
145
  | `app knowledge list / search` | Vector knowledge bases |
@@ -146,24 +148,30 @@ discover every subcommand.
146
148
 
147
149
  | Command | Description |
148
150
  |---|---|
149
- | `worksheet list / info / fields / field-types` | Discover structure |
150
- | `worksheet create / update / copy / delete` | Worksheet lifecycle |
151
+ | `worksheet list / info / fields / field-types` | Discover structure (`info --with-form --with-views` pulls the layout and views in the same call) |
152
+ | `worksheet list --workflows / --without-workflows` | See which worksheets have automation, and which have none |
153
+ | `worksheet references` | What else points at a worksheet — fields in other sheets, and workflow steps |
154
+ | `worksheet create / update / copy / delete` | Worksheet lifecycle (`update --visibility` hides a sheet from the app navigation) |
155
+ | `worksheet pair-relation` | Make a relation field point both ways (`--repair` fixes one paired by hand) |
156
+ | `worksheet add-fields / update-fields` | Append fields, or replace the whole field layout |
157
+ | `worksheet mount-subtable` | Embed an existing worksheet as a sub-table |
151
158
  | `worksheet rules / save-rule` | Business rules |
152
- | `worksheet switches / edit-switch` | Feature switches |
159
+ | `worksheet switches / switch-types / edit-switch / batch-edit-switch` | Feature switches |
153
160
  | `worksheet form-settings / save-form-settings` | Form submission settings |
154
161
  | `worksheet custom-actions / create-custom-action / delete-custom-action` | Custom action buttons |
155
- | `worksheet create-chart` | Build a statistics chart on a worksheet |
156
- | `worksheet view list / info / create / copy / delete / sort` | View management |
162
+ | `worksheet chart list / get / create / update / delete` | Statistics charts on a worksheet |
163
+ | `worksheet view list / info / create / copy / delete / sort` | View management (`list --deleted` is the recycle bin; a spec can group a table, restrict its columns, or name a plugin) |
157
164
 
158
165
  ### worksheet record — record CRUD
159
166
 
160
167
  | Command | Description |
161
168
  |---|---|
162
169
  | `worksheet record list / get` | Query and read |
163
- | `worksheet record create / update / delete` | Single-row CRUD |
164
- | `worksheet record batch-create / batch-update` | Bulk operations (main-site path; relation/sub-table cells persist) |
170
+ | `worksheet record create / update / delete` | Single-row CRUD (`update --lock` / `--unlock` locks a record against edits) |
171
+ | `worksheet record batch-create / batch-update` | Bulk operations (relation/sub-table cells persist; `batch-create --single-request` writes them all in one call) |
165
172
  | `worksheet record relations / share-link` | Linked records and share URLs |
166
- | `worksheet record discussions / add-discussion / delete-discussion` | Discussion threads |
173
+ | `worksheet record run-action` | Press a custom action button on one or more records (`--button` by name or ID, `--row-ids` comma-separated or repeated) |
174
+ | `worksheet record discussions / add-discussion / delete-discussion` | Discussion threads (mention people with `--at-all` / `--at`) |
167
175
  | `worksheet record logs` | Per-record change log |
168
176
  | `worksheet record pivot / bottom-stats` | Aggregations and summary rows |
169
177
 
@@ -171,13 +179,12 @@ discover every subcommand.
171
179
 
172
180
  | Command | Description |
173
181
  |---|---|
174
- | `workflow list / get / structure / history / groups / stats` | Inspect |
175
- | `workflow create / update / copy / move / delete` | Lifecycle |
182
+ | `workflow list / get / structure / history / groups / stats / pbp-parameters` | Inspect (`list --kind` filters by trigger) |
183
+ | `workflow create / update / copy / move / delete / restore / purge` | Lifecycle (delete is the recycle bin; restore and purge are the way out) |
176
184
  | `workflow publish / rollback` | Versioning |
177
185
  | `workflow trigger / trigger-pbp` | Manual trigger |
178
186
  | `workflow config-get / config-set` | Global config |
179
- | `workflow create-approval / update-approval / delete-approval` | Approval blocks |
180
- | `workflow node …` | Node CRUD, batch-add / batch-update / batch-delete (and `*-approval` variants), test-code / test-webhook / test-ai, controls, types, code templates |
187
+ | `workflow node …` | Node CRUD, batch-add, save-action / save-search / save-get-more, test-code / test-webhook / test-ai, controls, types, code templates |
181
188
 
182
189
  > Always run `hap workflow structure PROCESS_ID` before computing insertion
183
190
  > points, branch IDs, or approval block IDs. Don't fabricate node / block /
@@ -187,9 +194,9 @@ discover every subcommand.
187
194
 
188
195
  | Command | Description |
189
196
  |---|---|
190
- | `approval todo / todo-count / todo-filters / archived` | Pending and archived |
191
- | `approval get / get-by-row / list-by-row / work-item / operations / op-history / history / history-detail` | Read instance state |
192
- | `approval approve / reject / submit / sign / forward / urge` | Act on a task |
197
+ | `approval todo / todo-count / done-count / todo-filters / archived` | Pending, finished and archived |
198
+ | `approval get / work-item / operations / op-history / history / history-detail` | Read instance state |
199
+ | `approval approve / reject / submit / sign / forward / transfer / undo-approval / urge` | Act on a task (signature, attachments and the next step's approvers included) |
193
200
  | `approval revoke / terminate / restart / retry` | Lifecycle |
194
201
  | `approval batch / retry-batch / end-batch` | Bulk variants |
195
202
  | `approval list-types` | Enum reference |
@@ -210,6 +217,7 @@ discover every subcommand.
210
217
  | `contact search / resolve` | Find members by keyword / name / email / phone |
211
218
  | `contact friends / friend-requests` | Address book |
212
219
  | `contact add-friend / accept-friend / reject-friend / ignore-friend / remove-friend` | Friend management |
220
+ | `contact org-roles / org-role-members` | Organization roles and who holds them |
213
221
 
214
222
  ### department — directory
215
223
 
@@ -235,6 +243,7 @@ discover every subcommand.
235
243
  | `calendar list / get / create / update / delete` | Event lifecycle |
236
244
  | `calendar categories` | Built-in categories |
237
245
  | `calendar add-member / remove-member` | Membership |
246
+ | `calendar add-discussion` | Comment on an event (attachments supported; mention people with `--at-all` / `--at`) |
238
247
 
239
248
  ### chat — chat & messaging
240
249
 
@@ -251,6 +260,7 @@ discover every subcommand.
251
260
 
252
261
  | Command | Description |
253
262
  |---|---|
263
+ | `group list` | List open groups you have joined (`--org-id`, `--keywords`, and pagination options) |
254
264
  | `group info GROUP_ID` | Group metadata |
255
265
  | `group create` | Create a new group (`--name`, `--org-id`, optional `--member`) |
256
266
  | `group add-member` | Add one or more members (`--group-id`, `--account-id`) |
@@ -273,7 +283,7 @@ discover every subcommand.
273
283
 
274
284
  | Command | Description |
275
285
  |---|---|
276
- | `attachment share ADDRESS` | Create a link to a stored file that you can pass on (`--hours`, default 48) |
286
+ | `attachment share [ADDRESS]` | Create a link to a stored file that you can pass on (`--hours`, default 48; `--file-id` to share by attachment id, `--short` for a landing page instead of the storage address) |
277
287
 
278
288
  > ADDRESS is the file's link — one that has already stopped working is fine, paste it as-is — or just the path part of it. The file itself does not expire, only the link does, so a dead link can always be revived.
279
289
 
@@ -281,7 +291,7 @@ discover every subcommand.
281
291
 
282
292
  | Command | Description |
283
293
  |---|---|
284
- | `guide` | Built-in usage guide: what this version can do, and the value formats that are easy to get wrong (`hap guide <topic>` for detail) |
294
+ | `guide` | Built-in usage guide: what this version can do, and the value formats that are easy to get wrong. `hap guide` lists the topics, `hap guide <topic>` what one covers section by section, `hap guide <topic> <number or name>` one section |
285
295
 
286
296
  ### upload — file upload
287
297
 
@@ -0,0 +1 @@
1
+ """Long-lived live fixtures. Built once, kept, reused by later work."""
@@ -0,0 +1,256 @@
1
+ """Build the FB- scenario: the shape the feedback report was written about.
2
+
3
+ Twenty-odd near-identical document tables spread over sub-groups, copied
4
+ from one template, wired together with sub-tables, relations, look-ups,
5
+ roll-ups, formulas, dynamic defaults and one two-way pair. That shape is
6
+ what made the report's problems visible, so the fixes need it standing.
7
+
8
+ This is deliberately **not** torn down: it is the baseline later work
9
+ reads from. Everything it makes is named ``FB-*`` and lives in the
10
+ persistent live-test application.
11
+
12
+ Every server interaction goes through the ``hap`` CLI. That is the point
13
+ — the report's complaint was that none of this could be done with the
14
+ CLI, so a fixture that reached for ``session.api_call`` would be
15
+ assuming away the thing under test.
16
+
17
+ Run:
18
+ python3 -m app_live_tests.fixtures.feedback_scenario # build / repair
19
+ python3 -m app_live_tests.fixtures.feedback_scenario --show # print ids
20
+
21
+ It is idempotent: anything already there by name is reused, so a second
22
+ run makes no new objects.
23
+
24
+ FB-单据B-模板 is deliberately left in a damaged state — see below.
25
+
26
+ Two-way pairing, and why one sheet here is broken on purpose
27
+ -----------------------------------------------------------
28
+ There is no supported way to pair a relation two-way from the CLI. The
29
+ report's author worked one out (3.5): read the placeholder the server
30
+ puts on the forward field's ``sourceControlId``, then create a field on
31
+ the target sheet whose ``controlId`` is forced to that placeholder. It
32
+ does produce a pair that reads as two-way — and it leaves the target
33
+ sheet corrupting on every later save.
34
+
35
+ Measured 2026-09-10 on this fixture:
36
+
37
+ * ``FB-单据B-模板`` holds such a forged reverse end. Reading its 14
38
+ controls and posting the same 14 back answers ``操作成功`` and reads
39
+ back 15, the reverse-end control duplicated under one ``controlId``.
40
+ Repeated three times: 14 in, 15 out, every time. Sending a
41
+ de-duplicated layout does not help; the only clean layout is one that
42
+ drops the pairing altogether.
43
+ * ``FB-明细-隐藏`` holds a reverse end created by ``mount-subtable``,
44
+ which pairs through the supported path. Same no-op replace: 5 in, 5
45
+ out, clean.
46
+ * ``FB-单据A-模板`` is the forward side and carries all six bridge
47
+ fields. Same no-op replace: 22 in, 22 out, clean, every bridge intact.
48
+
49
+ So a full-layout replace is not broadly unsafe, and this is not a
50
+ server-side defect in ``SaveWorksheetControls``. What corrupts is a
51
+ reverse end that was never registered as one — the server re-materialises
52
+ the real far side beside the forged one on every save. Which means the
53
+ recipe in report 3.5 quietly damages every sheet it is applied to, and
54
+ sheets built that way accumulate a copy per edit.
55
+
56
+ The damage is left standing here on purpose: a fix for report 3.4 has to
57
+ classify this pair as two-way, and the ``--check`` validator asked for in
58
+ 3.7 has to notice the duplicate ``controlId``.
59
+ """
60
+ from __future__ import annotations
61
+
62
+ import json
63
+ import sys
64
+ from pathlib import Path
65
+
66
+ from app_live_tests import state
67
+ from app_live_tests.harness import hap
68
+
69
+ STATE_PATH = Path(__file__).resolve().parent / "state" / "feedback_scenario.json"
70
+
71
+ PREFIX = "FB-"
72
+ TEMPLATE_GROUP = "FB-模板组"
73
+ TARGET_GROUP = "FB-目标组"
74
+ HELPER_GROUP = "FB-辅助组"
75
+
76
+ # The twelve columns every document table in the report carries, plus the
77
+ # title. Kept here as data so later work can rebuild or compare against
78
+ # them without re-reading the report.
79
+ STANDARD_FIELDS = [
80
+ {"type": "TEXT", "name": "名称", "required": True},
81
+ {"type": "DROP_DOWN", "name": "单据状态",
82
+ "options": ["草稿", "已提交", "已完成"]},
83
+ {"type": "DROP_DOWN", "name": "审核状态",
84
+ "options": ["待审核", "通过", "驳回"]},
85
+ {"type": "DATE", "name": "业务日期"},
86
+ {"type": "USER_PICKER", "name": "经手人"},
87
+ {"type": "DEPARTMENT", "name": "业务部门"},
88
+ {"type": "USER_PICKER", "name": "部门负责人"},
89
+ {"type": "USER_PICKER", "name": "待审核人"},
90
+ {"type": "USER_PICKER", "name": "已审核人"},
91
+ {"type": "TEXT", "name": "审核意见"},
92
+ {"type": "AUTO_ID", "name": "流水号"},
93
+ {"type": "TEXT", "name": "备注"},
94
+ {"type": "ATTACHMENT", "name": "附件"},
95
+ ]
96
+
97
+ DETAIL_FIELDS = [
98
+ {"type": "TEXT", "name": "明细名称", "required": True},
99
+ {"type": "NUMBER", "name": "数量"},
100
+ {"type": "MONEY", "name": "单价"},
101
+ {"type": "TEXT", "name": "明细备注"},
102
+ ]
103
+
104
+ TEMPLATE_SHEETS = ["FB-单据A-模板", "FB-单据B-模板", "FB-单据C-模板"]
105
+ TARGET_SHEETS = ["FB-单据A-目标", "FB-单据B-目标", "FB-单据C-目标"]
106
+ DETAIL_SHEET = "FB-明细-隐藏"
107
+
108
+
109
+ def _load() -> dict:
110
+ if STATE_PATH.exists():
111
+ return json.loads(STATE_PATH.read_text(encoding="utf-8"))
112
+ return {}
113
+
114
+
115
+ def _save(data: dict) -> None:
116
+ STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
117
+ STATE_PATH.write_text(
118
+ json.dumps(data, ensure_ascii=False, indent=1) + "\n", encoding="utf-8")
119
+
120
+
121
+ def _app_tree(app_id: str) -> dict:
122
+ detail = hap(["app", "info", "-a", app_id], check=False)
123
+ return detail.get("data", detail) if isinstance(detail, dict) else {}
124
+
125
+
126
+ def _child_sections(app_id: str) -> dict[str, str]:
127
+ """Name → id for every second-level group under the app's root."""
128
+ out: dict[str, str] = {}
129
+ for sec in _app_tree(app_id).get("sections") or []:
130
+ for child in sec.get("childSections") or []:
131
+ if child.get("name"):
132
+ out[child["name"]] = child.get("id") or ""
133
+ return out
134
+
135
+
136
+ def _items(app_id: str) -> dict[str, str]:
137
+ """Name → id for every worksheet anywhere in the app, groups included."""
138
+ out: dict[str, str] = {}
139
+
140
+ def walk(sections):
141
+ for sec in sections or []:
142
+ for item in sec.get("items") or []:
143
+ if item.get("type", 0) == 0 and item.get("name"):
144
+ out[item["name"]] = item.get("id") or ""
145
+ walk(sec.get("childSections"))
146
+
147
+ walk(_app_tree(app_id).get("sections"))
148
+ return out
149
+
150
+
151
+ def _fields(ws_id: str) -> list[dict]:
152
+ data = hap(["worksheet", "fields", ws_id, "--raw"], check=False)
153
+ return data if isinstance(data, list) else []
154
+
155
+
156
+ def _by_name(ws_id: str, name: str) -> str:
157
+ for c in _fields(ws_id):
158
+ if c.get("controlName") == name:
159
+ return c.get("controlId") or ""
160
+ return ""
161
+
162
+
163
+ def _ensure_section(app_id: str, root_id: str, name: str) -> str:
164
+ have = _child_sections(app_id)
165
+ if name in have:
166
+ return have[name]
167
+ made = hap(["app", "add-section", app_id, "-n", name,
168
+ "--parent-id", root_id], check=False)
169
+ return made if isinstance(made, str) else ""
170
+
171
+
172
+ def build(show_only: bool = False) -> dict:
173
+ app_id, org_id = state.ensure_app()
174
+ root_id = state.first_section_id(app_id)
175
+ data = _load()
176
+ data.update({"app_id": app_id, "org_id": org_id, "root_section": root_id})
177
+ if show_only:
178
+ print(json.dumps(data, ensure_ascii=False, indent=1))
179
+ return data
180
+
181
+ # ── the three second-level groups ────────────────────────────────
182
+ sections = {}
183
+ for name in (TEMPLATE_GROUP, TARGET_GROUP, HELPER_GROUP):
184
+ sections[name] = _ensure_section(app_id, root_id, name)
185
+ print(f" group {name}: {sections[name]}")
186
+ data["sections"] = sections
187
+
188
+ items = _items(app_id)
189
+
190
+ # ── the template table, then five copies of it ───────────────────
191
+ # Copies keep the source's controlIds — that is the product's own
192
+ # behaviour and the reason the report's author first suspected
193
+ # cross-sheet mis-references (report 3.10). The fixture keeps it.
194
+ template = TEMPLATE_SHEETS[0]
195
+ if template in items:
196
+ tpl_id = items[template]
197
+ else:
198
+ made = hap(["worksheet", "create", app_id, template,
199
+ "--section-id", sections[TEMPLATE_GROUP]], check=False)
200
+ tpl_id = (made.get("workSheetId") or made.get("id")
201
+ if isinstance(made, dict) else "") or ""
202
+ hap(["worksheet", "update-fields", tpl_id, "--title-name", "名称",
203
+ "--fields", json.dumps(STANDARD_FIELDS, ensure_ascii=False)],
204
+ check=False)
205
+ print(f" template {template}: {tpl_id}")
206
+
207
+ sheets = {template: tpl_id}
208
+ plan = [(n, sections[TEMPLATE_GROUP]) for n in TEMPLATE_SHEETS[1:]]
209
+ plan += [(n, sections[TARGET_GROUP]) for n in TARGET_SHEETS]
210
+ for name, sec in plan:
211
+ if name in items:
212
+ sheets[name] = items[name]
213
+ else:
214
+ made = hap(["worksheet", "copy", tpl_id, name, "-a", app_id,
215
+ "--section-id", sec], check=False)
216
+ sheets[name] = made if isinstance(made, str) else ""
217
+ print(f" sheet {name}: {sheets[name]}")
218
+
219
+ # ── the hidden detail sheet, mounted as a sub-table ──────────────
220
+ if DETAIL_SHEET in items:
221
+ detail_id = items[DETAIL_SHEET]
222
+ else:
223
+ made = hap(["worksheet", "create", app_id, DETAIL_SHEET,
224
+ "--section-id", sections[HELPER_GROUP]], check=False)
225
+ detail_id = (made.get("workSheetId") or made.get("id")
226
+ if isinstance(made, dict) else "") or ""
227
+ hap(["worksheet", "update-fields", detail_id,
228
+ "--title-name", "明细名称",
229
+ "--fields", json.dumps(DETAIL_FIELDS, ensure_ascii=False)],
230
+ check=False)
231
+ hap(["worksheet", "mount-subtable", tpl_id, detail_id,
232
+ "--name", "明细子表", "-a", app_id], check=False)
233
+ hap(["worksheet", "update", detail_id, "-a", app_id,
234
+ "--visibility", "hidden"], check=False)
235
+ sheets[DETAIL_SHEET] = detail_id
236
+ print(f" detail {DETAIL_SHEET}: {detail_id} (hidden)")
237
+
238
+ data["sheets"] = sheets
239
+ data["fields"] = {
240
+ name: {c.get("controlName"): c.get("controlId")
241
+ for c in _fields(wid) if c.get("controlName")}
242
+ for name, wid in sheets.items()
243
+ }
244
+ _save(data)
245
+ print(f"\nwrote {STATE_PATH}")
246
+ return data
247
+
248
+
249
+ def main(argv: list[str] | None = None) -> int:
250
+ argv = list(sys.argv[1:] if argv is None else argv)
251
+ build(show_only="--show" in argv)
252
+ return 0
253
+
254
+
255
+ if __name__ == "__main__":
256
+ raise SystemExit(main())