# Bounded diagnostic-output compression

Reckon can deterministically compress already-produced build and test output
without running the command that created it. This capability is available from
the CLI and the single MCP gateway in post-0.3 development.

Reckon deliberately does **not** expose `reckon run`. Portable command
execution remains excluded until the containment gate below can be proven.

## Use it

Prefer a repository-relative file or stdin so the full log does not first cross
an agent's context boundary:

```bash
build-command > build.log 2>&1
reckon compress build.log --exit-code 1 --lines 200

build-command 2>&1 | reckon compress - --exit-code 1 --json
```

The same operation is available through the one-tool MCP gateway:

```json
{
  "operation": "compress",
  "artifactPath": "build.log",
  "exitCode": 1,
  "lineBudget": 200,
  "compressionByteBudget": 16384
}
```

`artifactPath` is repository-bound and must be a regular, non-symlinked file.
Direct `text` and ordered `events` inputs support integrations and behavioral
parity, but they do not prove context savings if the raw value has already been
placed in the model's context.

The always-loaded MCP schema advertises the common path to stay within its
token ceiling. Advanced, still runtime-validated arguments are `events`,
`signal`, `strategy`, `adapter`, `contextLines`, `retain`, `redactSecrets`,
`maxInputBytes`, and `raw`. Use this canonical guide when composing them.

## Contract

- Strategies: `smart`, `head-tail`, and `errors-only`.
- Adapters: generic fallback plus Vitest, Jest, pytest, Go test, Maven, Gradle,
  .NET, and Cargo detection.
- Preserved metadata: original exit code and terminating signal.
- Preserved signals: detected errors, causes, stack frames, failing tests,
  summaries, warnings, and bounded surrounding context.
- Hard limits: rendered content never exceeds the requested line count or
  UTF-8 content-byte budget.
- Truthfulness: the status is `complete`, `compressed`, or
  `insufficient-budget`; detected signals that cannot fit are listed rather
  than silently described as preserved.
- Accounting: every omitted range has inclusive source-line bounds and its
  exact source bytes, including original delimiters.
- Recovery: raw ordered events are retained locally by default and can be read
  in bounded ranges without rerunning the command.

The default compact MCP result uses documented tuples:

- `exit`: `[exitCode, signal]`;
- `budget`: `[usedLines, lineLimit, usedUtf8Bytes, byteLimit]`;
- `fidelity`: `[detectedSignals, preservedSignals, unpreservedSignalIds]`;
- each `omitted` entry:
  `[inclusiveStartLine, inclusiveEndLine, exactSourceBytes]`.

`artifactId` is the SHA-256 identity used with
`compressionAction: "read"`, `"diagnose"`, or `"delete"`. Request
`detailLevel: "standard"` for the fully named audit envelope.

CLI drill-down and cleanup are explicit:

```bash
reckon compress read <artifact-id> --start 80 --end 140
reckon compress read <artifact-id> --raw
reckon compress delete <artifact-id>
```

Human output prints an explicit fidelity warning when a budget cannot retain
every detected signal. `--json` emits the stable, fully named core result.

## Connect a failure to code

After compression, diagnose the retained artifact without rerunning the failed
command:

```bash
reckon compress diagnose <artifact-id> --limit 10 --context 2
reckon compress diagnose <artifact-id> --max-output-bytes 16384 --json
```

The same graph read is available through the single MCP gateway:

```json
{
  "operation": "compress",
  "compressionAction": "diagnose",
  "artifactId": "<sha256>",
  "limit": 10,
  "contextLines": 2,
  "compressionByteBudget": 16384,
  "detailLevel": "standard"
}
```

MCP callers may provide already-produced `text` instead of `artifactId`, but
must provide exactly one. Direct text is bounded and secret-redacted before
diagnosis. Retained artifacts are preferable because omitted regions remain
available locally and the raw log need not first enter the agent context.

Diagnosis recognizes source locations emitted by major JavaScript/TypeScript,
Python, Java, C#, Go, and Rust toolchains. Every candidate is resolved against
tracked files inside the current repository. Foreign CI checkout prefixes can
map by a unique tracked suffix; basename-only matches remain unresolved when
ambiguous. Traversal, symlinks outside the repository, untracked files, and
missing graph records are refused rather than guessed.

For each resolved location, the fully named result contains:

- the reported path, line, column, and original evidence line;
- the uniquely resolved tracked file and nearest package manifest;
- the smallest enclosing graph symbol, stable identity, signature, and source
  span;
- related tests, upstream callers, and downstream dependencies;
- recent commits touching the file;
- a source snippet inside a hard aggregate UTF-8 byte budget; and
- the indexed commit, current commit, and freshness state.

The default compact MCP result preserves the same evidence with tuples:

- `package`: `[name, manifest, ecosystem]`;
- `owner`: `[identity, symbol, kind, startLine, endLine, signature]`;
- relation entries:
  `[identity, symbol, file, kind, line, confidence]`;
- `recent`: `[shortCommit, authoredAt, subject]`; and
- `freshness`: `[state, indexedHead, currentHead]`.

`resolved` means every detected reference was mapped with complete input,
current graph evidence, and an untruncated context bundle. `partial` identifies
any omitted input, unresolved reference, stale graph, or exhausted context
budget. `unresolved` means no safe repository location was established.

The relationships are static diagnostic candidates, not proof of runtime
causality. Package ownership is evidenced by the nearest tracked
`package.json`, `pyproject.toml`, `pom.xml`, `Cargo.toml`, `go.mod`, or
`.csproj`; malformed or unnamed manifests remain explicit. Dynamic dispatch,
generated paths, source maps, and framework wiring can require additional
runtime evidence.

## Local retention and redaction

Artifacts are stored beneath `.reckon/output/` with a private directory mode
and `0600` files. The default returned content and bounded reads redact common
credential forms and remove ANSI/control bytes. `--raw` is an explicit local
request and can reveal the original secrets. Redaction is defense in depth,
not a guarantee that every possible secret format is recognized.

Input is bounded to 16 MiB by default and cannot be configured above 64 MiB.
Oversized input is rejected rather than partially retained. Output artifacts
are content-addressed, reads are byte-bounded, deletion requires an exact
artifact identity, and symlinked storage paths are refused.

## Command-execution security gate

The safe compressor processes data only; it does not invoke a shell or child
process. A future runner must address this threat model with executable,
platform-specific evidence:

| Threat | Required proof before shipping a runner |
|---|---|
| Shell injection | Argument-vector execution by default; no implicit shell |
| Repository prompt injection | Repository text cannot alter executable or policy authorization |
| Arbitrary filesystem access | Repository-root binding plus an enforceable filesystem sandbox |
| Network access and exfiltration | Deny-by-default network containment where claimed |
| Environment or credential leakage | Minimal allowlisted environment and no ambient credentials |
| Child-process escape | Complete descendant tracking and termination |
| Timeout | Process-tree termination, not only parent termination |
| CPU, memory, disk, output exhaustion | Enforced resource and output caps |
| Symlink or path traversal | Realpath containment and race-resistant file handling |
| Destructive commands | Allowlisted profiles or per-call approval with an explicit audit record |
| Cross-worktree effects | Authorized worktree binding and named affected roots |
| Telemetry leakage | No command text or raw output in default telemetry; redact before opt-in export |
| Platform differences | Separate verified guarantees and explicit unsupported cases |

Node's cross-platform child-process API alone cannot impose a hard memory limit
on an arbitrary executable, Windows job-object behavior differs from POSIX
process groups, and portable network/filesystem containment requires more than
an output buffer and timeout. Until a reviewed native or operating-system
containment adapter proves the table above, command execution is an intentional
safety non-goal. Existing trusted execution tools can write a log and pass that
artifact to Reckon for bounded compression.
