netizen-cli 0.13.3__tar.gz → 0.14.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 (324) hide show
  1. {netizen_cli-0.13.3/netizen_cli.egg-info → netizen_cli-0.14.0}/PKG-INFO +1 -1
  2. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/README.md +3 -3
  3. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/__init__.py +1 -1
  4. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/presentation.py +11 -0
  5. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/admin.css +5 -0
  6. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/admin.js +161 -43
  7. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/index.html +45 -13
  8. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/worktrees.js +12 -12
  9. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/web.py +29 -15
  10. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/bindings.py +30 -15
  11. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/controls.py +64 -21
  12. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/defaults.py +3 -3
  13. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/reply.py +113 -47
  14. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/scheduled.py +21 -21
  15. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/workspace.py +17 -17
  16. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel_app.py +14 -9
  17. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/codex_runtime.py +78 -83
  18. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/database_migrations.py +2 -0
  19. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/defaults/service.py +4 -4
  20. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/defaults/store.py +1 -1
  21. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/domain.py +7 -0
  22. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/chat_labels.py +152 -69
  23. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/service.py +36 -28
  24. netizen_cli-0.14.0/netizen_cli/migrations/v18.py +132 -0
  25. netizen_cli-0.14.0/netizen_cli/progress_card_settings.py +42 -0
  26. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/runtime/contracts.py +4 -0
  27. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/service.py +7 -7
  28. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/store.py +6 -6
  29. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sdk_gap_adapter.py +14 -1
  30. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/session_settings.py +12 -2
  31. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/turn_activity.py +49 -27
  32. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/turn_plan_observer.py +4 -0
  33. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/policy.py +3 -3
  34. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/service.py +14 -14
  35. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/store.py +15 -15
  36. {netizen_cli-0.13.3 → netizen_cli-0.14.0/netizen_cli.egg-info}/PKG-INFO +1 -1
  37. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli.egg-info/SOURCES.txt +5 -0
  38. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/pyproject.toml +1 -1
  39. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/admin.md +24 -19
  40. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/concepts.md +1 -1
  41. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/feedback-and-files.md +42 -3
  42. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/fork-side-goal.md +1 -1
  43. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/native-capabilities.md +1 -1
  44. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/scheduled-tasks.md +28 -26
  45. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/session-collaboration.md +4 -4
  46. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/sessions.md +33 -31
  47. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/user-guide.md +4 -4
  48. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cards.py +8 -5
  49. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_channel_app.py +1 -1
  50. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_data.py +6 -6
  51. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_codex_runtime.py +257 -4
  52. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cron_chat_targets.py +2 -2
  53. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_database_migrations.py +4 -4
  54. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_defaults_cards.py +6 -6
  55. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_defaults_channel.py +4 -4
  56. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_migration_schema_validation.py +1 -1
  57. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_persistent_fork_channel.py +4 -1
  58. netizen_cli-0.14.0/tests/test_progress_card_entrypoints.py +182 -0
  59. netizen_cli-0.14.0/tests/test_progress_card_presentation.py +273 -0
  60. netizen_cli-0.14.0/tests/test_progress_card_settings_migration.py +177 -0
  61. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_cards.py +8 -8
  62. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_service.py +4 -1
  63. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_workspace_cards.py +2 -2
  64. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_workspace_migration.py +15 -4
  65. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedules_storage.py +4 -1
  66. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_sdk_gap_adapter.py +25 -0
  67. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_collaboration_app.py +7 -2
  68. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_defaults_migration.py +15 -3
  69. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_settings.py +48 -0
  70. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_turn_activity.py +57 -0
  71. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_turn_plan_observer.py +23 -0
  72. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_new.py +3 -3
  73. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_storage.py +16 -1
  74. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/MANIFEST.in +0 -0
  75. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/_build.py +0 -0
  76. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/config.example.yaml +0 -0
  77. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/__main__.py +0 -0
  78. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/account_rate_limits.py +0 -0
  79. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/__init__.py +0 -0
  80. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/auth.py +0 -0
  81. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/credentials.py +0 -0
  82. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/errors.py +0 -0
  83. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/feishu.py +0 -0
  84. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/login.py +0 -0
  85. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/port_config.py +0 -0
  86. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/queries.py +0 -0
  87. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/chat-picker.css +0 -0
  88. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/chat-picker.js +0 -0
  89. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/identity.js +0 -0
  90. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/login.html +0 -0
  91. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/login.js +0 -0
  92. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/static/session-access.js +0 -0
  93. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/transport.py +0 -0
  94. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/admin/users.py +0 -0
  95. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/builtin_skills.py +0 -0
  96. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/__init__.py +0 -0
  97. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/callbacks.py +0 -0
  98. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/chat_target.py +0 -0
  99. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/fork.py +0 -0
  100. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/model_info.py +0 -0
  101. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/pagination.py +0 -0
  102. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/questions.py +0 -0
  103. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/session_ids.py +0 -0
  104. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/status.py +0 -0
  105. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cards/usage.py +0 -0
  106. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/__init__.py +0 -0
  107. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/completion_mentions.py +0 -0
  108. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/input_preparation.py +0 -0
  109. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/messages.py +0 -0
  110. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/ports.py +0 -0
  111. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/question_inputs.py +0 -0
  112. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/reactions.py +0 -0
  113. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/reply_presenter.py +0 -0
  114. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/session_pages.py +0 -0
  115. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/channel/topics.py +0 -0
  116. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/chat_avatars.py +0 -0
  117. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/chat_targets.py +0 -0
  118. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli.py +0 -0
  119. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_data.py +0 -0
  120. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_packages.py +0 -0
  121. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_services.py +0 -0
  122. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_setup.py +0 -0
  123. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_update.py +0 -0
  124. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_update_restore.py +0 -0
  125. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/cli_update_worker.py +0 -0
  126. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/completion_mention.py +0 -0
  127. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/defaults/__init__.py +0 -0
  128. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/defaults/models.py +0 -0
  129. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/deployment/__init__.py +0 -0
  130. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/deployment/restart_worker.py +0 -0
  131. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/deployment/update_executor.py +0 -0
  132. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/deployment/update_protocol.py +0 -0
  133. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/error_messages.py +0 -0
  134. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/experience.py +0 -0
  135. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/feishu_app_onboarding.py +0 -0
  136. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/feishu_app_permissions.py +0 -0
  137. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/feishu_links.py +0 -0
  138. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/git_status.py +0 -0
  139. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/image_inputs.py +0 -0
  140. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/instance.py +0 -0
  141. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/lark_app.py +0 -0
  142. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/main.py +0 -0
  143. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/__init__.py +0 -0
  144. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/blocking_io.py +0 -0
  145. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/chat_directory.py +0 -0
  146. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/coordination.py +0 -0
  147. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/management/updates.py +0 -0
  148. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/markdown_images.py +0 -0
  149. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/mcp_transport.py +0 -0
  150. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/message_content.py +0 -0
  151. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/message_history.py +0 -0
  152. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/message_preparation.py +0 -0
  153. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/message_projection.py +0 -0
  154. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/__init__.py +0 -0
  155. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/schema.py +0 -0
  156. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/v14.py +0 -0
  157. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/v15.py +0 -0
  158. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/v16.py +0 -0
  159. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/migrations/v17.py +0 -0
  160. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/model_settings.py +0 -0
  161. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/package_resources.py +0 -0
  162. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/pagination.py +0 -0
  163. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/partial_answers.py +0 -0
  164. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/projects.py +0 -0
  165. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/prompt_projection.py +0 -0
  166. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/quoted_context.py +0 -0
  167. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/result_images.py +0 -0
  168. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/runtime/__init__.py +0 -0
  169. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/runtime/name_writes.py +0 -0
  170. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/runtime/thread_naming.py +0 -0
  171. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/__init__.py +0 -0
  172. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/mcp.py +0 -0
  173. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/models.py +0 -0
  174. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/schedules/scheduler.py +0 -0
  175. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/service_launcher.py +0 -0
  176. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/session_inventory.py +0 -0
  177. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/__init__.py +0 -0
  178. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/delegation.py +0 -0
  179. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/errors.py +0 -0
  180. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/mcp.py +0 -0
  181. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/policy.py +0 -0
  182. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/presentation.py +0 -0
  183. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/schema.py +0 -0
  184. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/sessions/service.py +0 -0
  185. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/settings.py +0 -0
  186. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/skill_references.py +0 -0
  187. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/task_text.py +0 -0
  188. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/terminal_cleanup.py +0 -0
  189. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/thread_history.py +0 -0
  190. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/turn_files.py +0 -0
  191. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/turn_patch_children.py +0 -0
  192. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/user_questions.py +0 -0
  193. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/errors.py +0 -0
  194. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/git.py +0 -0
  195. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/models.py +0 -0
  196. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli/worktrees/settings.py +0 -0
  197. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli.egg-info/dependency_links.txt +0 -0
  198. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli.egg-info/entry_points.txt +0 -0
  199. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli.egg-info/requires.txt +0 -0
  200. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/netizen_cli.egg-info/top_level.txt +0 -0
  201. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/setup.cfg +0 -0
  202. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-lark/SKILL.md +0 -0
  203. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/SKILL.md +0 -0
  204. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/commands.md +0 -0
  205. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/faq.md +0 -0
  206. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/messages.md +0 -0
  207. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/skills/netizen-user-guide/references/status-and-control.md +0 -0
  208. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_account_rate_limits.py +0 -0
  209. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_admin_update_executor_probe.py +0 -0
  210. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_binding_scheduled_channel.py +0 -0
  211. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_bindings.py +0 -0
  212. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_channel_fixtures.py +0 -0
  213. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_channel_input_preparation.py +0 -0
  214. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_chat_avatars.py +0 -0
  215. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_chat_target_cards.py +0 -0
  216. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_check_sdk.py +0 -0
  217. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli.py +0 -0
  218. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_distribution.py +0 -0
  219. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_integration.py +0 -0
  220. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_packages.py +0 -0
  221. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_packaging.py +0 -0
  222. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_services.py +0 -0
  223. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_setup.py +0 -0
  224. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_cli_update.py +0 -0
  225. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_codex_sdk_capabilities.py +0 -0
  226. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_codex_sdk_upgrade_0161.py +0 -0
  227. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_codex_sdk_upgrade_0163.py +0 -0
  228. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_completion_mention_cards.py +0 -0
  229. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_completion_mentions.py +0 -0
  230. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_completion_topic_delivery.py +0 -0
  231. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_defaults_runtime.py +0 -0
  232. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_defaults_worktree_channel.py +0 -0
  233. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_deployment.py +0 -0
  234. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_documentation_links.py +0 -0
  235. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_domain_experience.py +0 -0
  236. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_error_messages.py +0 -0
  237. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_feishu_app_onboarding.py +0 -0
  238. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_feishu_app_permissions.py +0 -0
  239. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_file_pagination.py +0 -0
  240. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_fork_cards.py +0 -0
  241. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_git_status.py +0 -0
  242. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_goal_reply_separation.py +0 -0
  243. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_image_inputs.py +0 -0
  244. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_lark_app.py +0 -0
  245. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_lark_sdk_contract.py +0 -0
  246. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_main.py +0 -0
  247. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_markdown_images.py +0 -0
  248. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_message_content.py +0 -0
  249. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_message_history.py +0 -0
  250. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_message_material_inputs.py +0 -0
  251. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_message_preparation.py +0 -0
  252. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_model_info_cards.py +0 -0
  253. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_model_settings.py +0 -0
  254. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_name_writes.py +0 -0
  255. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_pagination.py +0 -0
  256. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_partial_answer_delivery.py +0 -0
  257. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_partial_answers.py +0 -0
  258. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_persistent_fork_bindings.py +0 -0
  259. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_persistent_fork_runtime.py +0 -0
  260. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_child_files.py +0 -0
  261. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_feishu_completion_mention.py +0 -0
  262. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_feishu_partial_answers.py +0 -0
  263. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_feishu_turn_file_card.py +0 -0
  264. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_persistent_fork.py +0 -0
  265. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_python_sdk.py +0 -0
  266. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_scheduled_tasks.py +0 -0
  267. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_sdk_completion_race.py +0 -0
  268. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_sdk_response_recovery.py +0 -0
  269. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_skill_execution.py +0 -0
  270. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_probe_thread_naming.py +0 -0
  271. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_project_delete_channel.py +0 -0
  272. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_project_delete_runtime.py +0 -0
  273. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_project_deletion_storage.py +0 -0
  274. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_prompt_projection.py +0 -0
  275. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_question_cards.py +0 -0
  276. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_question_channel.py +0 -0
  277. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_question_target_parity.py +0 -0
  278. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_quoted_context.py +0 -0
  279. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_release_script.py +0 -0
  280. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_repository_hygiene.py +0 -0
  281. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_result_images.py +0 -0
  282. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_resume_channel.py +0 -0
  283. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_retired_deployment.py +0 -0
  284. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_runtime_resume_activation.py +0 -0
  285. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_runtime_thread_naming.py +0 -0
  286. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_card_retry.py +0 -0
  287. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_mcp.py +0 -0
  288. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_run_now.py +0 -0
  289. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_scope_matrix.py +0 -0
  290. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_workspace_service.py +0 -0
  291. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_schedule_workspace_storage.py +0 -0
  292. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_scheduled_channel.py +0 -0
  293. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_scheduled_runtime.py +0 -0
  294. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_scheduled_worktrees.py +0 -0
  295. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_scheduler.py +0 -0
  296. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_scheduler_presenter.py +0 -0
  297. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_service_launcher.py +0 -0
  298. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_card_pages.py +0 -0
  299. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_defaults.py +0 -0
  300. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_external_runtime.py +0 -0
  301. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_id_cards.py +0 -0
  302. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_policy.py +0 -0
  303. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_session_tools.py +0 -0
  304. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_settings_projects.py +0 -0
  305. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_status_cards.py +0 -0
  306. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_status_commands.py +0 -0
  307. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_task_text.py +0 -0
  308. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_terminal_cleanup.py +0 -0
  309. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_thread_history.py +0 -0
  310. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_thread_naming.py +0 -0
  311. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_turn_files.py +0 -0
  312. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_turn_patch_children.py +0 -0
  313. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_turn_patch_statistics.py +0 -0
  314. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_update_executor.py +0 -0
  315. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_usage_card.py +0 -0
  316. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_usage_control.py +0 -0
  317. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_user_guide_skill.py +0 -0
  318. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_user_questions.py +0 -0
  319. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_channel_cwd.py +0 -0
  320. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_git.py +0 -0
  321. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_runtime_cwd.py +0 -0
  322. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_service.py +0 -0
  323. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_settings.py +0 -0
  324. {netizen_cli-0.13.3 → netizen_cli-0.14.0}/tests/test_worktree_tools_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netizen-cli
3
- Version: 0.13.3
3
+ Version: 0.14.0
4
4
  Summary: Use native Codex threads through a Feishu Channel.
5
5
  Requires-Python: <3.15,>=3.11
6
6
  Requires-Dist: h11==0.16.0
@@ -116,10 +116,10 @@ Agent/脚本使用 `netizen update --json`:stdout 只输出最终 JSON,进
116
116
  群聊和群话题中的每条请求都需要重新 **@机器人**,包括命令。`/new` 只通过卡片创建会话,
117
117
  不接受参数。普通任务执行中发来的新消息用于调整当前任务,不会排队成下一个任务。
118
118
 
119
- Git 项目可在 `/new` 中加载项目目录选项,选择已有受管 worktree 或新建 worktree;默认
119
+ Git 项目可在 `/new` 中加载 worktree 选项,选择已有受管 worktree 或新建 worktree;默认
120
120
  仍使用项目目录。新建只检出提交内容,不复制本地改动或执行环境初始化。
121
- 配置、状态查询与删除在 [Admin Worktrees](skills/netizen-user-guide/references/admin.md#worktree-配置与管理)
122
- 中完成;不同会话可以共享同一工作区。`/fork` 不提供新建或选择 worktree 的入口。
121
+ 配置、状态查询与删除在 [Admin worktree](skills/netizen-user-guide/references/admin.md#worktree-配置与管理)
122
+ 中完成;不同会话可以共享同一 worktree。`/fork` 不提供新建或选择 worktree 的入口。
123
123
 
124
124
  安装遇到问题可从[部署文档](docs/deployment.md)继续;已能对话时,常见疑问见
125
125
  [使用 FAQ](skills/netizen-user-guide/references/faq.md#常见问题)。
@@ -1,3 +1,3 @@
1
1
  """Netizen: a thin Feishu Channel for native Codex Threads."""
2
2
 
3
- __version__ = "0.13.3"
3
+ __version__ = "0.14.0"
@@ -23,6 +23,17 @@ def _chat_open_url(chat: ChatLabel) -> str:
23
23
  )
24
24
 
25
25
 
26
+ def _chat_label_json(chat: ChatLabel) -> dict[str, object]:
27
+ return {
28
+ "chatId": chat.chat_id,
29
+ "chatLabel": chat.display_name,
30
+ "chatLabelResolved": chat.resolved,
31
+ "chatMode": chat.chat_mode,
32
+ "chatType": chat.chat_type,
33
+ "chatOpenUrl": _chat_open_url(chat),
34
+ }
35
+
36
+
26
37
  def _schedule_plan_json(plan: dict[str, Any], chat: ChatLabel) -> dict[str, Any]:
27
38
  rule = plan.get("schedule")
28
39
  local_at = None
@@ -380,6 +380,11 @@ body.schedule-detail-open { overflow: hidden; }
380
380
  .defaults-feedback { display: flex; flex-wrap: wrap; gap: 18px; }
381
381
  .defaults-feedback label { display: flex; align-items: center; gap: 7px; }
382
382
  .drawer-form .defaults-feedback input { width: 16px; height: 16px; margin: 0; accent-color: var(--blue); }
383
+ .progress-settings { margin-top: 18px; padding: 16px; border: 1px solid var(--line); border-radius: 8px; }
384
+ .progress-settings > .defaults-feedback { margin-top: 16px; }
385
+ .progress-settings > .schedule-form-grid { margin-top: 10px; }
386
+ .progress-settings > .session-settings-help { margin-bottom: 0; }
387
+ .progress-settings-error { color: var(--danger); font-size: 13px; line-height: 1.6; }
383
388
  #defaults-note.error { color: var(--danger); }
384
389
  #defaults-workspace-help.error, #schedule-editor #schedule-workspace-help.error { color: var(--danger); }
385
390
  #session-settings-editor[hidden], #session-settings-editor [hidden] { display: none; }
@@ -55,6 +55,7 @@ async function api(path, options = {}) {
55
55
  function expireAdminSession() {
56
56
  if (state.authExpired) return;
57
57
  state.authExpired = true;
58
+ invalidateSessionListRequest();
58
59
  stopUpdatePolling();
59
60
  window.NetizenSelect?.close();
60
61
  // Release these modal drawers so the page's login link remains reachable.
@@ -609,7 +610,7 @@ function confirmProjectDelete(preview) {
609
610
  + "\n定时计划将被删除;后续会话清理失败也不会恢复计划。"
610
611
  + "\n\n原生会话、派生子会话、Codex App/CLI 历史和本地会话登记将永久删除,无法恢复。"
611
612
  + "\n全部会话删除确认成功后,才会删除 Project 登记;部分失败时会保留 Project 和剩余会话。"
612
- + `\n关联受管 Worktrees:${preview.worktreeCount || 0},${preview.deleteWorktrees ? "同时安全删除;失败项保留,不强制丢弃成果" : "保留目录,可在 Worktrees 页面处理;不会自动关联到同名新 Project"}。`
613
+ + `\n关联受管 worktree:${preview.worktreeCount || 0},${preview.deleteWorktrees ? "同时安全删除;失败项保留,不强制丢弃成果" : "保留目录,可在 worktree 页面处理;不会自动关联到同名新 Project"}。`
613
614
  + (preview.deleteWorktrees && preview.worktrees?.length ? `\n将删除的 checkout 根目录:\n${preview.worktrees.map((item) => `${item.id} · ${item.root}`).join("\n")}` : "")
614
615
  + `\n\n磁盘代码目录保留:${preview.project.cwd}`,
615
616
  );
@@ -665,10 +666,10 @@ async function deleteProject(project, deleteWorktrees = false) {
665
666
  if (result.remainingScheduledRunCount) {
666
667
  details.push(`仍有 ${result.remainingScheduledRunCount} 条定时执行的交接或清理未确认。`);
667
668
  }
668
- if (result.deletedWorktreeCount) message += `\n已删除 ${result.deletedWorktreeCount} 个受管 Worktree。`;
669
+ if (result.deletedWorktreeCount) message += `\n已删除 ${result.deletedWorktreeCount} 个受管 worktree。`;
669
670
  if (result.remainingWorktreeCount) {
670
- if (result.deleteWorktrees) details.push(`仍有 ${result.remainingWorktreeCount} 个受管 Worktree 未安全删除,请在 Worktrees 页面检查。`);
671
- else message += `\n已按选择保留 ${result.remainingWorktreeCount} 个受管 Worktree,可在 Worktrees 页面处理。`;
671
+ if (result.deleteWorktrees) details.push(`仍有 ${result.remainingWorktreeCount} 个受管 worktree 未安全删除,请在 worktree 页面检查。`);
672
+ else message += `\n已按选择保留 ${result.remainingWorktreeCount} 个受管 worktree,可在 worktree 页面处理。`;
672
673
  }
673
674
  return result;
674
675
  } catch (error) {
@@ -727,7 +728,7 @@ async function loadProjects(cursor = undefined) {
727
728
  cascadeLabel.className = "cascade-choice";
728
729
  const cascade = document.createElement("input");
729
730
  cascade.type = "checkbox";
730
- cascadeLabel.append(cascade, document.createTextNode("同时删除关联受管 Worktrees"));
731
+ cascadeLabel.append(cascade, document.createTextNode("同时删除关联受管 worktree"));
731
732
  actions.append(cascadeLabel);
732
733
  actions.append(actionButton(
733
734
  "删除 Project 及关联 Sessions", () => deleteProject(project, cascade.checked), true,
@@ -1824,24 +1825,33 @@ function locationFallback(session) {
1824
1825
 
1825
1826
  function sessionLocationCell(row, session, { showIdentity = true } = {}) {
1826
1827
  const td = document.createElement("td");
1828
+ td.className = "session-location";
1827
1829
  const link = document.createElement("a");
1828
1830
  link.className = "chat-link";
1829
- link.href = session.topicOpenUrl || session.chatOpenUrl;
1830
1831
  link.target = "_blank";
1831
1832
  link.rel = "noopener noreferrer";
1832
- link.textContent = session.chatLabelResolved
1833
- ? session.chatLabel
1834
- : showIdentity ? locationFallback(session) : `${chatModeLabel(session.chatMode, session.scopeKind)}(名称暂不可用)`;
1835
- link.title = session.topicOpenUrl
1836
- ? "打开飞书话题"
1837
- : "打开飞书会话";
1838
1833
  const mode = document.createElement("div");
1839
1834
  mode.className = "meta-line";
1840
1835
  mode.append(badge(chatModeLabel(session.chatMode, session.scopeKind)));
1841
1836
  td.append(link, mode);
1837
+ updateSessionLocationCell(td, session, { showIdentity });
1842
1838
  row.append(td);
1843
1839
  }
1844
1840
 
1841
+ function updateSessionLocationCell(td, session, { showIdentity = true, loading = false } = {}) {
1842
+ const link = td.querySelector(".chat-link");
1843
+ link.href = session.topicOpenUrl || session.chatOpenUrl;
1844
+ link.textContent = session.chatLabelResolved
1845
+ ? session.chatLabel
1846
+ : loading ? `${chatModeLabel(session.chatMode, session.scopeKind)}(名称加载中)`
1847
+ : showIdentity ? locationFallback(session) : `${chatModeLabel(session.chatMode, session.scopeKind)}(名称暂不可用)`;
1848
+ link.title = session.topicOpenUrl
1849
+ ? "打开飞书话题"
1850
+ : "打开飞书会话";
1851
+ td.querySelector(".badge").textContent = chatModeLabel(session.chatMode, session.scopeKind);
1852
+ td.setAttribute("aria-busy", String(loading));
1853
+ }
1854
+
1845
1855
  function sessionIdentityCell(row, session) {
1846
1856
  const td = document.createElement("td");
1847
1857
  const title = document.createElement("strong");
@@ -2039,12 +2049,58 @@ function resetSessionFilters(kind = "session") {
2039
2049
  return refresh("sessions", page);
2040
2050
  }
2041
2051
 
2052
+ let pendingSessionChatLabels = null;
2053
+
2042
2054
  function invalidateSessionListRequest() {
2043
2055
  state.sessionListRequest = (state.sessionListRequest || 0) + 1;
2056
+ // A failed replacement read can leave these same rows on screen. Their old
2057
+ // enrichment must stop showing a loading placeholder when it is invalidated.
2058
+ pendingSessionChatLabels?.();
2059
+ pendingSessionChatLabels = null;
2060
+ }
2061
+
2062
+ async function loadSessionChatLabels(kind, data, page, request) {
2063
+ const name = kind === "side" ? "sides" : "sessions";
2064
+ const isCurrent = () => !state.authExpired && request === state.sessionListRequest
2065
+ && state.tab === "sessions" && state.sessionTab === (kind === "side" ? "temporary" : "ordinary")
2066
+ && state[name] === data && state[`${kind}Page`] === page;
2067
+ if (!isCurrent()) return;
2068
+ const body = document.querySelector(`#${name}-body`);
2069
+ const targets = data.items.flatMap((item, index) => item.chatLabelResolved || !item.chatId
2070
+ ? [] : [{ item, cell: body.children[index].querySelector(".session-location") }]);
2071
+ if (!targets.length) return;
2072
+ const showIdentity = kind !== "side";
2073
+ const finish = () => {
2074
+ for (const { item, cell } of targets) updateSessionLocationCell(cell, item, { showIdentity });
2075
+ };
2076
+ pendingSessionChatLabels = finish;
2077
+ for (const { item, cell } of targets) updateSessionLocationCell(cell, item, { showIdentity, loading: true });
2078
+ try {
2079
+ const query = new URLSearchParams({ chatIds: [...new Set(targets.map(({ item }) => item.chatId))].join(",") });
2080
+ const labels = await api(`/api/v1/chat-labels?${query}`);
2081
+ if (!isCurrent()) return;
2082
+ const byChat = new Map(labels.items.map((label) => [label.chatId, label]));
2083
+ for (const { item } of targets) {
2084
+ const label = byChat.get(item.chatId);
2085
+ if (!label) continue;
2086
+ // Enrichment changes display facts only; retain exact identities, topic
2087
+ // links, runtime and action grants from the successful list response.
2088
+ for (const field of ["chatLabel", "chatLabelResolved", "chatMode", "chatType", "chatOpenUrl"]) {
2089
+ if (Object.hasOwn(label, field)) item[field] = label[field];
2090
+ }
2091
+ }
2092
+ } catch {
2093
+ // Name failures are local to the location cells. Authentication expiry is
2094
+ // already handled by api(), and list status/freshness stay unchanged.
2095
+ } finally {
2096
+ if (isCurrent()) finish();
2097
+ if (pendingSessionChatLabels === finish) pendingSessionChatLabels = null;
2098
+ }
2044
2099
  }
2045
2100
 
2046
2101
  async function loadSessionPage(kind, page, render) {
2047
- const request = state.sessionListRequest = (state.sessionListRequest || 0) + 1;
2102
+ invalidateSessionListRequest();
2103
+ const request = state.sessionListRequest;
2048
2104
  const isCurrent = () => request === state.sessionListRequest;
2049
2105
  const name = kind === "side" ? "sides" : "sessions";
2050
2106
  setStatus("正在读取服务端事实…");
@@ -2075,6 +2131,7 @@ async function loadSessionPage(kind, page, render) {
2075
2131
  }
2076
2132
  syncPageUrl();
2077
2133
  setStatus("已更新。");
2134
+ void loadSessionChatLabels(kind, data, state[`${kind}Page`], request);
2078
2135
  return true;
2079
2136
  } catch (error) {
2080
2137
  if (isCurrent()) setStatus(error.message + (state[name] ? " 当前仍显示上次成功读取的结果。" : ""), true);
@@ -2278,7 +2335,8 @@ function renderSessionSettingsEditor() {
2278
2335
  }
2279
2336
  sessionSettingsInput("note").textContent = notes.filter(Boolean).join(" ");
2280
2337
  sessionSettingsInput("note").classList.toggle("error", Boolean(editor.error));
2281
- sessionSettingsInput("save").disabled = editor.loading || editor.saving || !editor.action;
2338
+ sessionSettingsInput("save").disabled = editor.loading || editor.saving || !editor.action
2339
+ || Boolean(progressCardSettingsError(editor.settings));
2282
2340
  sessionSettingsInput("save").textContent = editor.saving ? "保存中…" : "保存";
2283
2341
  sessionSettingsInput("cancel").disabled = editor.saving;
2284
2342
  sessionSettingsInput("close").disabled = editor.saving;
@@ -2366,7 +2424,7 @@ function changeSessionSettings(field) {
2366
2424
  async function saveSessionSettings(event) {
2367
2425
  event.preventDefault();
2368
2426
  const editor = sessionSettingsEditor;
2369
- if (!editor || editor.loading || editor.saving || !editor.action) return;
2427
+ if (!editor || editor.loading || editor.saving || !editor.action || progressCardSettingsError(editor.settings)) return;
2370
2428
  const action = editor.action;
2371
2429
  editor.action = null;
2372
2430
  editor.session.actions.configure = null;
@@ -2533,9 +2591,9 @@ function workspacePolicyAvailable(workspace, options, project) {
2533
2591
 
2534
2592
  function workspacePolicySummary(workspace, { scheduled = false } = {}) {
2535
2593
  if (!workspace) return "沿用原会话的实际工作目录";
2536
- if (workspace.mode === "existing") return `指定 Worktree:${workspace.worktree_id}`;
2537
- if (workspace.mode === "new") return `${scheduled ? "每次执行" : "每个新会话"}创建 Worktree · ${workspace.ref || "创建时 Project HEAD"}`;
2538
- return "项目目录";
2594
+ if (workspace.mode === "existing") return `使用已有 worktree:${workspace.worktree_id}`;
2595
+ if (workspace.mode === "new") return `${scheduled ? "每次执行" : "每个新会话"}新建 worktree · ${workspace.ref || "创建时 Project HEAD"}`;
2596
+ return "项目目录(不使用 worktree)";
2539
2597
  }
2540
2598
 
2541
2599
  function renderWorkspacePolicy(input, editor, { project, loading = false, scheduled = false } = {}) {
@@ -2549,8 +2607,8 @@ function renderWorkspacePolicy(input, editor, { project, loading = false, schedu
2549
2607
  }
2550
2608
  input("worktree-field").hidden = workspace.mode !== "existing";
2551
2609
  input("workspace-ref-field").hidden = workspace.mode !== "new";
2552
- scheduleSelectOptions(input("worktree"), [["", "选择受管 Worktree"],
2553
- ...items.map((item) => [item.id, `${item.cwd} · ${item.branch || "detached"} · ${item.id}`])],
2610
+ scheduleSelectOptions(input("worktree"), [["", "选择受管 worktree"],
2611
+ ...items.map((item) => [item.id, `已有 worktree · ${item.branch || "detached"} · ${item.cwd}`])],
2554
2612
  workspace.worktree_id || "");
2555
2613
  input("worktree").required = workspace.mode === "existing";
2556
2614
  input("workspace-ref").value = workspace.ref || "";
@@ -2563,21 +2621,21 @@ function renderWorkspacePolicy(input, editor, { project, loading = false, schedu
2563
2621
  input("workspace-refs").append(option);
2564
2622
  }
2565
2623
  const notes = [];
2566
- if (loading) notes.push("正在读取工作区选项…");
2624
+ if (loading) notes.push("正在读取 worktree 选项…");
2567
2625
  if (editor.workspaceError) notes.push(workspaceErrorMessage(editor.workspaceError));
2568
2626
  else if (options?.isGit === false) notes.push("该 Project 不是 Git 仓库,只支持项目目录。");
2569
- else if (!project) notes.push("先选择 Project,再选择工作区策略。");
2627
+ else if (!project) notes.push("先选择 Project,再选择 worktree 使用方式。");
2570
2628
  if (workspace.mode === "existing") {
2571
- notes.push(scheduled ? "各次执行共享所选 Worktree 的文件和分支;资源不可用时保留计划并跳过执行。"
2572
- : "新会话共享所选 Worktree 的文件和分支;删除或失效后保留此配置,自动创建会话时明确报错。");
2629
+ notes.push(scheduled ? "各次执行共享所选 worktree 的文件和分支;资源不可用时保留计划并跳过执行。"
2630
+ : "新会话共享所选 worktree 的文件和分支;删除或失效后保留此配置,自动创建会话时明确报错。");
2573
2631
  if (!loading && !workspacePolicyAvailable(workspace, options, project)) {
2574
- notes.push("所选 Worktree 当前不可用,请重新选择;不会切回项目目录。");
2632
+ notes.push("所选 worktree 当前不可用,请重新选择;不会切回项目目录。");
2575
2633
  }
2576
2634
  } else if (workspace.mode === "new") {
2577
2635
  notes.push(scheduled
2578
- ? "每次执行创建一份 detached Worktree;该次会话的后续消息复用。留空使用执行时 Project 的 HEAD,预览和保存不创建目录。"
2579
- : "每次自动创建新会话时创建一次 detached Worktree;后续消息复用。留空使用创建时 Project 的 HEAD,保存配置不创建目录。");
2580
- if (!loading && !available) notes.push("当前无法使用新建 Worktree 策略,请检查 Project。");
2636
+ ? "每次执行新建 detached worktree;该次会话的后续消息复用。留空使用执行时 Project 的 HEAD,预览和保存不创建目录。"
2637
+ : "每个自动创建的新会话新建 detached worktree;后续消息复用。留空使用创建时 Project 的 HEAD,保存配置不创建目录。");
2638
+ if (!loading && !available) notes.push("当前无法使用新建 worktree 方式,请检查 Project。");
2581
2639
  } else notes.push(scheduled ? "每次执行创建的会话使用 Project 的项目目录。" : "新会话使用 Project 的项目目录。");
2582
2640
  input("workspace-help").textContent = notes.join(" ");
2583
2641
  input("workspace-help").classList.toggle("error", !loading && !workspacePolicyAvailable(workspace, options, project));
@@ -2646,7 +2704,8 @@ function renderDefaultSettings() {
2646
2704
  if (editor.contextAvailable === false) notes.push("单聊不支持补齐未读上下文,请使用当前消息。");
2647
2705
  defaultsInput("note").textContent = notes.filter(Boolean).join(" ");
2648
2706
  defaultsInput("note").classList.toggle("error", Boolean(editor.error));
2649
- defaultsInput("save").disabled = defaultsBusy || editor.loading || !editor.action || !defaultWorkspaceAvailable();
2707
+ defaultsInput("save").disabled = defaultsBusy || editor.loading || !editor.action || !defaultWorkspaceAvailable()
2708
+ || Boolean(progressCardSettingsError(editor.settings));
2650
2709
  defaultsInput("save").textContent = defaultsBusy ? "保存中…" : "保存";
2651
2710
  defaultsInput("editor").setAttribute("aria-busy", String(defaultsBusy || editor.loading));
2652
2711
  }
@@ -2864,7 +2923,8 @@ async function defaultMutation(mode, action, extra = {}) {
2864
2923
  async function saveDefault(event) {
2865
2924
  event.preventDefault();
2866
2925
  const editor = defaultsEditor;
2867
- if (!editor || editor.loading || !editor.action || defaultsBusy || !defaultWorkspaceAvailable()) return;
2926
+ if (!editor || editor.loading || !editor.action || defaultsBusy || !defaultWorkspaceAvailable()
2927
+ || progressCardSettingsError(editor.settings)) return;
2868
2928
  if (editor.kind === "chat") {
2869
2929
  editor.loading = true;
2870
2930
  renderDefaultSettings();
@@ -3027,7 +3087,8 @@ function sessionSettingsFingerprint(settings) {
3027
3087
  const turn = settings.turn_settings;
3028
3088
  return JSON.stringify([turn ? [turn.model_id, turn.effort_id, turn.service_tier_id] : null,
3029
3089
  settings.message_context_mode, settings.reaction_pulse_enabled,
3030
- settings.progress_card_enabled, settings.completion_mention_enabled]);
3090
+ settings.progress_card_enabled, settings.completion_mention_enabled,
3091
+ progressCardFields.map((field) => progressCardSettings(settings)[field.replaceAll("-", "_")])]);
3031
3092
  }
3032
3093
 
3033
3094
  function confirmDiscardChanges(changed) {
@@ -3093,10 +3154,10 @@ function scheduleRunStatus(status) {
3093
3154
  not_started: "尚未执行", expired: "已过期,未执行", missed: "已错过",
3094
3155
  skipped_busy: "上次仍在执行,本次跳过", blocked_unknown: "上次结果待确认,本次跳过",
3095
3156
  project_disabled: "Project 已停用,本次未执行", project_unavailable: "Project 不可用,本次未执行",
3096
- workspace_unavailable: "工作区不可用,本次未执行",
3097
- workspace_creation_failed: "工作区创建失败,本次未执行",
3098
- workspace_creation_unknown: "工作区创建结果待确认,本次未执行",
3099
- workspace_handoff_failed: "工作区已保留,会话交接失败",
3157
+ workspace_unavailable: "worktree 不可用,本次未执行",
3158
+ workspace_creation_failed: "worktree 创建失败,本次未执行",
3159
+ workspace_creation_unknown: "worktree 创建结果待确认,本次未执行",
3160
+ workspace_handoff_failed: "worktree 已保留,会话交接失败",
3100
3161
  released: "调度已收尾", recovery_no_start: "服务恢复,本次未启动",
3101
3162
  publishing_unknown: "话题投递待确认", deleted: "执行会话已删除",
3102
3163
  initial_start_rejected: "启动被拒绝", publishing_failed: "话题发布失败",
@@ -3113,7 +3174,7 @@ function scheduleTriggerSource(source) {
3113
3174
 
3114
3175
  function scheduleWorktreeReceipt(run, { details = true } = {}) {
3115
3176
  if (!run?.worktree_id) return "";
3116
- const labels = [`Worktree:${run.worktree_id}`];
3177
+ const labels = [`worktree:${run.worktree_id}`];
3117
3178
  const receipt = run.worktree;
3118
3179
  if (details && receipt) {
3119
3180
  if (receipt.cwd) labels.push(`工作目录:${receipt.cwd}`);
@@ -3139,7 +3200,7 @@ function scheduleBlockedLabel(plan) {
3139
3200
  project_unavailable: "Project 不可用", target_inactive: "原会话已切走或归档,自动暂停",
3140
3201
  target_missing: "原会话不可用", target_mismatch: "原会话位置不匹配" }[plan.blocked_reason] || "";
3141
3202
  const workspace = workspaceErrorMessage(plan.workspace_error)
3142
- || ([plan.blocked_reason, plan.suspended_reason].includes("workspace_unavailable") ? "工作区不可用" : "");
3203
+ || ([plan.blocked_reason, plan.suspended_reason].includes("workspace_unavailable") ? "worktree 不可用" : "");
3143
3204
  return [primary, workspace].filter(Boolean).join(" · ");
3144
3205
  }
3145
3206
 
@@ -3153,7 +3214,7 @@ function scheduleInheritedWorkspace(plan) {
3153
3214
  const labels = [workspace.working_cwd
3154
3215
  ? `${workspace.native_cwd_unresolved ? "已登记" : "已选"}工作目录:${workspace.working_cwd}`
3155
3216
  : "工作目录尚未登记"];
3156
- if (workspace.worktree_id) labels.push(`Worktree:${workspace.worktree_id}`);
3217
+ if (workspace.worktree_id) labels.push(`worktree:${workspace.worktree_id}`);
3157
3218
  labels.push(workspace.native_cwd_unresolved
3158
3219
  ? "实际目录由原会话确定,本次未查询原生目录。" : "执行时沿用原会话的工作目录。");
3159
3220
  return labels.join(" · ");
@@ -3273,8 +3334,8 @@ function validateScheduleFields({ saving = false } = {}) {
3273
3334
  setScheduleFieldError("weekdays", "请至少选择一天。");
3274
3335
  }
3275
3336
  if (saving && !scheduleWorkspaceCanSave()) {
3276
- setScheduleFieldError("workspace", scheduleEditor.workspaceLoading ? "工作区选项仍在读取,请稍后保存。"
3277
- : workspaceErrorMessage(scheduleEditor.workspaceError) || "请选择可用的工作区策略。");
3337
+ setScheduleFieldError("workspace", scheduleEditor.workspaceLoading ? "worktree 选项仍在读取,请稍后保存。"
3338
+ : workspaceErrorMessage(scheduleEditor.workspaceError) || "请选择可用的 worktree 使用方式。");
3278
3339
  }
3279
3340
  if (scheduleFieldErrors.size) {
3280
3341
  if (scheduleEditor?.action) showScheduleFormError("请检查标红的表单项。");
@@ -3489,7 +3550,54 @@ function resetScheduleEndOffset() {
3489
3550
 
3490
3551
  function defaultScheduleSessionSettings() {
3491
3552
  return { turn_settings: null, reaction_pulse_enabled: false, progress_card_enabled: true, completion_mention_enabled: true,
3492
- message_context_mode: "current-only" };
3553
+ message_context_mode: "current-only", progress_card_settings: {
3554
+ show_commentary: true, show_operations: true, show_plan: true,
3555
+ commentary_limit: 4, operation_limit: 8, commentary_max_chars: 160, operation_max_chars: 120,
3556
+ organization: "content",
3557
+ } };
3558
+ }
3559
+
3560
+ const progressCardFields = ["show-commentary", "show-operations", "show-plan", "commentary-limit",
3561
+ "operation-limit", "commentary-max-chars", "operation-max-chars", "organization"];
3562
+
3563
+ function progressCardSettings(settings) {
3564
+ return settings.progress_card_settings || defaultScheduleSessionSettings().progress_card_settings;
3565
+ }
3566
+
3567
+ function progressCardSettingsError(settings) {
3568
+ const progress = progressCardSettings(settings);
3569
+ for (const [key, label, maximum] of [
3570
+ ["commentary_limit", "进展条数", 8], ["operation_limit", "操作条数", 16],
3571
+ ["commentary_max_chars", "进展摘要长度", 320], ["operation_max_chars", "操作摘要长度", 240],
3572
+ ]) {
3573
+ if (!Number.isInteger(progress[key]) || progress[key] < 1 || progress[key] > maximum) {
3574
+ return `${label}必须是 1 到 ${maximum} 之间的整数。`;
3575
+ }
3576
+ }
3577
+ return "";
3578
+ }
3579
+
3580
+ function renderProgressCardSettings(input, settings) {
3581
+ const container = input("progress-settings");
3582
+ if (!container) return;
3583
+ const progress = progressCardSettings(settings);
3584
+ container.hidden = !settings.progress_card_enabled;
3585
+ for (const node of container.querySelectorAll("input, select")) {
3586
+ const field = node.id.split("-progress-").at(-1);
3587
+ const key = field.replaceAll("-", "_");
3588
+ if (field.startsWith("show-")) node.checked = progress[key];
3589
+ else node.value = progress[key];
3590
+ node.disabled = !settings.progress_card_enabled
3591
+ || (field.startsWith("commentary-") && !progress.show_commentary)
3592
+ || (field.startsWith("operation-") && !progress.show_operations);
3593
+ }
3594
+ for (const [kind, shown] of [["commentary", progress.show_commentary], ["operation", progress.show_operations]]) {
3595
+ input(`progress-${kind}-capacity`).hidden = !shown;
3596
+ }
3597
+ const error = progressCardSettingsError(settings);
3598
+ const note = input("progress-error");
3599
+ note.textContent = error;
3600
+ note.hidden = !error;
3493
3601
  }
3494
3602
 
3495
3603
  function scheduleSessionSummary(settings) {
@@ -3535,6 +3643,7 @@ function renderSessionSettingsFields(input, settings, models, contextAvailable)
3535
3643
  input("reactions").checked = settings.reaction_pulse_enabled;
3536
3644
  input("progress").checked = settings.progress_card_enabled;
3537
3645
  input("completion-mention").checked = settings.completion_mention_enabled;
3646
+ renderProgressCardSettings(input, settings);
3538
3647
  return model;
3539
3648
  }
3540
3649
 
@@ -3552,6 +3661,13 @@ function changeSessionSettingsField(input, settings, models, field, baseTurn = n
3552
3661
  else if (field === "reactions") settings.reaction_pulse_enabled = input("reactions").checked;
3553
3662
  else if (field === "progress") settings.progress_card_enabled = input("progress").checked;
3554
3663
  else if (field === "completion-mention") settings.completion_mention_enabled = input("completion-mention").checked;
3664
+ else if (field.startsWith("progress-") && progressCardFields.includes(field.slice(9))) {
3665
+ const key = field.slice(9).replaceAll("-", "_");
3666
+ const node = input(field);
3667
+ const value = key.startsWith("show_") ? node.checked
3668
+ : key === "organization" || node.value === "" ? node.value : Number(node.value);
3669
+ settings.progress_card_settings = { ...progressCardSettings(settings), [key]: value };
3670
+ }
3555
3671
  }
3556
3672
 
3557
3673
  function renderScheduleSessionSettings() {
@@ -4652,7 +4768,8 @@ sessionSettingsInput("drawer").addEventListener("cancel", (event) => {
4652
4768
  closeSessionSettingsEditor();
4653
4769
  });
4654
4770
  sessionSettingsInput("editor").addEventListener("submit", saveSessionSettings);
4655
- for (const field of ["model", "effort", "tier", "context", "reactions", "progress", "completion-mention"]) {
4771
+ for (const field of ["model", "effort", "tier", "context", "reactions", "progress", "completion-mention",
4772
+ ...progressCardFields.map((name) => `progress-${name}`)]) {
4656
4773
  sessionSettingsInput(field).addEventListener("change", () => changeSessionSettings(field));
4657
4774
  }
4658
4775
  defaultsInput("new").addEventListener("click", () => openDefaultEditor(defaultsTab));
@@ -4679,7 +4796,8 @@ for (const field of ["workspace", "worktree"]) {
4679
4796
  defaultsInput(field).addEventListener("change", () => changeDefaultWorkspace(field));
4680
4797
  }
4681
4798
  defaultsInput("workspace-ref").addEventListener("input", () => changeDefaultWorkspace("workspace-ref"));
4682
- for (const field of ["model", "effort", "tier", "context", "reactions", "progress", "completion-mention"]) {
4799
+ for (const field of ["model", "effort", "tier", "context", "reactions", "progress", "completion-mention",
4800
+ ...progressCardFields.map((name) => `progress-${name}`)]) {
4683
4801
  defaultsInput(field).addEventListener("change", () => changeDefaultSettings(field));
4684
4802
  }
4685
4803
  for (const [name, delta] of [["previous", -50], ["next", 50]]) {
@@ -25,7 +25,7 @@
25
25
 
26
26
  <nav class="tabs" aria-label="管理模块">
27
27
  <a class="tab active" data-tab="projects" href="/projects" aria-current="page">Projects</a>
28
- <a class="tab" data-tab="worktrees" href="/worktrees">Worktrees</a>
28
+ <a class="tab" data-tab="worktrees" href="/worktrees">worktree</a>
29
29
  <a class="tab" data-tab="sessions" href="/sessions/ordinary">Sessions</a>
30
30
  <a class="tab" data-tab="schedules" href="/schedules">定时任务</a>
31
31
  <a class="tab" data-tab="defaults" href="/defaults">默认会话配置</a>
@@ -79,16 +79,16 @@
79
79
  </dialog>
80
80
 
81
81
  <section id="worktrees" class="panel" aria-labelledby="worktrees-heading" hidden>
82
- <div class="section-head"><div><p class="eyebrow">MANAGED CHECKOUTS</p><h2 id="worktrees-heading">Worktrees</h2></div><div class="actions"><button id="worktree-new" class="action">新建 Worktree</button><button id="worktree-configure" class="refresh">创建配置</button><button class="refresh" data-refresh="worktrees">刷新</button></div></div>
83
- <p class="hint">仅管理本实例创建的工作区。多个会话可共享文件和分支;列表按需查询,不扫描未提交内容,也不能证明没有外部客户端使用。</p>
82
+ <div class="section-head"><div><p class="eyebrow">managed worktree</p><h2 id="worktrees-heading">worktree</h2></div><div class="actions"><button id="worktree-new" class="action">新建 worktree</button><button id="worktree-configure" class="refresh">创建配置</button><button class="refresh" data-refresh="worktrees">刷新</button></div></div>
83
+ <p class="hint">仅管理本实例创建的 worktree。多个会话可共享文件和分支;列表按需查询,不扫描未提交内容,也不能证明没有外部客户端使用。</p>
84
84
  <p id="worktree-result" class="status" role="status" aria-live="polite"></p>
85
85
  <div class="table-wrap"><table><thead><tr><th>Project / 标识</th><th>工作目录</th><th>当前状态</th><th>分支 / HEAD</th><th>关联会话</th><th>操作</th></tr></thead><tbody id="worktrees-body"></tbody></table></div>
86
- <nav class="pagination" aria-label="Worktrees 分页"><button id="worktrees-previous" class="next" disabled>上一页</button><span id="worktrees-page" aria-live="polite">第 1 页</span><button id="worktrees-next" class="next" disabled>下一页</button></nav>
86
+ <nav class="pagination" aria-label="worktree 分页"><button id="worktrees-previous" class="next" disabled>上一页</button><span id="worktrees-page" aria-live="polite">第 1 页</span><button id="worktrees-next" class="next" disabled>下一页</button></nav>
87
87
  </section>
88
88
 
89
89
  <dialog id="worktree-create-drawer" class="editor-drawer" aria-labelledby="worktree-create-title">
90
90
  <form id="worktree-create" class="card-form drawer-form workspace-form" hidden>
91
- <div class="drawer-head"><div><p class="eyebrow">WORKTREE</p><h3 id="worktree-create-title">新建 Worktree</h3></div><button id="worktree-create-close" class="drawer-close" type="button" aria-label="关闭新建 Worktree 表单">×</button></div>
91
+ <div class="drawer-head"><div><p class="eyebrow">worktree</p><h3 id="worktree-create-title">新建 worktree</h3></div><button id="worktree-create-close" class="drawer-close" type="button" aria-label="关闭新建 worktree 表单">×</button></div>
92
92
  <div class="drawer-body">
93
93
  <div class="workspace-fields">
94
94
  <label>Project<select id="worktree-project" required><option value="">选择 Project</option></select></label>
@@ -100,19 +100,19 @@
100
100
  <p id="worktree-create-note" class="hint">只检出已提交内容,不复制未提交、未跟踪或忽略文件,不执行环境初始化。不创建会话。</p>
101
101
  <h4>当前创建配置</h4>
102
102
  <p id="worktree-create-config" class="target-summary hint"></p>
103
- <p class="hint">使用本实例已保存的配置;可在 Worktrees 页的“创建配置”中修改。</p>
103
+ <p class="hint">使用本实例已保存的配置;可在 worktree 页的“创建配置”中修改。</p>
104
104
  <p id="worktree-create-status" class="status" role="status" aria-live="polite"></p>
105
105
  <button id="worktree-create-check" class="drawer-cancel" type="button" hidden>刷新列表核对</button>
106
106
  </div>
107
- <div class="drawer-footer"><button id="worktree-create-cancel" class="drawer-cancel" type="button">取消</button><button id="worktree-create-submit" type="submit" disabled>创建 Worktree</button></div>
107
+ <div class="drawer-footer"><button id="worktree-create-cancel" class="drawer-cancel" type="button">取消</button><button id="worktree-create-submit" type="submit" disabled>创建 worktree</button></div>
108
108
  </form>
109
109
  </dialog>
110
110
 
111
111
  <dialog id="worktree-settings-drawer" class="editor-drawer" aria-labelledby="worktree-settings-title">
112
112
  <form id="worktree-settings" class="card-form drawer-form workspace-form" hidden>
113
- <div class="drawer-head"><div><p class="eyebrow">WORKTREE SETTINGS</p><h3 id="worktree-settings-title">Worktree 创建配置</h3></div><button id="worktree-settings-close" class="drawer-close" type="button" aria-label="关闭 Worktree 创建配置">×</button></div>
113
+ <div class="drawer-head"><div><p class="eyebrow">worktree settings</p><h3 id="worktree-settings-title">worktree 创建配置</h3></div><button id="worktree-settings-close" class="drawer-close" type="button" aria-label="关闭 worktree 创建配置">×</button></div>
114
114
  <div class="drawer-body">
115
- <p class="hint">用于本实例后续创建,包括 Admin、飞书和 Agent 入口。已有工作区仍按原路径管理;不修改 Codex App 配置。</p>
115
+ <p class="hint">用于本实例后续创建,包括 Admin、飞书和 Agent 入口。已有 worktree 仍按原路径管理;不修改 Codex App 配置。</p>
116
116
  <div class="workspace-fields">
117
117
  <label>新建根目录(留空使用实例默认目录)<input id="worktree-root" maxlength="4096" aria-describedby="worktree-effective-root"></label>
118
118
  <p id="worktree-effective-root" class="hint"></p>
@@ -221,6 +221,22 @@
221
221
  <label><input id="session-settings-progress" type="checkbox">进度卡片</label>
222
222
  <label><input id="session-settings-completion-mention" type="checkbox">结束时 @ 提醒</label>
223
223
  </div>
224
+ <div id="session-settings-progress-settings" class="progress-settings" hidden>
225
+ <label>过程卡组织方式<select id="session-settings-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
226
+ <p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
227
+ <div class="defaults-feedback"><label><input id="session-settings-progress-show-commentary" type="checkbox">最近进展</label></div>
228
+ <div id="session-settings-progress-commentary-capacity" class="schedule-form-grid">
229
+ <label>进展条数(1–8)<input id="session-settings-progress-commentary-limit" type="number" min="1" max="8" step="1" required></label>
230
+ <label>进展摘要长度(1–320 字符)<input id="session-settings-progress-commentary-max-chars" type="number" min="1" max="320" step="1" required></label>
231
+ </div>
232
+ <div class="defaults-feedback"><label><input id="session-settings-progress-show-operations" type="checkbox">最近操作</label></div>
233
+ <div id="session-settings-progress-operation-capacity" class="schedule-form-grid">
234
+ <label>操作条数(1–16)<input id="session-settings-progress-operation-limit" type="number" min="1" max="16" step="1" required></label>
235
+ <label>操作摘要长度(1–240 字符)<input id="session-settings-progress-operation-max-chars" type="number" min="1" max="240" step="1" required></label>
236
+ </div>
237
+ <div class="defaults-feedback"><label><input id="session-settings-progress-show-plan" type="checkbox">任务清单</label></div>
238
+ </div>
239
+ <p id="session-settings-progress-error" class="progress-settings-error" role="status" hidden></p>
224
240
  </fieldset>
225
241
  <p id="session-settings-note" class="session-settings-help" role="status" aria-live="polite"></p>
226
242
  </div>
@@ -271,8 +287,8 @@
271
287
  <h4>会话配置</h4>
272
288
  <div class="schedule-form-grid">
273
289
  <label>Project<select id="defaults-project" required><option value="">选择 Project</option></select></label>
274
- <label>工作区策略<select id="defaults-workspace"><option value="project">项目目录</option><option value="existing">指定已有 Worktree</option><option value="new">每个新会话创建 Worktree</option></select></label>
275
- <label id="defaults-worktree-field" hidden>受管 Worktree<select id="defaults-worktree"></select></label>
290
+ <label>worktree 使用方式<select id="defaults-workspace"><option value="project">项目目录(不使用 worktree)</option><option value="existing">使用已有 worktree</option><option value="new">每个新会话新建 worktree</option></select></label>
291
+ <label id="defaults-worktree-field" hidden>受管 worktree<select id="defaults-worktree"></select></label>
276
292
  <label id="defaults-workspace-ref-field" hidden>起点提交 / 分支<input id="defaults-workspace-ref" list="defaults-workspace-refs" maxlength="256" placeholder="留空使用创建时 Project 的 HEAD"><datalist id="defaults-workspace-refs"></datalist></label>
277
293
  </div>
278
294
  <p id="defaults-workspace-help" class="defaults-field-help" role="status"></p>
@@ -288,6 +304,22 @@
288
304
  <label><input id="defaults-progress" type="checkbox">进度卡片</label>
289
305
  <label><input id="defaults-completion-mention" type="checkbox">结束时 @ 提醒</label>
290
306
  </div>
307
+ <div id="defaults-progress-settings" class="progress-settings" hidden>
308
+ <label>过程卡组织方式<select id="defaults-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
309
+ <p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
310
+ <div class="defaults-feedback"><label><input id="defaults-progress-show-commentary" type="checkbox">最近进展</label></div>
311
+ <div id="defaults-progress-commentary-capacity" class="schedule-form-grid">
312
+ <label>进展条数(1–8)<input id="defaults-progress-commentary-limit" type="number" min="1" max="8" step="1" required></label>
313
+ <label>进展摘要长度(1–320 字符)<input id="defaults-progress-commentary-max-chars" type="number" min="1" max="320" step="1" required></label>
314
+ </div>
315
+ <div class="defaults-feedback"><label><input id="defaults-progress-show-operations" type="checkbox">最近操作</label></div>
316
+ <div id="defaults-progress-operation-capacity" class="schedule-form-grid">
317
+ <label>操作条数(1–16)<input id="defaults-progress-operation-limit" type="number" min="1" max="16" step="1" required></label>
318
+ <label>操作摘要长度(1–240 字符)<input id="defaults-progress-operation-max-chars" type="number" min="1" max="240" step="1" required></label>
319
+ </div>
320
+ <div class="defaults-feedback"><label><input id="defaults-progress-show-plan" type="checkbox">任务清单</label></div>
321
+ </div>
322
+ <p id="defaults-progress-error" class="progress-settings-error" role="status" hidden></p>
291
323
  </fieldset>
292
324
  <p id="defaults-note" class="defaults-field-help" role="status"></p>
293
325
  </div>
@@ -380,8 +412,8 @@
380
412
  </div>
381
413
  <label id="schedule-project-field">Project<select id="schedule-project" required><option value="">选择 Project</option></select></label>
382
414
  <div id="schedule-workspace-fields" class="schedule-section-fields">
383
- <label>工作区策略<select id="schedule-workspace"><option value="project">项目目录</option><option value="existing">指定已有 Worktree</option><option value="new">每次执行创建 Worktree</option></select></label>
384
- <label id="schedule-worktree-field" hidden>受管 Worktree<select id="schedule-worktree"></select></label>
415
+ <label>worktree 使用方式<select id="schedule-workspace"><option value="project">项目目录(不使用 worktree)</option><option value="existing">使用已有 worktree</option><option value="new">每次执行新建 worktree</option></select></label>
416
+ <label id="schedule-worktree-field" hidden>受管 worktree<select id="schedule-worktree"></select></label>
385
417
  <label id="schedule-workspace-ref-field" hidden>起点提交 / 分支<input id="schedule-workspace-ref" list="schedule-workspace-refs" maxlength="256" placeholder="留空使用执行时 Project 的 HEAD"><datalist id="schedule-workspace-refs"></datalist></label>
386
418
  <p id="schedule-workspace-help" class="schedule-field-help" role="status"></p>
387
419
  </div>