devcouncil 0.1.0 → 0.2.0
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 +201 -201
- package/README.md +197 -494
- package/package.json +9 -2
- package/pyproject.toml +62 -27
- package/src/devcouncil/__main__.py +4 -4
- package/src/devcouncil/app/__init__.py +28 -28
- package/src/devcouncil/app/config.py +297 -108
- package/src/devcouncil/app/errors.py +23 -23
- package/src/devcouncil/app/events.py +44 -44
- package/src/devcouncil/app/orchestrator.py +67 -67
- package/src/devcouncil/app/project_status.py +29 -0
- package/src/devcouncil/app/run_context.py +39 -39
- package/src/devcouncil/app/state_machine.py +108 -108
- package/src/devcouncil/artifacts/__init__.py +1 -1
- package/src/devcouncil/artifacts/coverage.py +96 -96
- package/src/devcouncil/artifacts/graph.py +163 -143
- package/src/devcouncil/artifacts/migrations.py +20 -20
- package/src/devcouncil/artifacts/schemas.py +23 -23
- package/src/devcouncil/artifacts/serializer.py +21 -21
- package/src/devcouncil/artifacts/validators.py +27 -27
- package/src/devcouncil/assets/__init__.py +1 -0
- package/src/devcouncil/assets/devcouncil-logo.svg +60 -0
- package/src/devcouncil/assets/devcouncil_logo_premium.png +0 -0
- package/src/devcouncil/cli/commands/agents.py +292 -0
- package/src/devcouncil/cli/commands/artifacts.py +54 -48
- package/src/devcouncil/cli/commands/ast.py +22 -0
- package/src/devcouncil/cli/commands/baseline.py +35 -32
- package/src/devcouncil/cli/commands/check.py +209 -0
- package/src/devcouncil/cli/commands/config.py +115 -54
- package/src/devcouncil/cli/commands/cost.py +57 -0
- package/src/devcouncil/cli/commands/dashboard.py +31 -0
- package/src/devcouncil/cli/commands/doctor.py +291 -47
- package/src/devcouncil/cli/commands/evidence.py +48 -0
- package/src/devcouncil/cli/commands/go.py +656 -0
- package/src/devcouncil/cli/commands/handoff.py +69 -0
- package/src/devcouncil/cli/commands/hook.py +209 -33
- package/src/devcouncil/cli/commands/init.py +204 -57
- package/src/devcouncil/cli/commands/integrate.py +1171 -76
- package/src/devcouncil/cli/commands/lsp.py +20 -0
- package/src/devcouncil/cli/commands/map.py +96 -22
- package/src/devcouncil/cli/commands/plan.py +422 -210
- package/src/devcouncil/cli/commands/prompt.py +48 -34
- package/src/devcouncil/cli/commands/repair.py +89 -69
- package/src/devcouncil/cli/commands/report.py +120 -54
- package/src/devcouncil/cli/commands/reset_demo_state.py +33 -28
- package/src/devcouncil/cli/commands/rollback.py +55 -54
- package/src/devcouncil/cli/commands/run.py +285 -220
- package/src/devcouncil/cli/commands/runs.py +223 -0
- package/src/devcouncil/cli/commands/scaffold.py +32 -0
- package/src/devcouncil/cli/commands/semantic.py +47 -0
- package/src/devcouncil/cli/commands/setup.py +300 -20
- package/src/devcouncil/cli/commands/shell.py +73 -0
- package/src/devcouncil/cli/commands/show.py +76 -57
- package/src/devcouncil/cli/commands/skills.py +88 -0
- package/src/devcouncil/cli/commands/status.py +141 -105
- package/src/devcouncil/cli/commands/tasks.py +55 -41
- package/src/devcouncil/cli/commands/trace.py +49 -4
- package/src/devcouncil/cli/commands/verify.py +293 -128
- package/src/devcouncil/cli/commands/version.py +20 -20
- package/src/devcouncil/cli/commands/watch.py +574 -0
- package/src/devcouncil/cli/commands/watch_fs.py +40 -0
- package/src/devcouncil/cli/main.py +92 -25
- package/src/devcouncil/council/prompts/arbiter.md +19 -19
- package/src/devcouncil/council/prompts/critic_a.md +10 -10
- package/src/devcouncil/council/prompts/critic_b.md +10 -10
- package/src/devcouncil/council/prompts/implementation_reviewer.md +16 -16
- package/src/devcouncil/council/prompts/planner_a.md +16 -16
- package/src/devcouncil/council/prompts/planner_b.md +16 -16
- package/src/devcouncil/council/prompts/rebuttal.md +10 -10
- package/src/devcouncil/council/prompts/spec_writer.md +12 -12
- package/src/devcouncil/domain/assumption.py +17 -17
- package/src/devcouncil/domain/critique.py +32 -32
- package/src/devcouncil/domain/evidence.py +47 -27
- package/src/devcouncil/domain/gap.py +52 -26
- package/src/devcouncil/domain/requirement.py +22 -22
- package/src/devcouncil/domain/task.py +55 -26
- package/src/devcouncil/execution/__init__.py +1 -1
- package/src/devcouncil/execution/checkpoints.py +246 -0
- package/src/devcouncil/execution/context_builder.py +54 -54
- package/src/devcouncil/execution/executor.py +15 -15
- package/src/devcouncil/execution/fs_watcher.py +180 -0
- package/src/devcouncil/execution/handoff.py +102 -0
- package/src/devcouncil/execution/hook_policy.py +186 -77
- package/src/devcouncil/execution/patch.py +77 -28
- package/src/devcouncil/execution/permissions.py +52 -59
- package/src/devcouncil/execution/policy_engine.py +343 -0
- package/src/devcouncil/execution/prompt_builder.py +650 -38
- package/src/devcouncil/execution/shell_session.py +225 -0
- package/src/devcouncil/execution/task_runner.py +68 -64
- package/src/devcouncil/executors/__init__.py +1 -1
- package/src/devcouncil/executors/agent_registry.py +575 -0
- package/src/devcouncil/executors/coding_cli.py +736 -0
- package/src/devcouncil/executors/mini_swe.py +63 -63
- package/src/devcouncil/executors/native/agent.py +186 -85
- package/src/devcouncil/executors/openhands.py +56 -56
- package/src/devcouncil/gating/__init__.py +1 -1
- package/src/devcouncil/gating/checks/clean_git.py +52 -45
- package/src/devcouncil/gating/checks/planned_files_check.py +32 -32
- package/src/devcouncil/gating/checks/requirement_coverage.py +26 -26
- package/src/devcouncil/gating/checks/secret_scan_check.py +53 -34
- package/src/devcouncil/gating/policy.py +315 -167
- package/src/devcouncil/hardware.py +184 -0
- package/src/devcouncil/indexing/__init__.py +1 -1
- package/src/devcouncil/indexing/ast_matcher.py +168 -0
- package/src/devcouncil/indexing/graph_index.py +48 -48
- package/src/devcouncil/indexing/lsp.py +161 -0
- package/src/devcouncil/indexing/repo_mapper.py +1455 -204
- package/src/devcouncil/indexing/semantic_index.py +205 -0
- package/src/devcouncil/integrations/actions.py +146 -0
- package/src/devcouncil/integrations/check.py +423 -0
- package/src/devcouncil/integrations/github.py +35 -35
- package/src/devcouncil/integrations/github_intent.py +142 -0
- package/src/devcouncil/integrations/gitnexus.py +62 -27
- package/src/devcouncil/integrations/graphify.py +34 -34
- package/src/devcouncil/integrations/mcp/server.py +2072 -96
- package/src/devcouncil/integrations/opencode_devcouncil_plugin.mjs +24 -0
- package/src/devcouncil/integrations/pr_comments.py +62 -0
- package/src/devcouncil/live/__init__.py +2 -0
- package/src/devcouncil/live/cards.py +349 -0
- package/src/devcouncil/live/models.py +63 -0
- package/src/devcouncil/live/repair_prompt.py +83 -0
- package/src/devcouncil/live/reviewer.py +70 -0
- package/src/devcouncil/live/signals.py +135 -0
- package/src/devcouncil/live/summary.py +34 -0
- package/src/devcouncil/live/tasks.py +18 -0
- package/src/devcouncil/live/transcripts.py +141 -0
- package/src/devcouncil/llm/__init__.py +1 -1
- package/src/devcouncil/llm/cache.py +42 -38
- package/src/devcouncil/llm/model_defaults.yaml +44 -0
- package/src/devcouncil/llm/provider.py +627 -125
- package/src/devcouncil/llm/router.py +303 -118
- package/src/devcouncil/optimization/__init__.py +1 -0
- package/src/devcouncil/optimization/gepa_agent.py +318 -0
- package/src/devcouncil/planning/__init__.py +1 -1
- package/src/devcouncil/planning/arbiter_service.py +57 -57
- package/src/devcouncil/planning/correction_manifest.py +303 -0
- package/src/devcouncil/planning/critique_service.py +71 -66
- package/src/devcouncil/planning/plan_service.py +60 -46
- package/src/devcouncil/planning/prompt_enhancer_service.py +167 -0
- package/src/devcouncil/planning/repair_service.py +39 -39
- package/src/devcouncil/planning/spec_service.py +70 -44
- package/src/devcouncil/repo/ci_scaffold.py +157 -0
- package/src/devcouncil/repo/gitignore.py +123 -0
- package/src/devcouncil/repo/sca.py +374 -0
- package/src/devcouncil/reporting/github_check.py +32 -32
- package/src/devcouncil/reporting/json_report.py +30 -17
- package/src/devcouncil/reporting/markdown_report.py +83 -46
- package/src/devcouncil/reporting/report_builder.py +14 -14
- package/src/devcouncil/skills/__init__.py +19 -0
- package/src/devcouncil/skills/library/README.md +46 -0
- package/src/devcouncil/skills/library/ai-training.md +50 -0
- package/src/devcouncil/skills/library/android.md +50 -0
- package/src/devcouncil/skills/library/backend.md +52 -0
- package/src/devcouncil/skills/library/core-engineering.md +95 -0
- package/src/devcouncil/skills/library/data-engineering.md +47 -0
- package/src/devcouncil/skills/library/desktop.md +46 -0
- package/src/devcouncil/skills/library/devops.md +48 -0
- package/src/devcouncil/skills/library/game-dev.md +46 -0
- package/src/devcouncil/skills/library/ios.md +48 -0
- package/src/devcouncil/skills/library/mobile-cross-platform.md +46 -0
- package/src/devcouncil/skills/library/security.md +48 -0
- package/src/devcouncil/skills/library/systems.md +48 -0
- package/src/devcouncil/skills/library/web.md +47 -0
- package/src/devcouncil/skills/library/windows.md +47 -0
- package/src/devcouncil/skills/registry.py +330 -0
- package/src/devcouncil/storage/db.py +147 -66
- package/src/devcouncil/storage/models.py +204 -83
- package/src/devcouncil/storage/native.py +557 -0
- package/src/devcouncil/storage/repositories.py +388 -249
- package/src/devcouncil/telemetry/cost.py +140 -34
- package/src/devcouncil/telemetry/model_pricing.yaml +48 -0
- package/src/devcouncil/telemetry/pricing.py +28 -0
- package/src/devcouncil/telemetry/traces.py +62 -7
- package/src/devcouncil/telemetry/tracker.py +52 -49
- package/src/devcouncil/ui/__init__.py +1 -0
- package/src/devcouncil/ui/dashboard.py +423 -0
- package/src/devcouncil/utils/__init__.py +1 -1
- package/src/devcouncil/utils/redaction.py +147 -141
- package/src/devcouncil/utils/subprocess_env.py +69 -0
- package/src/devcouncil/verification/__init__.py +1 -1
- package/src/devcouncil/verification/acceptance_compiler.py +125 -0
- package/src/devcouncil/verification/ad_hoc_check.py +129 -0
- package/src/devcouncil/verification/diff_coverage.py +353 -0
- package/src/devcouncil/verification/implementation_reviewer.py +55 -55
- package/src/devcouncil/verification/next_actions.py +189 -0
- package/src/devcouncil/verification/sandbox.py +178 -0
- package/src/devcouncil/verification/test_resolver.py +91 -0
- package/src/devcouncil/verification/verifier.py +1342 -307
- package/uv.lock +205 -64
- package/src/devcouncil/indexing/symbol_index.py +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from devcouncil.indexing.lsp import LspInspector
|
|
7
|
+
|
|
8
|
+
app = typer.Typer(help="Inspect optional LSP integration readiness.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("inspect")
|
|
12
|
+
def inspect(
|
|
13
|
+
project_root: Path = typer.Option(Path("."), "--project-root", help="Repository root."),
|
|
14
|
+
):
|
|
15
|
+
"""Print detected language servers and initialize payloads."""
|
|
16
|
+
root = project_root.expanduser().resolve()
|
|
17
|
+
if not root.exists():
|
|
18
|
+
typer.echo(json.dumps({"languages": [], "servers": [], "initialize_requests": {}, "error": f"{root} does not exist"}, indent=2))
|
|
19
|
+
raise typer.Exit(code=1)
|
|
20
|
+
typer.echo(LspInspector(root).summary_json())
|
|
@@ -2,37 +2,111 @@ import json
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
|
-
from rich.console import Console
|
|
6
|
-
|
|
7
|
-
from devcouncil.
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from devcouncil.cli.commands.init import initialize_project
|
|
8
|
+
from devcouncil.indexing.repo_mapper import RepoMap, RepoMapper
|
|
8
9
|
from devcouncil.integrations.code_review_graph import CodeReviewGraphAdapter
|
|
9
10
|
from devcouncil.storage.db import get_db
|
|
10
|
-
|
|
11
|
+
|
|
11
12
|
console = Console()
|
|
12
13
|
status_console = Console(stderr=True)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
|
|
15
|
+
AGENT_GUIDE_MARKER = "<!-- Managed by dev map: keep this file in sync with .devcouncil/repo_map.json. -->"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _important_surfaces(repo_map: RepoMap) -> list[str]:
|
|
19
|
+
"""Derive the 'important surfaces' list from the computed map, so the guide points
|
|
20
|
+
at THIS repo's real subsystems instead of hardcoded DevCouncil paths."""
|
|
21
|
+
lines: list[str] = []
|
|
22
|
+
for index, subsystem in enumerate(repo_map.subsystems[:6], start=1):
|
|
23
|
+
lines.append(f"{index}. `{subsystem.area}/` — {subsystem.summary}")
|
|
24
|
+
if not lines:
|
|
25
|
+
for index, path in enumerate(repo_map.important_files[:6], start=1):
|
|
26
|
+
lines.append(f"{index}. `{path}`")
|
|
27
|
+
return lines or ["1. See `.devcouncil/repo_map.json` for the file index."]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _agent_guide_text(repo_map_path: Path, repo_root: Path, repo_map: RepoMap) -> str:
|
|
31
|
+
return "\n".join(
|
|
32
|
+
[
|
|
33
|
+
AGENT_GUIDE_MARKER,
|
|
34
|
+
"",
|
|
35
|
+
"# Agent Workspace Guide",
|
|
36
|
+
"",
|
|
37
|
+
"Use `.devcouncil/repo_map.json` as the primary file index for this workspace.",
|
|
38
|
+
f"Repo map: `{repo_map_path.relative_to(repo_root).as_posix() if repo_map_path.is_relative_to(repo_root) else repo_map_path}`",
|
|
39
|
+
"",
|
|
40
|
+
"Workflow for agents:",
|
|
41
|
+
"1. Open `.devcouncil/repo_map.json` before guessing at file locations.",
|
|
42
|
+
"2. Use the `files` list to resolve module ownership and nearby siblings.",
|
|
43
|
+
"3. Use `subsystems` for subsystem-level navigation.",
|
|
44
|
+
"4. In `subsystems`, use `entry_points` + `critical_files` for entry points and starting context.",
|
|
45
|
+
"5. Use `role_files` in `subsystems` for subsystem role buckets (entry, runtime, policy, adapters, etc.).",
|
|
46
|
+
"6. Use `neighbors` and `handoff_paths` in `subsystems` to follow cross-subsystem flow.",
|
|
47
|
+
"7. Run `dev map` again after large refactors to refresh the map.",
|
|
48
|
+
"",
|
|
49
|
+
"Important surfaces:",
|
|
50
|
+
*_important_surfaces(repo_map),
|
|
51
|
+
"",
|
|
52
|
+
"If the map and source disagree, trust the source and regenerate the map.",
|
|
53
|
+
]
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _write_agent_guides(repo_root: Path, repo_map_path: Path, repo_map: RepoMap) -> None:
|
|
58
|
+
for filename in ("AGENTS.md", "CLAUDE.md"):
|
|
59
|
+
path = repo_root / filename
|
|
60
|
+
if path.exists():
|
|
61
|
+
existing = path.read_text(encoding="utf-8")
|
|
62
|
+
if AGENT_GUIDE_MARKER not in existing:
|
|
63
|
+
continue
|
|
64
|
+
path.write_text(_agent_guide_text(repo_map_path, repo_root, repo_map) + "\n", encoding="utf-8")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def generate_map_artifacts(root: Path, output: Path, goal: str = "", *, scan_dependencies: bool = False) -> RepoMap:
|
|
68
|
+
"""Build the repo map and write repo_map.json + agent guides (no LLM, no re-init).
|
|
69
|
+
|
|
70
|
+
Assumes ``.devcouncil/`` already exists. Shared by the ``dev map`` command and
|
|
71
|
+
by project initialization so a freshly set-up repo is immediately navigable.
|
|
72
|
+
``scan_dependencies`` is opt-in (off for init and default mapping) because it can
|
|
73
|
+
shell out to dependency auditors.
|
|
74
|
+
"""
|
|
75
|
+
repo_map = RepoMapper(root).map_repo(goal, scan_dependencies=scan_dependencies)
|
|
76
|
+
graph_context = CodeReviewGraphAdapter(root).get_context()
|
|
77
|
+
output = output if output.is_absolute() else root / output
|
|
31
78
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
32
79
|
output.write_text(repo_map.model_dump_json(indent=2), encoding="utf-8")
|
|
80
|
+
_write_agent_guides(root, output, repo_map)
|
|
33
81
|
if graph_context.available:
|
|
34
82
|
graph_output = output.with_name("code_review_graph_context.json")
|
|
35
83
|
graph_output.write_text(graph_context.model_dump_json(indent=2), encoding="utf-8")
|
|
36
84
|
status_console.print(f"[green]Wrote code-review-graph context to {graph_output}[/green]")
|
|
85
|
+
return repo_map
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def map_repo(
|
|
89
|
+
goal: str = typer.Argument("", help="Goal text used for candidate-file ranking."),
|
|
90
|
+
output: Path = typer.Option(
|
|
91
|
+
Path(".devcouncil/repo_map.json"),
|
|
92
|
+
"--output",
|
|
93
|
+
"-o",
|
|
94
|
+
help="Path to write repo_map.json.",
|
|
95
|
+
),
|
|
96
|
+
project_root: Path = typer.Option(Path("."), "--project-root", help="Repository root containing .devcouncil/."),
|
|
97
|
+
scan_deps: bool = typer.Option(
|
|
98
|
+
False,
|
|
99
|
+
"--scan-deps",
|
|
100
|
+
help="Run available dependency auditors (pip-audit/npm audit/osv-scanner) and record dependency_risks in the map. Off by default.",
|
|
101
|
+
),
|
|
102
|
+
):
|
|
103
|
+
"""Build the deterministic repository map without calling an LLM."""
|
|
104
|
+
root = project_root.expanduser().resolve()
|
|
105
|
+
initialize_project(root, quiet=True, with_map=False)
|
|
106
|
+
if not get_db(root):
|
|
107
|
+
raise typer.Exit(code=1)
|
|
108
|
+
|
|
109
|
+
output = output if output.is_absolute() else root / output
|
|
110
|
+
repo_map = generate_map_artifacts(root, output, goal, scan_dependencies=scan_deps)
|
|
37
111
|
typer.echo(json.dumps(repo_map.model_dump(), indent=2))
|
|
38
112
|
status_console.print(f"[green]Wrote repository map to {output}[/green]")
|