Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ccc/ccc-surface.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema": "ccc-surface/1",
"name": "codecache",
"name": "code-change-capture",
"generated": "20260921-21-51-30",
"languages": ["rust", "typescript"],
"provides": [],
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/target
*.bin
/example/
/examples
bench/
/dist

Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ to pick the new one up.
- a symbol: take the handle a `find` / `references` answer ends with and pass it to `edit_rename`,
`edit_replace`, `edit_delete` or `edit_insert`
- anything else (lines inside a function, docs, config, a new or removed file): `edit_text`
- a moved or renamed file or directory: `edit_move`, never `mv`
- read the staged diff, then `edit_apply`; `edit_discard` drops a changeset, `edit_revert` undoes an applied one
- `edit_apply` rescans the map before it answers; call `refresh` only after a change made outside ccc.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Because the static analyser provides an overwhelming amount of data; I've added
- **Controls** - All replays are encrypted by default for repo owners [runccc teams](https://teams.runccc.dev)
- **Info Sec** - Search can be restricted to allow/block list
- **Info Sec** - Bash/terminal use is disabled
- **Audit** - Violations are tracked by ccc and reported on for the engineer
- **Audit** - Violations reported for human review

## Install

Expand All @@ -46,8 +46,14 @@ Run ccc from a terminal or a pipeline. Serve the map to your agents, see what a

**[CLI.md](docs/CLI.md)** has one section per command: the command, its options, and what it is for.

### 2. Advanced
### 2. Developers And Agents

Watch and review the work. Explore the project in the architecture visualiser, get hints in VS Code, and replay how an agent made a change.

**[Advanced.md](docs/Advanced.md)** has one section each for the visualiser, IDEs and replays.
**[Developers And Agents](docs/Advanced.md)** has one section each for the visualiser, IDEs and replays.

### 3. Runtime Instrumentation

Record one run of your test suites with ccc's probes in, and ccc knows which tests actually ran which functions, across every service and language they passed through. For any change, it picks the tests that ran the changed code. In the [examples](examples), changes that would otherwise run the whole 50-test suite need between 1 and 5 tests.

**[Instrumentation.md](docs/Instrumentation.md)** covers what the examples prove, how tests and services are instrumented, and how to record in CI.
7 changes: 3 additions & 4 deletions docs/Advanced.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<p align="center" style="width:100%"><a href="https://github.com/colwill/ccc" target="_blank"><img src="../visual.png" alt="Code Change Capture Visualiser Example"></a></p>

# Advanced
# Developers And Agents

Ways to see and review what changed, beyond the command line:

Expand All @@ -23,7 +23,7 @@ ccc run --vis

| Level | Boxes | Arrows |
|---|---|---|
| Context | the system; peer repositories from `externals` in `.ccc/map.json`; endpoints nothing in the map answers | `ccc:calls` / `ccc:serves` crossings, by transport |
| Context | the system; peer repositories from `externals` in `.ccc/map.json`; endpoints nothing in the map answers | cross-calls, by transport |
| Containers | services from `.ccc/map.json`, or top-level directories without one | resolved and declared calls between services |
| Components | the files in one container; other containers it touches sit outside the boundary | file-to-file calls |
| Code | the functions in one file, each with an input pin and one output pin per function it calls | resolved calls; functions in other files as stand-ins |
Expand Down Expand Up @@ -103,7 +103,6 @@ To build only the extension: `cd extensions/vscode && npm install && npm run pac
| `▲ 37 callers` | A hot path: among the most called, most complex or widest fan-out. |
| `↻ cycle of 3` | The function is in a call cycle. |
| `↑ calls billing in acme/billing` | The call leaves the repository. Opens the handler when that peer is checked out locally. |
| `? billing.v1.Charge unanswered` | A `ccc:calls` whose key nothing serves: a typo at one end, or a peer missing from `externals`. |

Test, coverage and service-boundary hints are based on the diff. A file identical to the base ref has none, by design. Hot paths and cycles come from the call graph alone, so they show on any file. Every function also shows its complexity as a circled number from 1 to 10 between its name and signature, coloured from grey to red as it climbs.

Expand Down Expand Up @@ -182,7 +181,7 @@ This repo has a Code Change Capture (ccc) map, served over MCP. Use it as the en
- Every interaction: use `ccc` tool calls to gather information about the source of this project.
- All thinking, navigation, and questions about the codebase go through the MCP server tools: (index, find, references, dependencies, vulnerabilities, deps, security, file, notes, changes, prompts, pr_summary, test_triggers, test_targets, lints, hot, services, search, violations, refresh)
- The web, internal docs and portals included, goes through `search`: `query` to search the configured endpoints, `url` to fetch one https page. Never WebFetch, WebSearch, another MCP server's fetch or browser tool, or `curl`/`wget` - ccc can't track those, and `violations` reports each one. If `search` refuses a URL, leave it unreached.
- ccc is the only writer: make every change through its edit tools - `edit_rename`, `edit_replace`, `edit_delete`, `edit_insert` or `edit_text`, then `edit_apply` - never your own Edit/Write tools, `sed -i` or shell redirection. `edit_discard` drops a staged changeset and `edit_revert` undoes an applied one.
- ccc is the only writer: make every change through its edit tools - `edit_rename`, `edit_replace`, `edit_delete`, `edit_insert`, `edit_text` or `edit_move`, then `edit_apply` - never your own Edit/Write tools, `sed -i`, `mv` or shell redirection. `edit_discard` drops a staged changeset and `edit_revert` undoes an applied one.
- `edit_apply` rescans the map before it answers; call `refresh` only after a change made outside ccc.
```

Expand Down
46 changes: 41 additions & 5 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ claude mcp add --transport http ccc http://127.0.0.1:6767/mcp # Claude Code
copilot mcp add --transport http ccc http://127.0.0.1:6767/mcp # Copilot
```

Then tell your agent to use the `ccc` MCP tools. [Advanced.md](Advanced.md#agents) has an `AGENTS.md` block that does this.
Then tell your agent to use the `ccc` MCP tools. [Developers And Agents](Advanced.md#agents) has an `AGENTS.md` block that does this.

## Commands

Expand All @@ -22,6 +22,7 @@ Then tell your agent to use the `ccc` MCP tools. [Advanced.md](Advanced.md#agent
| [`ccc run`](#ccc-run) | Serving the map to agents (MCP) and people (the visualiser) |
| [`ccc changes`](#ccc-changes) | What a branch changed, function by function, and which services it puts at risk |
| [`ccc insights`](#ccc-insights) | The full analysis as JSON, including which tests to run for the branch |
| [`ccc probe`](#ccc-probe) | A copy of the project that records which tests ran which functions |
| [`ccc deps`](#ccc-deps) | What a branch did to the dependency tree |
| [`ccc audit`](#ccc-audit) | Known vulnerabilities in your locked dependencies |
| [`ccc sast`](#ccc-sast) | Security risks in your own source |
Expand Down Expand Up @@ -183,24 +184,59 @@ Each line of a record file is one JSON object, `ccc-observed/1`: one fixture, as
"run": "nightly-4812",
"service": {"name": "billing", "commit": "3f2a9c1e"},
"duration_ms": 1840,
"files": [{"path": "internal/billing/fee.go", "functions": [{"name": "(*Server).ApplyFee", "line": 88}]}]}
"files": [{"path": "internal/billing/fee.go", "functions": [{"name": "(*Server).ApplyFee", "line": 88, "calls": 3}]}]}
```

- `fixture.name` is what the test runner selects it by. `kind` is `unit`, `contract`, `interop`, `integration` or `smoke`.
- `fixture.name` is what the test runner selects it by. `kind` is `unit`, `contract`, `interop`, `integration`, `smoke` or `load`.
- `files[].path` is relative to the repository root. An absolute path is matched by its tail, so a CI checkout's paths work. A relative path the map doesn't hold belongs to another repository, and is counted as unmatched.
- A function is matched by name, then by owner, then by the nearest line, so a recording keeps matching after the code moves. A probe that sees lines rather than functions can send `"lines": [[start, end], ...]` instead. Those are used only while the file is unchanged since `service.commit`.
- `calls` is how many times the fixture ran the function in that process. It is optional. A function listed without it still counts as run, just without a count. The counts from every service in one `run` are added together. When a fixture appears in several runs, ccc keeps its highest total, so a rerun doesn't double it.

With records:

- A function a fixture ran counts as tested. The fixture is listed first among the tests that cover it, with evidence `observed`.
- `test_triggers.observed` lists the fixtures that ran the branch's changed functions, two ways, each with its own run commands:
- `safe`, the default: every fixture that ran a changed function.
- `minimal`: the cheapest fixtures that still run each changed function once. A fixture costs its recorded duration, weighted by kind: unit 1, contract 2, interop 3, integration 4, smoke 5. The set is the cheapest possible unless `exact` is `false`.
- `minimal`: the cheapest fixtures that still run each changed function once. A fixture costs its recorded duration, weighted by kind: unit 1, contract 2, interop 3, integration 4, smoke 5, load 6. The set is the cheapest possible unless `exact` is `false`.
- Each chosen fixture lists the changed functions it ran under `ran`, with the `calls` the records gave each one. A tested-by row with evidence `observed` carries `calls` too. The `test_triggers` tool prints them as `Checksum ×2`, and the VS Code hover says how many times the run saw each test execute the function. The counts don't change which fixtures are chosen.
- `test_triggers.observed.unobserved` lists the changed functions no fixture ran. The static `run` list is all there is for those.
- The static `run` list stays as it was. A test written since the recording exists only in the source.

Agents get the same from the `test_triggers` tool. `select: "minimal"` asks for the cheaper set.

[`ccc probe`](#ccc-probe) produces records. What they change on the example projects is in [Instrumentation.md](Instrumentation.md).

## ccc probe

Writes a copy of the project with ccc's runtime probes in. One run of your suites in the copy records which tests executed which functions, across every service and language the tests reach. Those records are what [observed coverage](#observed-coverage) reads. The project itself is never changed.

```sh
ccc probe go . --out /tmp/probed # one language
ccc probe go,python . --out /tmp/probed # several, into one copy
ccc probe rust services/billing --out /tmp/billing --kind 'tests/e2e/**=smoke'
```

In the copy:

- Every function the map holds counts its runs, under the name and owner the map gives it.
- Every test names itself a fixture: Go `TestXxx`, Rust `#[test]` and its kin, pytest tests and unittest methods, `it` and `test` callbacks, and gtest, Catch2, doctest and Boost.Test macros.
- Servers, clients and work handed to other threads carry the fixture, between processes as a W3C `baggage` header or gRPC metadata.
- The runtime goes in `.ccc-probe/`, or in `node_modules/ccc-probe` for TypeScript, and the build files that need to find it are edited.

Probes go in on the line they belong to, so the copy keeps every line number. Python is the exception, for a function that opens with a block statement. [Instrumentation.md](Instrumentation.md#instrumenting-a-project) lists what each language covers.

The probes record nothing until `CCC_OBSERVED_DIR` names a directory. `CCC_SERVICE` names the process in its records, `CCC_RUN` names the run, and `CCC_COMMIT` overrides the commit the copy was made from.

| Option | Default | What it does |
|---|---|---|
| `LANG` | required | `go`, `rust`, `cpp` (or `c++`), `typescript` (or `ts`) or `python` (or `py`). Comma-separate several to probe them into one copy. |
| `PATH` | `.` | The project, or the part of it, to instrument. |
| `--out DIR` | required | Where the copy goes. |
| `--kind GLOB=KIND` | from the path | The fixture kind of the tests a glob matches: `unit`, `contract`, `interop`, `integration`, `smoke` or `load`. Repeatable, and the first match wins. Without one, the kind comes from the test file's name, then its directories, innermost first. |
| `--root DIR` | the nearest `.ccc` or `.git` above `PATH` | The directory record paths are relative to. Records match the map only when this is the directory ccc runs in. |
| `--force` | off | Write into an `--out` that already holds files. |
| `--format FMT` | `text` | `json` prints the report as one object. |

## ccc deps

Reports what the branch did to the dependency tree: which packages entered, left or changed version, and any advisory that came with them.
Expand Down Expand Up @@ -315,7 +351,7 @@ Copilot's chat log keeps no record of tool calls, so only Claude Code sessions a

## ccc replay

Manages replays: the story of what agents did on a branch, kept under `refs/ccc/replay/<branch>`. They sit beside your branches, never in them, so a merge can't carry one into the default branch. Recording is opt-in per repository. [Advanced.md](Advanced.md#replays) covers how replays are kept private.
Manages replays: the story of what agents did on a branch, kept under `refs/ccc/replay/<branch>`. They sit beside your branches, never in them, so a merge can't carry one into the default branch. Recording is opt-in per repository. [Developers And Agents](Advanced.md#replays) covers how replays are kept private.

### ccc replay enable

Expand Down
Loading
Loading