grain-kit 0.2.0__tar.gz → 0.3.1__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.
- {grain_kit-0.2.0/src/grain_kit.egg-info → grain_kit-0.3.1}/PKG-INFO +146 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/README.md +141 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/pyproject.toml +6 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/manifest.py +104 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/__init__.py +145 -1
- grain_kit-0.3.1/src/grain/cli/archive.py +233 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/context.py +21 -0
- grain_kit-0.3.1/src/grain/cli/docs.py +192 -0
- grain_kit-0.3.1/src/grain/cli/doctor.py +107 -0
- grain_kit-0.3.1/src/grain/cli/hooks.py +132 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/init.py +9 -1
- grain_kit-0.3.1/src/grain/cli/mcp.py +44 -0
- grain_kit-0.3.1/src/grain/cli/notes.py +151 -0
- grain_kit-0.3.1/src/grain/cli/office.py +291 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/phase.py +3 -2
- grain_kit-0.3.1/src/grain/cli/status.py +292 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/task.py +109 -6
- grain_kit-0.3.1/src/grain/cli/tui.py +19 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/upgrade.py +35 -5
- grain_kit-0.3.1/src/grain/cli/verify.py +135 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/workflow.py +151 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/task.execute.md +1 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.close.md +5 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.next_and_implement.md +3 -0
- grain_kit-0.3.1/src/grain/data/prompts/workflow.resume.md +84 -0
- grain_kit-0.3.1/src/grain/data/runtime/CHANGELOG.md +19 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/PROJECT_RULES.md +33 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/adapter_profiles.md +201 -0
- grain_kit-0.3.1/src/grain/data/runtime/architecture.md +19 -0
- grain_kit-0.3.1/src/grain/data/runtime/backlog.md +19 -0
- grain_kit-0.3.1/src/grain/data/runtime/change_proposals.md +30 -0
- grain_kit-0.3.1/src/grain/data/runtime/current_focus.md +17 -0
- grain_kit-0.3.1/src/grain/data/runtime/current_task_template.md +7 -0
- grain_kit-0.3.1/src/grain/data/runtime/decisions.md +25 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/docs_manifest.yaml +72 -1
- grain_kit-0.3.1/src/grain/data/runtime/landscape_canonical.md +14 -0
- grain_kit-0.3.1/src/grain/data/runtime/landscape_working.md +13 -0
- grain_kit-0.3.1/src/grain/data/runtime/open_questions.md +35 -0
- grain_kit-0.3.1/src/grain/data/runtime/product_scope.md +19 -0
- grain_kit-0.3.1/src/grain/data/runtime/roadmap.md +16 -0
- grain_kit-0.3.1/src/grain/data/runtime/workflow_metrics.md +30 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/__init__.py +20 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/documents.py +1 -1
- grain_kit-0.3.1/src/grain/domain/office_writes.py +111 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/workflow.py +8 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/agents_md_service.py +22 -13
- grain_kit-0.3.1/src/grain/services/archive_service.py +495 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/context_service.py +319 -3
- grain_kit-0.3.1/src/grain/services/docs_audit_service.py +1002 -0
- grain_kit-0.3.1/src/grain/services/doctor_service.py +194 -0
- grain_kit-0.3.1/src/grain/services/docx_write_service.py +153 -0
- grain_kit-0.3.1/src/grain/services/guard_service.py +442 -0
- grain_kit-0.3.1/src/grain/services/hooks_service.py +194 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/impact_ranking_service.py +1 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/init_service.py +26 -0
- grain_kit-0.3.1/src/grain/services/mcp_service.py +269 -0
- grain_kit-0.3.1/src/grain/services/office_artifact_review_service.py +196 -0
- grain_kit-0.3.1/src/grain/services/office_write_service.py +82 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/phase_close_service.py +20 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/reconcile_service.py +1 -1
- grain_kit-0.3.1/src/grain/services/spreadsheet_write_service.py +112 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/task_advice_service.py +1 -1
- grain_kit-0.3.1/src/grain/services/task_observability_service.py +112 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/upgrade_service.py +108 -0
- grain_kit-0.3.1/src/grain/services/verification_service.py +460 -0
- grain_kit-0.3.1/src/grain/services/workflow_diagnostics_service.py +248 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/workflow_loop_service.py +8 -5
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/workflow_run_service.py +129 -3
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/workflow_service.py +331 -47
- grain_kit-0.3.1/src/grain/templates/__init__.py +0 -0
- grain_kit-0.3.1/src/grain/tui/__init__.py +23 -0
- grain_kit-0.3.1/src/grain/tui/app.py +730 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/packet_validator.py +21 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1/src/grain_kit.egg-info}/PKG-INFO +146 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain_kit.egg-info/SOURCES.txt +54 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain_kit.egg-info/requires.txt +5 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_config_loader.py +23 -0
- grain_kit-0.3.1/tests/test_archive_cmd.py +388 -0
- grain_kit-0.3.1/tests/test_branch_policy.py +337 -0
- grain_kit-0.3.1/tests/test_cli_ergonomics.py +296 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_closure_validation.py +18 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_command_groups.py +3 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_build_cmd.py +20 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_export_cmd.py +2 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_doc_existence_validator.py +0 -1
- grain_kit-0.3.1/tests/test_docs_audit_cmd.py +595 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_docs_index_cmd.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_docs_validate_cmd.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_document_adapters_integration.py +271 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_document_registry.py +1 -2
- grain_kit-0.3.1/tests/test_docx_write_service.py +140 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_error_handler.py +0 -3
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_filesystem_adapter.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_impact_ranking_service.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_init_service.py +73 -2
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_manifest_loader.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_manifest_validator.py +0 -1
- grain_kit-0.3.1/tests/test_mcp_cmd.py +173 -0
- grain_kit-0.3.1/tests/test_office_artifact_review_service.py +149 -0
- grain_kit-0.3.1/tests/test_office_cmd.py +261 -0
- grain_kit-0.3.1/tests/test_office_write_service.py +156 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_packet_file_validation.py +20 -4
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_packet_status.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase15_integration.py +3 -3
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase_archive_cmd.py +1 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_prompt_show_cmd.py +19 -6
- grain_kit-0.3.1/tests/test_release_surface.py +124 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_runner_integration.py +5 -5
- grain_kit-0.3.1/tests/test_spreadsheet_write_service.py +150 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_close_cmd.py +30 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_create_dir.py +0 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_id.py +0 -2
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_next_cmd.py +1 -1
- grain_kit-0.3.1/tests/test_task_observe_cmd.py +134 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_template_loader.py +0 -1
- grain_kit-0.3.1/tests/test_tui_cmd.py +524 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_upgrade_cmd.py +62 -1
- grain_kit-0.3.1/tests/test_upgrade_enforcement.py +339 -0
- grain_kit-0.3.1/tests/test_verify_submit_cmd.py +248 -0
- grain_kit-0.3.1/tests/test_workflow_explain_cmd.py +130 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_loop_cmd.py +8 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_next_cmd.py +58 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_run_cmd.py +57 -1
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_state_service.py +148 -7
- grain_kit-0.2.0/src/grain/cli/docs.py +0 -89
- grain_kit-0.2.0/src/grain/data/runtime/workflow_metrics.md +0 -3
- grain_kit-0.2.0/tests/test_release_surface.py +0 -43
- {grain_kit-0.2.0 → grain_kit-0.3.1}/LICENSE +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/setup.cfg +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/__init__.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/__init__.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/adapter_config.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/capabilities.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/export.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/filesystem.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/adapters/model_config.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/adapter.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/embedding.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/error_handler.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/model.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/onboard.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/orchestrate.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/output.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/prompt.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/cli/review.py +0 -0
- {grain_kit-0.2.0/src/grain/services → grain_kit-0.3.1/src/grain/contracts}/__init__.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/README.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/close.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/context.build.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/context.export.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/context.show.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/docs.canonical.generate.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/docs.change.apply.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/docs.working.generate.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/docs.working.reconcile.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/execute.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/feature.classify.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/model.escalate.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/model.select.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/model.show.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/open_questions.resolve.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.close.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.plan.next.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.replan.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.review.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.review_and_close.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.tasks.generate.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/phase.tasks.seed.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/project.health.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/review.check.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/review.handoff.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/review.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/review.summary.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/task.close.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/task.plan.next.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/task.review.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.implement.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.packet.first.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.packet.next.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.packet.phase.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.plan.next.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.review.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/tasks.validate.packet.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/workflow.init.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/workflow.onboard.existing.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/prompts/workflow.onboard.new.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/agent_profiles.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/context_loading.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/docs_index.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/implementation_plan.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/tooling_notes.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/runtime/workflow_loop.yaml +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/context.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/deliverable_spec.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/handoff.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/plan.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/results.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/task.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/data/templates/tasks/task_packet.md +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/adapters.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/completion_policy.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/context.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/embedding.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/errors.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/onboard.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/orchestrator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/packets.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/ranking.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/review_bundle.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/routing.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/scan_result.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/domain/workflow_loop.py +0 -0
- {grain_kit-0.2.0/src/grain/templates → grain_kit-0.3.1/src/grain/services}/__init__.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/adapter_install_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/adapter_package_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/bm25_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/codebase_scanner.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/data_artifact_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/docs_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/docs_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/embedding_resolver.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/embedding_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/graph_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/handoff_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/local_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/model_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/notebook_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/ollama_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/onboard_doc_generator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/onboard_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/openai_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/orchestration_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/pdf_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/phase_archive_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/prompt_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/ranking_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/review_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/spreadsheet_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/structural_intelligence_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/task_prepare_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/task_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/services/workflow_loop_config_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/templates/loader.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/__init__.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/authority_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/doc_existence_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/manifest_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain/validators/orchestrator_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain_kit.egg-info/dependency_links.txt +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain_kit.egg-info/entry_points.txt +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/src/grain_kit.egg-info/top_level.txt +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_capability.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_context.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_domain.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_install_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_loading.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_adapter_package_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_agents_md_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_authority_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_bm25_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_bump_version_script.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_canonical_doc_selection.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_cli_entrypoint.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_codebase_scanner.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_build.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_bundle.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_export.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_show_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_context_sources.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_data_artifact_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_docs_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_docs_show_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_embedding_domain.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_embedding_resolver.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_embedding_show_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_grain_config.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_graph_adapter_capability.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_graph_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_handoff_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_help_ergonomics.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_imports.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_local_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_config_loader.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_escalate_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_routing.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_select_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_model_show_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_notebook_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_ollama_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_onboard_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_onboard_doc_generator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_openai_provider.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_orchestrate_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_orchestration_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_orchestration_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_orchestrator_domain.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_orchestrator_validator.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_output_formatter.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_pdf_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase10_integration_pipeline.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase13_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase16_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase17_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase18_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase19_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase19_registry_ci_docs.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase19_registry_scaffold.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase5_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase7_integration.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase_close_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_phase_next_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_ranking_domain.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_ranking_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_review_check_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_review_handoff_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_review_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_review_summary_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_smoke.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_spreadsheet_extractor.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_structural_intelligence_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_advice_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_create_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_lifecycle.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_list_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_prepare_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_show_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_status_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_task_validate_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_loop_config_service.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_onboard_existing_prompt.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_workflow_reconcile_cmd.py +0 -0
- {grain_kit-0.2.0 → grain_kit-0.3.1}/tests/test_working_doc_selection.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: grain-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: CLI-first workflow toolkit for structured AI-assisted software development.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/Diwata-Labs/Grain
|
|
@@ -22,11 +22,15 @@ License-File: LICENSE
|
|
|
22
22
|
Requires-Dist: click>=8.1
|
|
23
23
|
Requires-Dist: PyYAML>=6.0
|
|
24
24
|
Requires-Dist: networkx>=3.3
|
|
25
|
+
Requires-Dist: textual>=0.67
|
|
25
26
|
Requires-Dist: tree-sitter>=0.25.2
|
|
26
27
|
Requires-Dist: tree-sitter-language-pack>=0.13.0
|
|
27
28
|
Requires-Dist: openpyxl>=3.1
|
|
28
29
|
Requires-Dist: python-docx>=1.1
|
|
29
30
|
Requires-Dist: pdfplumber>=0.11
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
30
34
|
Provides-Extra: release
|
|
31
35
|
Requires-Dist: build>=1.4.3; extra == "release"
|
|
32
36
|
Requires-Dist: twine>=5.1; extra == "release"
|
|
@@ -235,6 +239,87 @@ In practice, the agent should use Grain as the workflow layer for the repository
|
|
|
235
239
|
The CLI is the delivery surface.
|
|
236
240
|
The product value is the workflow structure it gives the agent.
|
|
237
241
|
|
|
242
|
+
### Codex and CLI-first usage
|
|
243
|
+
|
|
244
|
+
For Codex or any environment that can invoke local commands directly, the canonical integration path is still the Grain CLI.
|
|
245
|
+
|
|
246
|
+
Preferred operating pattern:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
grain --format json workflow next
|
|
250
|
+
grain prompt show --format json
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Use JSON output when the calling environment wants structured state.
|
|
254
|
+
Use text output when a human operator is driving the loop directly.
|
|
255
|
+
|
|
256
|
+
For Codex-style usage:
|
|
257
|
+
- call `grain` commands directly
|
|
258
|
+
- prefer `grain workflow next` to decide the next legal state transition
|
|
259
|
+
- use `grain prompt show` to surface the stable prompt entrypoint
|
|
260
|
+
- keep task execution packet-first and file-backed
|
|
261
|
+
- treat `grain mcp` as optional, not required
|
|
262
|
+
|
|
263
|
+
### Claude Desktop and MCP-style usage
|
|
264
|
+
|
|
265
|
+
For desktop clients that prefer MCP tools over direct CLI execution, use the local MCP wrapper:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
grain --format json mcp manifest
|
|
269
|
+
grain mcp serve
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Current intent:
|
|
273
|
+
- Codex/tool-execution path: direct CLI
|
|
274
|
+
- Claude/Desktop-style path: local stdio MCP wrapper over the same Grain services
|
|
275
|
+
- both paths preserve the same workflow rules and packet-first boundaries
|
|
276
|
+
|
|
277
|
+
### Assay verification loop
|
|
278
|
+
|
|
279
|
+
Phase 28 adds the first packet-local verification bridge for Assay-backed review.
|
|
280
|
+
|
|
281
|
+
Current commands:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
grain verify submit --id TASK-0001
|
|
285
|
+
grain verify status --verification-id VERIFY-0001-001
|
|
286
|
+
grain verify ingest --verification-id VERIFY-0001-001 --payload payload.json
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Operator rules for this slice:
|
|
290
|
+
- submit verification only after the packet has `results.md` and is in `review` or `done`
|
|
291
|
+
- treat `verification_request.json` and `verification_result.json` as packet-local workflow artifacts
|
|
292
|
+
- do not close a task while verification is `pending`
|
|
293
|
+
- if verification is `failed`, resolve the findings or explicitly waive verification before closure
|
|
294
|
+
- keep the loop file-backed: Assay can produce the payload elsewhere, but Grain only reads and records the packet-local artifacts
|
|
295
|
+
|
|
296
|
+
### Obsidian vault usage
|
|
297
|
+
|
|
298
|
+
For Obsidian vault work, keep the CLI and packet workflow canonical:
|
|
299
|
+
|
|
300
|
+
- declare `obsidian_adapter` on the active packet when the task is about vault notes
|
|
301
|
+
- let `grain context build` and the normal workflow loop assemble context from the target note and nearby wiki-linked notes
|
|
302
|
+
- treat `.obsidian/` config as secondary context unless the task is explicitly about vault settings
|
|
303
|
+
- use the local MCP wrapper only as a desktop invocation surface; it does not replace the Grain workflow rules
|
|
304
|
+
|
|
305
|
+
### Database workflow usage
|
|
306
|
+
|
|
307
|
+
For database work, keep the same packet-first and local-first posture:
|
|
308
|
+
|
|
309
|
+
- declare `database_adapter` on the active packet when the task is about schema, migrations, queries, or persistence layers
|
|
310
|
+
- let `grain context build` assemble focused schema, migration, query, and repository context instead of loading broad app code by default
|
|
311
|
+
- review destructive migration risk, rollback expectations, and schema/query drift before closing the task
|
|
312
|
+
- treat database execution or live mutation tooling as separate future work; the current `v0.3.0` slice is about context, review, and validation guidance
|
|
313
|
+
|
|
314
|
+
### Crawler workflow usage
|
|
315
|
+
|
|
316
|
+
For crawler work, keep the same packet-first and local-first posture:
|
|
317
|
+
|
|
318
|
+
- declare `crawler_adapter` on the active packet when the task is about crawl configs, selectors, extraction schemas, or output validation
|
|
319
|
+
- let `grain context build` assemble focused crawl, selector, extraction, and validation context instead of loading broad app code by default
|
|
320
|
+
- review robots constraints, rate limits, retry policy risk, selector brittleness, and extraction drift before closing the task
|
|
321
|
+
- treat broad crawl execution or live scraping automation as separate future work; the current `v0.3.0` slice is about context, review, and validation guidance
|
|
322
|
+
|
|
238
323
|
Example instruction for an agent:
|
|
239
324
|
|
|
240
325
|
```text
|
|
@@ -257,6 +342,8 @@ Your role is to execute work through Grain's state-driven workflow.
|
|
|
257
342
|
|
|
258
343
|
Rules:
|
|
259
344
|
- Run `grain workflow next` before deciding what to do.
|
|
345
|
+
- If Grain stops or the repo state looks inconsistent, run `grain workflow explain` before improvising.
|
|
346
|
+
- If the explanation points to drift, run `grain workflow reconcile --dry-run` before making manual repairs.
|
|
260
347
|
- Run `grain prompt show` before executing the next step.
|
|
261
348
|
- Follow the recommended prompt exactly.
|
|
262
349
|
- Work on only one active task packet at a time.
|
|
@@ -293,11 +380,20 @@ Typical commands:
|
|
|
293
380
|
|
|
294
381
|
```bash
|
|
295
382
|
grain workflow next
|
|
383
|
+
grain workflow explain
|
|
384
|
+
grain workflow reconcile --dry-run
|
|
296
385
|
grain prompt show
|
|
297
386
|
grain review check --id TASK-0001
|
|
298
387
|
grain task close --id TASK-0001
|
|
388
|
+
grain tui
|
|
299
389
|
```
|
|
300
390
|
|
|
391
|
+
When Grain stops:
|
|
392
|
+
|
|
393
|
+
- use `grain workflow explain` to translate the current gate into concrete operator actions
|
|
394
|
+
- use `grain workflow reconcile --dry-run` when the explanation points to packet/backlog drift
|
|
395
|
+
- return to `grain workflow next` only after the file-backed issue is repaired
|
|
396
|
+
|
|
301
397
|
If you want Grain to execute one legal state transition and stop at gates:
|
|
302
398
|
|
|
303
399
|
```bash
|
|
@@ -318,6 +414,55 @@ Grain controls:
|
|
|
318
414
|
The agent controls:
|
|
319
415
|
- executing the current step correctly
|
|
320
416
|
|
|
417
|
+
## Terminal UI
|
|
418
|
+
|
|
419
|
+
`grain tui` is the first operator shell over Grain’s existing CLI and file-backed workflow.
|
|
420
|
+
|
|
421
|
+
Current TUI surfaces:
|
|
422
|
+
- workflow dashboard and current task status
|
|
423
|
+
- phase backlog and packet artifact inspection
|
|
424
|
+
- prompt preview and compact context summary
|
|
425
|
+
- blocker detail and action feedback
|
|
426
|
+
- execute, review, and close launchers that delegate to the normal Grain workflow services
|
|
427
|
+
|
|
428
|
+
The TUI is intentionally thin:
|
|
429
|
+
- it reads the same repo files and service outputs the CLI already uses
|
|
430
|
+
- it does not maintain hidden workflow state
|
|
431
|
+
- it does not bypass review or close gates
|
|
432
|
+
|
|
433
|
+
Current deferrals:
|
|
434
|
+
- deep packet content editors
|
|
435
|
+
- full prompt-body rendering
|
|
436
|
+
- full context export rendering
|
|
437
|
+
- embedded agent terminals
|
|
438
|
+
- multi-project views
|
|
439
|
+
- broad GUI beyond the terminal shell
|
|
440
|
+
|
|
441
|
+
## Writable office artifacts
|
|
442
|
+
|
|
443
|
+
Phase 23 adds the first packet-first office mutation workflow for `.docx` and spreadsheets.
|
|
444
|
+
|
|
445
|
+
Current commands:
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
grain office docx propose --source docs/brief.docx --replace "old=new"
|
|
449
|
+
grain office docx export --source docs/brief.docx --replace "old=new"
|
|
450
|
+
grain office spreadsheet propose --source data/report.xlsx --set "Sheet1!B2=14"
|
|
451
|
+
grain office spreadsheet export --source data/report.xlsx --set "Sheet1!B2=14"
|
|
452
|
+
grain office review show --task-id TASK-0001
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Operator rules for this slice:
|
|
456
|
+
- run office commands inside an active task packet, or pass `--task-id` explicitly
|
|
457
|
+
- `.docx` and spreadsheet writes currently support `propose` and `export-as-new-file`
|
|
458
|
+
- every office command persists `office_review.json` into the packet for review inspection
|
|
459
|
+
- review the artifact summary and validator results before closing the packet
|
|
460
|
+
|
|
461
|
+
What this does not do yet:
|
|
462
|
+
- in-place `apply` for `.docx` or spreadsheets
|
|
463
|
+
- TUI-native office editors
|
|
464
|
+
- desktop/MCP office invocation layers
|
|
465
|
+
|
|
321
466
|
## Onboarding flow
|
|
322
467
|
|
|
323
468
|
Onboarding is one of the most important workflows in Grain because it gives the agent the initial structure it will follow later.
|
|
@@ -198,6 +198,87 @@ In practice, the agent should use Grain as the workflow layer for the repository
|
|
|
198
198
|
The CLI is the delivery surface.
|
|
199
199
|
The product value is the workflow structure it gives the agent.
|
|
200
200
|
|
|
201
|
+
### Codex and CLI-first usage
|
|
202
|
+
|
|
203
|
+
For Codex or any environment that can invoke local commands directly, the canonical integration path is still the Grain CLI.
|
|
204
|
+
|
|
205
|
+
Preferred operating pattern:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
grain --format json workflow next
|
|
209
|
+
grain prompt show --format json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Use JSON output when the calling environment wants structured state.
|
|
213
|
+
Use text output when a human operator is driving the loop directly.
|
|
214
|
+
|
|
215
|
+
For Codex-style usage:
|
|
216
|
+
- call `grain` commands directly
|
|
217
|
+
- prefer `grain workflow next` to decide the next legal state transition
|
|
218
|
+
- use `grain prompt show` to surface the stable prompt entrypoint
|
|
219
|
+
- keep task execution packet-first and file-backed
|
|
220
|
+
- treat `grain mcp` as optional, not required
|
|
221
|
+
|
|
222
|
+
### Claude Desktop and MCP-style usage
|
|
223
|
+
|
|
224
|
+
For desktop clients that prefer MCP tools over direct CLI execution, use the local MCP wrapper:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
grain --format json mcp manifest
|
|
228
|
+
grain mcp serve
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Current intent:
|
|
232
|
+
- Codex/tool-execution path: direct CLI
|
|
233
|
+
- Claude/Desktop-style path: local stdio MCP wrapper over the same Grain services
|
|
234
|
+
- both paths preserve the same workflow rules and packet-first boundaries
|
|
235
|
+
|
|
236
|
+
### Assay verification loop
|
|
237
|
+
|
|
238
|
+
Phase 28 adds the first packet-local verification bridge for Assay-backed review.
|
|
239
|
+
|
|
240
|
+
Current commands:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
grain verify submit --id TASK-0001
|
|
244
|
+
grain verify status --verification-id VERIFY-0001-001
|
|
245
|
+
grain verify ingest --verification-id VERIFY-0001-001 --payload payload.json
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Operator rules for this slice:
|
|
249
|
+
- submit verification only after the packet has `results.md` and is in `review` or `done`
|
|
250
|
+
- treat `verification_request.json` and `verification_result.json` as packet-local workflow artifacts
|
|
251
|
+
- do not close a task while verification is `pending`
|
|
252
|
+
- if verification is `failed`, resolve the findings or explicitly waive verification before closure
|
|
253
|
+
- keep the loop file-backed: Assay can produce the payload elsewhere, but Grain only reads and records the packet-local artifacts
|
|
254
|
+
|
|
255
|
+
### Obsidian vault usage
|
|
256
|
+
|
|
257
|
+
For Obsidian vault work, keep the CLI and packet workflow canonical:
|
|
258
|
+
|
|
259
|
+
- declare `obsidian_adapter` on the active packet when the task is about vault notes
|
|
260
|
+
- let `grain context build` and the normal workflow loop assemble context from the target note and nearby wiki-linked notes
|
|
261
|
+
- treat `.obsidian/` config as secondary context unless the task is explicitly about vault settings
|
|
262
|
+
- use the local MCP wrapper only as a desktop invocation surface; it does not replace the Grain workflow rules
|
|
263
|
+
|
|
264
|
+
### Database workflow usage
|
|
265
|
+
|
|
266
|
+
For database work, keep the same packet-first and local-first posture:
|
|
267
|
+
|
|
268
|
+
- declare `database_adapter` on the active packet when the task is about schema, migrations, queries, or persistence layers
|
|
269
|
+
- let `grain context build` assemble focused schema, migration, query, and repository context instead of loading broad app code by default
|
|
270
|
+
- review destructive migration risk, rollback expectations, and schema/query drift before closing the task
|
|
271
|
+
- treat database execution or live mutation tooling as separate future work; the current `v0.3.0` slice is about context, review, and validation guidance
|
|
272
|
+
|
|
273
|
+
### Crawler workflow usage
|
|
274
|
+
|
|
275
|
+
For crawler work, keep the same packet-first and local-first posture:
|
|
276
|
+
|
|
277
|
+
- declare `crawler_adapter` on the active packet when the task is about crawl configs, selectors, extraction schemas, or output validation
|
|
278
|
+
- let `grain context build` assemble focused crawl, selector, extraction, and validation context instead of loading broad app code by default
|
|
279
|
+
- review robots constraints, rate limits, retry policy risk, selector brittleness, and extraction drift before closing the task
|
|
280
|
+
- treat broad crawl execution or live scraping automation as separate future work; the current `v0.3.0` slice is about context, review, and validation guidance
|
|
281
|
+
|
|
201
282
|
Example instruction for an agent:
|
|
202
283
|
|
|
203
284
|
```text
|
|
@@ -220,6 +301,8 @@ Your role is to execute work through Grain's state-driven workflow.
|
|
|
220
301
|
|
|
221
302
|
Rules:
|
|
222
303
|
- Run `grain workflow next` before deciding what to do.
|
|
304
|
+
- If Grain stops or the repo state looks inconsistent, run `grain workflow explain` before improvising.
|
|
305
|
+
- If the explanation points to drift, run `grain workflow reconcile --dry-run` before making manual repairs.
|
|
223
306
|
- Run `grain prompt show` before executing the next step.
|
|
224
307
|
- Follow the recommended prompt exactly.
|
|
225
308
|
- Work on only one active task packet at a time.
|
|
@@ -256,11 +339,20 @@ Typical commands:
|
|
|
256
339
|
|
|
257
340
|
```bash
|
|
258
341
|
grain workflow next
|
|
342
|
+
grain workflow explain
|
|
343
|
+
grain workflow reconcile --dry-run
|
|
259
344
|
grain prompt show
|
|
260
345
|
grain review check --id TASK-0001
|
|
261
346
|
grain task close --id TASK-0001
|
|
347
|
+
grain tui
|
|
262
348
|
```
|
|
263
349
|
|
|
350
|
+
When Grain stops:
|
|
351
|
+
|
|
352
|
+
- use `grain workflow explain` to translate the current gate into concrete operator actions
|
|
353
|
+
- use `grain workflow reconcile --dry-run` when the explanation points to packet/backlog drift
|
|
354
|
+
- return to `grain workflow next` only after the file-backed issue is repaired
|
|
355
|
+
|
|
264
356
|
If you want Grain to execute one legal state transition and stop at gates:
|
|
265
357
|
|
|
266
358
|
```bash
|
|
@@ -281,6 +373,55 @@ Grain controls:
|
|
|
281
373
|
The agent controls:
|
|
282
374
|
- executing the current step correctly
|
|
283
375
|
|
|
376
|
+
## Terminal UI
|
|
377
|
+
|
|
378
|
+
`grain tui` is the first operator shell over Grain’s existing CLI and file-backed workflow.
|
|
379
|
+
|
|
380
|
+
Current TUI surfaces:
|
|
381
|
+
- workflow dashboard and current task status
|
|
382
|
+
- phase backlog and packet artifact inspection
|
|
383
|
+
- prompt preview and compact context summary
|
|
384
|
+
- blocker detail and action feedback
|
|
385
|
+
- execute, review, and close launchers that delegate to the normal Grain workflow services
|
|
386
|
+
|
|
387
|
+
The TUI is intentionally thin:
|
|
388
|
+
- it reads the same repo files and service outputs the CLI already uses
|
|
389
|
+
- it does not maintain hidden workflow state
|
|
390
|
+
- it does not bypass review or close gates
|
|
391
|
+
|
|
392
|
+
Current deferrals:
|
|
393
|
+
- deep packet content editors
|
|
394
|
+
- full prompt-body rendering
|
|
395
|
+
- full context export rendering
|
|
396
|
+
- embedded agent terminals
|
|
397
|
+
- multi-project views
|
|
398
|
+
- broad GUI beyond the terminal shell
|
|
399
|
+
|
|
400
|
+
## Writable office artifacts
|
|
401
|
+
|
|
402
|
+
Phase 23 adds the first packet-first office mutation workflow for `.docx` and spreadsheets.
|
|
403
|
+
|
|
404
|
+
Current commands:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
grain office docx propose --source docs/brief.docx --replace "old=new"
|
|
408
|
+
grain office docx export --source docs/brief.docx --replace "old=new"
|
|
409
|
+
grain office spreadsheet propose --source data/report.xlsx --set "Sheet1!B2=14"
|
|
410
|
+
grain office spreadsheet export --source data/report.xlsx --set "Sheet1!B2=14"
|
|
411
|
+
grain office review show --task-id TASK-0001
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Operator rules for this slice:
|
|
415
|
+
- run office commands inside an active task packet, or pass `--task-id` explicitly
|
|
416
|
+
- `.docx` and spreadsheet writes currently support `propose` and `export-as-new-file`
|
|
417
|
+
- every office command persists `office_review.json` into the packet for review inspection
|
|
418
|
+
- review the artifact summary and validator results before closing the packet
|
|
419
|
+
|
|
420
|
+
What this does not do yet:
|
|
421
|
+
- in-place `apply` for `.docx` or spreadsheets
|
|
422
|
+
- TUI-native office editors
|
|
423
|
+
- desktop/MCP office invocation layers
|
|
424
|
+
|
|
284
425
|
## Onboarding flow
|
|
285
426
|
|
|
286
427
|
Onboarding is one of the most important workflows in Grain because it gives the agent the initial structure it will follow later.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "grain-kit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "CLI-first workflow toolkit for structured AI-assisted software development."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -31,6 +31,7 @@ dependencies = [
|
|
|
31
31
|
"click>=8.1",
|
|
32
32
|
"PyYAML>=6.0",
|
|
33
33
|
"networkx>=3.3",
|
|
34
|
+
"textual>=0.67",
|
|
34
35
|
"tree-sitter>=0.25.2",
|
|
35
36
|
"tree-sitter-language-pack>=0.13.0",
|
|
36
37
|
"openpyxl>=3.1",
|
|
@@ -42,6 +43,10 @@ dependencies = [
|
|
|
42
43
|
grain = "grain.cli:cli"
|
|
43
44
|
|
|
44
45
|
[project.optional-dependencies]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=8.0",
|
|
48
|
+
"ruff>=0.4",
|
|
49
|
+
]
|
|
45
50
|
release = [
|
|
46
51
|
"build>=1.4.3",
|
|
47
52
|
"twine>=5.1",
|
|
@@ -98,6 +98,110 @@ def load_grain_config(root: Path) -> GrainConfig:
|
|
|
98
98
|
)
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
@dataclass
|
|
102
|
+
class UpgradePolicy:
|
|
103
|
+
"""upgrade_policy block from docs_manifest.yaml."""
|
|
104
|
+
|
|
105
|
+
min_version: str = ""
|
|
106
|
+
min_version_set_at: str = ""
|
|
107
|
+
enforce: bool = False
|
|
108
|
+
enforce_after_days: int = 0
|
|
109
|
+
message: str = ""
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def load_upgrade_policy(root: Path) -> UpgradePolicy:
|
|
113
|
+
"""Read the optional ``upgrade_policy:`` block from docs_manifest.yaml.
|
|
114
|
+
|
|
115
|
+
Returns an :class:`UpgradePolicy` with defaults for any field not present.
|
|
116
|
+
Never raises.
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
manifest = load_manifest(root)
|
|
120
|
+
except Exception:
|
|
121
|
+
return UpgradePolicy()
|
|
122
|
+
|
|
123
|
+
raw = manifest.get("upgrade_policy")
|
|
124
|
+
if not isinstance(raw, dict):
|
|
125
|
+
return UpgradePolicy()
|
|
126
|
+
|
|
127
|
+
def _str(key: str) -> str:
|
|
128
|
+
val = raw.get(key, "")
|
|
129
|
+
return str(val).strip() if val is not None else ""
|
|
130
|
+
|
|
131
|
+
def _bool_val(key: str) -> bool:
|
|
132
|
+
val = raw.get(key, False)
|
|
133
|
+
return val if isinstance(val, bool) else False
|
|
134
|
+
|
|
135
|
+
def _int_val(key: str) -> int:
|
|
136
|
+
val = raw.get(key, 0)
|
|
137
|
+
try:
|
|
138
|
+
return int(val)
|
|
139
|
+
except (TypeError, ValueError):
|
|
140
|
+
return 0
|
|
141
|
+
|
|
142
|
+
return UpgradePolicy(
|
|
143
|
+
min_version=_str("min_version"),
|
|
144
|
+
min_version_set_at=_str("min_version_set_at"),
|
|
145
|
+
enforce=_bool_val("enforce"),
|
|
146
|
+
enforce_after_days=_int_val("enforce_after_days"),
|
|
147
|
+
message=_str("message"),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@dataclass
|
|
152
|
+
class BranchPolicy:
|
|
153
|
+
"""branch_policy block from docs_manifest.yaml."""
|
|
154
|
+
|
|
155
|
+
mode: str = "off" # "phase" | "task" | "off"
|
|
156
|
+
pattern: str = "" # optional override; empty = use mode default
|
|
157
|
+
enforce: bool = False
|
|
158
|
+
enforce_after_days: int = 0
|
|
159
|
+
message: str = ""
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def load_branch_policy(root: Path) -> BranchPolicy:
|
|
163
|
+
"""Read the optional ``branch_policy:`` block from docs_manifest.yaml.
|
|
164
|
+
|
|
165
|
+
Returns a :class:`BranchPolicy` with defaults (mode: off) for any field not present.
|
|
166
|
+
Never raises.
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
manifest = load_manifest(root)
|
|
170
|
+
except Exception:
|
|
171
|
+
return BranchPolicy()
|
|
172
|
+
|
|
173
|
+
raw = manifest.get("branch_policy")
|
|
174
|
+
if not isinstance(raw, dict):
|
|
175
|
+
return BranchPolicy()
|
|
176
|
+
|
|
177
|
+
def _str(key: str, default: str = "") -> str:
|
|
178
|
+
val = raw.get(key, default)
|
|
179
|
+
return str(val).strip() if val is not None else default
|
|
180
|
+
|
|
181
|
+
def _bool_val(key: str) -> bool:
|
|
182
|
+
val = raw.get(key, False)
|
|
183
|
+
return val if isinstance(val, bool) else False
|
|
184
|
+
|
|
185
|
+
def _int_val(key: str) -> int:
|
|
186
|
+
val = raw.get(key, 0)
|
|
187
|
+
try:
|
|
188
|
+
return int(val)
|
|
189
|
+
except (TypeError, ValueError):
|
|
190
|
+
return 0
|
|
191
|
+
|
|
192
|
+
mode = _str("mode", "off")
|
|
193
|
+
if mode not in {"phase", "task", "off"}:
|
|
194
|
+
mode = "off"
|
|
195
|
+
|
|
196
|
+
return BranchPolicy(
|
|
197
|
+
mode=mode,
|
|
198
|
+
pattern=_str("pattern"),
|
|
199
|
+
enforce=_bool_val("enforce"),
|
|
200
|
+
enforce_after_days=_int_val("enforce_after_days"),
|
|
201
|
+
message=_str("message"),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
101
205
|
def load_completion_policy(root: Path) -> CompletionPolicy:
|
|
102
206
|
try:
|
|
103
207
|
manifest = load_manifest(root)
|