Metadata-Version: 2.4
Name: matcha-core
Version: 0.2.0
Summary: Analyze repositories against SPECS.md and generate implementation reports.
Author: Patominer
License-Expression: Apache-2.0
Keywords: specs,analysis,llm,qa,repository
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: gitpython>=3.1.41
Requires-Dist: openai>=2.15.0
Requires-Dist: PyYAML>=6.0.2
Provides-Extra: dev
Requires-Dist: build>=1.2.2; extra == "dev"
Requires-Dist: twine>=5.1.1; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/TheFreeRangeTester/matcha-core/main/assets/branding/matcha-logo.png" alt="Matcha logo" width="180">
</p>

# Matcha Core

`matcha-core` analyzes a repository against its `SPECS.md` and produces structured implementation reports.

It can be used in two ways:

- as an installable CLI
- as a Python library

## Install

From PyPI:

```bash
python3 -m pip install matcha-core
```

For local development:

```bash
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -e ".[dev]"
```

## CLI

OpenAI:

```bash
export OPENAI_API_KEY=...
matcha-core analyze /path/to/repo --output ./report.html
```

Ollama:

```bash
export OLLAMA_MODEL=llama3.2
matcha-core analyze /path/to/repo --provider ollama
```

If the specs file is not at the repo root:

```bash
matcha-core analyze /path/to/repo --specs /path/to/repo/docs/SPECS.md
```

To analyze only one feature:

```bash
matcha-core analyze /path/to/repo --feature FEAT-004 --output report.html
```

`matcha-core` infers the report format from `--output` when possible, so
`report.html`, `report.json`, and `report.md` automatically render the expected
format. If no format is specified and no output file is provided, the CLI
defaults to a terminal table view. You can also use `--reporter` as an alias
for `--format`.

## Library

```python
from matcha_core import OpenAICompatibleEvaluator, RepositoryAnalyzer
from matcha_core.reporting import report_to_html

evaluator = OpenAICompatibleEvaluator.from_env(provider="openai")
analyzer = RepositoryAnalyzer(evaluator=evaluator)
report = analyzer.analyze_path("/path/to/repo")

html = report_to_html(report)
```

## Onboard an existing repository

Onboarding is local-first because it sends broader repository context than a
normal criterion analysis. Ollama is the default provider and does not require
an OpenAI API key.

Local prerequisites:

1. [Install Ollama](https://ollama.com/download).
2. Start the Ollama application, or run `ollama serve` and leave it running.
3. Download the model used by Matcha and verify that it is available:

```bash
ollama pull llama3.2
ollama ls
```

Then generate the draft:

```bash
matcha-core onboard /path/to/repo
```

This writes `/path/to/repo/SPECS.draft.md`. It does not create or overwrite the
canonical `SPECS.md`. Every proposed feature is marked `Draft`, cites repository
evidence, carries a confidence score, and can include questions that require
product-owner judgment.

### One file or one file per feature

The default `single` layout preserves the existing `SPECS.draft.md` output. For
larger products, generate a manifest-backed bundle instead:

```bash
matcha-core onboard /path/to/repo \
  --layout per-feature \
  --output /path/to/repo/SPECS.draft
```

The bundle is written atomically and has this shape:

```text
SPECS.draft/
├── SPECS.md
├── FEAT-001-feature-name.md
├── FEAT-002-another-feature.md
└── REVIEW-QUESTIONS.md
```

`SPECS.md` is the ordered manifest, each `FEAT-*.md` file contains one feature,
and review questions remain outside the executable feature contract. Existing
output is preserved unless `--force` is explicitly supplied.

After the broad inventory pass, deepen one existing draft without regenerating
the bundle:

```bash
matcha-core onboard /path/to/repo \
  --mode enrich \
  --specs /path/to/repo/SPECS.draft \
  --feature FEAT-003 \
  --provider ollama \
  --model llama3:latest \
  --language Spanish
```

Enrichment reads the selected feature, prioritizes its cited components and
related repository evidence, and replaces only that feature document. Its ID,
name, description, and priority remain stable; the manifest and other feature
files are not rewritten. Existing criteria and evidence are merged back
deterministically, so the model can refine or add to them but cannot silently
delete them. New
model-generated review questions are appended without deleting existing
questions. Only features with `Status: Draft` can be enriched, so a reviewed
product contract is never silently converted back into generated draft text.

Preview the generated change first with `--dry-run`. The command prints a
unified diff and leaves the bundle untouched:

```bash
matcha-core onboard /path/to/repo \
  --mode enrich \
  --specs /path/to/repo/SPECS.draft \
  --feature FEAT-003 \
  --dry-run
```

`--include` and `--exclude` can further bound enrichment. `--max-context-chars`
controls the focused evidence budget. Enrichment is intentionally one feature
per invocation and does not require `--force`; Matcha aborts if the target file
changes while generation is running.

Both `analyze` and `check` accept a traditional Markdown file, a bundle
directory, or a manifest file that links to `FEAT-*.md` documents:

```bash
matcha-core analyze /path/to/repo --specs /path/to/repo/specs
matcha-core check /path/to/repo --specs /path/to/repo/specs
```

Bundle IDs and acceptance criteria are validated across all feature files, so
duplicate IDs cannot hide in separate documents. Gate artifacts record every
spec file and SHA-256 plus one deterministic aggregate `specs_sha256`. Default
discovery prefers a root `SPECS.md`, then a root `specs/` directory. Draft
bundles are never promoted or selected automatically.

Onboarding uses the `clustered` evidence strategy by default. Matcha indexes all
supported repository files, assigns stable evidence IDs for the run, and groups
files that reference related symbols. Each group is analyzed separately before
the candidates are consolidated into one draft. This allows a feature to cite
related UI, state, service, model, and test files instead of depending on a
single alphabetical context slice. Large source files use bounded excerpts
sampled across declarations and behavioral entry points.
The complete file index is visible to discovery, while only the files listed
in each batch's `SELECTED FILE CONTENT` are valid evidence. Inspect
`--debug-llm` for exact coverage instead of assuming every byte was analyzed.

Because clustered onboarding can make several model calls, `--max-features`
limits the consolidated draft rather than the number of intermediate
candidates. Use `--debug-llm` to inspect the batches, selected files, evidence
ID mapping, provider responses, and consolidation result.

Scope a run with repeatable repository-relative glob patterns:

```bash
matcha-core onboard /path/to/repo \
  --include "Sources/**" \
  --include "Tests/**" \
  --exclude "**/Mocks/**"
```

Use `--strategy single-pass` when you explicitly want the previous one-request
behavior. `--max-context-chars` is a per-batch budget in clustered mode.

Choose a different OpenAI-compatible model explicitly when local output is not
good enough:

```bash
export OPENAI_API_KEY=...
matcha-core onboard /path/to/repo \
  --provider openai \
  --model gpt-5.6-sol \
  --language English
```

Matcha never silently falls back from Ollama to a remote provider. Files that
look like credentials, private keys, environment files, generated output, and
dependency directories are excluded from onboarding context. Use `--force`
only when intentionally replacing an existing draft. Ollama defaults to a
smaller per-batch context and eight final features so local models have room to
produce complete structured output. It also allows 180 seconds for each local
generation request. Context, feature count, strategy, scope, and `--timeout`
can all be overridden.
OpenAI reasoning models default to `--reasoning-effort low` for structured
onboarding so reasoning does not consume the entire completion budget. Override
it explicitly when an evaluated quality gain justifies the added latency and
cost.

`matcha-core bootstrap` remains available as a compatibility alias, but
`matcha-core onboard` is the documented command.

The Python API exposes the same workflow through `RepositoryBootstrapper` and
`OpenAICompatibleSpecGenerator`. See [docs/ONBOARDING.md](docs/ONBOARDING.md) for
the review and promotion workflow and the optional Codex skill.

## Output formats

- `json`
- `markdown`
- `html`
- `table`

For terminal output with evidence snippets:

```bash
matcha-core analyze /path/to/repo --format table --show-evidence
```

## CI gate

Copy [docs/POLICY_TEMPLATE.yml](docs/POLICY_TEMPLATE.yml) to
`.matcha/policy.yml` in the repository being checked, then run:

```yaml
version: 1
fail_on: [not_implemented, implemented_differently, not_specified]
priorities: [critical, high]
min_confidence: 0.75
on_inconclusive: block
allow: []
```

```bash
matcha-core check /path/to/repo --output matcha-gate.json
```

The gate applies deterministic policy rules after analysis. Model or retrieval
failures do not become implementation findings.

Exit codes are stable:

- `0`: policy passed
- `10`: one or more definitive findings violated the policy
- `20`: the result is inconclusive and the policy uses `on_inconclusive: block`
- `30`: configuration or execution error

These values do not overlap with argparse's standard exit code `2` for invalid
command-line usage.

Use `baseline` in the policy, or `--baseline`, to grandfather findings from a
previous Matcha JSON report. Only explicit IDs with complete matching contracts are eligible: feature,
criterion ID, versioned fingerprint and status must all match. Legacy positional
IDs or unknown text completeness are diagnosed and cannot waive findings.
Edited requirements invalidate their previous exception.

Temporary exceptions belong in `allow`. Every exception requires an ISO
`expires` date and a reason; expired exceptions
no longer apply. Findings below `min_confidence` make the gate inconclusive
rather than allowing a false pass. Every run writes a JSON gate artifact with
the decision, violations, incomplete findings, waivers, complete analysis,
provider/model identity, repository commit and dirty state, and SHA-256 hashes
for specs, policy, and baseline.

A complete GitHub Actions example is available in
[docs/CI.md](docs/CI.md).

## Tests

```bash
python3 -m unittest discover -s tests
```

## Specs Authoring

Use [docs/SPECS_TEMPLATE.md](docs/SPECS_TEMPLATE.md) as a starting point when
onboarding an existing repository into Matcha.

Matcha validates specs before analysis. Feature headings must include a stable
ID such as `## FEAT-1 User login`, IDs must be unique, and every feature must
have at least one acceptance criterion. Fenced Markdown examples are ignored.

Reports distinguish definitive findings from execution state:

- `skipped` means the contract is Draft/Retired, or legacy progress marks it planned
- `inconclusive` means Matcha did not find enough relevant context
- `analysis_failed` means the evaluator could not produce a valid result

These states are never counted as `not_implemented`. JSON reports include a
`schema_version` field so consumers can validate the output contract.

### Evidence and analysis coverage

Analysis reports and gate artifacts use schema `1.3`. Existing fields
remain available. Each criterion now includes structured `evidence`, a source
`context` manifest, `evidence_issues`, and an optional abstention `reason`.
The manifest identifies the exact source fragments sent to the evaluator,
original line ranges, file hashes, omitted content, and unresolved references.
`referenced_files` lists files actually sent; retrieved candidates are recorded
separately in `context.selected_files`. `code_snippets` remains a compatibility
representation of verified citations.

The engine checks citations against the snapshot sent for that criterion,
including results from custom evaluators and repaired model responses. Legacy
path/code citations are accepted only when they match a unique source excerpt.
Custom evaluators keep their existing signature but definitive implementation
verdicts now require citations and a rationale. Missing or invalid evidence
produces `inconclusive`, not a claim that the behavior is absent or different.
`not_implemented` requires localized evidence of missing behavior; an empty
search is insufficient. `not_specified` means the requirement is ambiguous.

Provenance checks do not prove that the model interpreted the cited code
correctly. Reports describe static source observations, not executed tests,
runtime behavior or deployment. Model confidence is not a calibrated
probability. Context uses deterministic bounded source windows; related
components guide retrieval, while omitted dependencies may still prevent a
conclusion.

Reports distinguish criteria in scope, skipped, evaluated (including failed or
inconclusive attempts), and conclusive. The gate recomputes coverage for its
priority scope and counts a result as conclusive only when it meets the policy's
confidence threshold. With `on_inconclusive: block`, an empty effective scope
or all-skipped run returns `20` with reason `no_criteria_evaluated`. With
`ignore`, these reasons and incomplete findings remain visible even if the
exit code is `0`. Exit codes and policy version `1` are unchanged.

For the opt-in synthetic real-model evaluation, see
[docs/SDD_FEEDBACK_VALIDATION.md](docs/SDD_FEEDBACK_VALIDATION.md).

Bootstrap-generated `Draft` features are also skipped. Change each reviewed
feature to an intentional lifecycle status such as `Done` or `Planned` before
using it in a gate.

## Release

The package metadata and release flow are documented in `RELEASING.md`.

## License

This project is licensed under the Apache License 2.0. See `LICENSE`.

### Feedback for Spec Driven Development

Use explicit persistent criterion IDs and separate contract approval from
implementation progress:

```md
## FEAT-INV Invitations
**Priority**: High
**Contract Status**: Approved
**Implementation Status**: Planned
**Related Components**: `src/invitations.py`

Acceptance Criteria:
- [AC-INV-001] Reject expired invitations before creating a membership.
```

Approved contracts are analyzed even when implementation is Planned. Draft and
Retired contracts are skipped. Without `Contract Status`, legacy skip rules
remain in effect. Product review, not observed code, determines approval.

```bash
matcha-core specs migrate SPECS.md --output criterion-ids.patch
matcha-core specs review SPECS.md --format json --output spec-review.json
matcha-core analyze . --output current.json
matcha-core compare previous.json current.json --output feedback.md
matcha-core analyze . --test-results executions.json --output with-tests.json
```

Migration prints a diff for review; it never rewrites specs. Authoring review
provides deterministic hints rather than exhaustive semantic validation.
Reports contain structured next actions, contract identity, scope, configuration
and provenance. Comparisons separate changed requirements from static findings;
filters, uncertainty and incompatible configurations never count as resolutions.
Test references are labelled as not executed. Imported results retain their
caller-supplied provenance and only match a clean analyzed commit and the exact
criterion fingerprint; they never override a static verdict.

See [docs/SDD_WORKFLOW.md](docs/SDD_WORKFLOW.md) for the complete workflow,
import format and compatibility rules.
