@khoavu882/doflow 0.0.0-stage → 2.0.0-beta.4
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.
- package/LICENSE +21 -0
- package/README.md +132 -2
- package/bin/doflow.js +44 -0
- package/core/.antigravity-plugin/hooks.json +39 -0
- package/core/.antigravity-plugin/mcp_config.json +18 -0
- package/core/.antigravity-plugin/plugin.json +31 -0
- package/core/.claude-plugin/marketplace.json +20 -0
- package/core/.claude-plugin/plugin.json +21 -0
- package/core/.codex-plugin/marketplace.json +20 -0
- package/core/.codex-plugin/plugin.json +35 -0
- package/core/.plugin/plugin.json +19 -0
- package/core/harnesses/antigravity/hooks/pre-implementation-gate.sh +9 -0
- package/core/harnesses/antigravity/hooks/stop-check.sh +10 -0
- package/core/harnesses/claude/hooks/lib.sh +304 -0
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +20 -0
- package/core/harnesses/claude/hooks/permission-audit.sh +47 -0
- package/core/harnesses/claude/hooks/post-compact.sh +74 -0
- package/core/harnesses/claude/hooks/post-edit-lint.sh +36 -0
- package/core/harnesses/claude/hooks/post-tool-failure.sh +47 -0
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +20 -0
- package/core/harnesses/claude/hooks/pre-compact.sh +43 -0
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +21 -0
- package/core/harnesses/claude/hooks/session-end.sh +89 -0
- package/core/harnesses/claude/hooks/session-start.sh +5 -0
- package/core/harnesses/claude/hooks/skill-config-audit.sh +39 -0
- package/core/harnesses/claude/hooks/stop-check.sh +5 -0
- package/core/harnesses/claude/hooks/subagent-audit.sh +7 -0
- package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -0
- package/core/harnesses/claude/settings/keybindings.json +20 -0
- package/core/harnesses/claude/settings/settings.json +201 -0
- package/core/harnesses/claude/statusline/doflow-statusline.sh +49 -0
- package/core/harnesses/codex/agents/core-implementer.toml +7 -0
- package/core/harnesses/codex/agents/quality-guardian.toml +8 -0
- package/core/harnesses/codex/agents/research-writer.toml +8 -0
- package/core/harnesses/codex/agents/spec-analyst.toml +8 -0
- package/core/harnesses/codex/agents/system-architect.toml +9 -0
- package/core/harnesses/codex/config/config.toml +10 -0
- package/core/harnesses/codex/hooks/hooks.json +122 -0
- package/core/harnesses/codex/hooks/lib.sh +335 -0
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +18 -0
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +52 -0
- package/core/harnesses/codex/hooks/post-edit-lint.sh +6 -0
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +18 -0
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +46 -0
- package/core/harnesses/codex/hooks/pre-compact.sh +9 -0
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +19 -0
- package/core/harnesses/codex/hooks/session-end.impl.sh +92 -0
- package/core/harnesses/codex/hooks/session-end.sh +5 -0
- package/core/harnesses/codex/hooks/session-start.sh +5 -0
- package/core/harnesses/codex/hooks/stop-check.sh +8 -0
- package/core/harnesses/codex/hooks/subagent-audit.sh +8 -0
- package/core/harnesses/codex/hooks/user-prompt-submit.sh +6 -0
- package/core/harnesses/gemini/hooks/hooks.json +77 -0
- package/core/harnesses/gemini/hooks/lib.sh +302 -0
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +21 -0
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +39 -0
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +21 -0
- package/core/harnesses/gemini/hooks/pre-compact.sh +38 -0
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +22 -0
- package/core/harnesses/gemini/hooks/session-end.impl.sh +89 -0
- package/core/harnesses/gemini/hooks/session-end.sh +5 -0
- package/core/harnesses/gemini/hooks/session-start.sh +5 -0
- package/core/harnesses/gemini/settings/adapter-defaults.json +4 -0
- package/core/harnesses/kiro/agents/doflow.json +58 -0
- package/core/harnesses/kiro/hooks/doflow.json +53 -0
- package/core/harnesses/kiro/hooks/lib.sh +324 -0
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +9 -0
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +9 -0
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +9 -0
- package/core/harnesses/kiro/hooks/session-start.sh +9 -0
- package/core/harnesses/kiro/hooks/stop-check.sh +43 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +39 -0
- package/core/harnesses/shared/hooks/adapters/antigravity.js +111 -0
- package/core/harnesses/shared/hooks/adapters/arg-fields.js +19 -0
- package/core/harnesses/shared/hooks/adapters/gemini.js +114 -0
- package/core/harnesses/shared/hooks/hooks.json +47 -0
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +91 -0
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +97 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +29 -0
- package/core/harnesses/shared/hooks/policies/lib.sh +501 -0
- package/core/harnesses/shared/hooks/policies/mcp-policy.conf +21 -0
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +91 -0
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +328 -0
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +496 -0
- package/core/harnesses/shared/hooks/policies/prompt-nudge.jq +131 -0
- package/core/harnesses/shared/hooks/policies/session-context.sh +141 -0
- package/core/harnesses/shared/hooks/policies/stop-check.sh +264 -0
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +46 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +235 -0
- package/core/harnesses/shared/hooks/stream-hook-runner.js +590 -0
- package/core/harnesses/shared/locator/doflow-run +87 -0
- package/core/registry/advice.json +101 -0
- package/core/registry/assets.json +792 -0
- package/core/registry/capabilities.json +120 -0
- package/core/registry/contracts.json +189 -0
- package/core/registry/external-tools.json +191 -0
- package/core/registry/harnesses.json +2062 -0
- package/core/registry/lifecycle.json +231 -0
- package/core/registry/mcp.json +18 -0
- package/core/registry/models.json +79 -0
- package/core/registry/readiness-templates.json +118 -0
- package/core/registry/routes.json +47 -0
- package/core/registry/storage.json +1061 -0
- package/core/registry/verification.json +258 -0
- package/core/registry/workflows.json +790 -0
- package/core/shared/agent-specs/core-implementer.md +73 -0
- package/core/shared/agent-specs/quality-guardian.md +28 -0
- package/core/shared/agent-specs/research-writer.md +31 -0
- package/core/shared/agent-specs/spec-analyst.md +33 -0
- package/core/shared/agent-specs/system-architect.md +29 -0
- package/core/shared/guidance/DOFLOW_CORE.md +8 -0
- package/core/shared/guidance/FLAGS.md +25 -0
- package/core/shared/guidance/PRINCIPLES.md +61 -0
- package/core/shared/guidance/VERSION +1 -0
- package/core/shared/guidance/mcp/MCP_Context7.md +18 -0
- package/core/shared/guidance/mcp/MCP_Sequential.md +17 -0
- package/core/shared/guidance/modes/MODE_Brainstorming.md +46 -0
- package/core/shared/guidance/modes/MODE_DeepResearch.md +69 -0
- package/core/shared/guidance/modes/MODE_Introspection.md +33 -0
- package/core/shared/guidance/modes/MODE_Orchestration.md +57 -0
- package/core/shared/guidance/modes/MODE_Task_Management.md +74 -0
- package/core/shared/guidance/pointers/claude-gemini.md +2 -0
- package/core/shared/guidance/pointers/codex.md +6 -0
- package/core/shared/guidance/references/ARTIFACT_FORMAT.md +373 -0
- package/core/shared/guidance/references/ARTIFACT_VOICE.md +104 -0
- package/core/shared/guidance/references/CONSTITUTION_BASE.md +47 -0
- package/core/shared/guidance/references/DIAGRAM_GUIDE.md +161 -0
- package/core/shared/guidance/references/DOFLOW_CHAIN.md +87 -0
- package/core/shared/guidance/references/EVIDENCE_LEDGER.md +93 -0
- package/core/shared/guidance/references/MODEL_SELECTION.md +74 -0
- package/core/shared/guidance/references/ORCHESTRATION.md +36 -0
- package/core/shared/guidance/references/RESEARCH_CONFIG.md +21 -0
- package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +81 -0
- package/core/shared/guidance/rules/RULE_01_SAFETY.md +25 -0
- package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +23 -0
- package/core/shared/guidance/rules/RULE_03_QUALITY.md +14 -0
- package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +46 -0
- package/core/shared/scripts/doflow/assets/mermaid-theme.json +46 -0
- package/core/shared/scripts/doflow/bash/do-exec-paths.sh +167 -0
- package/core/shared/scripts/doflow/bash/do-git-state.sh +546 -0
- package/core/shared/scripts/doflow/bash/do-parallel-check.sh +208 -0
- package/core/shared/scripts/doflow/bash/do-paths.sh +347 -0
- package/core/shared/scripts/doflow/bash/do-prereqs.sh +66 -0
- package/core/shared/scripts/doflow/bash/do-review-package.sh +127 -0
- package/core/shared/scripts/doflow/bash/do-task-brief.sh +698 -0
- package/core/shared/scripts/doflow/bash/render-audit.sh +224 -0
- package/core/shared/scripts/doflow/bash/render-diagrams.sh +177 -0
- package/core/shared/scripts/doflow/bash/render-puml.sh +223 -0
- package/core/shared/scripts/doflow/bash/sync-context.sh +66 -0
- package/core/shared/scripts/doflow/bash/validate-artifacts.sh +526 -0
- package/core/shared/scripts/doflow/bin/doflow-run +592 -0
- package/core/shared/skills/do/SKILL.md +128 -0
- package/core/shared/skills/do/references/estimation.md +13 -0
- package/core/shared/skills/do/references/pm_routing.md +25 -0
- package/core/shared/skills/do/references/tool_matrix.md +52 -0
- package/core/shared/skills/do-brainstorm/SKILL.md +252 -0
- package/core/shared/skills/do-code-review/README.md +49 -0
- package/core/shared/skills/do-code-review/SKILL.md +333 -0
- package/core/shared/skills/do-code-review/assets/sample_c_clean.c +71 -0
- package/core/shared/skills/do-code-review/assets/sample_c_smells.c +66 -0
- package/core/shared/skills/do-code-review/assets/sample_cpp_shift.cpp +19 -0
- package/core/shared/skills/do-code-review/assets/sample_csharp_clean.cs +100 -0
- package/core/shared/skills/do-code-review/assets/sample_csharp_smells.cs +78 -0
- package/core/shared/skills/do-code-review/assets/sample_java_clean.java +55 -0
- package/core/shared/skills/do-code-review/assets/sample_java_smells.java +56 -0
- package/core/shared/skills/do-code-review/assets/sample_json_clean.json +7 -0
- package/core/shared/skills/do-code-review/assets/sample_markdown_clean.md +30 -0
- package/core/shared/skills/do-code-review/assets/sample_markdown_smells.md +29 -0
- package/core/shared/skills/do-code-review/assets/sample_shell_heredoc.sh +38 -0
- package/core/shared/skills/do-code-review/assets/sample_shell_smells.sh +15 -0
- package/core/shared/skills/do-code-review/assets/sample_typescript_strings.ts +36 -0
- package/core/shared/skills/do-code-review/assets/sample_yaml_smells.yaml +6 -0
- package/core/shared/skills/do-code-review/content-types/config.md +83 -0
- package/core/shared/skills/do-code-review/content-types/markdown.md +132 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_c_clean_quality.json +79 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_c_smells_quality.json +169 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_cpp_shift_quality.json +49 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_clean_quality.json +149 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_smells_quality.json +157 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_java_clean_quality.json +67 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_java_smells_quality.json +97 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_json_clean_quality.json +33 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_clean_quality.json +1 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_smells_quality.json +16 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_shell_heredoc_quality.json +54 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_shell_smells_quality.json +91 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_typescript_strings_quality.json +60 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_yaml_smells_quality.json +46 -0
- package/core/shared/skills/do-code-review/languages/c.md +103 -0
- package/core/shared/skills/do-code-review/languages/cpp.md +103 -0
- package/core/shared/skills/do-code-review/languages/csharp.md +97 -0
- package/core/shared/skills/do-code-review/languages/dart.md +108 -0
- package/core/shared/skills/do-code-review/languages/go.md +92 -0
- package/core/shared/skills/do-code-review/languages/java.md +103 -0
- package/core/shared/skills/do-code-review/languages/kotlin.md +88 -0
- package/core/shared/skills/do-code-review/languages/php.md +109 -0
- package/core/shared/skills/do-code-review/languages/python.md +94 -0
- package/core/shared/skills/do-code-review/languages/ruby.md +105 -0
- package/core/shared/skills/do-code-review/languages/rust.md +99 -0
- package/core/shared/skills/do-code-review/languages/shell.md +90 -0
- package/core/shared/skills/do-code-review/languages/swift.md +88 -0
- package/core/shared/skills/do-code-review/languages/typescript.md +97 -0
- package/core/shared/skills/do-code-review/review-policy.json +47 -0
- package/core/shared/skills/do-code-review/rules/universal.md +49 -0
- package/core/shared/skills/do-code-review/scripts/code_quality_checker.py +1696 -0
- package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +532 -0
- package/core/shared/skills/do-code-review/scripts/pr_analyzer.py +620 -0
- package/core/shared/skills/do-code-review/scripts/review_report_generator.py +505 -0
- package/core/shared/skills/do-constitution/SKILL.md +72 -0
- package/core/shared/skills/do-design/SKILL.md +212 -0
- package/core/shared/skills/do-diagnose/SKILL.md +156 -0
- package/core/shared/skills/do-diagnose/references/code_audit.md +15 -0
- package/core/shared/skills/do-diagnose/references/refactoring.md +12 -0
- package/core/shared/skills/do-diagnose/references/root_cause.md +17 -0
- package/core/shared/skills/do-document/SKILL.md +81 -0
- package/core/shared/skills/do-document/references/api-reference.md +42 -0
- package/core/shared/skills/do-document/references/deep_research.md +18 -0
- package/core/shared/skills/do-document/references/embedded-research.md +11 -0
- package/core/shared/skills/do-document/references/implementation-flow.md +105 -0
- package/core/shared/skills/do-document/references/index_generator.md +9 -0
- package/core/shared/skills/do-document/references/user-guide.md +22 -0
- package/core/shared/skills/do-execute-plan/SKILL.md +261 -0
- package/core/shared/skills/do-execute-plan/references/handoff_record.md +57 -0
- package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +92 -0
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +155 -0
- package/core/shared/skills/do-execute-plan/references/run_position.md +63 -0
- package/core/shared/skills/do-execute-plan/references/scaffold.md +441 -0
- package/core/shared/skills/do-execute-plan/references/task_attempts.md +41 -0
- package/core/shared/skills/do-flow/SKILL.md +186 -0
- package/core/shared/skills/do-flow/references/task_classes.md +134 -0
- package/core/shared/skills/do-git/SKILL.md +115 -0
- package/core/shared/skills/do-git/references/hotfix-ritual.md +44 -0
- package/core/shared/skills/do-git/references/lifecycle-policy.md +54 -0
- package/core/shared/skills/do-git/references/release-ritual.md +64 -0
- package/core/shared/skills/do-implement/SKILL.md +222 -0
- package/core/shared/skills/do-plan/SKILL.md +219 -0
- package/core/shared/skills/do-test/SKILL.md +113 -0
- package/core/shared/templates/doflow/constitution-template.md +28 -0
- package/core/shared/templates/doflow/data-model-template.md +169 -0
- package/core/shared/templates/doflow/design-template.md +193 -0
- package/core/shared/templates/doflow/external-contract-template.md +35 -0
- package/core/shared/templates/doflow/intent-template.md +45 -0
- package/core/shared/templates/doflow/plan-template.md +151 -0
- package/core/shared/templates/doflow/question-log-template.md +51 -0
- package/core/shared/templates/doflow/requirement-template.md +126 -0
- package/core/shared/templates/doflow/specs-template.md +55 -0
- package/core/shared/templates/doflow/state-template.md +59 -0
- package/core/shared/workflows/do-flow-chain.md +17 -0
- package/package.json +48 -4
- package/src/adapters/antigravity/index.js +631 -0
- package/src/adapters/claude/index.js +548 -0
- package/src/adapters/claude/mcp.js +94 -0
- package/src/adapters/codex/agents.js +208 -0
- package/src/adapters/codex/config.js +272 -0
- package/src/adapters/codex/hooks.js +203 -0
- package/src/adapters/codex/index.js +707 -0
- package/src/adapters/codex/mcp.js +271 -0
- package/src/adapters/codex/native-projection.js +34 -0
- package/src/adapters/copilot/index.js +413 -0
- package/src/adapters/copy-tree.js +620 -0
- package/src/adapters/gemini/hooks.js +210 -0
- package/src/adapters/gemini/index.js +390 -0
- package/src/adapters/hook-commands.js +60 -0
- package/src/adapters/index.js +106 -0
- package/src/adapters/kiro/index.js +310 -0
- package/src/adapters/mcp-entries.js +331 -0
- package/src/adapters/opencode/index.js +466 -0
- package/src/adapters/pi/index.js +279 -0
- package/src/adapters/pi/json-members.js +185 -0
- package/src/adapters/pi/mcp.js +373 -0
- package/src/adapters/resolve-source.js +19 -0
- package/src/cli/commands/install.js +218 -0
- package/src/cli/commands/list-backups.js +21 -0
- package/src/cli/commands/reconcile.js +120 -0
- package/src/cli/commands/remove.js +82 -0
- package/src/cli/commands/rollback.js +172 -0
- package/src/cli/commands/self-update.js +33 -0
- package/src/cli/commands/status.js +138 -0
- package/src/cli/commands/tools.js +92 -0
- package/src/cli/commands/update.js +162 -0
- package/src/cli/index.js +568 -0
- package/src/cli/runtime-commands.js +281 -0
- package/src/cli/shared.js +218 -0
- package/src/helper/bash-helper.js +34 -0
- package/src/helper/git.js +24 -0
- package/src/helper/guardrails.js +49 -0
- package/src/helper/harness-paths.js +140 -0
- package/src/helper/marker-merge.js +116 -0
- package/src/helper/prompt.js +61 -0
- package/src/helper/repo-root.js +29 -0
- package/src/helper/settings-merge.js +151 -0
- package/src/helper/settings-scope.js +33 -0
- package/src/helper/toml.js +244 -0
- package/src/install/backup-set.js +149 -0
- package/src/install/backup.js +724 -0
- package/src/install/context.js +58 -0
- package/src/install/manifest.js +145 -0
- package/src/install/mcp.js +254 -0
- package/src/install/paths.js +84 -0
- package/src/install/targets.js +90 -0
- package/src/install/tool-lifecycle.js +151 -0
- package/src/lifecycle/bash-availability.js +25 -0
- package/src/lifecycle/index.js +812 -0
- package/src/lifecycle/mcp-index.js +28 -0
- package/src/lifecycle/policies.js +73 -0
- package/src/lifecycle/view.js +175 -0
- package/src/registry/index.js +611 -0
- package/src/release/build-package.js +91 -0
- package/src/release/changelog-section.js +70 -0
- package/src/release/sync-plugin-versions.js +66 -0
- package/src/runtime/advice/cli.js +283 -0
- package/src/runtime/advice/client.js +324 -0
- package/src/runtime/advice/config.js +189 -0
- package/src/runtime/advice/doctor.js +169 -0
- package/src/runtime/advice/endpoint-guard.js +134 -0
- package/src/runtime/advice/kinds.js +154 -0
- package/src/runtime/advice/providers/ollama-systemone.js +209 -0
- package/src/runtime/advice/record.js +166 -0
- package/src/runtime/advice/registry.js +170 -0
- package/src/runtime/advice/strength.js +66 -0
- package/src/runtime/brief-tools.js +342 -0
- package/src/runtime/c4-project.js +371 -0
- package/src/runtime/capability-router.js +484 -0
- package/src/runtime/checkouts.js +170 -0
- package/src/runtime/claims.js +468 -0
- package/src/runtime/cli-result.js +55 -0
- package/src/runtime/cli.js +678 -0
- package/src/runtime/command-detect.js +516 -0
- package/src/runtime/context-pack.js +492 -0
- package/src/runtime/decision-register.js +493 -0
- package/src/runtime/evidence-ledger.js +338 -0
- package/src/runtime/failure/capture.js +272 -0
- package/src/runtime/failure/classifier.js +68 -0
- package/src/runtime/failure/cli.js +178 -0
- package/src/runtime/failure/home.js +64 -0
- package/src/runtime/failure/store.js +226 -0
- package/src/runtime/feature-resolve.js +79 -0
- package/src/runtime/freshness.js +177 -0
- package/src/runtime/health.js +863 -0
- package/src/runtime/history-compactor.js +237 -0
- package/src/runtime/implementation-gate.js +321 -0
- package/src/runtime/inventory/coverage.js +218 -0
- package/src/runtime/inventory/identity.js +65 -0
- package/src/runtime/inventory/index.js +705 -0
- package/src/runtime/inventory/precedence.js +134 -0
- package/src/runtime/inventory/read-scopes.js +131 -0
- package/src/runtime/inventory/siblings.js +192 -0
- package/src/runtime/knowledge/chunker.js +124 -0
- package/src/runtime/knowledge/hybrid.js +149 -0
- package/src/runtime/knowledge/index-store.js +145 -0
- package/src/runtime/knowledge/retrieval.js +194 -0
- package/src/runtime/leak-scan.js +185 -0
- package/src/runtime/lifecycle/cli.js +276 -0
- package/src/runtime/lifecycle/event-store.js +340 -0
- package/src/runtime/lifecycle/fold.js +353 -0
- package/src/runtime/lifecycle/followup.js +432 -0
- package/src/runtime/lifecycle/goal.js +249 -0
- package/src/runtime/lifecycle/intent-writer.js +86 -0
- package/src/runtime/lifecycle/overview.js +292 -0
- package/src/runtime/lifecycle/release.js +241 -0
- package/src/runtime/lifecycle/report-store.js +221 -0
- package/src/runtime/lifecycle/retention.js +212 -0
- package/src/runtime/lifecycle/root.js +71 -0
- package/src/runtime/lifecycle/status.js +353 -0
- package/src/runtime/lifecycle/store-upkeep.js +393 -0
- package/src/runtime/locator-resolve.js +158 -0
- package/src/runtime/mask.js +210 -0
- package/src/runtime/mcp-consultations.js +412 -0
- package/src/runtime/mcp-reach.js +157 -0
- package/src/runtime/model-router.js +153 -0
- package/src/runtime/outcome.js +467 -0
- package/src/runtime/reach.js +148 -0
- package/src/runtime/readiness-record.js +150 -0
- package/src/runtime/readiness.js +435 -0
- package/src/runtime/recovery.js +282 -0
- package/src/runtime/research-request.js +231 -0
- package/src/runtime/retrieval-plan.js +578 -0
- package/src/runtime/scaffold/artifacts.js +217 -0
- package/src/runtime/scaffold/fingerprint.js +56 -0
- package/src/runtime/scaffold/generate.js +911 -0
- package/src/runtime/scaffold/languages.js +245 -0
- package/src/runtime/storage/cli.js +64 -0
- package/src/runtime/storage/engine.js +249 -0
- package/src/runtime/storage/registry.js +130 -0
- package/src/runtime/storage/roots.js +63 -0
- package/src/runtime/storage/rules.js +282 -0
- package/src/runtime/storage/upkeep.js +243 -0
- package/src/runtime/storage/work-status.js +326 -0
- package/src/runtime/task-attempts.js +415 -0
- package/src/runtime/task-classifier.js +550 -0
- package/src/runtime/task-scope.js +130 -0
- package/src/runtime/task-state.js +176 -0
- package/src/runtime/trace/indicators.js +235 -0
- package/src/runtime/trace/ledger.js +626 -0
- package/src/runtime/trace/render.js +76 -0
- package/src/runtime/trace/views.js +459 -0
- package/src/runtime/verification/contract-runner.js +341 -0
- package/src/runtime/verification/engine.js +1461 -0
- package/src/runtime/verification/registry.js +130 -0
- package/src/runtime/verification/scope-bound.js +418 -0
- package/src/runtime/verification/test-selection.js +172 -0
- package/src/runtime/workflow-engine.js +588 -0
- package/src/runtime/workflow-orchestrator.js +953 -0
- package/src/runtime/worktree.js +340 -0
- package/src/state/index.js +193 -0
- package/src/state/lockfile.js +136 -0
- package/src/state/run-lock.js +408 -0
- package/types/node-commonjs.d.ts +68 -0
- package/types/runtime.d.ts +91 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Review Report Generator
|
|
4
|
+
|
|
5
|
+
Generates comprehensive code review reports by combining PR analysis
|
|
6
|
+
and code quality findings into structured, actionable reports.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python review_report_generator.py /path/to/repo
|
|
10
|
+
python review_report_generator.py . --pr-analysis pr_results.json --quality-analysis quality_results.json
|
|
11
|
+
python review_report_generator.py /path/to/repo --format markdown --output review.md
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Dict, List, Optional, Tuple
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Severity weights for prioritization
|
|
25
|
+
SEVERITY_WEIGHTS = {
|
|
26
|
+
"critical": 100,
|
|
27
|
+
"high": 75,
|
|
28
|
+
"medium": 50,
|
|
29
|
+
"low": 25,
|
|
30
|
+
"info": 10
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Review verdict thresholds
|
|
34
|
+
VERDICT_THRESHOLDS = {
|
|
35
|
+
"approve": {"max_critical": 0, "max_high": 0, "max_score": 100},
|
|
36
|
+
"approve_with_suggestions": {"max_critical": 0, "max_high": 2, "max_score": 85},
|
|
37
|
+
"request_changes": {"max_critical": 0, "max_high": 5, "max_score": 70},
|
|
38
|
+
"block": {"max_critical": float("inf"), "max_high": float("inf"), "max_score": 0}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def load_json_file(filepath: str) -> Optional[Dict]:
|
|
43
|
+
"""Load JSON file if it exists."""
|
|
44
|
+
try:
|
|
45
|
+
with open(filepath, "r") as f:
|
|
46
|
+
return json.load(f)
|
|
47
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def run_pr_analyzer(repo_path: Path) -> Dict:
|
|
52
|
+
"""Run pr_analyzer.py and return results."""
|
|
53
|
+
script_path = Path(__file__).parent / "pr_analyzer.py"
|
|
54
|
+
if not script_path.exists():
|
|
55
|
+
return {"status": "error", "message": "pr_analyzer.py not found"}
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
result = subprocess.run(
|
|
59
|
+
[sys.executable, str(script_path), str(repo_path), "--json"],
|
|
60
|
+
capture_output=True,
|
|
61
|
+
text=True,
|
|
62
|
+
timeout=120
|
|
63
|
+
)
|
|
64
|
+
if result.returncode == 0:
|
|
65
|
+
return json.loads(result.stdout)
|
|
66
|
+
return {"status": "error", "message": result.stderr}
|
|
67
|
+
except Exception as e:
|
|
68
|
+
return {"status": "error", "message": str(e)}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def run_quality_checker(repo_path: Path) -> Dict:
|
|
72
|
+
"""Run code_quality_checker.py and return results."""
|
|
73
|
+
script_path = Path(__file__).parent / "code_quality_checker.py"
|
|
74
|
+
if not script_path.exists():
|
|
75
|
+
return {"status": "error", "message": "code_quality_checker.py not found"}
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
result = subprocess.run(
|
|
79
|
+
[sys.executable, str(script_path), str(repo_path), "--json"],
|
|
80
|
+
capture_output=True,
|
|
81
|
+
text=True,
|
|
82
|
+
timeout=300
|
|
83
|
+
)
|
|
84
|
+
if result.returncode == 0:
|
|
85
|
+
return json.loads(result.stdout)
|
|
86
|
+
return {"status": "error", "message": result.stderr}
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return {"status": "error", "message": str(e)}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def calculate_review_score(pr_analysis: Dict, quality_analysis: Dict) -> int:
|
|
92
|
+
"""Calculate overall review score (0-100)."""
|
|
93
|
+
score = 100
|
|
94
|
+
|
|
95
|
+
# Deduct for PR risks
|
|
96
|
+
if "risks" in pr_analysis:
|
|
97
|
+
risks = pr_analysis["risks"]
|
|
98
|
+
score -= len(risks.get("critical", [])) * 15
|
|
99
|
+
score -= len(risks.get("high", [])) * 10
|
|
100
|
+
score -= len(risks.get("medium", [])) * 5
|
|
101
|
+
score -= len(risks.get("low", [])) * 2
|
|
102
|
+
|
|
103
|
+
# Deduct for code quality issues
|
|
104
|
+
if "issues" in quality_analysis:
|
|
105
|
+
issues = quality_analysis["issues"]
|
|
106
|
+
score -= len([i for i in issues if i.get("severity") == "critical"]) * 12
|
|
107
|
+
score -= len([i for i in issues if i.get("severity") == "high"]) * 8
|
|
108
|
+
score -= len([i for i in issues if i.get("severity") == "medium"]) * 4
|
|
109
|
+
score -= len([i for i in issues if i.get("severity") == "low"]) * 1
|
|
110
|
+
|
|
111
|
+
# Deduct for complexity
|
|
112
|
+
if "summary" in pr_analysis:
|
|
113
|
+
complexity = pr_analysis["summary"].get("complexity_score", 0)
|
|
114
|
+
if complexity > 7:
|
|
115
|
+
score -= 10
|
|
116
|
+
elif complexity > 5:
|
|
117
|
+
score -= 5
|
|
118
|
+
|
|
119
|
+
return max(0, min(100, score))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def determine_verdict(score: int, critical_count: int, high_count: int) -> Tuple[str, str]:
|
|
123
|
+
"""Determine review verdict based on score and issue counts."""
|
|
124
|
+
if critical_count > 0:
|
|
125
|
+
return "block", "Critical issues must be resolved before merge"
|
|
126
|
+
|
|
127
|
+
if score >= 90 and high_count == 0:
|
|
128
|
+
return "approve", "Code meets quality standards"
|
|
129
|
+
|
|
130
|
+
if score >= 75 and high_count <= 2:
|
|
131
|
+
return "approve_with_suggestions", "Minor improvements recommended"
|
|
132
|
+
|
|
133
|
+
if score >= 50:
|
|
134
|
+
return "request_changes", "Several issues need to be addressed"
|
|
135
|
+
|
|
136
|
+
return "block", "Significant issues prevent approval"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def generate_findings_list(pr_analysis: Dict, quality_analysis: Dict) -> List[Dict]:
|
|
140
|
+
"""Combine and prioritize all findings."""
|
|
141
|
+
findings = []
|
|
142
|
+
|
|
143
|
+
# Add PR risk findings
|
|
144
|
+
if "risks" in pr_analysis:
|
|
145
|
+
for severity, items in pr_analysis["risks"].items():
|
|
146
|
+
for item in items:
|
|
147
|
+
findings.append({
|
|
148
|
+
"source": "pr_analysis",
|
|
149
|
+
"severity": severity,
|
|
150
|
+
"category": item.get("name", "unknown"),
|
|
151
|
+
"message": item.get("message", ""),
|
|
152
|
+
"file": item.get("file", ""),
|
|
153
|
+
"count": item.get("count", 1)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
# Add code quality findings
|
|
157
|
+
if "issues" in quality_analysis:
|
|
158
|
+
for issue in quality_analysis["issues"]:
|
|
159
|
+
findings.append({
|
|
160
|
+
"source": "quality_analysis",
|
|
161
|
+
"severity": issue.get("severity", "medium"),
|
|
162
|
+
"category": issue.get("type", "unknown"),
|
|
163
|
+
"message": issue.get("message", ""),
|
|
164
|
+
"file": issue.get("file", ""),
|
|
165
|
+
"line": issue.get("line", 0)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
# Sort by severity weight
|
|
169
|
+
findings.sort(
|
|
170
|
+
key=lambda x: -SEVERITY_WEIGHTS.get(x["severity"], 0)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return findings
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def generate_action_items(findings: List[Dict]) -> List[Dict]:
|
|
177
|
+
"""Generate prioritized action items from findings."""
|
|
178
|
+
action_items = []
|
|
179
|
+
seen_categories = set()
|
|
180
|
+
|
|
181
|
+
for finding in findings:
|
|
182
|
+
category = finding["category"]
|
|
183
|
+
severity = finding["severity"]
|
|
184
|
+
|
|
185
|
+
# Group similar issues
|
|
186
|
+
if category in seen_categories and severity not in ["critical", "high"]:
|
|
187
|
+
continue
|
|
188
|
+
|
|
189
|
+
action = {
|
|
190
|
+
"priority": "P0" if severity == "critical" else "P1" if severity == "high" else "P2",
|
|
191
|
+
"action": get_action_for_category(category, finding),
|
|
192
|
+
"severity": severity,
|
|
193
|
+
"files_affected": [finding["file"]] if finding.get("file") else []
|
|
194
|
+
}
|
|
195
|
+
action_items.append(action)
|
|
196
|
+
seen_categories.add(category)
|
|
197
|
+
|
|
198
|
+
return action_items[:15] # Top 15 actions
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_action_for_category(category: str, finding: Dict) -> str:
|
|
202
|
+
"""Get actionable recommendation for issue category."""
|
|
203
|
+
actions = {
|
|
204
|
+
"hardcoded_secrets": "Remove hardcoded credentials and use environment variables or a secrets manager",
|
|
205
|
+
"sql_concatenation": "Use parameterized queries to prevent SQL injection",
|
|
206
|
+
"debugger": "Remove debugger statements before merging",
|
|
207
|
+
"console_log": "Remove or replace console statements with proper logging",
|
|
208
|
+
"todo_fixme": "Address TODO/FIXME comments or create tracking issues",
|
|
209
|
+
"disable_eslint": "Address the underlying issue instead of disabling lint rules",
|
|
210
|
+
"any_type": "Replace 'any' types with proper type definitions",
|
|
211
|
+
"long_function": "Break down function into smaller, focused units",
|
|
212
|
+
"god_class": "Split class into smaller, single-responsibility classes",
|
|
213
|
+
"too_many_params": "Use parameter objects or builder pattern",
|
|
214
|
+
"deep_nesting": "Refactor using early returns, guard clauses, or extraction",
|
|
215
|
+
"high_complexity": "Reduce cyclomatic complexity through refactoring",
|
|
216
|
+
"missing_error_handling": "Add proper error handling and recovery logic",
|
|
217
|
+
"duplicate_code": "Extract duplicate code into shared functions",
|
|
218
|
+
"magic_numbers": "Replace magic numbers with named constants",
|
|
219
|
+
"large_file": "Consider splitting into multiple smaller modules"
|
|
220
|
+
}
|
|
221
|
+
return actions.get(category, f"Review and address: {finding.get('message', category)}")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def format_markdown_report(report: Dict) -> str:
|
|
225
|
+
"""Generate markdown-formatted report."""
|
|
226
|
+
lines = []
|
|
227
|
+
|
|
228
|
+
# Header
|
|
229
|
+
lines.append("# Code Review Report")
|
|
230
|
+
lines.append("")
|
|
231
|
+
lines.append(f"**Generated:** {report['metadata']['generated_at']}")
|
|
232
|
+
lines.append(f"**Repository:** {report['metadata']['repository']}")
|
|
233
|
+
lines.append("")
|
|
234
|
+
|
|
235
|
+
# Executive Summary
|
|
236
|
+
lines.append("## Executive Summary")
|
|
237
|
+
lines.append("")
|
|
238
|
+
summary = report["summary"]
|
|
239
|
+
verdict = summary["verdict"]
|
|
240
|
+
verdict_emoji = {
|
|
241
|
+
"approve": "✅",
|
|
242
|
+
"approve_with_suggestions": "✅",
|
|
243
|
+
"request_changes": "⚠️",
|
|
244
|
+
"block": "❌"
|
|
245
|
+
}.get(verdict, "❓")
|
|
246
|
+
|
|
247
|
+
lines.append(f"**Verdict:** {verdict_emoji} {verdict.upper().replace('_', ' ')}")
|
|
248
|
+
lines.append(f"**Score:** {summary['score']}/100")
|
|
249
|
+
lines.append(f"**Rationale:** {summary['rationale']}")
|
|
250
|
+
lines.append("")
|
|
251
|
+
|
|
252
|
+
# Issue Counts
|
|
253
|
+
lines.append("### Issue Summary")
|
|
254
|
+
lines.append("")
|
|
255
|
+
lines.append("| Severity | Count |")
|
|
256
|
+
lines.append("|----------|-------|")
|
|
257
|
+
for severity in ["critical", "high", "medium", "low"]:
|
|
258
|
+
count = summary["issue_counts"].get(severity, 0)
|
|
259
|
+
lines.append(f"| {severity.capitalize()} | {count} |")
|
|
260
|
+
lines.append("")
|
|
261
|
+
|
|
262
|
+
# PR Statistics (if available)
|
|
263
|
+
if "pr_summary" in report:
|
|
264
|
+
pr = report["pr_summary"]
|
|
265
|
+
lines.append("### Change Statistics")
|
|
266
|
+
lines.append("")
|
|
267
|
+
lines.append(f"- **Files Changed:** {pr.get('files_changed', 'N/A')}")
|
|
268
|
+
lines.append(f"- **Lines Added:** +{pr.get('total_additions', 0)}")
|
|
269
|
+
lines.append(f"- **Lines Removed:** -{pr.get('total_deletions', 0)}")
|
|
270
|
+
lines.append(f"- **Complexity:** {pr.get('complexity_label', 'N/A')}")
|
|
271
|
+
lines.append("")
|
|
272
|
+
|
|
273
|
+
# Action Items
|
|
274
|
+
if report.get("action_items"):
|
|
275
|
+
lines.append("## Action Items")
|
|
276
|
+
lines.append("")
|
|
277
|
+
for i, item in enumerate(report["action_items"], 1):
|
|
278
|
+
priority = item["priority"]
|
|
279
|
+
emoji = "🔴" if priority == "P0" else "🟠" if priority == "P1" else "🟡"
|
|
280
|
+
lines.append(f"{i}. {emoji} **[{priority}]** {item['action']}")
|
|
281
|
+
if item.get("files_affected"):
|
|
282
|
+
lines.append(f" - Files: {', '.join(item['files_affected'][:3])}")
|
|
283
|
+
lines.append("")
|
|
284
|
+
|
|
285
|
+
# Critical Findings
|
|
286
|
+
critical_findings = [f for f in report.get("findings", []) if f["severity"] == "critical"]
|
|
287
|
+
if critical_findings:
|
|
288
|
+
lines.append("## Critical Issues (Must Fix)")
|
|
289
|
+
lines.append("")
|
|
290
|
+
for finding in critical_findings:
|
|
291
|
+
lines.append(f"- **{finding['category']}** in `{finding.get('file', 'unknown')}`")
|
|
292
|
+
lines.append(f" - {finding['message']}")
|
|
293
|
+
lines.append("")
|
|
294
|
+
|
|
295
|
+
# High Priority Findings
|
|
296
|
+
high_findings = [f for f in report.get("findings", []) if f["severity"] == "high"]
|
|
297
|
+
if high_findings:
|
|
298
|
+
lines.append("## High Priority Issues")
|
|
299
|
+
lines.append("")
|
|
300
|
+
for finding in high_findings[:10]:
|
|
301
|
+
lines.append(f"- **{finding['category']}** in `{finding.get('file', 'unknown')}`")
|
|
302
|
+
lines.append(f" - {finding['message']}")
|
|
303
|
+
lines.append("")
|
|
304
|
+
|
|
305
|
+
# Review Order (if available)
|
|
306
|
+
if "review_order" in report:
|
|
307
|
+
lines.append("## Suggested Review Order")
|
|
308
|
+
lines.append("")
|
|
309
|
+
for i, filepath in enumerate(report["review_order"][:10], 1):
|
|
310
|
+
lines.append(f"{i}. `{filepath}`")
|
|
311
|
+
lines.append("")
|
|
312
|
+
|
|
313
|
+
# Footer
|
|
314
|
+
lines.append("---")
|
|
315
|
+
lines.append("*Generated by Code Reviewer*")
|
|
316
|
+
|
|
317
|
+
return "\n".join(lines)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def format_text_report(report: Dict) -> str:
|
|
321
|
+
"""Generate plain text report."""
|
|
322
|
+
lines = []
|
|
323
|
+
|
|
324
|
+
lines.append("=" * 60)
|
|
325
|
+
lines.append("CODE REVIEW REPORT")
|
|
326
|
+
lines.append("=" * 60)
|
|
327
|
+
lines.append("")
|
|
328
|
+
lines.append(f"Generated: {report['metadata']['generated_at']}")
|
|
329
|
+
lines.append(f"Repository: {report['metadata']['repository']}")
|
|
330
|
+
lines.append("")
|
|
331
|
+
|
|
332
|
+
summary = report["summary"]
|
|
333
|
+
verdict = summary["verdict"].upper().replace("_", " ")
|
|
334
|
+
lines.append(f"VERDICT: {verdict}")
|
|
335
|
+
lines.append(f"SCORE: {summary['score']}/100")
|
|
336
|
+
lines.append(f"RATIONALE: {summary['rationale']}")
|
|
337
|
+
lines.append("")
|
|
338
|
+
|
|
339
|
+
lines.append("--- ISSUE SUMMARY ---")
|
|
340
|
+
for severity in ["critical", "high", "medium", "low"]:
|
|
341
|
+
count = summary["issue_counts"].get(severity, 0)
|
|
342
|
+
lines.append(f" {severity.capitalize()}: {count}")
|
|
343
|
+
lines.append("")
|
|
344
|
+
|
|
345
|
+
if report.get("action_items"):
|
|
346
|
+
lines.append("--- ACTION ITEMS ---")
|
|
347
|
+
for i, item in enumerate(report["action_items"][:10], 1):
|
|
348
|
+
lines.append(f" {i}. [{item['priority']}] {item['action']}")
|
|
349
|
+
lines.append("")
|
|
350
|
+
|
|
351
|
+
critical = [f for f in report.get("findings", []) if f["severity"] == "critical"]
|
|
352
|
+
if critical:
|
|
353
|
+
lines.append("--- CRITICAL ISSUES ---")
|
|
354
|
+
for f in critical:
|
|
355
|
+
lines.append(f" [{f.get('file', 'unknown')}] {f['message']}")
|
|
356
|
+
lines.append("")
|
|
357
|
+
|
|
358
|
+
lines.append("=" * 60)
|
|
359
|
+
|
|
360
|
+
return "\n".join(lines)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def generate_report(
|
|
364
|
+
repo_path: Path,
|
|
365
|
+
pr_analysis: Optional[Dict] = None,
|
|
366
|
+
quality_analysis: Optional[Dict] = None
|
|
367
|
+
) -> Dict:
|
|
368
|
+
"""Generate comprehensive review report."""
|
|
369
|
+
# Run analyses if not provided
|
|
370
|
+
if pr_analysis is None:
|
|
371
|
+
pr_analysis = run_pr_analyzer(repo_path)
|
|
372
|
+
|
|
373
|
+
if quality_analysis is None:
|
|
374
|
+
quality_analysis = run_quality_checker(repo_path)
|
|
375
|
+
|
|
376
|
+
# Generate findings
|
|
377
|
+
findings = generate_findings_list(pr_analysis, quality_analysis)
|
|
378
|
+
|
|
379
|
+
# Count issues by severity
|
|
380
|
+
issue_counts = {
|
|
381
|
+
"critical": len([f for f in findings if f["severity"] == "critical"]),
|
|
382
|
+
"high": len([f for f in findings if f["severity"] == "high"]),
|
|
383
|
+
"medium": len([f for f in findings if f["severity"] == "medium"]),
|
|
384
|
+
"low": len([f for f in findings if f["severity"] == "low"])
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
# Calculate score and verdict
|
|
388
|
+
score = calculate_review_score(pr_analysis, quality_analysis)
|
|
389
|
+
verdict, rationale = determine_verdict(
|
|
390
|
+
score,
|
|
391
|
+
issue_counts["critical"],
|
|
392
|
+
issue_counts["high"]
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Generate action items
|
|
396
|
+
action_items = generate_action_items(findings)
|
|
397
|
+
|
|
398
|
+
# Build report
|
|
399
|
+
report = {
|
|
400
|
+
"metadata": {
|
|
401
|
+
"generated_at": datetime.now().isoformat(),
|
|
402
|
+
"repository": str(repo_path),
|
|
403
|
+
"version": "1.0.0"
|
|
404
|
+
},
|
|
405
|
+
"summary": {
|
|
406
|
+
"score": score,
|
|
407
|
+
"verdict": verdict,
|
|
408
|
+
"rationale": rationale,
|
|
409
|
+
"issue_counts": issue_counts
|
|
410
|
+
},
|
|
411
|
+
"findings": findings,
|
|
412
|
+
"action_items": action_items
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# Add PR summary if available
|
|
416
|
+
if pr_analysis.get("status") == "analyzed":
|
|
417
|
+
report["pr_summary"] = pr_analysis.get("summary", {})
|
|
418
|
+
report["review_order"] = pr_analysis.get("review_order", [])
|
|
419
|
+
|
|
420
|
+
# Add quality summary if available
|
|
421
|
+
if quality_analysis.get("status") == "analyzed":
|
|
422
|
+
report["quality_summary"] = quality_analysis.get("summary", {})
|
|
423
|
+
|
|
424
|
+
return report
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def main():
|
|
428
|
+
parser = argparse.ArgumentParser(
|
|
429
|
+
description="Generate comprehensive code review reports"
|
|
430
|
+
)
|
|
431
|
+
parser.add_argument(
|
|
432
|
+
"repo_path",
|
|
433
|
+
nargs="?",
|
|
434
|
+
default=".",
|
|
435
|
+
help="Path to repository (default: current directory)"
|
|
436
|
+
)
|
|
437
|
+
parser.add_argument(
|
|
438
|
+
"--pr-analysis",
|
|
439
|
+
help="Path to pre-computed PR analysis JSON"
|
|
440
|
+
)
|
|
441
|
+
parser.add_argument(
|
|
442
|
+
"--quality-analysis",
|
|
443
|
+
help="Path to pre-computed quality analysis JSON"
|
|
444
|
+
)
|
|
445
|
+
parser.add_argument(
|
|
446
|
+
"--format", "-f",
|
|
447
|
+
choices=["text", "markdown", "json"],
|
|
448
|
+
default="text",
|
|
449
|
+
help="Output format (default: text)"
|
|
450
|
+
)
|
|
451
|
+
parser.add_argument(
|
|
452
|
+
"--output", "-o",
|
|
453
|
+
help="Write output to file"
|
|
454
|
+
)
|
|
455
|
+
parser.add_argument(
|
|
456
|
+
"--json",
|
|
457
|
+
action="store_true",
|
|
458
|
+
help="Output as JSON (shortcut for --format json)"
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
args = parser.parse_args()
|
|
462
|
+
|
|
463
|
+
repo_path = Path(args.repo_path).resolve()
|
|
464
|
+
if not repo_path.exists():
|
|
465
|
+
print(f"Error: Path does not exist: {repo_path}", file=sys.stderr)
|
|
466
|
+
sys.exit(1)
|
|
467
|
+
|
|
468
|
+
# Load pre-computed analyses if provided
|
|
469
|
+
pr_analysis = None
|
|
470
|
+
quality_analysis = None
|
|
471
|
+
|
|
472
|
+
if args.pr_analysis:
|
|
473
|
+
pr_analysis = load_json_file(args.pr_analysis)
|
|
474
|
+
if not pr_analysis:
|
|
475
|
+
print(f"Warning: Could not load PR analysis from {args.pr_analysis}")
|
|
476
|
+
|
|
477
|
+
if args.quality_analysis:
|
|
478
|
+
quality_analysis = load_json_file(args.quality_analysis)
|
|
479
|
+
if not quality_analysis:
|
|
480
|
+
print(f"Warning: Could not load quality analysis from {args.quality_analysis}")
|
|
481
|
+
|
|
482
|
+
# Generate report
|
|
483
|
+
report = generate_report(repo_path, pr_analysis, quality_analysis)
|
|
484
|
+
|
|
485
|
+
# Format output
|
|
486
|
+
output_format = "json" if args.json else args.format
|
|
487
|
+
|
|
488
|
+
if output_format == "json":
|
|
489
|
+
output = json.dumps(report, indent=2)
|
|
490
|
+
elif output_format == "markdown":
|
|
491
|
+
output = format_markdown_report(report)
|
|
492
|
+
else:
|
|
493
|
+
output = format_text_report(report)
|
|
494
|
+
|
|
495
|
+
# Write or print output
|
|
496
|
+
if args.output:
|
|
497
|
+
with open(args.output, "w") as f:
|
|
498
|
+
f.write(output)
|
|
499
|
+
print(f"Report written to {args.output}")
|
|
500
|
+
else:
|
|
501
|
+
print(output)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
if __name__ == "__main__":
|
|
505
|
+
main()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: do-constitution
|
|
3
|
+
description: "Create or amend the per-repo constitution (tier-2), overlaying the base; bumps semver, writes a Sync Impact Report, and propagates a pointer into the agent context file. Use when the user wants to establish or change repo-specific governing principles that every later phase and agent must inherit, or says 'let's set some ground rules for this repo' or 'amend our constitution to require X' rather than asking for a feature."
|
|
4
|
+
argument-hint: "[principle inputs] [--amend]"
|
|
5
|
+
effort: high
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# do-constitution
|
|
9
|
+
|
|
10
|
+
Phase 0 of the doflow chain — the persistent rules every later phase and agent inherits.
|
|
11
|
+
Maintains the **tier-2** per-repo constitution that overlays the tier-1 `CONSTITUTION_BASE.md`.
|
|
12
|
+
|
|
13
|
+
## Invocation
|
|
14
|
+
```text
|
|
15
|
+
/do-constitution [principle inputs] [--amend]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Behavioral Flow
|
|
19
|
+
1. **Resolve** — run the resolver and note `constitution_base`, `constitution_local`, and
|
|
20
|
+
`repo_root`. Every DoFlow runtime call in this skill goes through the runtime seam. Resolve it
|
|
21
|
+
**once** here and reuse `$DOFLOW` for every later call in this skill:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Resolve the DoFlow runtime: nearest project install wins, then the global one.
|
|
25
|
+
D=$PWD; while [ "$D" != / ] && [ ! -x "$D/.doflow/scripts/doflow/bin/doflow-run" ]; do D=$(dirname "$D"); done
|
|
26
|
+
DOFLOW="$D/.doflow/scripts/doflow/bin/doflow-run"
|
|
27
|
+
[ -x "$DOFLOW" ] || DOFLOW="$HOME/.doflow/scripts/doflow/bin/doflow-run"
|
|
28
|
+
[ -x "$DOFLOW" ] || { echo "doflow: no runtime found in any .doflow/ above $PWD, nor at $HOME/.doflow. Run: npx @khoavu882/doflow install -t <harness>" >&2; exit 2; }
|
|
29
|
+
```
|
|
30
|
+
Run every command below from the project root — the walk-up starts at `$PWD`. On exit 2, print the message verbatim and stop; it names every path searched.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
"$DOFLOW" paths --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. **Read both tiers** — the base (read-only), and the local file when `has_constitution_local` is
|
|
37
|
+
true. You reconcile them yourself, tier-2 taking precedence — nothing merges them for you.
|
|
38
|
+
See the guidance tree's `references/DOFLOW_CHAIN.md` → "Two-tier constitution" for what is
|
|
39
|
+
computed and what is convention, and for the rule the two tiers are governed by.
|
|
40
|
+
3. **Create or amend** — branch on `has_constitution_local` from step 1, not a filesystem check of
|
|
41
|
+
your own (path math belongs to the resolver; `constitution_local` is still emitted when the file
|
|
42
|
+
is absent, which is exactly the create case):
|
|
43
|
+
- `has_constitution_local` false: copy the installed constitution template to
|
|
44
|
+
`constitution_local` and fill it from the user's principle inputs (repo-specific rules only;
|
|
45
|
+
don't restate base principles).
|
|
46
|
+
- true, and `--amend`: apply the requested change.
|
|
47
|
+
|
|
48
|
+
The template is `templates/doflow/constitution-template.md` in the install step 1 resolved: take `constitution_base` from that JSON and swap its trailing `guidance/references/CONSTITUTION_BASE.md` for that path.
|
|
49
|
+
|
|
50
|
+
4. **Version + Sync Impact** — bump the semver version line and fill the `SYNC IMPACT REPORT` comment
|
|
51
|
+
(old→new version, what changed, what it propagates to). If a change clarifies/renames a principle that
|
|
52
|
+
templates reference, note it.
|
|
53
|
+
5. **Propagate (deterministic)** — pipe a short pointer block to the `sync-context` verb so it lands
|
|
54
|
+
in the agent context file without rewriting it:
|
|
55
|
+
```bash
|
|
56
|
+
printf 'doflow: active constitution = agent-docs/constitution.md (v<version>), overlaying CONSTITUTION_BASE.md.\n' \
|
|
57
|
+
| "$DOFLOW" sync-context --file CLAUDE.md # or AGENTS.md for Codex
|
|
58
|
+
```
|
|
59
|
+
The verb acknowledges in plain text on success. **Any non-zero exit means the pointer did not
|
|
60
|
+
land** — 1 the write failed, 2 the call was malformed. Report it in step 6 as a failed
|
|
61
|
+
propagation; never claim the context file was updated on a non-zero exit.
|
|
62
|
+
6. **Stop** — report the version, the Sync Impact summary, and the propagated context file (or the
|
|
63
|
+
propagation failure from step 5).
|
|
64
|
+
|
|
65
|
+
## Boundaries
|
|
66
|
+
**Will:** maintain the tier-2 constitution, version it, write the Sync Impact Report, and propagate a
|
|
67
|
+
marker-delimited pointer via the `sync-context` verb.
|
|
68
|
+
**Will Not:** weaken base P1 (Safety), rewrite the whole context file (only the DOFLOW block), or edit code.
|
|
69
|
+
|
|
70
|
+
## CRITICAL BOUNDARIES
|
|
71
|
+
Output: `agent-docs/constitution.md` (tier-2) + an updated `<!-- DOFLOW START/END -->` block in the
|
|
72
|
+
context file. **Next Step:** `/do-brainstorm` to start a feature under this constitution.
|