campfire-cli 0.1.3__tar.gz → 0.1.4__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 (178) hide show
  1. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/PKG-INFO +1 -1
  2. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/pyproject.toml +1 -1
  3. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/__init__.py +1 -1
  4. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/moc_service.py +65 -32
  5. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/container.py +37 -0
  6. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/main.py +6 -30
  7. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/integration/test_cli.py +12 -2
  8. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_common_governance.py +24 -0
  9. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/.github/workflows/ci.yml +0 -0
  10. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/.github/workflows/release.yml +0 -0
  11. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/.gitignore +0 -0
  12. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/AGENTS.md +0 -0
  13. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/ARCHITECTURE.md +0 -0
  14. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/COMMAND.md +0 -0
  15. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/DECISIONS.md +0 -0
  16. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/LICENSE +0 -0
  17. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/README.md +0 -0
  18. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/SPEC.md +0 -0
  19. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/alembic/SPEC.md +0 -0
  20. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/alembic/env.py +0 -0
  21. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/alembic/script.py.mako +0 -0
  22. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/alembic/versions/001_initial_schema.py +0 -0
  23. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/alembic.ini +0 -0
  24. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/scripts/SPEC.md +0 -0
  25. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/__init__.py +0 -0
  26. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/env.py +0 -0
  27. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/script.py.mako +0 -0
  28. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/001_initial_schema.py +0 -0
  29. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/002_workspace_project_registry.py +0 -0
  30. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/003_unified_workspace_state.py +0 -0
  31. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/004_restructure_workspace_domain.py +0 -0
  32. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/005_decision_channel.py +0 -0
  33. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/006_workspace_topology_index.py +0 -0
  34. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/007_workspace_adoption.py +0 -0
  35. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/alembic/versions/__init__.py +0 -0
  36. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/SPEC.md +0 -0
  37. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/__init__.py +0 -0
  38. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/SPEC.md +0 -0
  39. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/__init__.py +0 -0
  40. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/cli/base_cli.py +0 -0
  41. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/repository/base_repository.py +0 -0
  42. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/schema/base_schema.py +0 -0
  43. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/base/service/base_service.py +0 -0
  44. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/SPEC.md +0 -0
  45. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/__init__.py +0 -0
  46. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/cli/decision_cli.py +0 -0
  47. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/repository/decision_repository.py +0 -0
  48. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/schema/decision_schema.py +0 -0
  49. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/service/decision_projection_service.py +0 -0
  50. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/decision/service/decision_service.py +0 -0
  51. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/SPEC.md +0 -0
  52. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/__init__.py +0 -0
  53. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/cli/__init__.py +0 -0
  54. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/cli/document_cli.py +0 -0
  55. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/cli/profile_cli.py +0 -0
  56. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/cli/type_cli.py +0 -0
  57. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/repository/__init__.py +0 -0
  58. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/repository/document_profile_repository.py +0 -0
  59. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/repository/document_type_repository.py +0 -0
  60. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/__init__.py +0 -0
  61. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/document_profile_service.py +0 -0
  62. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/document_rule_service.py +0 -0
  63. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/document_scanner.py +0 -0
  64. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/document_service.py +0 -0
  65. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/document_type_service.py +0 -0
  66. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/frontmatter_apply.py +0 -0
  67. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/frontmatter_formatter.py +0 -0
  68. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/frontmatter_plan.py +0 -0
  69. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/profile_registry.py +0 -0
  70. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/type_apply.py +0 -0
  71. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/document/service/type_plan.py +0 -0
  72. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/SPEC.md +0 -0
  73. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/__init__.py +0 -0
  74. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/cli/maintenance_cli.py +0 -0
  75. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/repository/maintenance_repository.py +0 -0
  76. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/schema/maintenance_schema.py +0 -0
  77. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/archive_service.py +0 -0
  78. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/link_service.py +0 -0
  79. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/maintenance_protocol.py +0 -0
  80. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/maintenance_service.py +0 -0
  81. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/maintenance/service/plan_service.py +0 -0
  82. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/SPEC.md +0 -0
  83. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/__init__.py +0 -0
  84. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/cli/skill_cli.py +0 -0
  85. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/repository/skill_repository.py +0 -0
  86. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/schema/skill_schema.py +0 -0
  87. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/skill/service/skill_service.py +0 -0
  88. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/SPEC.md +0 -0
  89. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/__init__.py +0 -0
  90. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/__init__.py +0 -0
  91. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/adoption_cli.py +0 -0
  92. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/config_cli.py +0 -0
  93. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/domain_cli.py +0 -0
  94. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/project_cli.py +0 -0
  95. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/restructure_cli.py +0 -0
  96. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/space_cli.py +0 -0
  97. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/cli/workspace_cli.py +0 -0
  98. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/repository/__init__.py +0 -0
  99. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/repository/adoption_repository.py +0 -0
  100. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/repository/manifest_repository.py +0 -0
  101. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/repository/restructure_repository.py +0 -0
  102. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/repository/workspace_repository.py +0 -0
  103. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/schema/__init__.py +0 -0
  104. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/schema/adoption_schema.py +0 -0
  105. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/schema/restructure_schema.py +0 -0
  106. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/schema/workspace_schema.py +0 -0
  107. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/__init__.py +0 -0
  108. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/adoption_protocol.py +0 -0
  109. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/adoption_service.py +0 -0
  110. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/config_service.py +0 -0
  111. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/domain_restructure_service.py +0 -0
  112. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/project_service.py +0 -0
  113. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/restructure_protocol.py +0 -0
  114. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/restructure_service.py +0 -0
  115. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/restructure_verifier.py +0 -0
  116. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/structure_service.py +0 -0
  117. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/workspace_protocol.py +0 -0
  118. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/app/workspace/service/workspace_service.py +0 -0
  119. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/SPEC.md +0 -0
  120. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/__init__.py +0 -0
  121. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/agent_hints.py +0 -0
  122. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/database/__init__.py +0 -0
  123. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/database/migrations.py +0 -0
  124. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/database/models.py +0 -0
  125. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/database/session.py +0 -0
  126. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/documents/__init__.py +0 -0
  127. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/documents/document_types.py +0 -0
  128. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/documents/frontmatter_schema.py +0 -0
  129. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/documents/markdown.py +0 -0
  130. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/exceptions/__init__.py +0 -0
  131. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/exceptions/base.py +0 -0
  132. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/filesystem/__init__.py +0 -0
  133. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/filesystem/atomic.py +0 -0
  134. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/filesystem/locking.py +0 -0
  135. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/governance/__init__.py +0 -0
  136. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/governance/issues.py +0 -0
  137. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/governance/locking.py +0 -0
  138. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/governance/snapshots.py +0 -0
  139. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/hashing.py +0 -0
  140. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/reports/__init__.py +0 -0
  141. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/reports/json_report.py +0 -0
  142. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/common/reports/markdown_report.py +0 -0
  143. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/config/SPEC.md +0 -0
  144. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/config/defaults.py +0 -0
  145. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/config/settings.py +0 -0
  146. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/__init__.py +0 -0
  147. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases/Agent/346/211/247/350/241/214/345/267/245/344/275/234/345/217/260.base" +0 -0
  148. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases/SPEC.md +0 -0
  149. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases//344/273/273/345/212/241/345/267/245/344/275/234/345/217/260.base" +0 -0
  150. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases//345/206/263/347/255/226/345/267/245/344/275/234/345/217/260.base" +0 -0
  151. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases//345/276/205/345/275/222/346/241/243/346/226/207/346/241/243.base" +0 -0
  152. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/bases//351/241/271/347/233/256/346/226/207/346/241/243.base" +0 -0
  153. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/defaults/__init__.py +0 -0
  154. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/defaults/config.yml +0 -0
  155. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/SPEC.md +0 -0
  156. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-context-bootstrap/SKILL.md +0 -0
  157. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-context-bootstrap/agents/openai.yaml +0 -0
  158. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-conversation-router/SKILL.md +0 -0
  159. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-conversation-router/agents/openai.yaml +0 -0
  160. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-conversation-router/references/inbox-handoff.md +0 -0
  161. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-conversation-router/references/learning-intake.md +0 -0
  162. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-conversation-router/references/task-intake.md +0 -0
  163. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-document-capture/SKILL.md +0 -0
  164. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-inbox-triage/SKILL.md +0 -0
  165. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/SKILL.md +0 -0
  166. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/agents/openai.yaml +0 -0
  167. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-workspace-adoption/SKILL.md +0 -0
  168. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-workspace-maintenance/SKILL.md +0 -0
  169. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-workspace-maintenance/references//344/273/273/345/212/241/346/255/243/346/226/207/347/273/223/346/236/204.md" +0 -0
  170. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/src/campfire_cli/resources/skills/campfire-workspace-restructure/SKILL.md +0 -0
  171. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/SPEC.md +0 -0
  172. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/conftest.py +0 -0
  173. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_agent_hints.py +0 -0
  174. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_atomic_write.py +0 -0
  175. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_config.py +0 -0
  176. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_frontmatter.py +0 -0
  177. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/tests/unit/test_repository_boundaries.py +0 -0
  178. {campfire_cli-0.1.3 → campfire_cli-0.1.4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: campfire-cli
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Local-first shared context and governance CLI for humans and agents
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "campfire-cli"
3
- version = "0.1.3"
3
+ version = "0.1.4"
4
4
  description = "Local-first shared context and governance CLI for humans and agents"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """Campfire CLI package."""
2
2
 
3
- __version__ = "0.1.3"
3
+ __version__ = "0.1.4"
@@ -35,18 +35,8 @@ LATIN_RE = re.compile(r"[A-Za-z][A-Za-z0-9.+#_-]{1,}")
35
35
  CHINESE_RE = re.compile(r"[\u4e00-\u9fff]{2,}")
36
36
 
37
37
 
38
- def note_title(path: Path) -> str:
39
- text = path.read_text(encoding="utf-8")
40
- match = re.search(r"^#\s+(.+)$", text, re.MULTILINE)
41
- return match.group(1).strip() if match else path.stem
42
-
43
-
44
- def note_terms(path: Path) -> Counter[str]:
45
- text = path.read_text(encoding="utf-8")
46
- terms: list[str] = [token.lower() for token in LATIN_RE.findall(text)]
47
- for block in CHINESE_RE.findall(text):
48
- terms.extend(block[index : index + 2] for index in range(len(block) - 1))
49
- ignored = {
38
+ IGNORED_TERMS = frozenset(
39
+ {
50
40
  "text",
51
41
  "true",
52
42
  "false",
@@ -73,7 +63,31 @@ def note_terms(path: Path) -> Counter[str]:
73
63
  "因为",
74
64
  "所以",
75
65
  }
76
- return Counter(term for term in terms if term not in ignored)
66
+ )
67
+
68
+ IGNORED_TITLE_KEYWORDS = frozenset(
69
+ {"go", "agent", "development", "document", "guide", "note", "over", "and", "with"}
70
+ )
71
+
72
+
73
+ def note_title(path: Path) -> str:
74
+ return title_from_text(path.read_text(encoding="utf-8"), path.stem)
75
+
76
+
77
+ def title_from_text(text: str, fallback: str) -> str:
78
+ match = re.search(r"^#\s+(.+)$", text, re.MULTILINE)
79
+ return match.group(1).strip() if match else fallback
80
+
81
+
82
+ def note_terms(path: Path) -> Counter[str]:
83
+ return terms_from_text(path.read_text(encoding="utf-8"))
84
+
85
+
86
+ def terms_from_text(text: str) -> Counter[str]:
87
+ terms: list[str] = [token.lower() for token in LATIN_RE.findall(text)]
88
+ for block in CHINESE_RE.findall(text):
89
+ terms.extend(block[index : index + 2] for index in range(len(block) - 1))
90
+ return Counter(term for term in terms if term not in IGNORED_TERMS)
77
91
 
78
92
 
79
93
  def similarity(left: Counter[str], right: Counter[str]) -> tuple[float, list[str]]:
@@ -83,22 +97,25 @@ def similarity(left: Counter[str], right: Counter[str]) -> tuple[float, list[str
83
97
  if not union:
84
98
  return 0.0, []
85
99
  common = left_terms & right_terms
86
- score = len(common) / len(union)
87
- reasons = [
100
+ return len(common) / len(union), top_reasons(left, right, common)
101
+
102
+
103
+ def top_reasons(left: Counter[str], right: Counter[str], common: set[str]) -> list[str]:
104
+ return [
88
105
  term
89
106
  for term, _ in sorted(
90
107
  ((term, left[term] + right[term]) for term in common),
91
108
  key=lambda item: (-item[1], item[0]),
92
109
  )[:5]
93
110
  ]
94
- return score, reasons
95
111
 
96
112
 
97
113
  def title_keywords(path: Path) -> set[str]:
98
- title = f"{path.stem} {note_title(path)}"
99
- keywords = {token.lower() for token in LATIN_RE.findall(title)}
100
- ignored = {"go", "agent", "development", "document", "guide", "note", "over", "and", "with"}
101
- return keywords - ignored
114
+ return keywords_from_title(f"{path.stem} {note_title(path)}")
115
+
116
+
117
+ def keywords_from_title(title: str) -> set[str]:
118
+ return {token.lower() for token in LATIN_RE.findall(title)} - IGNORED_TITLE_KEYWORDS
102
119
 
103
120
 
104
121
  def direct_notes(domain: Domain, marker_name: str) -> list[Path]:
@@ -118,8 +135,16 @@ def generate_relations(
118
135
  cross_limit: int,
119
136
  cross_minimum: float,
120
137
  ) -> dict[Path, list[dict[str, Any]]]:
121
- vectors = {note: note_terms(note) for note in notes}
138
+ # 全库 O(n^2) 配对:每篇笔记只读一次文件,词表/标题关键词/显式链接全部预计算,
139
+ # 相似度得分只在候选保留时才展开 reasons,避免内层循环重复 I/O。
122
140
  texts = {note: note.read_text(encoding="utf-8") for note in notes}
141
+ vectors = {note: terms_from_text(texts[note]) for note in notes}
142
+ term_sets = {note: frozenset(vector) for note, vector in vectors.items()}
143
+ term_sizes = {note: len(terms) for note, terms in term_sets.items()}
144
+ title_keywords_by_note = {
145
+ note: keywords_from_title(f"{note.stem} {title_from_text(texts[note], note.stem)}")
146
+ for note in notes
147
+ }
123
148
  explicit_links = {
124
149
  note: {Path(value).stem for value in WIKILINK_RE.findall(texts[note])} for note in notes
125
150
  }
@@ -128,11 +153,14 @@ def generate_relations(
128
153
  strong: list[dict[str, Any]] = []
129
154
  same_domain_semantic: list[dict[str, Any]] = []
130
155
  cross_domain_semantic: list[dict[str, Any]] = []
156
+ source_terms = term_sets[source]
157
+ source_links = explicit_links[source]
158
+ source_domain = domain_by_note[source]
131
159
  for target in notes:
132
160
  if source == target:
133
161
  continue
134
- score, reasons = similarity(vectors[source], vectors[target])
135
- if target.stem in explicit_links[source]:
162
+ reasons: list[str] = []
163
+ if target.stem in source_links:
136
164
  relation_type = "direct-link"
137
165
  score = 1.0
138
166
  reasons = ["正文直接链接"]
@@ -141,19 +169,24 @@ def generate_relations(
141
169
  score = 1.0
142
170
  reasons = ["目标文档引用本文"]
143
171
  else:
144
- same_domain = domain_by_note[source] == domain_by_note[target]
145
- relation_type = (
146
- "same-domain-similarity" if same_domain else "cross-domain-similarity"
147
- )
148
- if not same_domain:
149
- common_title_keywords = sorted(title_keywords(source) & title_keywords(target))
172
+ if source_domain == domain_by_note[target]:
173
+ relation_type = "same-domain-similarity"
174
+ else:
175
+ common_title_keywords = sorted(
176
+ title_keywords_by_note[source] & title_keywords_by_note[target]
177
+ )
150
178
  if not common_title_keywords:
151
179
  continue
152
- reasons = [
153
- f"标题共同关键词:{value}" for value in common_title_keywords
154
- ] + reasons
180
+ relation_type = "cross-domain-similarity"
181
+ reasons = [f"标题共同关键词:{value}" for value in common_title_keywords]
182
+ target_terms = term_sets[target]
183
+ common = source_terms & target_terms
184
+ union_size = term_sizes[source] + term_sizes[target] - len(common)
185
+ score = len(common) / union_size if union_size else 0.0
155
186
  threshold = cross_minimum if relation_type == "cross-domain-similarity" else minimum
156
187
  if relation_type in {"direct-link", "backlink"} or score >= threshold:
188
+ if relation_type not in {"direct-link", "backlink"}:
189
+ reasons = reasons + top_reasons(vectors[source], vectors[target], common)
157
190
  item = {
158
191
  "target": str(target.relative_to(vault_root).with_suffix("")),
159
192
  "target_name": target.stem,
@@ -66,6 +66,43 @@ class AppContainer:
66
66
  "health": container.maintenance.check(summary=True).model_dump(mode="json"),
67
67
  }
68
68
 
69
+ @classmethod
70
+ def setup_global_resources(cls) -> dict:
71
+ """无 Workspace 时的降级 setup:同步不依赖 Manifest 的全局资源,跳过其余步骤。"""
72
+ return {
73
+ "status": "needs-input",
74
+ "message": (
75
+ "未指定 Workspace:已同步全局治理资源;接入 Workspace 后可执行完整 setup。"
76
+ "按场景选择以下入口之一"
77
+ ),
78
+ "paths": [
79
+ {
80
+ "scenario": "接入已有 Vault(目录已存在,含或不含 .campfire.yaml)",
81
+ "command": "campfire setup --workspace <vault路径> --default",
82
+ },
83
+ {
84
+ "scenario": "从零创建新 Workspace(初始化目录结构并注册)",
85
+ "command": "campfire workspace create --id <id> --path <路径> --default",
86
+ },
87
+ {
88
+ "scenario": "已注册 Workspace 的本机资源全量对齐",
89
+ "command": "campfire upgrade",
90
+ },
91
+ ],
92
+ "resources": {
93
+ "skills": cls.build_skill().sync(dry_run=False).model_dump(mode="json"),
94
+ "agent_hints": cls._inject_hints(),
95
+ },
96
+ "skipped": [
97
+ "workspace-registration",
98
+ "manifest",
99
+ "config-check",
100
+ "bases",
101
+ "document-index",
102
+ "health-check",
103
+ ],
104
+ }
105
+
69
106
  @classmethod
70
107
  def upgrade(cls) -> dict:
71
108
  """对齐本机治理资源与当前包版本:Schema 迁移、Skill、Base 与提示词路标。"""
@@ -122,41 +122,17 @@ def tree(ctx: typer.Context) -> None:
122
122
  @app.command("setup")
123
123
  def setup(
124
124
  workspace: Path | None = typer.Option(
125
- None, "--workspace", help="要初始化的 Workspace 根目录;缺省时输出接入引导"
125
+ None, "--workspace", help="要初始化的 Workspace 根目录;缺省时仅同步全局资源并输出接入引导"
126
126
  ),
127
127
  make_default: bool = typer.Option(False, "--default", help="设为默认 Workspace"),
128
128
  ) -> None:
129
129
  """从 .campfire.yaml 配置本机,或为已注册 Workspace 创建首份 Manifest。"""
130
- if workspace is None:
131
- typer.echo(
132
- json.dumps(
133
- {
134
- "status": "needs-input",
135
- "message": "需要指定 Vault 根目录;按场景选择以下入口之一",
136
- "paths": [
137
- {
138
- "scenario": "接入已有 Vault(目录已存在,含或不含 .campfire.yaml)",
139
- "command": "campfire setup --workspace <vault路径> --default",
140
- },
141
- {
142
- "scenario": "从零创建新 Workspace(初始化目录结构并注册)",
143
- "command": (
144
- "campfire workspace create --id <id> --path <路径> --default"
145
- ),
146
- },
147
- {
148
- "scenario": "暂不接入 Vault,仅安装全局资源(Skill 与提示词路标)",
149
- "command": "campfire upgrade",
150
- },
151
- ],
152
- },
153
- ensure_ascii=False,
154
- indent=2,
155
- )
156
- )
157
- return
158
130
  try:
159
- result = AppContainer.setup(workspace, make_default)
131
+ result = (
132
+ AppContainer.setup_global_resources()
133
+ if workspace is None
134
+ else AppContainer.setup(workspace, make_default)
135
+ )
160
136
  except AppError as exc:
161
137
  typer.echo(json.dumps({"status": "error", "message": str(exc)}, ensure_ascii=False))
162
138
  raise typer.Exit(exc.exit_code) from exc
@@ -2148,8 +2148,13 @@ def test_upgrade_syncs_resources_and_accepts_update_alias(
2148
2148
  assert stale.read_text(encoding="utf-8") != "过时内容\n"
2149
2149
 
2150
2150
 
2151
- def test_setup_without_workspace_prints_guidance(tmp_path: Path, monkeypatch) -> None:
2152
- monkeypatch.setenv("CAMPFIRE_HOME", str(tmp_path / "home"))
2151
+ def test_setup_without_workspace_syncs_global_resources_and_prints_guidance(
2152
+ tmp_path: Path, monkeypatch
2153
+ ) -> None:
2154
+ home = tmp_path / "home"
2155
+ monkeypatch.setenv("CAMPFIRE_HOME", str(home))
2156
+ hint_file = tmp_path / "CLAUDE.md"
2157
+ monkeypatch.setenv("CAMPFIRE_AGENT_HINT_PATH", str(hint_file))
2153
2158
  result = runner.invoke(app, ["setup"])
2154
2159
  assert result.exit_code == 0, result.output
2155
2160
  payload = json.loads(result.output)
@@ -2158,3 +2163,8 @@ def test_setup_without_workspace_prints_guidance(tmp_path: Path, monkeypatch) ->
2158
2163
  assert "campfire setup --workspace <vault路径> --default" in commands
2159
2164
  assert any("workspace create" in command for command in commands)
2160
2165
  assert any("upgrade" in command for command in commands)
2166
+ assert payload["resources"]["skills"]["status"] == "synced"
2167
+ assert {item["action"] for item in payload["resources"]["agent_hints"]} == {"created"}
2168
+ assert "campfire:agent-hints:start" in hint_file.read_text(encoding="utf-8")
2169
+ assert "manifest" in payload["skipped"]
2170
+ assert "health-check" in payload["skipped"]
@@ -106,6 +106,30 @@ class RelationTests(unittest.TestCase):
106
106
  self.assertEqual("cross-domain-similarity", relations[left][0]["type"])
107
107
  self.assertEqual("Go MCP Server", relations[left][0]["target_name"])
108
108
 
109
+ def test_preserves_all_relation_types_and_reason_order(self) -> None:
110
+ with tempfile.TemporaryDirectory() as temporary:
111
+ root = Path(temporary)
112
+ hub = root / "Hub.md"
113
+ linked = root / "Linked.md"
114
+ backlinked = root / "Backlinked.md"
115
+ similar = root / "Similar Note.md"
116
+ hub.write_text("# Hub\nalpha beta gamma\n[[Linked]]\n", encoding="utf-8")
117
+ linked.write_text("# Linked\n[[Hub]]\n", encoding="utf-8")
118
+ backlinked.write_text("# Backlinked\n[[Hub]] delta\n", encoding="utf-8")
119
+ similar.write_text("# Similar\nalpha beta gamma delta\n", encoding="utf-8")
120
+ domains = {note: "core" for note in (hub, linked, backlinked, similar)}
121
+ relations = generate_relations([hub, linked, backlinked, similar], domains, root, 3, 0.1, 2, 0.05)
122
+ by_type = {item["type"]: item for item in relations[hub]}
123
+ self.assertEqual({"direct-link", "backlink", "same-domain-similarity"}, set(by_type))
124
+ self.assertEqual(1.0, by_type["direct-link"]["score"])
125
+ self.assertEqual(["正文直接链接"], by_type["direct-link"]["reasons"])
126
+ self.assertEqual(["目标文档引用本文"], by_type["backlink"]["reasons"])
127
+ self.assertIn("alpha", by_type["same-domain-similarity"]["reasons"])
128
+ cross = generate_relations(
129
+ [hub, similar], {hub: "core", similar: "other"}, root, 3, 0.1, 2, 0.05
130
+ )
131
+ self.assertEqual([], cross[hub])
132
+
109
133
 
110
134
  class RestructureCheckTests(unittest.TestCase):
111
135
  def test_before_and_after_accept_unchanged_move(self) -> None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes