# Liscopelens

A graph-driven license compatibility analyzer for software projects. Liscopelens detects license conflicts by propagating obligations through dependency graphs and checking compatibility using a knowledge base of license rules.

## Features

- **Graph-driven analysis**: Models software dependencies as graphs for accurate obligation propagation
- **Scope-aware compatibility**: Handles conditional compatibility based on usage context (static/dynamic linking, etc.)
- **Configuration-driven**: Customize propagation rules for your build system and legal interpretation
- **Library API**: Integrate license analysis into your toolchain programmatically
- **150+ licenses**: Built-in knowledge base covering common open-source licenses

## Installation

```bash
pip install liscopelens
```

## Quick Start

### CLI Usage

The CLI entrypoint is `liscopelens` and expects a `project_path` first:

**Basic analysis (GN + ScanCode):**
```bash
liscopelens /path/to/project clang \
  --gn-file /path/to/gn.json \
  --scancode-file /path/to/scancode.json \
  --output out
```

**With custom configuration (`.toml`):**
```bash
liscopelens /path/to/project clang \
  --gn-file /path/to/gn.json \
  --scancode-file /path/to/scancode.json \
  --output out \
  -c custom.toml
```

**Inspect results (TUI):**
```bash
# "project_path" is required by the CLI but not used by `inspect`; "." is fine.
liscopelens . inspect out
```

**Rebuild the license compatibility knowledge base:**
```bash
liscopelens kb --rebuild
```

Use `liscopelens --help` for all available options.

### Library API Usage

**Check compatibility between two licenses:**
```python
from liscopelens.api import check_license_compatibility

result = check_license_compatibility("MIT", "GPL-3.0-only")
print(result["compatibility"])  # 0 = UNCONDITIONAL_COMPATIBLE
print(result["message"])
```

**Analyze a project's license compatibility:**
```python
from liscopelens.api import check_compatibility
from liscopelens.utils import GraphManager

license_map = {
    "//src/main.c": "GPL-3.0-only",
    "//lib/helper.c": "MIT",
}

graph = GraphManager()
graph.add_node(graph.create_vertex("//src/main.c", type="code"))
graph.add_node(graph.create_vertex("//lib/helper.c", type="code"))
graph.add_edge(graph.create_edge("//src/main.c", "//lib/helper.c", label="deps"))

context, results = check_compatibility(license_map, graph)
```

**Override license detection and ignore specific conflicts:**
```python
context, results = check_compatibility(
    license_map,
    graph,
    file_shadow={"//lib/crypto.c": "Apache-2.0"},      # Override detected license
    license_shadow={"GPL-3.0-only": ["OpenSSL"]}       # Ignore specific conflicts
)
```

## Prerequisites (CLI)

For CLI usage with C/C++ projects, generate input files first:

1. **GN Dependency Graph**:
   ```bash
   gn gen out/Default --ide=json
   ```

2. **Scancode License Report**:
   ```bash
   scancode -l -c --json-pp scancode.json /path/to/project
   ```

## Documentation

| Document | Description |
|----------|-------------|
| [Design Philosophy](docs/design.md) | System design, graph-driven propagation, and configuration philosophy |
| [Library API Reference](docs/library-api.md) | Public Python API, input formats, and end-to-end examples |
| [Configuration Guide](docs/configuration.md) | Full config reference, enums, and precise behavioral semantics |
| [Reproduction](docs/reproduction.md) | Dataset and reproduction steps for the case study |

## Output

With `--output out`, the `clang` pipeline writes:
- `out/propagated.json`: graph after obligation propagation
- `out/compatible_checked.json`: graph after compatibility checking
- `out/results.json`: conflict groups and involved nodes/licenses

## License

Apache License, Version 2.0. See [LICENSE](LICENSE) for details.
