devcouncil 0.4.0 → 0.4.2
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/README.md +48 -6
- package/examples/build-week-demo/README.md +13 -0
- package/examples/build-week-demo/broken_calc.py +11 -0
- package/examples/build-week-demo/calc.py +11 -0
- package/examples/build-week-demo/test_calc.py +21 -0
- package/package.json +7 -2
- package/pyproject.toml +2 -2
- package/scripts/build-week-demo.sh +200 -0
- package/src/devcouncil/cli/commands/watch.py +7 -10
- package/src/devcouncil/indexing/viz.py +40 -12
- package/src/devcouncil/integrations/mcp/handlers/cli_gate.py +1 -1
- package/src/devcouncil/integrations/mcp/handlers/git.py +199 -17
- package/src/devcouncil/integrations/mcp/handlers/graph.py +6 -8
- package/src/devcouncil/integrations/mcp/handlers/knowledge.py +6 -8
- package/src/devcouncil/integrations/mcp/handlers/provenance.py +25 -39
- package/src/devcouncil/integrations/mcp/handlers/read.py +30 -1
- package/src/devcouncil/integrations/mcp/handlers/runs.py +3 -18
- package/src/devcouncil/integrations/mcp/handlers/status.py +117 -32
- package/src/devcouncil/integrations/mcp/handlers/task.py +5 -17
- package/src/devcouncil/integrations/mcp/handlers/tool_specs.py +28 -10
- package/src/devcouncil/integrations/mcp/handlers/wiki.py +4 -11
- package/src/devcouncil/integrations/mcp/server.py +1 -1
- package/src/devcouncil/integrations/mcp/util.py +27 -5
- package/src/devcouncil/live/summary.py +21 -3
- package/uv.lock +5 -5
package/README.md
CHANGED
|
@@ -1,26 +1,64 @@
|
|
|
1
1
|
# DevCouncil: The Gated AI Orchestrator
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<img src="https://raw.githubusercontent.com/bharathvbcr/DevCouncil/main/src/devcouncil/assets/
|
|
4
|
+
<img src="https://raw.githubusercontent.com/bharathvbcr/DevCouncil/main/src/devcouncil/assets/devcouncil_social_preview.jpg" alt="DevCouncil gated AI orchestration" width="720">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.python.org/downloads/)
|
|
9
9
|
[](https://github.com/astral-sh/uv)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## OpenAI Build Week 2026
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Coding agents -- including Codex and other prompt-taking CLIs -- often claim success without proving that the change satisfied the original requirements. DevCouncil turns that claim into a gated engineering workflow: every change is scoped, verified, and traceable back to a requirement. Model confidence is not the final authority; evidence is.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### What judges should see
|
|
16
|
+
|
|
17
|
+
1. **Provider-free red-to-green evidence gate** -- install once, then watch a controlled sample fail verification and pass after a real fix, with no API keys.
|
|
18
|
+
2. **Self-contained interactive code graph** -- open the packed `demo.html` artifact and navigate filters, path highlighting, and neighborhoods (no blank canvas).
|
|
19
|
+
3. **Codex / MCP agent-control path** -- status, diffs, and task tools stay correct under real project-sized JSON so an agent can resume from evidence instead of chat memory.
|
|
20
|
+
|
|
21
|
+
### Judge path (package: `devcouncil@0.4.2`)
|
|
22
|
+
|
|
23
|
+
DevCouncil supports macOS, Linux, and Windows. Requires Node.js 18+, Python 3.12+, and Git. No model provider key is needed for the deterministic demos below.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Install the Build Week release:
|
|
27
|
+
npm install -g devcouncil@0.4.2
|
|
28
|
+
devcouncil --help
|
|
29
|
+
|
|
30
|
+
# Core demo: red verdict -> apply fix -> green verdict (no API keys)
|
|
31
|
+
devcouncil-build-week-demo
|
|
32
|
+
# Equivalent: bash "$(npm root -g)/devcouncil/scripts/build-week-demo.sh"
|
|
33
|
+
|
|
34
|
+
# Interactive graph artifact (self-contained HTML)
|
|
35
|
+
mkdir -p /tmp/devcouncil-judge-demo
|
|
36
|
+
dev graph demo --project-root /tmp/devcouncil-judge-demo --json
|
|
37
|
+
# Open /tmp/devcouncil-judge-demo/.devcouncil/graph/demo.html
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Checkout fallback: clone the repo and run `bash scripts/build-week-demo.sh` (`uv sync --group dev` if you need a local `dev`).
|
|
41
|
+
|
|
42
|
+
### Eligible Build Week work
|
|
43
|
+
|
|
44
|
+
DevCouncil existed before OpenAI Build Week. This submission covers only meaningful extensions on or after **July 13, 2026**. Eligible history begins at commit `6f5bd73` (baseline before eligible work: `3cfd5d1`). Major themes:
|
|
45
|
+
|
|
46
|
+
- canonical SQLite code-intelligence index, multi-language grammars, incremental watching, graph queries/community detection, and a self-contained interactive code-graph artifact (including a ForceGraph compatibility fix for the packed demo);
|
|
47
|
+
- stronger deterministic verification: stop gates, claim checking, diff-to-evidence coverage, task leases, PDG/corpus checks, bounded repair, machine-readable next actions;
|
|
48
|
+
- deeper CLI, MCP, dashboard, coding-agent, and CI integration, plus the installable npm release path aimed at `0.4.2` for judges.
|
|
49
|
+
|
|
50
|
+
During Build Week, Codex and GPT-5.6 were used as an engineering partner to map paths, challenge claims, run install/browser checks, implement focused repairs, and verify behavior. The maintainer set requirements, scope, and acceptance evidence. The primary Codex `/feedback` session ID is on the Devpost submission. This does **not** claim that all eligible code was authored exclusively by Codex/GPT-5.6.
|
|
51
|
+
|
|
52
|
+
See [docs/build-week-demo.md](docs/build-week-demo.md) for the provider-free demo walkthrough.
|
|
16
53
|
|
|
17
54
|
## Documentation
|
|
18
55
|
|
|
56
|
+
- [Build Week demo](docs/build-week-demo.md): provider-free red-to-green judge script.
|
|
19
57
|
- [Quickstart](docs/quickstart.md): shortest install-to-first-task path.
|
|
20
58
|
- [Daily workflow](docs/workflow.md): manual sidecar loop, verification, repair, rollback, and `dev watch`.
|
|
21
59
|
- [Coding CLI integration](docs/coding-cli-integration.md): tiers, Claude Code, Codex, OpenCode, Antigravity, Cursor, Grok Build, Aider, MCP, hooks, stop gate / claim checks, and automated executors (Gemini deprecated).
|
|
22
60
|
- [CLI command reference](docs/cli-reference.md): available `dev` commands.
|
|
23
|
-
- [Repo map & code graph](docs/code-graph.md): `dev map` / `dev graph`
|
|
61
|
+
- [Repo map & code graph](docs/code-graph.md): `dev map` / `dev graph` -- navigation, dead code, blast radius, PDG (opt-in), HTML visualizer.
|
|
24
62
|
- [Corpus side index](docs/corpus.md): `dev corpus` for docs/PDFs/images and optional verify gates.
|
|
25
63
|
- [Hero loop](docs/hero-loop.md): certified Claude Code + MCP closed loop, leases, rigor, and `dev check --verify` on-ramp.
|
|
26
64
|
- [Architecture](docs/architecture.md): components, artifact graph, state machine, gating policy, and gated execution.
|
|
@@ -152,7 +190,11 @@ DevCouncil is an application layer around coding agents. It does not just emit p
|
|
|
152
190
|
### Workflow Features
|
|
153
191
|
|
|
154
192
|
- **Repository onboarding:** `dev setup` initializes `.devcouncil/`, generates the repo map + `AGENTS.md`/`CLAUDE.md` guides, scaffolds applicable engineering skills, runs environment checks, offers integration setup, and prints the next useful commands. Use `--skip-map` / `--skip-skills` to opt out, or `--scaffold-ci` to also write a starter GitHub Actions workflow. **`dev boot "goal"`** chains setup, `dev integrate --apply`, optional CI scaffold flags, and `dev go` in one command (see [quickstart](docs/quickstart.md)).
|
|
155
|
-
- **Repository mapping:** `dev map` writes `.devcouncil/repo_map.json` and a symbol-level `.devcouncil/graph/code_graph.json`, identifies important files and subsystems, filters generated/temp files, and keeps managed `AGENTS.md` / `CLAUDE.md` workspace guides synchronized. Subsystems, entry points, neighbors, and important surfaces are inferred generically for **any** repository — grouped from the directory tree and ranked by an import-graph in-degree. Freshness uses git HEAD, tracked-file hash, and a content fingerprint so plain edits mark the map stale; a **missing map is stale** (fail-closed on hard rigor). Post-tool-use hooks and `dev map --watch` refresh incrementally. Unified analyze entry: `dev graph ingest`. Query with `dev graph query|trace|dead|search|cypher|html`. Liveness lists are capped at 5000 per list and 256 dependents per file (truncation metadata when hit). The map is also generated automatically on first init.
|
|
193
|
+
- **Repository mapping:** `dev map` writes `.devcouncil/repo_map.json` and a symbol-level `.devcouncil/graph/code_graph.json`, identifies important files and subsystems, filters generated/temp files, and keeps managed `AGENTS.md` / `CLAUDE.md` workspace guides synchronized. Subsystems, entry points, neighbors, and important surfaces are inferred generically for **any** repository — grouped from the directory tree and ranked by an import-graph in-degree. Freshness uses git HEAD, tracked-file hash, and a content fingerprint so plain edits mark the map stale; a **missing map is stale** (fail-closed on hard rigor). Post-tool-use hooks and `dev map --watch` refresh incrementally. Unified analyze entry: `dev graph ingest`. Query with `dev graph query|trace|dead|search|cypher|html`. Liveness lists are capped at 5000 per list and 256 dependents per file (truncation metadata when hit). The map is also generated automatically on first init. (See [docs/code-graph.md](docs/code-graph.md) for details).
|
|
194
|
+
|
|
195
|
+
<p align="center">
|
|
196
|
+
<img src="docs/graph_preview.png" alt="Repository Code Graph Preview" width="600">
|
|
197
|
+
</p>
|
|
156
198
|
- **Engineering skills:** `dev skills` lists the bundled skills and shows which apply to the repository; `dev skills scaffold` writes them into `.claude/skills/<name>/SKILL.md`. A merged always-on `core-engineering` skill (think-before-coding, simplicity, surgical changes, goal-driven execution, evidence-grounded communication) plus domain skills (Android, iOS, Windows, web, AI training) that brief the agent on current SDKs, deprecations, and tooling before coding. Applicable skills are also embedded into `dev prompt` output.
|
|
157
199
|
- **CI scaffolding:** `dev scaffold-ci` writes a starter `.github/workflows/devcouncil.yml` derived from the configured test/lint/typecheck commands, filtered to the detected language stack; it never overwrites existing CI unless `--force`. Run `dev scaffold-ci --evidence` to generate `.github/workflows/devcouncil-evidence.yml` which automates verifying PRs and uploading evidence JSON and HTML reports.
|
|
158
200
|
- **Planning council:** `dev plan` turns a goal into requirements, acceptance criteria, assumptions, critique findings, and executable tasks. When advisory gaps remain, the project stays in `AWAITING_USER_DECISIONS` until you run `dev approve` (or `dev e2e`/`dev go --force`).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Build Week calculator sample
|
|
2
|
+
|
|
3
|
+
Tiny provider-free sample used by `scripts/build-week-demo.sh`.
|
|
4
|
+
|
|
5
|
+
| File | Role |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `calc.py` | Correct calculator (green / repaired state) |
|
|
8
|
+
| `broken_calc.py` | Deliberate `sub` bug used for the red evidence-gate pass |
|
|
9
|
+
| `test_calc.py` | Regression checks proving `add` and `sub` |
|
|
10
|
+
|
|
11
|
+
The demo script copies these into an isolated git repository, runs
|
|
12
|
+
`dev check --verify` (no API keys), applies the repair, and reruns to a
|
|
13
|
+
compiled zero-gap pass. See [docs/build-week-demo.md](../../docs/build-week-demo.md) and the fixture index in [examples/README.md](../README.md).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Deliberately buggy calculator used only for the demo's red evidence-gate pass."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def add(a: int, b: int) -> int:
|
|
5
|
+
"""Return the sum of ``a`` and ``b``."""
|
|
6
|
+
return a + b
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def sub(a: int, b: int) -> int:
|
|
10
|
+
"""Intended to return ``a`` minus ``b`` — intentionally wrong for the demo."""
|
|
11
|
+
return a + b
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Regression checks for the Build Week calculator demo."""
|
|
2
|
+
|
|
3
|
+
from calc import add, sub
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_add() -> None:
|
|
7
|
+
assert add(2, 3) == 5
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_sub() -> None:
|
|
11
|
+
assert sub(5, 3) == 2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
test_add()
|
|
16
|
+
test_sub()
|
|
17
|
+
print("ok")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devcouncil",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Gated orchestrator for AI-assisted software development",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/bharathvbcr/DevCouncil#readme",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
],
|
|
22
22
|
"bin": {
|
|
23
23
|
"devcouncil": "bin/devcouncil.js",
|
|
24
|
-
"dev": "bin/devcouncil.js"
|
|
24
|
+
"dev": "bin/devcouncil.js",
|
|
25
|
+
"devcouncil-build-week-demo": "scripts/build-week-demo.sh"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
28
|
"bin/",
|
|
@@ -35,6 +36,8 @@
|
|
|
35
36
|
"packages/codeintel-grammars/pyproject.toml",
|
|
36
37
|
"packages/codeintel-grammars/hatch_build.py",
|
|
37
38
|
"packages/codeintel-grammars/src/devcouncil_codeintel_grammars/__init__.py",
|
|
39
|
+
"scripts/build-week-demo.sh",
|
|
40
|
+
"examples/build-week-demo/**",
|
|
38
41
|
"pyproject.toml",
|
|
39
42
|
"uv.lock",
|
|
40
43
|
"README.md",
|
|
@@ -47,6 +50,8 @@
|
|
|
47
50
|
"pack:check": "npm pack --dry-run",
|
|
48
51
|
"smoke:wheel": "uv run python scripts/check-wheel-assets.py",
|
|
49
52
|
"smoke:package": "node scripts/npm-runtime-smoke.mjs",
|
|
53
|
+
"smoke:registry": "node scripts/npm-registry-smoke.mjs",
|
|
54
|
+
"demo:build-week": "bash scripts/build-week-demo.sh",
|
|
50
55
|
"test": "uv run pytest",
|
|
51
56
|
"lint": "uv run ruff check .",
|
|
52
57
|
"typecheck": "uv run mypy src",
|
package/pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "devcouncil"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "Gated orchestrator for AI-assisted software development"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -11,7 +11,7 @@ dependencies = [
|
|
|
11
11
|
"pyyaml>=6.0.1",
|
|
12
12
|
"sqlmodel>=0.0.19",
|
|
13
13
|
"httpx>=0.27.0",
|
|
14
|
-
"gitpython>=3.1.
|
|
14
|
+
"gitpython>=3.1.53",
|
|
15
15
|
"mcp>=1.27.2",
|
|
16
16
|
"gepa>=0.1.1",
|
|
17
17
|
"watchdog>=4.0.0",
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Provider-free red→green evidence-gate demo for OpenAI Build Week judges.
|
|
3
|
+
#
|
|
4
|
+
# Creates an isolated calculator git repo, runs `dev check --verify` against a
|
|
5
|
+
# deliberately buggy change (blocking / red), applies the real repair + regression
|
|
6
|
+
# test, then reruns to a compiled zero-gap (green) pass. No API keys required.
|
|
7
|
+
#
|
|
8
|
+
# Usage (checkout):
|
|
9
|
+
# bash scripts/build-week-demo.sh
|
|
10
|
+
#
|
|
11
|
+
# From npm global install (preferred judge path):
|
|
12
|
+
# npm install -g devcouncil@0.4.2
|
|
13
|
+
# devcouncil-build-week-demo
|
|
14
|
+
#
|
|
15
|
+
# Optional:
|
|
16
|
+
# BUILD_WEEK_DEMO_ROOT=/tmp/my-demo bash scripts/build-week-demo.sh
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
21
|
+
SAMPLE_DIR="${REPO_ROOT}/examples/build-week-demo"
|
|
22
|
+
GOAL='sub returns a - b'
|
|
23
|
+
TEST_CMD='python test_calc.py'
|
|
24
|
+
|
|
25
|
+
if [[ ! -f "${SAMPLE_DIR}/calc.py" || ! -f "${SAMPLE_DIR}/broken_calc.py" || ! -f "${SAMPLE_DIR}/test_calc.py" ]]; then
|
|
26
|
+
echo "error: missing sample files under ${SAMPLE_DIR}" >&2
|
|
27
|
+
exit 2
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
resolve_dev() {
|
|
31
|
+
if [[ -n "${DEVCOUNCIL_DEV_BIN:-}" && -x "${DEVCOUNCIL_DEV_BIN}" ]]; then
|
|
32
|
+
printf '%s\n' "${DEVCOUNCIL_DEV_BIN}"
|
|
33
|
+
return
|
|
34
|
+
fi
|
|
35
|
+
if [[ -x "${REPO_ROOT}/.venv/bin/dev" ]]; then
|
|
36
|
+
printf '%s\n' "${REPO_ROOT}/.venv/bin/dev"
|
|
37
|
+
return
|
|
38
|
+
fi
|
|
39
|
+
if command -v dev >/dev/null 2>&1; then
|
|
40
|
+
command -v dev
|
|
41
|
+
return
|
|
42
|
+
fi
|
|
43
|
+
if [[ -x "${REPO_ROOT}/.venv/bin/python" ]]; then
|
|
44
|
+
printf '%s\n' "${REPO_ROOT}/.venv/bin/python -m devcouncil"
|
|
45
|
+
return
|
|
46
|
+
fi
|
|
47
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
48
|
+
printf '%s\n' "python3 -m devcouncil"
|
|
49
|
+
return
|
|
50
|
+
fi
|
|
51
|
+
echo "error: could not find a DevCouncil CLI (dev / python -m devcouncil)" >&2
|
|
52
|
+
exit 2
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
DEV_BIN="$(resolve_dev)"
|
|
56
|
+
# shellcheck disable=SC2206
|
|
57
|
+
DEV=( ${DEV_BIN} )
|
|
58
|
+
|
|
59
|
+
PROVIDER_FREE_ENV=(
|
|
60
|
+
-u OPENAI_API_KEY
|
|
61
|
+
-u ANTHROPIC_API_KEY
|
|
62
|
+
-u OPENROUTER_API_KEY
|
|
63
|
+
-u GEMINI_API_KEY
|
|
64
|
+
-u GOOGLE_API_KEY
|
|
65
|
+
-u AZURE_OPENAI_API_KEY
|
|
66
|
+
-u COHERE_API_KEY
|
|
67
|
+
-u MISTRAL_API_KEY
|
|
68
|
+
-u GROQ_API_KEY
|
|
69
|
+
-u DEEPSEEK_API_KEY
|
|
70
|
+
-u TOGETHER_API_KEY
|
|
71
|
+
-u FIREWORKS_API_KEY
|
|
72
|
+
-u XAI_API_KEY
|
|
73
|
+
-u DEVCOUNCIL_API_KEY
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
run_check() {
|
|
77
|
+
local label="$1"
|
|
78
|
+
echo
|
|
79
|
+
echo "────────────────────────────────────────────────────────────"
|
|
80
|
+
echo " ${label}"
|
|
81
|
+
echo "────────────────────────────────────────────────────────────"
|
|
82
|
+
# Keep set +e through return: a non-zero return under set -e aborts the script.
|
|
83
|
+
set +e
|
|
84
|
+
env "${PROVIDER_FREE_ENV[@]}" "${DEV[@]}" check --verify \
|
|
85
|
+
--project-root "${DEMO_ROOT}" \
|
|
86
|
+
--goal "${GOAL}" \
|
|
87
|
+
--test "${TEST_CMD}"
|
|
88
|
+
local rc=$?
|
|
89
|
+
return "${rc}"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if [[ -n "${BUILD_WEEK_DEMO_ROOT:-}" ]]; then
|
|
93
|
+
DEMO_ROOT="${BUILD_WEEK_DEMO_ROOT}"
|
|
94
|
+
rm -rf "${DEMO_ROOT}"
|
|
95
|
+
mkdir -p "${DEMO_ROOT}"
|
|
96
|
+
else
|
|
97
|
+
_tmp="${TMPDIR:-/tmp}"
|
|
98
|
+
DEMO_ROOT="$(mktemp -d "${_tmp%/}/devcouncil-build-week-demo.XXXXXX")"
|
|
99
|
+
unset _tmp
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
echo "DevCouncil Build Week demo"
|
|
103
|
+
echo " CLI: ${DEV_BIN}"
|
|
104
|
+
echo " Sample templates: ${SAMPLE_DIR}"
|
|
105
|
+
echo " Generated repo: ${DEMO_ROOT}"
|
|
106
|
+
echo
|
|
107
|
+
echo "Judges: leave this path open to inspect the repaired working tree."
|
|
108
|
+
|
|
109
|
+
cd "${DEMO_ROOT}"
|
|
110
|
+
git init -q
|
|
111
|
+
git config user.email "build-week-demo@devcouncil.local"
|
|
112
|
+
git config user.name "DevCouncil Build Week Demo"
|
|
113
|
+
|
|
114
|
+
cat > calc.py <<'EOF'
|
|
115
|
+
def add(a: int, b: int) -> int:
|
|
116
|
+
return a + b
|
|
117
|
+
EOF
|
|
118
|
+
git add calc.py
|
|
119
|
+
git commit -q -m "baseline: add()"
|
|
120
|
+
|
|
121
|
+
cp "${SAMPLE_DIR}/broken_calc.py" calc.py
|
|
122
|
+
cp "${SAMPLE_DIR}/test_calc.py" test_calc.py
|
|
123
|
+
|
|
124
|
+
echo
|
|
125
|
+
echo ">>> Phase 1: RED — expect a blocking evidence-gate failure"
|
|
126
|
+
START_TS="${SECONDS}"
|
|
127
|
+
set +e
|
|
128
|
+
run_check "RED verdict (blocking gaps expected)"
|
|
129
|
+
RED_RC=$?
|
|
130
|
+
set -e
|
|
131
|
+
|
|
132
|
+
if [[ "${RED_RC}" -eq 0 ]]; then
|
|
133
|
+
echo
|
|
134
|
+
echo "error: expected RED (non-zero) from dev check --verify, got exit 0" >&2
|
|
135
|
+
echo "Generated repo left at: ${DEMO_ROOT}" >&2
|
|
136
|
+
exit 1
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
echo
|
|
140
|
+
echo "RED confirmed (exit ${RED_RC}): blocking gaps — change is not verified."
|
|
141
|
+
|
|
142
|
+
cp "${SAMPLE_DIR}/calc.py" calc.py
|
|
143
|
+
|
|
144
|
+
echo
|
|
145
|
+
echo ">>> Phase 2: GREEN — apply repair + regression test, expect zero-gap pass"
|
|
146
|
+
set +e
|
|
147
|
+
run_check "GREEN verdict (compiled, zero blocking gaps expected)"
|
|
148
|
+
GREEN_RC=$?
|
|
149
|
+
set -e
|
|
150
|
+
|
|
151
|
+
if [[ "${GREEN_RC}" -ne 0 ]]; then
|
|
152
|
+
echo
|
|
153
|
+
echo "error: expected GREEN (exit 0) after repair, got exit ${GREEN_RC}" >&2
|
|
154
|
+
echo "Generated repo left at: ${DEMO_ROOT}" >&2
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
GREEN_JSON_FILE="${DEMO_ROOT}/.devcouncil-demo-green.json"
|
|
159
|
+
set +e
|
|
160
|
+
env "${PROVIDER_FREE_ENV[@]}" "${DEV[@]}" check --verify \
|
|
161
|
+
--project-root "${DEMO_ROOT}" \
|
|
162
|
+
--goal "${GOAL}" \
|
|
163
|
+
--test "${TEST_CMD}" \
|
|
164
|
+
--json > "${GREEN_JSON_FILE}"
|
|
165
|
+
JSON_RC=$?
|
|
166
|
+
set -e
|
|
167
|
+
if [[ "${JSON_RC}" -ne 0 ]]; then
|
|
168
|
+
echo "error: green JSON re-check failed with exit ${JSON_RC}" >&2
|
|
169
|
+
exit 1
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
python3 - "${GREEN_JSON_FILE}" <<'PY'
|
|
173
|
+
import json, sys
|
|
174
|
+
from pathlib import Path
|
|
175
|
+
payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
176
|
+
if not payload.get("verified", False):
|
|
177
|
+
raise SystemExit("green JSON missing verified=true")
|
|
178
|
+
if int(payload.get("blocking_gap_count", 1)) != 0:
|
|
179
|
+
raise SystemExit(f"green JSON still has blocking gaps: {payload.get('blocking_gap_count')}")
|
|
180
|
+
if int(payload.get("gap_count", 1)) != 0:
|
|
181
|
+
raise SystemExit(f"green JSON still has gaps: {payload.get('gap_count')}")
|
|
182
|
+
mode = str(payload.get("verification_mode", ""))
|
|
183
|
+
if mode != "compiled":
|
|
184
|
+
raise SystemExit(f"expected verification_mode=compiled, got {mode!r}")
|
|
185
|
+
print(f"JSON confirmed: verified=true, gaps=0, mode={mode}")
|
|
186
|
+
PY
|
|
187
|
+
|
|
188
|
+
ELAPSED=$((SECONDS - START_TS))
|
|
189
|
+
echo
|
|
190
|
+
echo "════════════════════════════════════════════════════════════"
|
|
191
|
+
echo " Demo complete: RED then GREEN in ${ELAPSED}s"
|
|
192
|
+
echo " Generated repository (inspect me):"
|
|
193
|
+
echo " ${DEMO_ROOT}"
|
|
194
|
+
echo "════════════════════════════════════════════════════════════"
|
|
195
|
+
|
|
196
|
+
if [[ "${ELAPSED}" -gt 60 ]]; then
|
|
197
|
+
echo "warning: demo took ${ELAPSED}s (>60s target after package install)" >&2
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
exit 0
|
|
@@ -210,23 +210,20 @@ def status(
|
|
|
210
210
|
|
|
211
211
|
if payload["pending_signal_items"]:
|
|
212
212
|
table = Table(title="Pending Agent Responses")
|
|
213
|
-
table.add_column("
|
|
213
|
+
table.add_column("ID", style="cyan")
|
|
214
|
+
table.add_column("Client")
|
|
214
215
|
table.add_column("Task")
|
|
215
|
-
table.add_column("Transcript", overflow="fold")
|
|
216
|
-
table.add_column("Review Command", overflow="fold")
|
|
217
216
|
for signal in payload["pending_signal_items"]:
|
|
218
217
|
table.add_row(
|
|
218
|
+
signal.get("id") or "",
|
|
219
219
|
signal.get("client") or "",
|
|
220
220
|
signal.get("task_id") or "(unscoped)",
|
|
221
|
-
signal.get("transcript_path") or "",
|
|
222
|
-
signal.get("review_command") or "",
|
|
223
221
|
)
|
|
224
222
|
console.print(table)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
console.print(command)
|
|
223
|
+
console.print(
|
|
224
|
+
"[dim]Sensitive transcript paths and review commands: "
|
|
225
|
+
"`dev watch signals` / `dev watch review`.[/dim]"
|
|
226
|
+
)
|
|
230
227
|
|
|
231
228
|
|
|
232
229
|
@app.command("resolve")
|
|
@@ -47,7 +47,7 @@ def _vendor_js() -> str:
|
|
|
47
47
|
"nodeVal:function(){return this},linkColor:function(){return this},"
|
|
48
48
|
"linkDirectionalParticles:function(){return this},"
|
|
49
49
|
"linkDirectionalParticleWidth:function(){return this},"
|
|
50
|
-
"onNodeClick:function(){return this},
|
|
50
|
+
"onNodeClick:function(){return this},"
|
|
51
51
|
"width:function(){return this},height:function(){return this},_missing:true};};"
|
|
52
52
|
)
|
|
53
53
|
|
|
@@ -321,6 +321,8 @@ label {{ color:var(--muted); font-size:12px; display:block; }}
|
|
|
321
321
|
label.inline {{ display:flex; align-items:center; gap:6px; margin:4px 0; }}
|
|
322
322
|
label.inline input {{ width:auto; margin:0; }}
|
|
323
323
|
#detail {{ margin-top:8px; font-size:12px; color:var(--muted); white-space:pre-wrap; }}
|
|
324
|
+
.interaction-hint {{ margin:8px 0; padding:8px; border:1px solid #334155; border-radius:4px; background:#0f1419; color:var(--fg); font-size:12px; line-height:1.45; }}
|
|
325
|
+
#counts {{ margin:8px 0 4px; font-size:12px; color:var(--accent); font-weight:600; }}
|
|
324
326
|
.flag-dead {{ color:var(--dead); }}
|
|
325
327
|
.badge-entry {{ color:var(--entry); font-weight:600; }}
|
|
326
328
|
.list {{ list-style:none; padding:0; margin:0; font-size:12px; }}
|
|
@@ -342,6 +344,8 @@ label.inline input {{ width:auto; margin:0; }}
|
|
|
342
344
|
</div>
|
|
343
345
|
<div id="panel-graph" class="panel active">
|
|
344
346
|
<h1>DevCouncil Code Graph</h1>
|
|
347
|
+
<div id="counts" aria-live="polite">Nodes: -- · Edges: -- · Filtered: --</div>
|
|
348
|
+
<div class="interaction-hint" id="interactionHint"><strong>Click</strong> a node for details. <strong>Select two nodes</strong> to highlight the shortest path. <strong>Double-click</strong> a node to expand its neighborhood.</div>
|
|
345
349
|
<label>Mode</label>
|
|
346
350
|
<select id="mode"><option value="file">File-level</option><option value="symbol">Symbol-level</option></select>
|
|
347
351
|
<label>Search</label>
|
|
@@ -360,7 +364,7 @@ label.inline input {{ width:auto; margin:0; }}
|
|
|
360
364
|
<label>Dead confidence</label>
|
|
361
365
|
<select id="deadConf"><option value="">(any)</option><option>extracted</option><option>inferred</option><option>ambiguous</option></select>
|
|
362
366
|
<div class="row"><button class="primary" id="reset">Reset view</button><button class="primary" id="clearPath">Clear path</button></div>
|
|
363
|
-
<div id="detail">
|
|
367
|
+
<div id="detail" class="muted">Select a node to inspect callers, callees, and path state.</div>
|
|
364
368
|
</div>
|
|
365
369
|
<div id="panel-dead" class="panel">
|
|
366
370
|
<h1>Dead code</h1>
|
|
@@ -565,7 +569,16 @@ const g = Graph(elem)
|
|
|
565
569
|
if (pathHighlight.size && pathHighlight.has(s) && pathHighlight.has(t)) return 3;
|
|
566
570
|
return 1.5;
|
|
567
571
|
}})
|
|
568
|
-
.onNodeClick(n => {{
|
|
572
|
+
.onNodeClick((n, event) => {{
|
|
573
|
+
// ForceGraph exposes click events but no double-click chain method.
|
|
574
|
+
// The native event detail increments for a double click, so use it to
|
|
575
|
+
// preserve neighbor expansion without depending on a nonexistent API.
|
|
576
|
+
if (event && event.detail >= 2) {{
|
|
577
|
+
const links = activePayload().links;
|
|
578
|
+
expandIds = neighborExpand(n.id, links, 1);
|
|
579
|
+
redraw();
|
|
580
|
+
return;
|
|
581
|
+
}}
|
|
569
582
|
showDetail(n);
|
|
570
583
|
if (selected.length === 1 && selected[0] === n.id) {{ selected = []; pathHighlight = new Set(); redraw(); return; }}
|
|
571
584
|
if (selected.length >= 2) selected = [];
|
|
@@ -577,18 +590,31 @@ const g = Graph(elem)
|
|
|
577
590
|
showDetail(n);
|
|
578
591
|
}}
|
|
579
592
|
redraw();
|
|
580
|
-
}})
|
|
581
|
-
.onNodeDblClick(n => {{
|
|
582
|
-
const links = activePayload().links;
|
|
583
|
-
expandIds = neighborExpand(n.id, links, 1);
|
|
584
|
-
redraw();
|
|
585
593
|
}});
|
|
586
594
|
|
|
595
|
+
function updateCounts(fd) {{
|
|
596
|
+
const totalNodes = (activePayload().nodes || []).length;
|
|
597
|
+
const totalEdges = (activePayload().links || []).length;
|
|
598
|
+
const shownNodes = (fd.nodes || []).length;
|
|
599
|
+
const shownEdges = (fd.links || []).length;
|
|
600
|
+
const el = document.getElementById("counts");
|
|
601
|
+
if (el) el.textContent = "Nodes: " + shownNodes + " / " + totalNodes + " · Edges: " + shownEdges + " / " + totalEdges + " · Filtered: " + Math.max(0, totalNodes - shownNodes) + (expandIds ? " · neighborhood focus" : "");
|
|
602
|
+
}}
|
|
603
|
+
|
|
604
|
+
function fitView() {{
|
|
605
|
+
if (g && typeof g.zoomToFit === 'function') {{
|
|
606
|
+
requestAnimationFrame(() => {{
|
|
607
|
+
try {{ g.zoomToFit(400, 40); }} catch (err) {{ /* vendor stub */ }}
|
|
608
|
+
}});
|
|
609
|
+
}}
|
|
610
|
+
}}
|
|
611
|
+
|
|
587
612
|
function redraw() {{
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
613
|
+
const fd = filtered();
|
|
614
|
+
g.graphData(fd);
|
|
615
|
+
g.nodeAutoColorBy(n => colorKey(n));
|
|
616
|
+
g.width(elem.clientWidth).height(elem.clientHeight);
|
|
617
|
+
updateCounts(fd);
|
|
592
618
|
}}
|
|
593
619
|
|
|
594
620
|
function renderDeadList() {{
|
|
@@ -720,6 +746,7 @@ document.getElementById('reset').addEventListener('click', () => {{
|
|
|
720
746
|
selected = [];
|
|
721
747
|
pathHighlight = new Set();
|
|
722
748
|
redraw();
|
|
749
|
+
fitView();
|
|
723
750
|
}});
|
|
724
751
|
document.getElementById('clearPath').addEventListener('click', () => {{
|
|
725
752
|
selected = [];
|
|
@@ -730,6 +757,7 @@ window.addEventListener('resize', () => g.width(elem.clientWidth).height(elem.cl
|
|
|
730
757
|
if (!g || typeof g.zoomToFit !== 'function') document.getElementById('vendorWarn').style.display = 'block';
|
|
731
758
|
refillArea();
|
|
732
759
|
redraw();
|
|
760
|
+
fitView();
|
|
733
761
|
renderDeadList();
|
|
734
762
|
renderCommunities();
|
|
735
763
|
renderProcesses();
|
|
@@ -38,6 +38,6 @@ async def handle_cli(root: Path, arguments: dict) -> list[TextContent]:
|
|
|
38
38
|
if forbidden:
|
|
39
39
|
return error_text("forbidden flag(s) through MCP: " + ", ".join(forbidden), code="forbidden_flags", flags=forbidden)
|
|
40
40
|
try:
|
|
41
|
-
return json_text(run_cli_command(args, root))
|
|
41
|
+
return json_text(run_cli_command(args, root, truncate=True))
|
|
42
42
|
except Exception as exc:
|
|
43
43
|
return error_text(str(exc), code="cli_execution_error")
|