campfire-cli 0.1.25__tar.gz → 0.2.0a2__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 (261) hide show
  1. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.github/workflows/ci.yml +14 -0
  2. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.github/workflows/release.yml +15 -1
  3. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/ARCHITECTURE.md +48 -1
  4. campfire_cli-0.2.0a2/CHANGELOG.md +33 -0
  5. campfire_cli-0.1.25/README.md → campfire_cli-0.2.0a2/PKG-INFO +49 -0
  6. campfire_cli-0.1.25/PKG-INFO → campfire_cli-0.2.0a2/README.md +22 -20
  7. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/SPEC.md +2 -1
  8. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/pyproject.toml +5 -1
  9. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/scripts/pypi_verify.py +3 -1
  10. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/scripts/quality_check.py +2 -1
  11. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/__init__.py +1 -1
  12. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/SPEC.md +1 -0
  13. campfire_cli-0.2.0a2/src/campfire_cli/app/video/SPEC.md +13 -0
  14. campfire_cli-0.2.0a2/src/campfire_cli/app/video/__init__.py +0 -0
  15. campfire_cli-0.2.0a2/src/campfire_cli/app/video/cli/__init__.py +0 -0
  16. campfire_cli-0.2.0a2/src/campfire_cli/app/video/cli/video_cli.py +125 -0
  17. campfire_cli-0.2.0a2/src/campfire_cli/app/video/schema/__init__.py +0 -0
  18. campfire_cli-0.2.0a2/src/campfire_cli/app/video/schema/video_schema.py +68 -0
  19. campfire_cli-0.2.0a2/src/campfire_cli/app/video/service/__init__.py +0 -0
  20. campfire_cli-0.2.0a2/src/campfire_cli/app/video/service/video_protocol.py +16 -0
  21. campfire_cli-0.2.0a2/src/campfire_cli/app/video/service/video_service.py +498 -0
  22. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/SPEC.md +1 -0
  23. campfire_cli-0.2.0a2/src/campfire_cli/common/cli_output.py +149 -0
  24. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/change_set.py +5 -2
  25. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/cwd.py +1 -6
  26. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/plan.py +6 -1
  27. campfire_cli-0.2.0a2/src/campfire_cli/common/media/__init__.py +0 -0
  28. campfire_cli-0.2.0a2/src/campfire_cli/common/media/media_backend.py +49 -0
  29. campfire_cli-0.2.0a2/src/campfire_cli/common/media/media_worker.py +128 -0
  30. campfire_cli-0.2.0a2/src/campfire_cli/common/media/model_download.py +28 -0
  31. campfire_cli-0.2.0a2/src/campfire_cli/common/media/video_runtime.py +118 -0
  32. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/package_version.py +6 -11
  33. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/container.py +40 -0
  34. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/main.py +6 -22
  35. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/defaults/config.yml +15 -1
  36. campfire_cli-0.2.0a2/src/campfire_cli/resources/skills/campfire-video-capture/SKILL.md +79 -0
  37. campfire_cli-0.2.0a2/tests/integration/test_json_discovery.py +87 -0
  38. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_package_version.py +10 -2
  39. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_pypi_verify.py +2 -1
  40. campfire_cli-0.2.0a2/tests/unit/test_video.py +812 -0
  41. campfire_cli-0.2.0a2/tests/unit/test_video_runtime.py +85 -0
  42. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/uv.lock +468 -1
  43. campfire_cli-0.1.25/CHANGELOG.md +0 -20
  44. campfire_cli-0.1.25/src/campfire_cli/common/cli_output.py +0 -67
  45. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  46. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  47. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  48. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.gitignore +0 -0
  49. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/.python-version +0 -0
  50. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/AGENTS.md +0 -0
  51. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/COMMAND.md +0 -0
  52. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/CONTRIBUTING.md +0 -0
  53. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/DECISIONS.md +0 -0
  54. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/LICENSE +0 -0
  55. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/SECURITY.md +0 -0
  56. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/alembic/SPEC.md +0 -0
  57. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/alembic/env.py +0 -0
  58. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/alembic/script.py.mako +0 -0
  59. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/alembic/versions/001_initial_schema.py +0 -0
  60. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/alembic.ini +0 -0
  61. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/docs/quickstart.md +0 -0
  62. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/docs/safety.md +0 -0
  63. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/scripts/SPEC.md +0 -0
  64. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/scripts/release_check.py +0 -0
  65. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/__init__.py +0 -0
  66. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/env.py +0 -0
  67. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/script.py.mako +0 -0
  68. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/001_initial_schema.py +0 -0
  69. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/002_workspace_project_registry.py +0 -0
  70. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/003_unified_workspace_state.py +0 -0
  71. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/004_restructure_workspace_domain.py +0 -0
  72. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/005_decision_channel.py +0 -0
  73. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/006_workspace_topology_index.py +0 -0
  74. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/007_workspace_adoption.py +0 -0
  75. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/008_remove_adoption_batches.py +0 -0
  76. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/009_document_query_index.py +0 -0
  77. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/010_project_domain_identity.py +0 -0
  78. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/011_document_state_model.py +0 -0
  79. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/012_remove_decision_channel.py +0 -0
  80. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/alembic/versions/__init__.py +0 -0
  81. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/__init__.py +0 -0
  82. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/SPEC.md +0 -0
  83. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/__init__.py +0 -0
  84. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/cli/base_cli.py +0 -0
  85. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/repository/base_repository.py +0 -0
  86. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/schema/base_schema.py +0 -0
  87. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/schema/operation_schema.py +0 -0
  88. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/base/service/base_service.py +0 -0
  89. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/SPEC.md +0 -0
  90. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/__init__.py +0 -0
  91. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/cli/__init__.py +0 -0
  92. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/cli/document_cli.py +0 -0
  93. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/cli/profile_cli.py +0 -0
  94. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/cli/type_cli.py +0 -0
  95. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/repository/__init__.py +0 -0
  96. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/repository/document_index_repository.py +0 -0
  97. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/repository/document_profile_repository.py +0 -0
  98. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/repository/document_type_repository.py +0 -0
  99. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/schema/__init__.py +0 -0
  100. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/schema/document_schema.py +0 -0
  101. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/__init__.py +0 -0
  102. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/document_scanner.py +0 -0
  103. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/document_service.py +0 -0
  104. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/index/__init__.py +0 -0
  105. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/index/document_index_builder.py +0 -0
  106. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/index/document_index_protocol.py +0 -0
  107. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/index/document_index_service.py +0 -0
  108. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/mutation/__init__.py +0 -0
  109. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/mutation/document_apply_service.py +0 -0
  110. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/mutation/document_move_service.py +0 -0
  111. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/mutation/document_relocation.py +0 -0
  112. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/mutation/frontmatter_apply.py +0 -0
  113. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/__init__.py +0 -0
  114. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/document_patch_values.py +0 -0
  115. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/document_profile_service.py +0 -0
  116. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/document_rule_service.py +0 -0
  117. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/document_type_service.py +0 -0
  118. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/frontmatter_formatter.py +0 -0
  119. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/frontmatter_plan.py +0 -0
  120. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/kanban_service.py +0 -0
  121. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/profile_candidates.py +0 -0
  122. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/profile_registry.py +0 -0
  123. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/document/service/rules/type_plan.py +0 -0
  124. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/SPEC.md +0 -0
  125. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/__init__.py +0 -0
  126. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/cli/maintenance_cli.py +0 -0
  127. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/repository/maintenance_repository.py +0 -0
  128. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/schema/maintenance_schema.py +0 -0
  129. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/service/maintenance_protocol.py +0 -0
  130. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/service/maintenance_service.py +0 -0
  131. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/maintenance/service/moc_service.py +0 -0
  132. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/SPEC.md +0 -0
  133. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/__init__.py +0 -0
  134. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/cli/skill_cli.py +0 -0
  135. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/repository/skill_repository.py +0 -0
  136. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/schema/skill_schema.py +0 -0
  137. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/skill/service/skill_service.py +0 -0
  138. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/SPEC.md +0 -0
  139. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/__init__.py +0 -0
  140. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/__init__.py +0 -0
  141. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/config_cli.py +0 -0
  142. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/domain_cli.py +0 -0
  143. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/project_cli.py +0 -0
  144. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/restructure_cli.py +0 -0
  145. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/space_cli.py +0 -0
  146. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/cli/workspace_cli.py +0 -0
  147. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/repository/__init__.py +0 -0
  148. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/repository/manifest_repository.py +0 -0
  149. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/repository/restructure_repository.py +0 -0
  150. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/repository/workspace_repository.py +0 -0
  151. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/schema/__init__.py +0 -0
  152. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/schema/adoption_schema.py +0 -0
  153. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/schema/restructure_schema.py +0 -0
  154. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/schema/workspace_schema.py +0 -0
  155. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/__init__.py +0 -0
  156. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/adoption_service.py +0 -0
  157. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/config_service.py +0 -0
  158. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/domain_restructure_service.py +0 -0
  159. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/project_service.py +0 -0
  160. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/restructure_protocol.py +0 -0
  161. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/restructure_service.py +0 -0
  162. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/restructure_verifier.py +0 -0
  163. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/structure_service.py +0 -0
  164. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/workspace_protocol.py +0 -0
  165. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/app/workspace/service/workspace_service.py +0 -0
  166. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/__init__.py +0 -0
  167. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/agent_hints.py +0 -0
  168. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/database/__init__.py +0 -0
  169. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/database/migrations.py +0 -0
  170. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/database/models.py +0 -0
  171. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/database/session.py +0 -0
  172. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/__init__.py +0 -0
  173. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/document_types.py +0 -0
  174. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/domain_context.py +0 -0
  175. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/frontmatter_format.py +0 -0
  176. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/frontmatter_schema.py +0 -0
  177. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/markdown.py +0 -0
  178. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/documents/related_docs.py +0 -0
  179. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/exceptions/__init__.py +0 -0
  180. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/exceptions/base.py +0 -0
  181. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/__init__.py +0 -0
  182. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/atomic.py +0 -0
  183. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/filesystem/locking.py +0 -0
  184. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/governance/__init__.py +0 -0
  185. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/governance/issues.py +0 -0
  186. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/governance/locking.py +0 -0
  187. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/governance/snapshots.py +0 -0
  188. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/hashing.py +0 -0
  189. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/reports/__init__.py +0 -0
  190. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/reports/json_report.py +0 -0
  191. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/common/reports/markdown_report.py +0 -0
  192. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/config/SPEC.md +0 -0
  193. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/config/defaults.py +0 -0
  194. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/config/settings.py +0 -0
  195. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/__init__.py +0 -0
  196. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases/SPEC.md +0 -0
  197. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases//344/273/273/345/212/241/345/267/245/344/275/234/345/217/260-/344/270/252/344/272/272.base" +0 -0
  198. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases//344/273/273/345/212/241/345/267/245/344/275/234/345/217/260-/351/241/271/347/233/256.base" +0 -0
  199. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases//345/275/222/346/241/243/346/226/207/346/241/243/345/267/245/344/275/234/345/217/260.base" +0 -0
  200. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases//345/276/205/344/272/272/345/206/263/347/255/226/345/267/245/344/275/234/345/217/260.base" +0 -0
  201. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/bases//346/226/207/346/241/243/345/267/245/344/275/234/345/217/260.base" +0 -0
  202. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/defaults/__init__.py +0 -0
  203. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/SPEC.md +0 -0
  204. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/TEMPLATE.md +0 -0
  205. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-context-bootstrap/SKILL.md +0 -0
  206. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-context-bootstrap/agents/openai.yaml +0 -0
  207. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-conversation-router/SKILL.md +0 -0
  208. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-conversation-router/agents/openai.yaml +0 -0
  209. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-conversation-router/references/inbox-handoff.md +0 -0
  210. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-conversation-router/references/learning-intake.md +0 -0
  211. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-conversation-router/references/task-intake.md +0 -0
  212. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/SKILL.md +0 -0
  213. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/references//344/273/273/345/212/241/344/270/216/350/256/241/345/210/222/346/262/211/346/267/200.md" +0 -0
  214. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/references//345/267/262/346/234/211/346/226/207/346/241/243/346/233/264/346/226/260.md" +0 -0
  215. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/references//351/200/232/347/224/250/347/237/245/350/257/206/346/262/211/346/267/200.md" +0 -0
  216. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/references//351/227/256/351/242/230/344/270/216/345/206/263/347/255/226/346/262/211/346/267/200.md" +0 -0
  217. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-document-capture/references//351/241/271/347/233/256/345/206/205/345/256/271/346/262/211/346/267/200.md" +0 -0
  218. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-inbox-triage/SKILL.md +0 -0
  219. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-kanban-board/SKILL.md +0 -0
  220. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-task-management/SKILL.md +0 -0
  221. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/SKILL.md +0 -0
  222. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/agents/openai.yaml +0 -0
  223. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-adoption/SKILL.md +0 -0
  224. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-maintenance/SKILL.md +0 -0
  225. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-onboarding/SKILL.md +0 -0
  226. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-onboarding/references//346/240/207/345/207/206/345/267/245/344/275/234/345/214/272/347/273/223/346/236/204.md" +0 -0
  227. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-restructure/SKILL.md +0 -0
  228. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/skills/campfire-workspace-restructure/references/restructure-spec.md +0 -0
  229. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/workspace/_/346/250/241/346/235/277/README.md" +0 -0
  230. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/workspace/_/346/250/241/346/235/277//346/250/241/346/235/277-/344/273/273/345/212/241.md" +0 -0
  231. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/src/campfire_cli/resources/workspace/_/346/250/241/346/235/277//346/250/241/346/235/277-/347/211/210/346/234/254/345/217/221/345/270/203/346/270/205/345/215/225.md" +0 -0
  232. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/SPEC.md +0 -0
  233. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/conftest.py +0 -0
  234. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_cli.py +0 -0
  235. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_domain_rename_sync.py +0 -0
  236. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_profile_resolution.py +0 -0
  237. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_quickstart.py +0 -0
  238. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_relation_pages_cli.py +0 -0
  239. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_skill_examples.py +0 -0
  240. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/integration/test_workspace_templates.py +0 -0
  241. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/perf/test_read_counts.py +0 -0
  242. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/perf/test_resolve_subprocess_count.py +0 -0
  243. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_agent_hints.py +0 -0
  244. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_atomic_write.py +0 -0
  245. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_base_service.py +0 -0
  246. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_config.py +0 -0
  247. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_document_apply.py +0 -0
  248. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_document_index.py +0 -0
  249. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_document_scanner.py +0 -0
  250. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_domain_context.py +0 -0
  251. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_domain_paths.py +0 -0
  252. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_file_change_executor.py +0 -0
  253. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_frontmatter.py +0 -0
  254. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_generated_regions.py +0 -0
  255. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_kanban_service.py +0 -0
  256. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_migrations.py +0 -0
  257. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_operation_schema.py +0 -0
  258. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_related_docs.py +0 -0
  259. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_release_check.py +0 -0
  260. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_repository_boundaries.py +0 -0
  261. {campfire_cli-0.1.25 → campfire_cli-0.2.0a2}/tests/unit/test_workspace_manifest.py +0 -0
@@ -6,6 +6,20 @@ on:
6
6
  pull_request:
7
7
 
8
8
  jobs:
9
+ video:
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ os: [ubuntu-latest, macos-latest, windows-latest]
14
+ runs-on: ${{ matrix.os }}
15
+ env:
16
+ PYTHONUTF8: "1"
17
+ HF_HUB_OFFLINE: "1"
18
+ steps:
19
+ - uses: actions/checkout@v5
20
+ - uses: astral-sh/setup-uv@v10.1.0
21
+ - run: uv sync --frozen --extra video
22
+ - run: uv run --no-sync python -m pytest tests/unit/test_video.py tests/unit/test_video_runtime.py
9
23
  test:
10
24
  concurrency:
11
25
  group: ci-${{ github.workflow }}-${{ github.ref }}
@@ -6,6 +6,20 @@ on:
6
6
  tags: ["v*"]
7
7
 
8
8
  jobs:
9
+ video:
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ os: [ubuntu-latest, macos-latest, windows-latest]
14
+ runs-on: ${{ matrix.os }}
15
+ env:
16
+ PYTHONUTF8: "1"
17
+ HF_HUB_OFFLINE: "1"
18
+ steps:
19
+ - uses: actions/checkout@v5
20
+ - uses: astral-sh/setup-uv@v10.1.0
21
+ - run: uv sync --frozen --extra video
22
+ - run: uv run --no-sync python -m pytest tests/unit/test_video.py tests/unit/test_video_runtime.py
9
23
  quality:
10
24
  strategy:
11
25
  fail-fast: false
@@ -38,7 +52,7 @@ jobs:
38
52
 
39
53
  publish:
40
54
  if: github.event_name == 'push'
41
- needs: quality
55
+ needs: [quality, video]
42
56
  runs-on: ubuntu-latest
43
57
  permissions:
44
58
  id-token: write
@@ -46,6 +46,8 @@ Task Channel 是未来演进设想,借鉴 Go 的原则:**Do not communicate
46
46
 
47
47
  ## 4. 系统架构
48
48
 
49
+ 本地视频能力由 `app/video` 承担素材准备与交付校验,`common/media` 提供模型下载、媒体解码与抽帧机制;可选原生处理依赖在独立子进程中延迟加载。`AppContainer.deliver_video` 组合文档治理检查与视频交付,不让 Video Service 调用 Document Service。文档结构仍由 `document apply` 创建,正文和二进制图片复用文件变更集及乐观锁;没有新的数据库、独立下载服务或模型调度器。语义整理留给宿主 Agent 与内置 Skill,结构检查不等于语义保真验收。
50
+
49
51
  ```text
50
52
  人类 / Codex / Claude Code / 其他 Agent
51
53
  │
@@ -59,19 +61,62 @@ Task Channel 是未来演进设想,借鉴 Go 的原则:**Do not communicate
59
61
  │ document │
60
62
  │ maintenance │
61
63
  │ skill / base │
64
+ │ video (实验能力) │
62
65
  └─────────┬─────────┘
63
66
  │
64
67
  Common 治理与原子能力
65
68
  schema / documents / links /
66
- filesystem / database / reports
69
+ filesystem / database / reports / media
67
70
  │
68
71
  ┌───────────┴───────────┐
69
72
  Markdown Workspace Adapter 用户级状态
70
73
  文档事实、任务、知识、项目 ~/.campfire/
71
74
  campfire.db + config.yml
72
75
  batches/reports/locks
76
+ models/faster-whisper-small
77
+ ```
78
+
79
+ ### 本地视频模型与运行边界
80
+
81
+ ```text
82
+ video setup:统一初始化预览,不联网、不落盘
83
+ +-- Python 环境 -> 列出 video extra 缺失依赖
84
+ +-- 本地模型可用 -> 计划复用,不检查远端更新
85
+ +-- 默认模型缺失 -> 计划列出来源、固定版本、约 486 MB 与路径
86
+ +-- 已有目录不完整 -> 报错,不覆盖
87
+ |
88
+ v
89
+ 一次授权 -> --expected-plan + --confirm -> 复核环境与模型计划
90
+ |
91
+ +-- 缺依赖 -> uv / 环境内 pip -> 安装到当前隔离环境
92
+ |
93
+ +-- 需下载 -> huggingface-hub -> Hugging Face(仅下载模型)
94
+ | |
95
+ | 临时目录 -> 必要文件非空检查 -> 锁内安装
96
+ | |
97
+ | <CAMPFIRE_HOME>/models/faster-whisper-small
98
+ | |
99
+ +-- 直接复用 ----+--> 离线验证依赖与模型加载 -> ready
100
+
101
+ 日常:本地视频 -> video prepare(预览 / 确认)
102
+ |
103
+ v
104
+ 离线媒体子进程(复用已就绪环境)
105
+ +-- PyAV + Pillow:解码与截图
106
+ +-- faster-whisper + CTranslate2:CPU int8 转写
107
+ |
108
+ v
109
+ 素材包 -> Agent 核验与整理 -> 文档 + assets
73
110
  ```
74
111
 
112
+ `CAMPFIRE_HOME` 默认是各平台用户目录下的 `.campfire`,统一相对布局而非绝对路径;显式 `--model` 可覆盖模型位置。模型权重是用户级本地资源,Python 依赖属于 Campfire 安装环境,两者都不随 Vault 同步。公开模型下载不需要 Hugging Face Token,转写不调用云端模型;Agent 整理内容仍使用宿主自身的模型服务,不能把整条链路称为完全离线。
113
+
114
+ 下载失败或正常取消时清理本次临时目录,已有目录不覆盖;下载成功但后续转写失败时保留模型供重试。文件非空检查不等于模型可用性验证,实际加载由转写引擎完成。强制杀进程可能遗留临时目录,实验阶段不承诺自动恢复。
115
+
116
+ Python 依赖由 `pyproject.toml` 的 `video` extra 声明,初始化从包元数据读取需求并交给包管理器解析,不复制依赖版本。`video setup` 只向当前隔离环境安装缺失的二进制依赖,固定已有版本,不重装正在运行的 Campfire;无安全安装器时返回 `needs-input`,版本冲突时停止,不擅自修改系统 Python。安装与模型下载不是跨资源事务,失败保留已完成部分,重试补齐;包管理器后续同步若移除可选依赖,可再次初始化。`prepare` 不再安装或下载,缺环境提示 `setup`。
117
+
118
+ 当前 CPU 路径不要求 CUDA、PyTorch、Ollama 或独立模型服务。通常使用携带 FFmpeg 库的 PyAV wheel,无需独立 FFmpeg 命令;Windows 还需要 Visual C++ 运行库,缺失时须单独安装。参考 [faster-whisper 运行要求](https://github.com/SYSTRAN/faster-whisper#requirements)与 [CTranslate2 安装要求](https://opennmt.net/CTranslate2/installation.html)。本功能为实验能力,平台路径统一不等于全部平台已验收。
119
+
75
120
  待人确认以全局系统受管区 `_待用户确认/` 的 `human-request` 文档为事实来源;它不属于任何 Space、Domain 或 Project。`human_decision_status` 只表达待人处理状态,用户结论随后写回正式文档。不存在独立的 Decision SQLite 状态机或 `_协作/` 投影。
76
121
 
77
122
  `app/` 按可独立理解的业务能力组织,CLI 只做参数和输出适配,Service 承担业务流程,Repository 负责外部读写。跨 App 的用例编排由组合根 `AppContainer` 承担,`setup` 与 `upgrade` 是当前实例。`common/` 只放跨业务复用、无独立业务流程的原子能力;不能为了“复用”把业务编排下沉到 common。
@@ -88,6 +133,8 @@ Frontmatter 规则采用声明式 Profile:`base` 是最小公共契约,`task
88
133
 
89
134
  ### CLI 设计理念:治理原语 + Skill SOP
90
135
 
136
+ 公共命令统一 JSON:成功时 stdout 一个对象,错误时 stderr 一个单行对象并非零退出。`--help` 与无参数帮助返回结构化参数、类型、默认值和子命令;`version` 返回版本字段,`tree` 返回嵌套命令树。不维护文本输出模式或 shell 补全脚本入口;第三方安装与下载日志由适配器捕获,不污染 JSON。
137
+
91
138
  Campfire 不是“Markdown 版 kubectl”,而是面向人机协作场景组合成熟 CLI 经验形成的独立设计。它在资源心智模型、`apply` 语义和机器可读接口上借鉴 kubectl,在“计划—审查—执行”上借鉴 Terraform,在稳定原语与上层工作流分离上借鉴 Git/Unix;Markdown SSOT、Agent 语义判断和显式 Maintenance 则是 Campfire 自身边界。
92
139
 
93
140
  | 参考 | Campfire 采用的部分 | Campfire 不照搬的部分 |
@@ -0,0 +1,33 @@
1
+ # 版本记录
2
+
3
+ 只记录有提交或发布证据的变化,不补写无法核实的历史。未发布条目不代表已可从 PyPI 安装。
4
+
5
+ ## 0.2.0a2 - 2026-10-05(Alpha 预发布)
6
+
7
+ `0.2.0a1` 仅保留为未公开的本地候选标签;首次公开 Alpha 使用 `0.2.0a2`,包含最终素材目录约定。
8
+
9
+ - 首个视频能力实验预发布,不承诺高可用性,须显式指定版本安装。
10
+ - 公共输出统一为 JSON;`--help`、`version`、`tree` 不再输出文本,旧版本读取脚本需改读 JSON 字段;移除文本 shell 补全入口。
11
+
12
+ - 新增可选本地视频素材、时间戳转写、候选截图与指定时间补帧能力。
13
+ - 中间素材默认保存到 `<CAMPFIRE_HOME>/materials/<视频SHA-256>/`,支持 `--output` 覆盖;原视频不复制,交付后的图文不依赖素材目录。
14
+ - `video setup` 一次确认安装视频依赖、准备默认模型并验证加载;`prepare` 仅处理视频。模型统一存放于 Campfire 用户目录,已有资源复用,支持显式本地路径。
15
+ - 新增视频整理 Skill、草稿覆盖校验和受管空正文图文交付,不自动覆盖人工内容。
16
+ - 本轮不包含视频 URL 解析或下载;Codex 已用真实本地视频完成图文链路,Claude Code 实际验收延期。
17
+
18
+ ## 0.1.25 - 2026-10-03
19
+
20
+ - 整理公开文档与 Agent 提示词,修正旧关系页、Profile 和模板说明。
21
+ - 增加隔离上手、安全恢复与卸载指引、贡献及反馈入口。
22
+ - Obsidian 仅为推荐搭配,插件配置教程不在 CLI 重复维护。
23
+ - 补充包链接和示例验证,不改变领域或文档字段模型。
24
+ - 启用 GitHub 私密安全报告入口;独立用户试用尚未完成。
25
+
26
+ ## 0.1.24 - 2026-10-03
27
+
28
+ - 停止生成 `_generated/相关文档-*.md`,同步时移除 MOC 自动区域的对应入口。
29
+ - 保留 related_docs、关联查询、索引对账及 MOC 其他导航功能。
30
+ - 同步不删除旧生成页或修改人工正文;历史清理需要独立确认。
31
+ - 新增 CLI 进程端到端与回归测试,删除专用关系页展示接口和无调用方辅助函数。
32
+
33
+ [已发布安装包](https://pypi.org/project/campfire-cli/0.1.24/)。仓库重建前的标签和 Actions 记录不再保留。
@@ -1,3 +1,30 @@
1
+ Metadata-Version: 2.5
2
+ Name: campfire-cli
3
+ Version: 0.2.0a2
4
+ Summary: Local-first shared context and governance CLI for humans and agents
5
+ Project-URL: Repository, https://github.com/Kepler452Byte/campfire-cli
6
+ Project-URL: Documentation, https://github.com/Kepler452Byte/campfire-cli#readme
7
+ Project-URL: Issues, https://github.com/Kepler452Byte/campfire-cli/issues
8
+ Project-URL: Changelog, https://github.com/Kepler452Byte/campfire-cli/blob/main/CHANGELOG.md
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.12
12
+ Requires-Dist: alembic>=1.13
13
+ Requires-Dist: packaging>=24
14
+ Requires-Dist: psutil>=7.2.2
15
+ Requires-Dist: pydantic-settings>=2.2
16
+ Requires-Dist: pydantic>=2.7
17
+ Requires-Dist: pyyaml>=6.0
18
+ Requires-Dist: sqlalchemy>=2.0
19
+ Requires-Dist: typer>=0.12
20
+ Provides-Extra: video
21
+ Requires-Dist: av<19,>=14; extra == 'video'
22
+ Requires-Dist: faster-whisper<2,>=1.1; extra == 'video'
23
+ Requires-Dist: huggingface-hub<2,>=0.24; extra == 'video'
24
+ Requires-Dist: markdown-it-py>=3; extra == 'video'
25
+ Requires-Dist: pillow>=11; extra == 'video'
26
+ Description-Content-Type: text/markdown
27
+
1
28
  # Campfire
2
29
 
3
30
  `campfire` 是面向工作与学习场景的本地优先人机协作 CLI。它让人类和多个 Agent 围绕同一份持久共享上下文协作:把口头要求、临时笔记、任务进度、项目资料和长期知识沉淀进可检索、可交接、可审计的 Workspace。
@@ -18,6 +45,28 @@
18
45
 
19
46
  推荐搭配 Obsidian:内置 Bases 展示表格,大纲提供章节导航;Kanban 用于看板,Obsidian Git 用于版本历史。它们不是普通文档查询和治理的前提。Templater、TOC 不作为依赖。插件配置教程等待维护者提供博客链接,不在 CLI 输出或仓库重复编写,也不自动修改插件设置。
20
47
 
48
+ ## 本地视频图文(v0.2.0a2 Alpha 实验能力)
49
+
50
+ 本版统一公共 CLI 输出:成功在 stdout 返回一个 JSON 对象,错误在 stderr 返回一个 JSON 对象并以非零状态退出。`--help` 返回结构化参数,`tree` 返回层级命令树,`version` 返回 `{"status":"ok","version":"0.2.0a2"}`。旧脚本若将版本输出当纯字符串读取,须改读 `version` 字段;不再提供文本帮助或 shell 补全脚本输出。
51
+
52
+ 试用预发布版:`uv tool install "campfire-cli==0.2.0a2"`;已有 uv tool 安装可用 `uv tool upgrade "campfire-cli==0.2.0a2"`。Alpha 不是正式稳定版本,不建议替换重要工作环境;先在独立测试目录验收。
53
+
54
+ 本功能按实验性质逐步推进,不承诺高可用性、所有媒体兼容性或自动整理结果的准确性;生成内容须经人工或 Agent 核验。实验阶段仍保留只读来源、写入预览和冲突保护。
55
+
56
+ 本轮只接受本地单视频,不解析抖音、B站或其他 URL。核心 CLI 不依赖视频运行库;首次使用执行 `campfire video setup`,统一预览缺失依赖与默认模型下载,带回 `--expected-plan <摘要> --confirm` 后一次完成安装和模型加载验证。无需 Workspace 或输入视频。视频由 PyAV 解码,无需额外安装 FFmpeg 命令;语音由 faster-whisper 在 CPU 本地转写。PyAV 暂限 `<19`,避免其删除的 `metadata_errors` 参数与当前转写库冲突。
57
+
58
+ 初始化后运行 `campfire video prepare --source <本地视频> --output <Workspace外新目录>` 预览,带回 `--expected-plan` 和 `--confirm` 处理。`prepare` 不再安装依赖或下载模型,缺失时提示 `video setup`。默认模型位于 `<CAMPFIRE_HOME>/models/faster-whisper-small`,主目录默认 `~/.campfire`,Windows、macOS、Linux 沿用同一相对布局。初始化预览列出 Python 环境、缺失依赖、Hugging Face 固定版本、约 486 MB 模型体积及目标目录;确认后先安装再下载,最后在离线子进程中验证加载。已有依赖和模型复用,不静默更新模型,不上传媒体。
59
+
60
+ 依赖安装只支持当前 uv tool、pipx 或 venv 隔离环境,通过可用的 uv 或环境内 pip 安装二进制包;不修改系统 Python,不重装运行中的 Campfire,不替换已有包。无可用安装器时返回 `needs-input`;版本冲突或缺少兼容 wheel 时停止,由用户按原安装方式修复后重试。安装中断时保留已完成部分,不回滚卸载;正常下载失败清理本次模型临时目录,下载成功但验证失败则保留模型并报告错误。包管理器升级或同步后若移除了可选依赖,重新执行 `video setup` 补齐。源码开发者仍可用 `uv sync --extra video` 管理锁定依赖,再用 `video setup` 验证模型。
61
+
62
+ 可用 `--model <本地模型目录>` 覆盖默认位置;显式路径缺失或不完整时只报错,不下载或覆盖。已有默认目录不完整时也拒绝覆盖。也可用 `--transcript` 提供时间戳 JSON 数组,格式见命令帮助,此时不需要模型。模型权重目录须含非空的 `model.bin`、`config.json`、`tokenizer.json`;配置与权重能否实际加载仍由转写引擎校验。
63
+
64
+ 内置 `campfire-video-capture` Skill 引导 Agent 阅读全部转写、查看候选截图、用 `video frames` 补帧并整理草稿。`video inspect` 校验结构和引用,不能证明内容保真;`video deliver` 向已通过治理检查且正文为空的文档交付正文及图片。沿用 `document apply` 创建结构,不覆盖已有人工内容,不自动处理重复来源。
65
+
66
+ 默认限制为 4 GiB、2 小时、240 张截图、单次处理 3 小时,默认每 30 秒候选抽帧,超长素材按帧数上限增大间隔;配置在内置 `config.yml` 的 `video` 分区。只支持本地 MP4/MOV、Matroska/WebM、AVI、MPEG-TS 容器,具体解码依赖所装 PyAV。截图稀疏采样加精确像素去重,不保证捕获短暂画面,必须按内容补帧。
67
+
68
+ `prepare` 可省略 `--output`,素材默认保存到 `<CAMPFIRE_HOME>/materials/<视频SHA-256>/`,预览返回实际目录;显式指定时仍须为 Workspace 外的新目录。同一视频已有素材时拒绝覆盖,可复用素材或指定其他目录重新处理。素材目录包含转写与候选图片,保留用于核验,不自动过期;用户确认后可删除指定素材目录。原视频只读且不复制,Vault 仅接收选定图片与正文,交付后不依赖素材目录。模型权重及媒体内容各自的许可由使用者核对;PyAV/FFmpeg 许可随安装构建而异,本项目不捆绑模型或独立 FFmpeg 可执行文件。
69
+
21
70
  ## 安装
22
71
 
23
72
  ### 升级注意事项
@@ -1,23 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: campfire-cli
3
- Version: 0.1.25
4
- Summary: Local-first shared context and governance CLI for humans and agents
5
- Project-URL: Repository, https://github.com/Kepler452Byte/campfire-cli
6
- Project-URL: Documentation, https://github.com/Kepler452Byte/campfire-cli#readme
7
- Project-URL: Issues, https://github.com/Kepler452Byte/campfire-cli/issues
8
- Project-URL: Changelog, https://github.com/Kepler452Byte/campfire-cli/blob/main/CHANGELOG.md
9
- License-Expression: MIT
10
- License-File: LICENSE
11
- Requires-Python: >=3.12
12
- Requires-Dist: alembic>=1.13
13
- Requires-Dist: psutil>=7.2.2
14
- Requires-Dist: pydantic-settings>=2.2
15
- Requires-Dist: pydantic>=2.7
16
- Requires-Dist: pyyaml>=6.0
17
- Requires-Dist: sqlalchemy>=2.0
18
- Requires-Dist: typer>=0.12
19
- Description-Content-Type: text/markdown
20
-
21
1
  # Campfire
22
2
 
23
3
  `campfire` 是面向工作与学习场景的本地优先人机协作 CLI。它让人类和多个 Agent 围绕同一份持久共享上下文协作:把口头要求、临时笔记、任务进度、项目资料和长期知识沉淀进可检索、可交接、可审计的 Workspace。
@@ -38,6 +18,28 @@ Description-Content-Type: text/markdown
38
18
 
39
19
  推荐搭配 Obsidian:内置 Bases 展示表格,大纲提供章节导航;Kanban 用于看板,Obsidian Git 用于版本历史。它们不是普通文档查询和治理的前提。Templater、TOC 不作为依赖。插件配置教程等待维护者提供博客链接,不在 CLI 输出或仓库重复编写,也不自动修改插件设置。
40
20
 
21
+ ## 本地视频图文(v0.2.0a2 Alpha 实验能力)
22
+
23
+ 本版统一公共 CLI 输出:成功在 stdout 返回一个 JSON 对象,错误在 stderr 返回一个 JSON 对象并以非零状态退出。`--help` 返回结构化参数,`tree` 返回层级命令树,`version` 返回 `{"status":"ok","version":"0.2.0a2"}`。旧脚本若将版本输出当纯字符串读取,须改读 `version` 字段;不再提供文本帮助或 shell 补全脚本输出。
24
+
25
+ 试用预发布版:`uv tool install "campfire-cli==0.2.0a2"`;已有 uv tool 安装可用 `uv tool upgrade "campfire-cli==0.2.0a2"`。Alpha 不是正式稳定版本,不建议替换重要工作环境;先在独立测试目录验收。
26
+
27
+ 本功能按实验性质逐步推进,不承诺高可用性、所有媒体兼容性或自动整理结果的准确性;生成内容须经人工或 Agent 核验。实验阶段仍保留只读来源、写入预览和冲突保护。
28
+
29
+ 本轮只接受本地单视频,不解析抖音、B站或其他 URL。核心 CLI 不依赖视频运行库;首次使用执行 `campfire video setup`,统一预览缺失依赖与默认模型下载,带回 `--expected-plan <摘要> --confirm` 后一次完成安装和模型加载验证。无需 Workspace 或输入视频。视频由 PyAV 解码,无需额外安装 FFmpeg 命令;语音由 faster-whisper 在 CPU 本地转写。PyAV 暂限 `<19`,避免其删除的 `metadata_errors` 参数与当前转写库冲突。
30
+
31
+ 初始化后运行 `campfire video prepare --source <本地视频> --output <Workspace外新目录>` 预览,带回 `--expected-plan` 和 `--confirm` 处理。`prepare` 不再安装依赖或下载模型,缺失时提示 `video setup`。默认模型位于 `<CAMPFIRE_HOME>/models/faster-whisper-small`,主目录默认 `~/.campfire`,Windows、macOS、Linux 沿用同一相对布局。初始化预览列出 Python 环境、缺失依赖、Hugging Face 固定版本、约 486 MB 模型体积及目标目录;确认后先安装再下载,最后在离线子进程中验证加载。已有依赖和模型复用,不静默更新模型,不上传媒体。
32
+
33
+ 依赖安装只支持当前 uv tool、pipx 或 venv 隔离环境,通过可用的 uv 或环境内 pip 安装二进制包;不修改系统 Python,不重装运行中的 Campfire,不替换已有包。无可用安装器时返回 `needs-input`;版本冲突或缺少兼容 wheel 时停止,由用户按原安装方式修复后重试。安装中断时保留已完成部分,不回滚卸载;正常下载失败清理本次模型临时目录,下载成功但验证失败则保留模型并报告错误。包管理器升级或同步后若移除了可选依赖,重新执行 `video setup` 补齐。源码开发者仍可用 `uv sync --extra video` 管理锁定依赖,再用 `video setup` 验证模型。
34
+
35
+ 可用 `--model <本地模型目录>` 覆盖默认位置;显式路径缺失或不完整时只报错,不下载或覆盖。已有默认目录不完整时也拒绝覆盖。也可用 `--transcript` 提供时间戳 JSON 数组,格式见命令帮助,此时不需要模型。模型权重目录须含非空的 `model.bin`、`config.json`、`tokenizer.json`;配置与权重能否实际加载仍由转写引擎校验。
36
+
37
+ 内置 `campfire-video-capture` Skill 引导 Agent 阅读全部转写、查看候选截图、用 `video frames` 补帧并整理草稿。`video inspect` 校验结构和引用,不能证明内容保真;`video deliver` 向已通过治理检查且正文为空的文档交付正文及图片。沿用 `document apply` 创建结构,不覆盖已有人工内容,不自动处理重复来源。
38
+
39
+ 默认限制为 4 GiB、2 小时、240 张截图、单次处理 3 小时,默认每 30 秒候选抽帧,超长素材按帧数上限增大间隔;配置在内置 `config.yml` 的 `video` 分区。只支持本地 MP4/MOV、Matroska/WebM、AVI、MPEG-TS 容器,具体解码依赖所装 PyAV。截图稀疏采样加精确像素去重,不保证捕获短暂画面,必须按内容补帧。
40
+
41
+ `prepare` 可省略 `--output`,素材默认保存到 `<CAMPFIRE_HOME>/materials/<视频SHA-256>/`,预览返回实际目录;显式指定时仍须为 Workspace 外的新目录。同一视频已有素材时拒绝覆盖,可复用素材或指定其他目录重新处理。素材目录包含转写与候选图片,保留用于核验,不自动过期;用户确认后可删除指定素材目录。原视频只读且不复制,Vault 仅接收选定图片与正文,交付后不依赖素材目录。模型权重及媒体内容各自的许可由使用者核对;PyAV/FFmpeg 许可随安装构建而异,本项目不捆绑模型或独立 FFmpeg 可执行文件。
42
+
41
43
  ## 安装
42
44
 
43
45
  ### 升级注意事项
@@ -41,7 +41,7 @@ SQLite / Filesystem Implementation
41
41
 
42
42
  ## CLI 输出契约
43
43
 
44
- - 正常输出 indent JSON;错误输出单行 JSON 并写 stderr,退出码非 0。
44
+ - 所有公共命令成功时 stdout 只输出一个 indent JSON 对象,包括 `--help`、无参数帮助、`version` 与 `tree`;错误只输出一个单行 JSON 对象到 stderr,退出码非 0。帮助使用参数结构,命令树使用层级结构,不返回 ANSI 文本。第三方日志须捕获,不混入命令输出;不提供第二套文本模式或 shell 补全脚本输出入口。
45
45
  - `status` 字段是 Agent 依赖的公共契约,只允许复用既有词汇,不得发明近义词。命令级词汇:ok、error、blocked、needs-input、needs-review、dry-run、synced、planned、ready、applied、moved、renamed、issues-found、formatted、archived、up-to-date。文档、领域与 Decision 各有自己的字段词汇表。需要新状态先在本节登记。
46
46
  - 可恢复的输入错误必须包含稳定 `code`、对应字段和机器可读的期望类型;当正确序列化方式不直观时,同时返回示例值或修复提示。自然语言 message 与示例可以演进,不作为调用方分支判断依据。
47
47
  - 前置条件缺失时优先降级执行:能完成的部分照常完成,输出 `needs-input` 并以 `skipped` 字段显式列出被跳过的步骤,而非整体报错退出。
@@ -81,6 +81,7 @@ Campfire 使用语义化版本:
81
81
  ```
82
82
 
83
83
  - 已发布版本不可原地修改;同一版本号必须对应唯一、可重复构建的代码和资源。
84
+ - Python 预发布遵循 PEP 440,例如 `0.2.0a1` 对应标签 `v0.2.0a1`;GitHub Release 标记为 prerelease,版本比较使用标准解析器,不按字符串比较。
84
85
  - 已公开标签对象不可变。发布准备必须执行 `scripts/release_check.py --tag <tag>` 对比本地、远端对象及目标提交;对象或提交不一致即停止,禁止重建、强推或自动覆盖本地标签。发布重试复用原标签,不以提交相同为理由替换附注对象。
85
86
  - 只修复既有行为时增加补丁版本,例如 `0.17.0 -> 0.17.1`。
86
87
  - 新增 CLI 能力、改变治理契约或增加可选公共字段时增加次版本,例如 `0.17.x -> 0.18.0`。
@@ -1,12 +1,13 @@
1
1
  [project]
2
2
  name = "campfire-cli"
3
- version = "0.1.25"
3
+ version = "0.2.0a2"
4
4
  description = "Local-first shared context and governance CLI for humans and agents"
5
5
  readme = "README.md"
6
6
  license = "MIT"
7
7
  requires-python = ">=3.12"
8
8
  dependencies = [
9
9
  "alembic>=1.13",
10
+ "packaging>=24",
10
11
  "psutil>=7.2.2",
11
12
  "pydantic>=2.7",
12
13
  "pydantic-settings>=2.2",
@@ -21,6 +22,9 @@ Documentation = "https://github.com/Kepler452Byte/campfire-cli#readme"
21
22
  Issues = "https://github.com/Kepler452Byte/campfire-cli/issues"
22
23
  Changelog = "https://github.com/Kepler452Byte/campfire-cli/blob/main/CHANGELOG.md"
23
24
 
25
+ [project.optional-dependencies]
26
+ video = ["av>=14,<19", "Pillow>=11", "faster-whisper>=1.1,<2", "huggingface-hub>=0.24,<2", "markdown-it-py>=3"]
27
+
24
28
  [project.scripts]
25
29
  campfire = "campfire_cli.main:app"
26
30
 
@@ -9,6 +9,7 @@ side_effects:
9
9
  from __future__ import annotations
10
10
 
11
11
  import argparse
12
+ import json
12
13
  import os
13
14
  import subprocess
14
15
  import tempfile
@@ -50,7 +51,8 @@ def verify(version: str, environment: Path) -> None:
50
51
  capture_output=True,
51
52
  text=True,
52
53
  timeout=30,
53
- ).stdout.strip()
54
+ ).stdout
55
+ installed = json.loads(installed)["version"]
54
56
  if installed != version:
55
57
  raise SystemExit(f"installed version {installed} does not match {version}")
56
58
 
@@ -73,7 +73,8 @@ def smoke_test_wheel(version: str, artifact_dir: Path | None = None) -> None:
73
73
  capture_output=True,
74
74
  text=True,
75
75
  env=smoke_environment,
76
- ).stdout.strip()
76
+ ).stdout
77
+ installed = json.loads(installed)["version"]
77
78
  if installed != version:
78
79
  raise SystemExit(f"installed version {installed} does not match {version}")
79
80
  subprocess.run(
@@ -1,3 +1,3 @@
1
1
  """Campfire CLI package."""
2
2
 
3
- __version__ = "0.1.25"
3
+ __version__ = "0.2.0a2"
@@ -9,3 +9,4 @@
9
9
  - `workspace/`:注册、初始化、解析和选择多个 Workspace,并通过扁平的 Restructure Service 执行一次性、大规模、批次化结构重构。
10
10
  - `skill/`:Campfire SOP Skill 的发现、加载、校验和同步。
11
11
  - `base/`:Obsidian Base 标准治理视图。
12
+ - `video/`:实验性的本地视频素材准备、草稿校验与图文交付。
@@ -0,0 +1,13 @@
1
+ # Video App SPEC
2
+
3
+ 本模块提供实验性的本地视频素材准备、草稿校验与图文交付,不承诺高可用性或自动内容保真,不解析在线链接。
4
+
5
+ - `cli/` 解析参数与翻译异常;跨 App 的文档治理检查由 `AppContainer` 编排。
6
+ - `schema/` 定义素材与草稿的数据契约;`service/` 负责预览、校验、审批及安全写入用例。
7
+ - `service/video_protocol.py` 定义消费方媒体接口;`common/media/` 实现隔离进程、解码、抽帧和本地语音转写,不解释文档治理规则。
8
+ - 可选媒体依赖在处理时加载;不隐式下载模型,不上传视频,不修改来源,不覆盖已有正文。
9
+ - `video setup` 是视频环境唯一初始化入口:依赖安装与默认模型下载纳入一次预览和确认,最后通过离线子进程验证实际加载。已有部分复用,失败不卸载已安装依赖。`prepare` 仅处理视频,缺环境提示初始化,不安装或下载。
10
+ - Python 依赖从包元数据的 `video` extra 读取,禁止复制依赖清单。只在当前隔离环境安装缺失的二进制包,固定已有版本,不重装 Campfire 或自动修改系统 Python;无法安全安装时停止并报告。
11
+ - 模型默认位于 Campfire 用户目录的 `models/<模型仓库名>/`,支持 `CAMPFIRE_HOME` 与处理时显式 `--model`。下载到临时目录,必要文件非空后锁内安装;不覆盖已有目录。验证失败保留模型并报告,已有本地模型直接离线使用。
12
+ - 实验性质不降低路径、哈希、写入确认与冲突保护要求。结构校验不代替 Agent 对转写和图片的语义核验。
13
+ - 中间素材默认存放于 `<CAMPFIRE_HOME>/materials/<视频SHA-256>/`,`--output` 可指定 Workspace 外的新目录;预览不创建目录,已有素材不覆盖、不自动清理。原视频只读且不复制;最终正文和选定图片交付到 Vault 后不依赖中间素材目录。
@@ -0,0 +1,125 @@
1
+ from collections.abc import Callable
2
+ from pathlib import Path
3
+
4
+ import typer
5
+
6
+ from campfire_cli.common.cli_output import JsonTyperGroup, emit
7
+ from campfire_cli.common.cli_output import invoke as invoke_app
8
+ from campfire_cli.common.exceptions import InputError
9
+ from campfire_cli.container import AppContainer
10
+
11
+ video_cli = typer.Typer(help="本地视频素材与保真图文交付,不解析 URL", cls=JsonTyperGroup)
12
+
13
+
14
+ def invoke(operation: Callable[[], dict]) -> dict:
15
+ def guarded() -> dict:
16
+ try:
17
+ return operation()
18
+ except (OSError, UnicodeError) as exc:
19
+ raise InputError(
20
+ "视频文件操作失败,请检查路径、权限和 UTF-8 编码",
21
+ code="video-io-error",
22
+ field="path",
23
+ expected_type="accessible local path",
24
+ detail=str(exc),
25
+ ) from exc
26
+
27
+ return invoke_app(guarded)
28
+
29
+
30
+ @video_cli.command("setup")
31
+ def setup(
32
+ expected_plan: str | None = typer.Option(None, help="初始化预览返回的计划摘要"),
33
+ confirm: bool = typer.Option(False, help="确认安装缺失视频依赖、下载默认模型并验证加载"),
34
+ ) -> None:
35
+ """一次启用视频能力;已有依赖和模型直接复用,不要求 Workspace。"""
36
+ emit(
37
+ invoke(
38
+ lambda: AppContainer.build_video().setup(
39
+ confirm=confirm,
40
+ expected_plan=expected_plan,
41
+ )
42
+ )
43
+ )
44
+
45
+
46
+ @video_cli.command("prepare")
47
+ def prepare(
48
+ source: Path = typer.Option(..., help="只读本地视频路径,不接受 URL"),
49
+ output: Path | None = typer.Option(
50
+ None, help="Workspace 外尚不存在的素材目录;默认 <CAMPFIRE_HOME>/materials/<视频SHA-256>"
51
+ ),
52
+ model: Path | None = typer.Option(
53
+ None,
54
+ help="本地模型目录;默认使用 video setup 准备的模型,缺失时提示初始化",
55
+ ),
56
+ transcript: Path | None = typer.Option(
57
+ None, help='UTF-8 JSON 数组,如 [{"start":0,"end":1,"text":"文字"}];秒为单位'
58
+ ),
59
+ expected_plan: str | None = typer.Option(None, help="预览返回的计划摘要"),
60
+ confirm: bool = typer.Option(False, help="按预览计划处理视频,不安装依赖或下载模型"),
61
+ ) -> None:
62
+ emit(
63
+ invoke(
64
+ lambda: AppContainer.build_video().prepare(
65
+ source,
66
+ output,
67
+ model=model,
68
+ transcript=transcript,
69
+ expected_plan=expected_plan,
70
+ confirm=confirm,
71
+ )
72
+ )
73
+ )
74
+
75
+
76
+ @video_cli.command("inspect")
77
+ def inspect(
78
+ bundle: Path = typer.Option(..., help="包含 material.json 的素材目录"),
79
+ draft: Path | None = typer.Option(None, help="可选草稿 JSON;校验覆盖与图片引用"),
80
+ ) -> None:
81
+ emit(invoke(lambda: AppContainer.build_video().inspect(bundle, draft)))
82
+
83
+
84
+ @video_cli.command("frames")
85
+ def frames(
86
+ source: Path = typer.Option(..., help="原始本地视频,须与素材哈希一致"),
87
+ bundle: Path = typer.Option(..., help="已有素材目录"),
88
+ at: list[float] = typer.Option(..., help="补帧秒数,可重复 --at"),
89
+ expected_plan: str | None = typer.Option(None, help="预览返回的计划摘要"),
90
+ confirm: bool = typer.Option(False, help="按预览计划补帧"),
91
+ ) -> None:
92
+ emit(
93
+ invoke(
94
+ lambda: AppContainer.build_video().frames(
95
+ source,
96
+ bundle,
97
+ at,
98
+ confirm=confirm,
99
+ expected_plan=expected_plan,
100
+ )
101
+ )
102
+ )
103
+
104
+
105
+ @video_cli.command("deliver")
106
+ def deliver(
107
+ ctx: typer.Context,
108
+ bundle: Path = typer.Option(..., help="素材目录"),
109
+ draft: Path = typer.Option(..., help="经 Agent 整理的草稿 JSON,格式见内置视频 Skill"),
110
+ path: str = typer.Option(..., help="Workspace 内已有的受管空正文文档路径"),
111
+ expected_plan: str | None = typer.Option(None, help="预览返回的计划摘要"),
112
+ confirm: bool = typer.Option(False, help="按预览计划写入正文及图片"),
113
+ ) -> None:
114
+ workspace = ctx.find_root().params.get("workspace")
115
+ emit(
116
+ invoke(
117
+ lambda: AppContainer.build(workspace).deliver_video(
118
+ bundle,
119
+ draft,
120
+ path,
121
+ confirm=confirm,
122
+ expected_plan=expected_plan,
123
+ )
124
+ )
125
+ )
@@ -0,0 +1,68 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
6
+
7
+
8
+ class Contract(BaseModel):
9
+ model_config = ConfigDict(extra="forbid", allow_inf_nan=False)
10
+
11
+
12
+ class Segment(Contract):
13
+ start: float = Field(ge=0)
14
+ end: float = Field(gt=0)
15
+ text: str = Field(min_length=1)
16
+
17
+ @model_validator(mode="after")
18
+ def interval(self) -> Segment:
19
+ if self.end <= self.start or not self.text.strip():
20
+ raise ValueError("转写区间必须递增且文字不能为空")
21
+ return self
22
+
23
+
24
+ class Frame(Contract):
25
+ id: str
26
+ path: str
27
+ seconds: float = Field(ge=0)
28
+ sha256: str = Field(pattern=r"^[0-9a-f]{64}$")
29
+
30
+
31
+ class Material(Contract):
32
+ schema_version: Literal[1] = 1
33
+ source_name: str
34
+ source_sha256: str = Field(pattern=r"^[0-9a-f]{64}$")
35
+ duration: float = Field(gt=0)
36
+ width: int = Field(gt=0)
37
+ height: int = Field(gt=0)
38
+ transcript_source: str
39
+ segments: list[Segment]
40
+ frames: list[Frame]
41
+ warnings: list[str] = Field(default_factory=list)
42
+
43
+ @model_validator(mode="after")
44
+ def timeline(self) -> Material:
45
+ if any(s.end > self.duration + 0.5 for s in self.segments):
46
+ raise ValueError("转写超出媒体时长")
47
+ if any(a.start > b.start for a, b in zip(self.segments, self.segments[1:], strict=False)):
48
+ raise ValueError("转写必须按时间排序")
49
+ if any(f.seconds > self.duration + 0.5 for f in self.frames):
50
+ raise ValueError("截图超出媒体时长")
51
+ if len({f.id for f in self.frames}) != len(self.frames):
52
+ raise ValueError("截图 ID 重复")
53
+ return self
54
+
55
+
56
+ class Section(Contract):
57
+ title: str = Field(min_length=1)
58
+ body: str = Field(min_length=1)
59
+ segment_ids: list[int] = Field(default_factory=list)
60
+ frame_ids: list[str] = Field(default_factory=list)
61
+
62
+
63
+ class Draft(Contract):
64
+ title: str = Field(min_length=1)
65
+ source_sha256: str = Field(pattern=r"^[0-9a-f]{64}$")
66
+ sections: list[Section] = Field(min_length=1)
67
+ limitations: list[str] = Field(default_factory=list)
68
+ visual_reviewed: bool = False
@@ -0,0 +1,16 @@
1
+ from pathlib import Path
2
+ from typing import Protocol
3
+
4
+
5
+ class MediaBackend(Protocol):
6
+ def run(self, request: dict, timeout: int) -> dict: ...
7
+
8
+
9
+ class ModelDownloader(Protocol):
10
+ def __call__(self, repository: str, revision: str, output: Path) -> None: ...
11
+
12
+
13
+ class VideoRuntime(Protocol):
14
+ def plan(self) -> dict: ...
15
+
16
+ def install(self, plan: dict, timeout: int) -> None: ...