Skip to content

Commit d2d1feb

Browse files
authored
feat: merge module map, bounded agent context, durable evidence, and review UX into main (#47)
This release consolidates the Phase 32–34 work into a broader structural-review, observability, and MCP-governance update. It adds a derived Module Map and review-queue model to the canonical report, exposes the new projections through MCP, and introduces dedicated HTML surfaces for module topology, guided review, and Overview-to-Review navigation. The HTML application now shares one dependency-graph layout, one finding-card system, one filter system, and a unified token set for badges, counters, controls, tables, depth, focus states, and metric visualizations. The analysis pipeline now records deterministic phase-level observability, including core micro-phases, logical SQL counts, context-unit estimates, benchmark scenarios, and expanded cockpit views. Cached and incremental execution paths are surfaced explicitly so maintainers can distinguish actual work from reused state. MCP responses now follow a bounded-context contract across start, finish, memory retrieval, implementation context, and report-section access. The update adds passive context-governance metadata, explicit drill-down reachability, compact continuation cursors, paginated report sections, bounded start/finish payloads, and exact retrieval routes for durable receipts, Patch Trails, and blast artifacts. Controlled-change workflows are hardened with idempotent start replay, stable workspace-intent identity hashing, finish receipt deduplication, typed external-artifact restrictions, improved claim validation for negated statements, and corrected trajectory/Patch Trail digest alignment. Engineering Memory receives several performance and integrity improvements: incremental semantic sourcing, delta-based experience replacement, batched hydration instead of N+1 reads, safe handling of failed source reads, compact continuation cursors, and support for JetBrains as an IDE governance client. Runtime reachability analysis is extended for FastAPI, Pydantic, and Starlette patterns. Corpus benchmarking is integrated into CI, benchmark summaries are expanded, and dependency/runtime constraints are refreshed for supported Python versions. The documentation, README, help topics, plugin skills, manifests, and client-specific copies are synchronized with the new Module Map, Review Hub, observability, context-governance, durable artifact retrieval, replay, and architecture-triage contracts. Tests are expanded across MCP workflows, memory retrieval, continuation binding, trajectory retrieval, plugin synchronization, fail-closed paths, and coverage gaps. Existing report, baseline, cache, fingerprint, finding, gate, and controller-permission semantics remain unchanged.
1 parent 3e3a05a commit d2d1feb

235 files changed

Lines changed: 24234 additions & 3988 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/benchmark.yml

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ jobs:
112112
env:
113113
RUNS: ${{ matrix.runs }}
114114
WARMUPS: ${{ matrix.warmups }}
115+
SCENARIO_PROFILE: ${{ matrix.profile }}
116+
STARTUP_RUNS: "3"
115117
CPUS: ${{ matrix.cpus }}
116118
MEMORY: ${{ matrix.memory }}
117119
run: |
@@ -125,6 +127,8 @@ jobs:
125127
--target . \
126128
--runs "${{ matrix.runs }}" \
127129
--warmups "${{ matrix.warmups }}" \
130+
--scenario-profile "${{ matrix.profile }}" \
131+
--startup-runs 3 \
128132
--tmp-dir "/tmp/codeclone-bench-${{ matrix.label }}" \
129133
--output "$BENCH_JSON"
130134
@@ -143,21 +147,39 @@ jobs:
143147
raise SystemExit(1)
144148
145149
payload = json.loads(report_path.read_text(encoding="utf-8"))
150+
startup_probes = payload.get("startup_probes", [])
146151
scenarios = payload.get("scenarios", [])
147152
comparisons = payload.get("comparisons", {})
148153
149154
print("CodeClone benchmark summary")
150155
print(f"label={os.environ.get('RUNNER_OS','unknown').lower()} / {os.environ.get('GITHUB_JOB','benchmark')}")
156+
if startup_probes:
157+
print("startup probes:")
158+
for probe in startup_probes:
159+
name = str(probe.get("name", "unknown"))
160+
stats = probe.get("stats_seconds", {})
161+
cpu_stats = probe.get("child_cpu_stats_seconds", {})
162+
print(
163+
f"- {name:22s} median={float(stats.get('median', 0.0)):.4f}s "
164+
f"first={float(probe.get('first_seconds', 0.0)):.4f}s "
165+
f"cpu={float(cpu_stats.get('median', 0.0)):.4f}s"
166+
)
151167
for scenario in scenarios:
152168
name = str(scenario.get("name", "unknown"))
153169
stats = scenario.get("stats_seconds", {})
170+
cpu_stats = scenario.get("child_cpu_stats_seconds", {})
171+
inventory = scenario.get("inventory_sample", {})
154172
median = float(stats.get("median", 0.0))
155173
p95 = float(stats.get("p95", 0.0))
156174
stdev = float(stats.get("stdev", 0.0))
157175
digest = str(scenario.get("digest", ""))
158176
print(
159177
f"- {name:16s} median={median:.4f}s "
160-
f"p95={p95:.4f}s stdev={stdev:.4f}s digest={digest}"
178+
f"p95={p95:.4f}s stdev={stdev:.4f}s "
179+
f"cpu={float(cpu_stats.get('median', 0.0)):.4f}s "
180+
f"files={inventory.get('analyzed', 0)}/{inventory.get('cached', 0)} "
181+
f"artifacts={float(scenario.get('artifact_total_kib_sample', 0.0)):.1f}KiB "
182+
f"exit={scenario.get('exit_code_counts', {})} digest={digest}"
161183
)
162184
163185
if comparisons:
@@ -174,24 +196,57 @@ jobs:
174196
"",
175197
f"- Tool: `{payload['tool']['name']} {payload['tool']['version']}`",
176198
f"- Target: `{payload['config']['target']}`",
199+
f"- Scenario profile: `{payload['config'].get('scenario_profile', 'smoke')}`",
177200
f"- Runs: `{payload['config']['runs']}`",
178201
f"- Warmups: `{payload['config']['warmups']}`",
202+
f"- Startup runs: `{payload['config'].get('startup_runs', 0)}`",
179203
f"- Generated: `{payload['generated_at_utc']}`",
180204
"",
181-
"### Scenarios",
182-
"",
183-
"| Scenario | Median (s) | p95 (s) | Stdev (s) | Deterministic | Digest |",
184-
"|---|---:|---:|---:|:---:|---|",
185205
]
186206
207+
if startup_probes:
208+
lines.extend(
209+
[
210+
"### Startup / Import Probes",
211+
"",
212+
"| Probe | Median (s) | First (s) | CPU Median (s) |",
213+
"|---|---:|---:|---:|",
214+
]
215+
)
216+
for probe in startup_probes:
217+
stats = probe.get("stats_seconds", {})
218+
cpu_stats = probe.get("child_cpu_stats_seconds", {})
219+
lines.append(
220+
"| "
221+
f"{probe.get('name', '')} | "
222+
f"{float(stats.get('median', 0.0)):.4f} | "
223+
f"{float(probe.get('first_seconds', 0.0)):.4f} | "
224+
f"{float(cpu_stats.get('median', 0.0)):.4f} |"
225+
)
226+
lines.append("")
227+
228+
lines.extend(
229+
[
230+
"### Scenarios",
231+
"",
232+
"| Scenario | Median (s) | p95 (s) | CPU Median (s) | Files A/C | Artifacts KiB | Exit | Deterministic | Digest |",
233+
"|---|---:|---:|---:|---:|---:|---|:---:|---|",
234+
]
235+
)
236+
187237
for scenario in scenarios:
188238
stats = scenario.get("stats_seconds", {})
239+
cpu_stats = scenario.get("child_cpu_stats_seconds", {})
240+
inventory = scenario.get("inventory_sample", {})
189241
lines.append(
190242
"| "
191243
f"{scenario.get('name', '')} | "
192244
f"{float(stats.get('median', 0.0)):.4f} | "
193245
f"{float(stats.get('p95', 0.0)):.4f} | "
194-
f"{float(stats.get('stdev', 0.0)):.4f} | "
246+
f"{float(cpu_stats.get('median', 0.0)):.4f} | "
247+
f"{inventory.get('analyzed', 0)}/{inventory.get('cached', 0)} | "
248+
f"{float(scenario.get('artifact_total_kib_sample', 0.0)):.1f} | "
249+
f"{scenario.get('exit_code_counts', {})} | "
195250
f"{'yes' if bool(scenario.get('deterministic')) else 'no'} | "
196251
f"{scenario.get('digest', '')} |"
197252
)

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
uses: actions/configure-pages@v5
4040

4141
- name: Build docs site
42-
run: uv run --with zensical==0.0.43 zensical build --clean --strict
42+
run: uv run --with zensical==0.0.46 zensical build --clean --strict
4343

4444
- name: Generate sample report artifacts
4545
run: uv run python scripts/build_docs_example_report.py --output-dir site/examples/report/live
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: validation-corpus
2+
run-name: validation corpus • ${{ github.event_name }} • ${{ github.ref_name }}
3+
4+
on:
5+
push:
6+
branches: [ "**" ]
7+
pull_request:
8+
workflow_dispatch:
9+
inputs:
10+
tier:
11+
description: Corpus tier
12+
required: true
13+
default: all
14+
type: choice
15+
options:
16+
- smoke
17+
- gates
18+
- full
19+
- all
20+
corpus-ref:
21+
description: codeclone-validation-corpus ref
22+
required: true
23+
default: main
24+
25+
permissions:
26+
contents: read
27+
28+
concurrency:
29+
group: validation-corpus-${{ github.event.pull_request.number || github.ref }}
30+
cancel-in-progress: true
31+
32+
jobs:
33+
validation-corpus:
34+
name: corpus
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 20
37+
38+
steps:
39+
- name: Checkout CodeClone
40+
uses: actions/checkout@v6.0.2
41+
42+
- name: Checkout validation corpus
43+
uses: actions/checkout@v6.0.2
44+
with:
45+
repository: orenlab/codeclone-validation-corpus
46+
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.corpus-ref || 'main' }}
47+
path: validation-corpus
48+
49+
- name: Set up Python
50+
uses: actions/setup-python@v6.2.0
51+
with:
52+
python-version: "3.14"
53+
allow-prereleases: true
54+
55+
- name: Set up uv
56+
uses: astral-sh/setup-uv@v5
57+
with:
58+
enable-cache: true
59+
60+
- name: Install CodeClone from this checkout
61+
run: uv sync --all-extras
62+
63+
- name: Install validation corpus dependencies
64+
run: uv sync --project validation-corpus
65+
66+
- name: Resolve corpus tier
67+
shell: bash
68+
run: |
69+
tier="all"
70+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
71+
tier="${{ inputs.tier }}"
72+
fi
73+
echo "CORPUS_TIER=$tier" >> "$GITHUB_ENV"
74+
75+
- name: Run validation corpus
76+
run: |
77+
uv run --project validation-corpus python -m corpus_tools.cli \
78+
--tier "$CORPUS_TIER" \
79+
--codeclone-command "$GITHUB_WORKSPACE/.venv/bin/python -m codeclone.main" \
80+
--work-root "$RUNNER_TEMP/codeclone-validation-corpus-work"
81+
82+
- name: Write summary
83+
if: always()
84+
shell: bash
85+
run: |
86+
{
87+
echo "## CodeClone validation corpus"
88+
echo
89+
echo "- Tier: \`${CORPUS_TIER:-unknown}\`"
90+
echo "- Corpus: \`orenlab/codeclone-validation-corpus\`"
91+
echo "- CodeClone source: current checkout"
92+
} >> "$GITHUB_STEP_SUMMARY"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,5 @@ extensions/vscode-codeclone/node_modules
5252
/coverage.json
5353
/benchmarks/memory_semantic_eval.md
5454
/scripts/commit_memory_phases.sh
55+
/extensions/jetbrains-codeclone/
56+
/issues/

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ If you touched baseline/cache/report contracts or CLI/MCP audit surfaces, also e
156156
If you touched `docs/`, `zensical.toml`, docs publishing workflow, or sample-report generation, also run:
157157

158158
```bash
159-
uv run --with zensical==0.0.43 zensical build --clean --strict
159+
uv run --with zensical==0.0.46 zensical build --clean --strict
160160
```
161161

162162
If you touched the MCP surface, also run:

0 commit comments

Comments
 (0)