campfire-cli 0.1.6__tar.gz → 0.1.7__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.
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/ARCHITECTURE.md +50 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/COMMAND.md +4 -3
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/PKG-INFO +6 -4
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/README.md +5 -3
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/SPEC.md +3 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/pyproject.toml +1 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/__init__.py +1 -1
- campfire_cli-0.1.7/src/campfire_cli/app/base/schema/operation_schema.py +23 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/SPEC.md +9 -1
- campfire_cli-0.1.7/src/campfire_cli/app/document/cli/document_cli.py +143 -0
- campfire_cli-0.1.7/src/campfire_cli/app/document/schema/__init__.py +13 -0
- campfire_cli-0.1.7/src/campfire_cli/app/document/schema/document_schema.py +48 -0
- campfire_cli-0.1.7/src/campfire_cli/app/document/service/document_apply_service.py +228 -0
- campfire_cli-0.1.7/src/campfire_cli/app/document/service/document_move_service.py +314 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/document_rule_service.py +39 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/document_service.py +32 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/frontmatter_formatter.py +40 -5
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/profile_registry.py +11 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/type_apply.py +32 -12
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/SPEC.md +1 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/cli/maintenance_cli.py +0 -13
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/maintenance_service.py +1 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/SPEC.md +5 -3
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/project_cli.py +6 -6
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/workspace_cli.py +0 -31
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/repository/manifest_repository.py +6 -3
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/repository/workspace_repository.py +15 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/schema/adoption_schema.py +3 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/schema/restructure_schema.py +3 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/schema/workspace_schema.py +1 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/adoption_service.py +70 -48
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/config_service.py +11 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/domain_restructure_service.py +126 -80
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/project_service.py +10 -8
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/restructure_service.py +64 -77
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/workspace_protocol.py +2 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/workspace_service.py +19 -35
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/agent_hints.py +14 -4
- campfire_cli-0.1.7/src/campfire_cli/common/filesystem/__init__.py +20 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/filesystem/atomic.py +7 -3
- campfire_cli-0.1.7/src/campfire_cli/common/filesystem/change_set.py +134 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/governance/locking.py +1 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/container.py +10 -7
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/main.py +12 -9
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/defaults/config.yml +21 -0
- campfire_cli-0.1.7/src/campfire_cli/resources/skills/SPEC.md +25 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-context-bootstrap/SKILL.md +2 -2
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-document-capture/SKILL.md +1 -1
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-task-management/SKILL.md +6 -17
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-workspace-adoption/SKILL.md +2 -2
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-workspace-maintenance/SKILL.md +9 -5
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-workspace-restructure/SKILL.md +4 -3
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/integration/test_cli.py +259 -84
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/perf/test_resolve_subprocess_count.py +4 -2
- campfire_cli-0.1.7/tests/unit/test_document_apply.py +511 -0
- campfire_cli-0.1.7/tests/unit/test_file_change_executor.py +97 -0
- campfire_cli-0.1.7/tests/unit/test_repository_boundaries.py +34 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/uv.lock +1 -1
- campfire_cli-0.1.6/src/campfire_cli/app/document/cli/document_cli.py +0 -70
- campfire_cli-0.1.6/src/campfire_cli/common/filesystem/__init__.py +0 -6
- campfire_cli-0.1.6/src/campfire_cli/resources/skills/SPEC.md +0 -3
- campfire_cli-0.1.6/tests/unit/test_repository_boundaries.py +0 -14
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/.github/workflows/ci.yml +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/.github/workflows/release.yml +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/.gitignore +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/AGENTS.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/DECISIONS.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/LICENSE +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/alembic/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/alembic/env.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/alembic/script.py.mako +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/alembic/versions/001_initial_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/alembic.ini +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/scripts/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/env.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/script.py.mako +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/001_initial_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/002_workspace_project_registry.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/003_unified_workspace_state.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/004_restructure_workspace_domain.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/005_decision_channel.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/006_workspace_topology_index.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/007_workspace_adoption.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/alembic/versions/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/cli/base_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/repository/base_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/schema/base_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/base/service/base_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/cli/decision_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/repository/decision_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/schema/decision_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/service/decision_projection_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/decision/service/decision_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/cli/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/cli/profile_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/cli/type_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/repository/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/repository/document_profile_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/repository/document_type_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/document_profile_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/document_scanner.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/document_type_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/frontmatter_apply.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/frontmatter_plan.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/kanban_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/document/service/type_plan.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/repository/maintenance_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/schema/maintenance_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/archive_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/link_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/maintenance_protocol.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/moc_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/maintenance/service/plan_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/cli/skill_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/repository/skill_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/schema/skill_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/skill/service/skill_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/adoption_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/config_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/domain_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/restructure_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/cli/space_cli.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/repository/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/repository/adoption_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/repository/restructure_repository.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/schema/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/adoption_protocol.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/restructure_protocol.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/restructure_verifier.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/app/workspace/service/structure_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/database/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/database/migrations.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/database/models.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/database/session.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/documents/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/documents/document_types.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/documents/frontmatter_schema.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/documents/markdown.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/exceptions/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/exceptions/base.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/filesystem/cwd.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/filesystem/locking.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/governance/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/governance/issues.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/governance/snapshots.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/hashing.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/package_version.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/reports/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/reports/json_report.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/common/reports/markdown_report.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/config/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/config/defaults.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/config/settings.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases/Agent/346/211/247/350/241/214/345/267/245/344/275/234/345/217/260.base" +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases//344/273/273/345/212/241/345/267/245/344/275/234/345/217/260.base" +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases//345/206/263/347/255/226/345/267/245/344/275/234/345/217/260.base" +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases//345/276/205/345/275/222/346/241/243/346/226/207/346/241/243.base" +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/bases//351/241/271/347/233/256/346/226/207/346/241/243.base" +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/defaults/__init__.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-context-bootstrap/agents/openai.yaml +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-conversation-router/SKILL.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-conversation-router/agents/openai.yaml +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-conversation-router/references/inbox-handoff.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-conversation-router/references/learning-intake.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-conversation-router/references/task-intake.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-inbox-triage/SKILL.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-kanban-board/SKILL.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/SKILL.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/src/campfire_cli/resources/skills/campfire-weekly-report-writing/agents/openai.yaml +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/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
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/SPEC.md +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/conftest.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/perf/test_read_counts.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_agent_hints.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_atomic_write.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_common_governance.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_config.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_frontmatter.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_kanban_service.py +0 -0
- {campfire_cli-0.1.6 → campfire_cli-0.1.7}/tests/unit/test_package_version.py +0 -0
|
@@ -80,6 +80,55 @@ Document App 是所有面向用户和 Agent 的文档命令入口;Profile、
|
|
|
80
80
|
|
|
81
81
|
Frontmatter 规则采用声明式 Profile:`base` 是最小公共契约,`knowledge`、`project-doc`、`task` 只允许一层继承。Profile Loader 将配置编译为完整 EffectiveProfile,Resolver 根据文档类型和领域上下文选择 Profile,Validator 与 Formatter 共同消费该结果。字段规则不使用每种文档一个 Python 子类,也不在 Skill 中复制。
|
|
82
82
|
|
|
83
|
+
### CLI 设计理念:治理原语 + Skill SOP
|
|
84
|
+
|
|
85
|
+
Campfire 不是“Markdown 版 kubectl”,而是面向人机协作场景组合成熟 CLI 经验形成的独立设计。它在资源心智模型、`apply` 语义和机器可读接口上借鉴 kubectl,在“计划—审查—执行”上借鉴 Terraform,在稳定原语与上层工作流分离上借鉴 Git/Unix;Markdown SSOT、Agent 语义判断和显式 Maintenance 则是 Campfire 自身边界。
|
|
86
|
+
|
|
87
|
+
| 参考 | Campfire 采用的部分 | Campfire 不照搬的部分 |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| [kubectl 命令与资源模型](https://kubernetes.io/docs/reference/kubectl/) | 按对象域组织命令、用 `apply` 统一创建与更新、显式选择作用域、提供稳定机器输出 | 不复制 `kubectl <verb> <type> <name>` 语法,不引入 API Server、Controller 或持续调谐 |
|
|
90
|
+
| [kubectl 声明式 apply](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/) | 目标不存在时创建、存在时更新;把“期望变更”交给工具校验和执行 | 不保存 `last-applied-configuration`,不实现三方合并或字段所有权;Campfire apply 是 Profile 约束下的显式补丁 |
|
|
91
|
+
| [Terraform plan/apply](https://developer.hashicorp.com/terraform/cli/commands/plan) | 写入前预览,可审查计划后再执行,执行前重新确认输入未漂移 | 不把所有日常写入都升级为持久计划;单文档原子修改保持轻量 |
|
|
92
|
+
| [Git plumbing/porcelain](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain) | CLI 提供可组合、可脚本化的稳定原语,Skill 组合成人类可理解的 SOP | 不暴露仅供内部实现使用的隐藏命令,不要求用户理解底层存储 |
|
|
93
|
+
|
|
94
|
+
本文中的“原子命令”特指**意图原子命令**,不是把实现拆成最小文件操作或最小函数。一个公共命令需同时满足三层原子性:
|
|
95
|
+
|
|
96
|
+
| 层次 | 规范 | 例子 |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| 语义原子性 | 一条命令只表达一个可以用一句话说清的用户意图 | `document move` 表达“在已声明 Domain 之间正确移动一篇文档” |
|
|
99
|
+
| 一致性原子性 | 为保持该意图不变量而必须一起变更的事实,属于同一个变更集;整体成功或恢复到执行前 | 移动文档时同步修复可确定解析的引用 |
|
|
100
|
+
| 可组合原子性 | 不相关的派生治理不隐式执行;命令用结构化 `follow_up` 声明后续步骤,由 Skill 决定组合顺序 | `document apply` 不自动运行 `maintenance sync/check` |
|
|
101
|
+
|
|
102
|
+
命令副作用按下列边界分类:
|
|
103
|
+
|
|
104
|
+
- **必须纳入当前事务**:不执行就会让当前意图产生破损状态的变更,例如结构迁移时的 Domain 声明、Project 归属和可移植 Manifest 对齐。
|
|
105
|
+
- **必须显式返回**:可从原始事实重建的派生结果,例如 MOC、关系页、索引和治理报告;这些作为 `follow_up` 由 Skill 显式执行。
|
|
106
|
+
- **禁止捎带**:与当前意图无关的全 Workspace 格式化、归档、结构重构或其他写操作。
|
|
107
|
+
|
|
108
|
+
“一次改多个文件”不等于不原子;“一次只改一个字段”也不自动等于边界正确。评审新命令时必须逐项回答:
|
|
109
|
+
|
|
110
|
+
1. 用户意图能否用一句话准确表达?
|
|
111
|
+
2. 对象和作用域是否显式?
|
|
112
|
+
3. 所有被修改的事实是否都是维持该意图不变量所必需?
|
|
113
|
+
4. 预览和 JSON 输出能否完整说明变更、阻断和后续操作?
|
|
114
|
+
5. 重复执行是否幂等,或至少以稳定结果明确拒绝?
|
|
115
|
+
6. 预览后的并发变更是否会被锁与快照复核阻断?
|
|
116
|
+
7. 可重建的派生工作是否作为可组合 `follow_up` 返回?
|
|
117
|
+
|
|
118
|
+
命令设计遵循以下约束:
|
|
119
|
+
|
|
120
|
+
1. **对象域优先**:公共入口采用 `campfire <object-domain> <verb>`,例如 `document apply`、`maintenance check`;动词在所属业务对象内保持单义,不为同一行为保留多个别名。
|
|
121
|
+
2. **意图原子、派生显式**:`document apply` 只创建或更新目标文档,`document move` 原子完成单文档移动、目标 Profile 对齐和确定性引用修复;MOC、关系页和索引治理由 Skill 显式编排 `maintenance sync/check`。
|
|
122
|
+
3. **契约声明式,变更显式**:Profile 是字段、类型、枚举、顺序和条件必填的 SSOT。Agent 提交业务值,CLI 解析有效 Profile 并拒绝猜测;已有文档只修改明确给出的字段或正文操作。
|
|
123
|
+
4. **写入先证明安全**:写命令默认预览,显式确认后才提交;提交时在锁内复核快照或期望哈希,多文件变更作为一个 ChangeSet 执行,失败回滚,避免静默覆盖和部分写入。
|
|
124
|
+
5. **人类与 Agent 共用一个契约**:命令和结果只有一套语义。JSON 状态、issues、missing fields 与 follow-up 供 Agent 稳定消费,`tree` 和分层 `-h` 供人类与 Agent 渐进发现,不维护第二套参数目录。
|
|
125
|
+
6. **语义与机制分层**:人类决定高风险取舍,Agent 理解正文和业务语义,Skill 规定加载时机、事实门禁与 SOP,CLI 只执行可确定验证的治理机制。歧义进入 Decision,不为“自动化成功”而猜测。
|
|
126
|
+
7. **聚合入口是少数例外**:`setup` 和 `upgrade` 可以编排多个服务,因为它们表达完整安装生命周期;日常内容治理保持原子能力,避免重新出现 `maintenance run` 一类不可审查的聚合入口。
|
|
127
|
+
|
|
128
|
+
横切关注点与业务 SOP 不使用同一种复用手段。哈希复核、写锁、原子替换和失败恢复由显式 ChangeSet Executor 复用;`apply → sync → check` 等业务顺序由 Skill 明文编排。不为了复用 Maintenance 而引入 AOP 切面、命令总线、全局钩子或隐式中间件。
|
|
129
|
+
|
|
130
|
+
因此,`document apply` 的准确含义是“对一个 Markdown 文档应用经 Profile 校验的显式意图”,不是“把完整声明持续调谐到某个服务端状态”。用户或 Agent 可以直接 edit 已有正文;无论通过 apply 还是 edit 写入,跨文档派生结果都由后续显式 Maintenance 收敛。
|
|
131
|
+
|
|
83
132
|
## 5. SSOT 与派生数据
|
|
84
133
|
|
|
85
134
|
| 数据 | 唯一事实来源 | 派生或运行副本 |
|
|
@@ -132,7 +181,7 @@ SQLite 中的 `spaces`、`domains` 与 `documents` 是本机查询投影,不
|
|
|
132
181
|
|
|
133
182
|
### 存量文件夹接管
|
|
134
183
|
|
|
135
|
-
Adoption 是首次接管边界,不属于日常 Maintenance。外部目录只读并复制到 `_收件箱/待接管/<batch>`,Vault 内目录原地冻结事实;两者随后通过同一份计划建立一个粗粒度 Domain。CLI
|
|
184
|
+
Adoption 是首次接管边界,不属于日常 Maintenance。外部目录只读并复制到 `_收件箱/待接管/<batch>`,Vault 内目录原地冻结事实;两者随后通过同一份计划建立一个粗粒度 Domain。CLI 负责文件清单、哈希、软链接与冲突保护、声明、初始 MOC 和 Project/Manifest 联动;Agent 负责阅读正文、选择目标 Space/Domain,并按 `follow_up` 显式刷新派生视图与索引。
|
|
136
185
|
|
|
137
186
|
## 6. 本地 Web 工作台
|
|
138
187
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
人类与 Agent 先用 `campfire tree` 发现命令,再用任意层级的 `-h` 渐进加载参数。
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
campfire setup --workspace <vault-path> --default
|
|
6
|
+
campfire setup --workspace <vault-path> [--id <workspace-id>] --default
|
|
7
7
|
campfire upgrade
|
|
8
8
|
campfire skill sync
|
|
9
9
|
campfire base sync
|
|
@@ -14,7 +14,6 @@ campfire workspace adopt inventory --source <folder> --batch <id> [--confirm]
|
|
|
14
14
|
campfire workspace adopt plan --batch <id> --target-path <path> --domain-id <id> --name <name> --space <id> --type <type> --governance <policy> [--parent-domain <id>] [--project <id>]
|
|
15
15
|
campfire workspace adopt apply --batch <id> [--confirm]
|
|
16
16
|
campfire workspace adopt verify --batch <id>
|
|
17
|
-
campfire workspace attach --path <vault-path> --default
|
|
18
17
|
campfire workspace project bind --id <project-id> --local-path <repository-path>
|
|
19
18
|
campfire workspace space list
|
|
20
19
|
campfire workspace space check
|
|
@@ -28,6 +27,8 @@ campfire workspace restructure domain rename --domain <id> --name <name> [--rena
|
|
|
28
27
|
campfire workspace restructure domain move --domain <id> --target-path <path> [--parent-domain <id>] [--confirm]
|
|
29
28
|
campfire workspace restructure domain rekey --domain <id> --new-id <id> [--confirm]
|
|
30
29
|
campfire workspace project resolve --path "$PWD"
|
|
30
|
+
campfire document apply --path <workspace-relative-markdown> --type <type> --set <field=value> [--body-file <path>] [--confirm]
|
|
31
|
+
campfire document move --from <source> --to <target> [--set <field=value>] [--unset <field>] [--expected-hash <sha256>] [--confirm]
|
|
31
32
|
campfire document inspect --path <file>
|
|
32
33
|
campfire document type list
|
|
33
34
|
campfire document profile list
|
|
@@ -46,4 +47,4 @@ campfire maintenance verify --plan <plan-id>
|
|
|
46
47
|
campfire maintenance sync --scope <path> --dry-run
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
Space、Domain、Project 的 `create
|
|
50
|
+
Space、Domain、Project 的 `create`、存量对象的 `adopt`,以及文档移动、重构、归档写操作默认先预览;审查通过后才追加 `--confirm`。`document move` 可在任意已声明 Domain 之间移动单篇文档,自动对齐可确定的 `domain`/`project` 归属;目标 Profile 缺失语义字段时返回 `needs-input`,调用方通过 `--set`/`--unset` 显式补齐。`adopt` 只接入已有对象,不移动已有内容。具体参数以对应命令的 `-h` 为准,避免在文档中维护第二份参数目录。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: campfire-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Local-first shared context and governance CLI for humans and agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -94,6 +94,7 @@ campfire maintenance sync [--dry-run] [--scope] # 刷新 MOC 与相关文档页
|
|
|
94
94
|
campfire maintenance archive check / apply # 归档候选检查与执行
|
|
95
95
|
|
|
96
96
|
campfire document inspect / check / format # 单篇文档查看、校验、格式化
|
|
97
|
+
campfire document apply / move # 单篇文档创建更新、跨 Domain 移动
|
|
97
98
|
campfire document profile list / show / resolve # Frontmatter Profile 规则
|
|
98
99
|
campfire document type list # 文档类型与前缀
|
|
99
100
|
|
|
@@ -106,7 +107,7 @@ campfire decision create / list / answer / close # 持久决策通道
|
|
|
106
107
|
campfire workspace space create --id research --name "研究" --path myresearch --type research
|
|
107
108
|
campfire workspace domain create --id wiki --name "Wiki" --path "mywork/项目/wiki" \
|
|
108
109
|
--space work --type knowledge-domain --governance project-docs --confirm
|
|
109
|
-
campfire workspace project
|
|
110
|
+
campfire workspace project adopt --id example --workspace personal \
|
|
110
111
|
--name "Example" --document-domain "work/example" --local-path /path/to/repo
|
|
111
112
|
campfire workspace rebuild --confirm # 索引损坏时从 SSOT 完整恢复
|
|
112
113
|
```
|
|
@@ -124,7 +125,7 @@ campfire workspace adopt apply --batch notes-001 --confirm
|
|
|
124
125
|
campfire workspace adopt verify --batch notes-001
|
|
125
126
|
```
|
|
126
127
|
|
|
127
|
-
|
|
128
|
+
单篇文档在已声明 Domain 之间移动使用 `document move`。批量文档或 Domain 结构重构先冻结范围,再传入 YAML/JSON 意图规格(含 Frontmatter 修改),逐项审查 `approved` 后执行:
|
|
128
129
|
|
|
129
130
|
```bash
|
|
130
131
|
campfire workspace restructure inventory --scope work --batch move-001
|
|
@@ -139,7 +140,8 @@ campfire workspace restructure verify --batch move-001
|
|
|
139
140
|
|
|
140
141
|
- **校验分工**:`maintenance check` 统一负责正式文档的 Schema 与枚举校验,并刷新可重建索引;结构声明由 `workspace space/domain check` 校验;`maintenance sync` 只因结构、MOC、路径或并发安全问题阻塞,单篇文档问题不阻止其他领域刷新。
|
|
141
142
|
- **Frontmatter Profile**:声明式一层继承(`base` 或 `base → knowledge/project-doc/task`),`document profile show` 展示编译后的完整规则;Formatter 只按有效 Profile 排序并保留值,不允许字段由 Validator 报告、不自动删除。
|
|
142
|
-
-
|
|
143
|
+
- **并发与提交安全**:写入前在治理锁内复核内容哈希,外部变化返回 `concurrent-change` / `source-hash-changed`,拒绝覆盖;多文件写入和路径移动经同一 ChangeSet 提交,失败恢复到执行前。
|
|
144
|
+
- **显式后续治理**:写入命令以轻量 `follow_up` 返回 `maintenance sync/check` 的 Workspace 和 scope;Skill 顺序执行,CLI 不隐式捎带派生治理。
|
|
143
145
|
- **配置两层模型**:产品默认契约在包内 `resources/defaults/config.yml`(SSOT),用户只在 `~/.campfire/config.yml` 写覆盖项;Mapping 递归合并,`campfire workspace config check` 验证有效配置。
|
|
144
146
|
|
|
145
147
|
## Agent 协作
|
|
@@ -78,6 +78,7 @@ campfire maintenance sync [--dry-run] [--scope] # 刷新 MOC 与相关文档页
|
|
|
78
78
|
campfire maintenance archive check / apply # 归档候选检查与执行
|
|
79
79
|
|
|
80
80
|
campfire document inspect / check / format # 单篇文档查看、校验、格式化
|
|
81
|
+
campfire document apply / move # 单篇文档创建更新、跨 Domain 移动
|
|
81
82
|
campfire document profile list / show / resolve # Frontmatter Profile 规则
|
|
82
83
|
campfire document type list # 文档类型与前缀
|
|
83
84
|
|
|
@@ -90,7 +91,7 @@ campfire decision create / list / answer / close # 持久决策通道
|
|
|
90
91
|
campfire workspace space create --id research --name "研究" --path myresearch --type research
|
|
91
92
|
campfire workspace domain create --id wiki --name "Wiki" --path "mywork/项目/wiki" \
|
|
92
93
|
--space work --type knowledge-domain --governance project-docs --confirm
|
|
93
|
-
campfire workspace project
|
|
94
|
+
campfire workspace project adopt --id example --workspace personal \
|
|
94
95
|
--name "Example" --document-domain "work/example" --local-path /path/to/repo
|
|
95
96
|
campfire workspace rebuild --confirm # 索引损坏时从 SSOT 完整恢复
|
|
96
97
|
```
|
|
@@ -108,7 +109,7 @@ campfire workspace adopt apply --batch notes-001 --confirm
|
|
|
108
109
|
campfire workspace adopt verify --batch notes-001
|
|
109
110
|
```
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
单篇文档在已声明 Domain 之间移动使用 `document move`。批量文档或 Domain 结构重构先冻结范围,再传入 YAML/JSON 意图规格(含 Frontmatter 修改),逐项审查 `approved` 后执行:
|
|
112
113
|
|
|
113
114
|
```bash
|
|
114
115
|
campfire workspace restructure inventory --scope work --batch move-001
|
|
@@ -123,7 +124,8 @@ campfire workspace restructure verify --batch move-001
|
|
|
123
124
|
|
|
124
125
|
- **校验分工**:`maintenance check` 统一负责正式文档的 Schema 与枚举校验,并刷新可重建索引;结构声明由 `workspace space/domain check` 校验;`maintenance sync` 只因结构、MOC、路径或并发安全问题阻塞,单篇文档问题不阻止其他领域刷新。
|
|
125
126
|
- **Frontmatter Profile**:声明式一层继承(`base` 或 `base → knowledge/project-doc/task`),`document profile show` 展示编译后的完整规则;Formatter 只按有效 Profile 排序并保留值,不允许字段由 Validator 报告、不自动删除。
|
|
126
|
-
-
|
|
127
|
+
- **并发与提交安全**:写入前在治理锁内复核内容哈希,外部变化返回 `concurrent-change` / `source-hash-changed`,拒绝覆盖;多文件写入和路径移动经同一 ChangeSet 提交,失败恢复到执行前。
|
|
128
|
+
- **显式后续治理**:写入命令以轻量 `follow_up` 返回 `maintenance sync/check` 的 Workspace 和 scope;Skill 顺序执行,CLI 不隐式捎带派生治理。
|
|
127
129
|
- **配置两层模型**:产品默认契约在包内 `resources/defaults/config.yml`(SSOT),用户只在 `~/.campfire/config.yml` 写覆盖项;Mapping 递归合并,`campfire workspace config check` 验证有效配置。
|
|
128
130
|
|
|
129
131
|
## Agent 协作
|
|
@@ -105,7 +105,9 @@ Campfire 使用语义化版本:
|
|
|
105
105
|
|
|
106
106
|
- SQLite `spaces`、`domains`、`documents` 只允许作为可重建本机投影,不得反向覆盖 Markdown SSOT。
|
|
107
107
|
- `setup` 与 `maintenance check` 必须自动刷新完整拓扑和文档索引。
|
|
108
|
-
-
|
|
108
|
+
- 领域重构只提交当前结构意图,并返回 scoped `maintenance sync` 与
|
|
109
|
+
`maintenance check` follow-up;调用方必须显式执行它们以刷新受影响 MOC
|
|
110
|
+
和当前 Workspace 索引。
|
|
109
111
|
- `workspace rebuild` 默认只预览;`--confirm` 后从 Manifest 和 Markdown 完整替换派生索引。
|
|
110
112
|
|
|
111
113
|
## Workspace 接管
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CommandFollowUp(BaseModel):
|
|
8
|
+
"""Describe one deterministic governance command that a caller should run next."""
|
|
9
|
+
|
|
10
|
+
command: Literal["maintenance sync", "maintenance check"]
|
|
11
|
+
workspace: str
|
|
12
|
+
scope: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def maintenance_follow_up(workspace: str, scopes: Iterable[str]) -> list[CommandFollowUp]:
|
|
16
|
+
"""Build the ordered, deduplicated follow-up for derived workspace maintenance."""
|
|
17
|
+
|
|
18
|
+
unique_scopes = tuple(dict.fromkeys(scopes))
|
|
19
|
+
return [
|
|
20
|
+
CommandFollowUp(command=command, workspace=workspace, scope=scope)
|
|
21
|
+
for command in ("maintenance sync", "maintenance check")
|
|
22
|
+
for scope in unique_scopes
|
|
23
|
+
]
|
|
@@ -12,7 +12,11 @@ document/
|
|
|
12
12
|
│ ├── document_cli.py
|
|
13
13
|
│ ├── profile_cli.py
|
|
14
14
|
│ └── type_cli.py
|
|
15
|
+
├── schema/
|
|
16
|
+
│ └── document_schema.py
|
|
15
17
|
├── service/
|
|
18
|
+
│ ├── document_apply_service.py
|
|
19
|
+
│ ├── document_move_service.py
|
|
16
20
|
│ ├── document_profile_service.py
|
|
17
21
|
│ ├── document_type_service.py
|
|
18
22
|
│ ├── document_service.py
|
|
@@ -34,13 +38,17 @@ document/
|
|
|
34
38
|
- `frontmatter`:检查、规划、执行和格式化文档属性。
|
|
35
39
|
- `rule`:统一解释类型、Profile、枚举与跨字段不变量。
|
|
36
40
|
- `inspect`:向 Agent 返回单篇文档的 Domain、类型、有效 Profile 和具体问题。
|
|
41
|
+
- `apply`:根据目标路径和类型解析 Profile,不存在时生成文档,已存在时仅应用显式补丁;先完整渲染并校验,追加 `--confirm` 后原子写入。
|
|
42
|
+
- `move`:在任意已声明 Domain 之间移动或改名一篇文档,按目标 Profile 对齐可确定的 `domain`/`project` 归属,并更新可确定解析的 Wiki、Markdown 和路径引用。目标 Profile 缺少业务字段时返回 `needs-input`,不猜测。
|
|
37
43
|
- `scanner`:统一解释受管根、忽略目录和豁免文件;Document 与 Maintenance 共用。
|
|
38
44
|
|
|
39
45
|
Document Service 可以被 Maintenance 和 Workspace Restructure 编排,但不得反向依赖它们。批量计划文件、运行记录、MOC、Base、归档和重构批次不属于 Document App。
|
|
40
46
|
|
|
47
|
+
`apply` 与 `move` 只保证目标文档操作自身有效,不触发 Maintenance。Skill SOP 在写入后显式编排 scoped `maintenance sync` 和 `maintenance check`。所有写入先生成完整 ChangeSet,再经共享 Executor 在乐观锁内提交;多文件操作失败时恢复提交前内容。
|
|
48
|
+
|
|
41
49
|
包内 `config.yml` 的默认 Profile 与用户级 `~/.campfire/config.yml` 覆盖共同构成当前治理契约。
|
|
42
50
|
|
|
43
|
-
Profile 只允许一层 `base` 继承。Service 将声明配置编译为完整 `EffectiveProfile`;Validator、Formatter 和 CLI
|
|
51
|
+
Profile 只允许一层 `base` 继承。Service 将声明配置编译为完整 `EffectiveProfile`;Validator、Formatter 和 CLI 必须消费同一结果,不得复制字段、枚举与值类型。`value_types` 声明不能由 YAML 形状可靠推断的标量类型,当前支持 `string` 和 `boolean`。
|
|
44
52
|
|
|
45
53
|
标准字段用于格式化、补全和校验。默认 `unknown_fields: preserve`:已有业务扩展字段不参与标准排序但必须原样保留,不因尚未建立专属 Profile 而制造全库噪声;确需封闭字段集合的 Profile 可显式设为 `report`。
|
|
46
54
|
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
import yaml
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from campfire_cli.app.document.cli.profile_cli import profile_cli
|
|
13
|
+
from campfire_cli.app.document.cli.type_cli import type_cli
|
|
14
|
+
from campfire_cli.app.document.schema import DocumentApplyRequest
|
|
15
|
+
from campfire_cli.app.document.service.document_service import DocumentService
|
|
16
|
+
from campfire_cli.app.workspace.repository.workspace_repository import SqliteWorkspaceRepository
|
|
17
|
+
from campfire_cli.app.workspace.service.workspace_service import WorkspaceService
|
|
18
|
+
from campfire_cli.common.exceptions import AppError
|
|
19
|
+
from campfire_cli.common.filesystem.cwd import safe_cwd
|
|
20
|
+
from campfire_cli.config.settings import WorkspaceSettings, campfire_home
|
|
21
|
+
|
|
22
|
+
document_cli = typer.Typer(
|
|
23
|
+
help="创建、检查和维护文档及其规则",
|
|
24
|
+
context_settings={"help_option_names": ["-h", "--help"]},
|
|
25
|
+
)
|
|
26
|
+
document_cli.add_typer(profile_cli, name="profile")
|
|
27
|
+
document_cli.add_typer(type_cli, name="type")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def service(ctx: typer.Context) -> DocumentService:
|
|
31
|
+
selector = ctx.find_root().params.get("workspace")
|
|
32
|
+
root = campfire_home()
|
|
33
|
+
resolution = WorkspaceService(root, SqliteWorkspaceRepository(root)).resolve(
|
|
34
|
+
selector, safe_cwd()
|
|
35
|
+
)
|
|
36
|
+
settings = WorkspaceSettings.load(resolution.workspace_id, Path(resolution.workspace))
|
|
37
|
+
return DocumentService(settings)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def invoke(operation: Callable[[], dict[str, Any] | BaseModel]) -> None:
|
|
41
|
+
try:
|
|
42
|
+
result = operation()
|
|
43
|
+
payload = result.model_dump(mode="json") if isinstance(result, BaseModel) else result
|
|
44
|
+
typer.echo(json.dumps(payload, ensure_ascii=False, indent=2))
|
|
45
|
+
except AppError as exc:
|
|
46
|
+
typer.echo(json.dumps({"status": "error", "message": str(exc)}, ensure_ascii=False))
|
|
47
|
+
raise typer.Exit(exc.exit_code) from exc
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@document_cli.command("check")
|
|
51
|
+
def check(ctx: typer.Context, path: str = typer.Option(..., "--path")) -> None:
|
|
52
|
+
"""检查一篇 Markdown 文档是否符合当前类型与 Profile 契约。"""
|
|
53
|
+
invoke(lambda: service(ctx).check(path))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@document_cli.command("kanban-check")
|
|
57
|
+
def kanban_check(ctx: typer.Context, path: str = typer.Option(..., "--path")) -> None:
|
|
58
|
+
"""检查文档是否满足 Obsidian Kanban 插件的渲染契约。"""
|
|
59
|
+
invoke(lambda: service(ctx).kanban_check(path))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@document_cli.command("inspect")
|
|
63
|
+
def inspect(ctx: typer.Context, path: str = typer.Option(..., "--path")) -> None:
|
|
64
|
+
"""返回 Agent 治理单篇文档所需的类型、Profile、领域和问题上下文。"""
|
|
65
|
+
invoke(lambda: service(ctx).inspect(path))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@document_cli.command("format")
|
|
69
|
+
def format_document(
|
|
70
|
+
ctx: typer.Context,
|
|
71
|
+
path: str = typer.Option(..., "--path"),
|
|
72
|
+
confirm: bool = typer.Option(False, "--confirm"),
|
|
73
|
+
) -> None:
|
|
74
|
+
"""预览或执行一篇文档的 Frontmatter 字段排序。"""
|
|
75
|
+
invoke(lambda: service(ctx).format(path, confirm))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def parse_values(items: list[str]) -> dict[str, Any]:
|
|
79
|
+
values: dict[str, Any] = {}
|
|
80
|
+
for item in items:
|
|
81
|
+
if "=" not in item:
|
|
82
|
+
raise typer.BadParameter(f"--set 必须使用 field=value:{item}")
|
|
83
|
+
key, raw = item.split("=", 1)
|
|
84
|
+
if not key.strip():
|
|
85
|
+
raise typer.BadParameter("--set 字段名不能为空")
|
|
86
|
+
key = key.strip()
|
|
87
|
+
if key in values:
|
|
88
|
+
raise typer.BadParameter(f"--set 字段重复:{key}")
|
|
89
|
+
values[key] = yaml.safe_load(raw)
|
|
90
|
+
return values
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@document_cli.command("apply")
|
|
94
|
+
def apply_document(
|
|
95
|
+
ctx: typer.Context,
|
|
96
|
+
path: str = typer.Option(..., "--path"),
|
|
97
|
+
document_type: str | None = typer.Option(None, "--type"),
|
|
98
|
+
set_values: list[str] | None = typer.Option(None, "--set"),
|
|
99
|
+
body_file: Path | None = typer.Option(None, "--body-file"),
|
|
100
|
+
append_section: str | None = typer.Option(None, "--append-section"),
|
|
101
|
+
replace_body: bool = typer.Option(False, "--replace-body"),
|
|
102
|
+
expected_hash: str | None = typer.Option(None, "--expected-hash"),
|
|
103
|
+
confirm: bool = typer.Option(False, "--confirm"),
|
|
104
|
+
) -> None:
|
|
105
|
+
"""预览或应用一篇 Profile 合法文档的创建与补丁。"""
|
|
106
|
+
body = body_file.read_text(encoding="utf-8") if body_file else None
|
|
107
|
+
invoke(
|
|
108
|
+
lambda: service(ctx).apply(
|
|
109
|
+
DocumentApplyRequest(
|
|
110
|
+
path=path,
|
|
111
|
+
document_type=document_type,
|
|
112
|
+
values=parse_values(set_values or []),
|
|
113
|
+
body=body,
|
|
114
|
+
append_section=append_section,
|
|
115
|
+
replace_body=replace_body,
|
|
116
|
+
expected_hash=expected_hash,
|
|
117
|
+
confirm=confirm,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@document_cli.command("move")
|
|
124
|
+
def move_document(
|
|
125
|
+
ctx: typer.Context,
|
|
126
|
+
source: str = typer.Option(..., "--from"),
|
|
127
|
+
target: str = typer.Option(..., "--to"),
|
|
128
|
+
set_values: list[str] | None = typer.Option(None, "--set"),
|
|
129
|
+
unset_fields: list[str] | None = typer.Option(None, "--unset"),
|
|
130
|
+
expected_hash: str | None = typer.Option(None, "--expected-hash"),
|
|
131
|
+
confirm: bool = typer.Option(False, "--confirm"),
|
|
132
|
+
) -> None:
|
|
133
|
+
"""预览或移动一篇文档,并按目标 Domain 契约更新归属与引用。"""
|
|
134
|
+
invoke(
|
|
135
|
+
lambda: service(ctx).move(
|
|
136
|
+
source,
|
|
137
|
+
target,
|
|
138
|
+
values=parse_values(set_values or []),
|
|
139
|
+
unset_fields=tuple(unset_fields or []),
|
|
140
|
+
expected_hash=expected_hash,
|
|
141
|
+
confirm=confirm,
|
|
142
|
+
)
|
|
143
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Typed document application contracts."""
|
|
2
|
+
|
|
3
|
+
from campfire_cli.app.document.schema.document_schema import (
|
|
4
|
+
DocumentApplyRequest,
|
|
5
|
+
DocumentApplyResult,
|
|
6
|
+
DocumentMoveResult,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"DocumentApplyRequest",
|
|
11
|
+
"DocumentApplyResult",
|
|
12
|
+
"DocumentMoveResult",
|
|
13
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from campfire_cli.app.base.schema.operation_schema import CommandFollowUp
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DocumentApplyRequest(BaseModel):
|
|
11
|
+
path: str
|
|
12
|
+
document_type: str | None = None
|
|
13
|
+
values: dict[str, Any] = Field(default_factory=dict)
|
|
14
|
+
body: str | None = None
|
|
15
|
+
append_section: str | None = None
|
|
16
|
+
replace_body: bool = False
|
|
17
|
+
expected_hash: str | None = None
|
|
18
|
+
confirm: bool = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DocumentApplyResult(BaseModel):
|
|
22
|
+
status: Literal["planned", "needs-input", "blocked", "applied"]
|
|
23
|
+
workspace_id: str
|
|
24
|
+
action: Literal["create", "update"]
|
|
25
|
+
path: str
|
|
26
|
+
profile: str
|
|
27
|
+
expected_hash: str
|
|
28
|
+
write_performed: bool = False
|
|
29
|
+
issues: list[dict[str, Any]] = Field(default_factory=list)
|
|
30
|
+
missing_fields: list[str] = Field(default_factory=list)
|
|
31
|
+
follow_up: list[CommandFollowUp] = Field(default_factory=list)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DocumentMoveResult(BaseModel):
|
|
35
|
+
status: Literal["ready", "needs-input", "blocked", "moved"]
|
|
36
|
+
workspace_id: str
|
|
37
|
+
source: str
|
|
38
|
+
target: str
|
|
39
|
+
expected_hash: str
|
|
40
|
+
source_domain: str | None = None
|
|
41
|
+
target_domain: str | None = None
|
|
42
|
+
profile: str | None = None
|
|
43
|
+
write_performed: bool = False
|
|
44
|
+
updated_references: list[str] = Field(default_factory=list)
|
|
45
|
+
frontmatter_changes: dict[str, Any] = Field(default_factory=dict)
|
|
46
|
+
issues: list[dict[str, Any]] = Field(default_factory=list)
|
|
47
|
+
missing_fields: list[str] = Field(default_factory=list)
|
|
48
|
+
follow_up: list[CommandFollowUp] = Field(default_factory=list)
|