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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
compact path, with four clear community routes instead of overlapping link
lists; the benchmark guide also points to the correct contributor section.

### Fixed

- README links now resolve from package indexes as well as GitHub, and the
examples guide points to the current first-run section.

## [0.1.0.dev11] - 2026-09-09

### Added
Expand Down
52 changes: 33 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ReproMin is a repository-scale test-case reducer for repeatable Maven, Gradle,
and Python failures. It removes files, manifest entries, source structure, and
selected text only while the same failure still occurs.

[Maintainer-run Gradle pilot](docs/CASE_STUDY_GRADLE_38843.md): **854 -> 11
[Maintainer-run Gradle pilot](https://github.com/fly1d/repomin/blob/main/docs/CASE_STUDY_GRADLE_38843.md): **854 -> 11
files**, with the same failure reproduced in **5/5 fresh copies**.

## Try a real reduction
Expand Down Expand Up @@ -43,10 +43,11 @@ help you want. No ReproMin installation is required.

The demo leaves the reduced payload and evidence report available for
inspection and prints a copyable validation command. Continue with the
[five-minute quick start](docs/QUICKSTART.md), the
[PowerShell guide](docs/QUICKSTART.windows.md), or the
[Chinese guide](docs/QUICKSTART.zh-CN.md). For a failing CI job, start with the
[GitHub Action](docs/GITHUB_ACTION.md).
[five-minute quick start](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.md),
the [PowerShell guide](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.windows.md),
or the [Chinese guide](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.zh-CN.md).
For a failing CI job, start with the
[GitHub Action](https://github.com/fly1d/repomin/blob/main/docs/GITHUB_ACTION.md).

> **Project status:** ReproMin is a pre-alpha feasibility build. Use it on a
> reproducible failure in a repository you trust. The default host backend runs
Expand All @@ -58,8 +59,8 @@ Two maintainer-run pilots demonstrate the current technical scope:

| Pilot | Before | After | Fresh-copy evidence |
| --- | ---: | ---: | ---: |
| [Gradle #38843](docs/CASE_STUDY_GRADLE_38843.md) | 854 files, 3.8 MB | 11 files, 87.9 KB | 5/5 replays + cold start |
| [tsdown #979](docs/CASE_STUDY_TSDOWN_979.md) | 14 files | 8 files | 3/3 replays |
| [Gradle #38843](https://github.com/fly1d/repomin/blob/main/docs/CASE_STUDY_GRADLE_38843.md) | 854 files, 3.8 MB | 11 files, 87.9 KB | 5/5 replays + cold start |
| [tsdown #979](https://github.com/fly1d/repomin/blob/main/docs/CASE_STUDY_TSDOWN_979.md) | 14 files | 8 files | 3/3 replays |

These are feasibility results, not independent adoption or a promise that
every repository will shrink by the same amount. The current milestone is
Expand Down Expand Up @@ -113,14 +114,18 @@ repomin report validate ../checkout-repro.repomin/report.json \
ReproMin works in temporary copies and never changes the source repository.
Use a signal that identifies the target failure: stable output (`--match`), an
exact exit code, an exception identity, or a process-failure signature. The
[quick start](docs/QUICKSTART.md) explains the complete workflow; use the
[Doctor guide](docs/DOCTOR.md) for failed checks and the
[replay guide](docs/REPLAY.md) before executing an exported command.
[quick start](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.md)
explains the complete workflow; use the
[Doctor guide](https://github.com/fly1d/repomin/blob/main/docs/DOCTOR.md) for
failed checks and the
[replay guide](https://github.com/fly1d/repomin/blob/main/docs/REPLAY.md) before
executing an exported command.

## Local CLI or GitHub Action

The CLI is best for interactive reduction. The reusable
[GitHub Action](docs/GITHUB_ACTION.md) can reduce a repeatable CI failure and
[GitHub Action](https://github.com/fly1d/repomin/blob/main/docs/GITHUB_ACTION.md)
can reduce a repeatable CI failure and
upload the payload and validated report as an artifact:

```yaml
Expand All @@ -145,14 +150,16 @@ Pin a reviewed release tag or full commit SHA in real workflows.
| Custom semantic edits | Optional OpenAI-compatible HTTP integration; every edit still passes the oracle |

Other languages still benefit from repository, manifest, and explicit text
reduction. Start with the nearest [ecosystem example](docs/EXAMPLES.md).
reduction. Start with the nearest
[ecosystem example](https://github.com/fly1d/repomin/blob/main/docs/EXAMPLES.md).

## Safety and privacy

The host backend runs the supplied command with your user account. It is not a
sandbox. Only run repositories and commands you trust. Docker can reduce
access when configured carefully, but it is not a complete security boundary.
Read [SECURITY.md](SECURITY.md) before handling third-party code.
Read [SECURITY.md](https://github.com/fly1d/repomin/blob/main/SECURITY.md)
before handling third-party code.

Do not publish credentials, private URLs, proprietary source, customer data,
raw logs, commands, or environment values. The Markdown validation summary is
Expand All @@ -161,17 +168,24 @@ safe to publish.

## Documentation and community

- **Start:** [quick start](docs/QUICKSTART.md), [Windows](docs/QUICKSTART.windows.md),
[Chinese](docs/QUICKSTART.zh-CN.md), and [ecosystem examples](docs/EXAMPLES.md).
- **Start:** [quick start](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.md),
[Windows](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.windows.md),
[Chinese](https://github.com/fly1d/repomin/blob/main/docs/QUICKSTART.zh-CN.md),
and [ecosystem examples](https://github.com/fly1d/repomin/blob/main/docs/EXAMPLES.md).
- **Try a real failure:** offer a sanitized public case in
[pilot issue #11](https://github.com/fly1d/repomin/issues/11).
- **Ask or share:** use [Q&A](https://github.com/fly1d/repomin/discussions/new?category=q-a)
or [Show and tell](https://github.com/fly1d/repomin/discussions/new?category=show-and-tell).
- **Contribute:** read [CONTRIBUTING.md](CONTRIBUTING.md) and choose an
- **Contribute:** read
[CONTRIBUTING.md](https://github.com/fly1d/repomin/blob/main/CONTRIBUTING.md)
and choose an
[open starter task](https://github.com/fly1d/repomin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22).

The [documentation index](docs/README.md) covers configuration, reports, and
design. Use [SUPPORT.md](SUPPORT.md) for other help and [SECURITY.md](SECURITY.md)
The [documentation index](https://github.com/fly1d/repomin/blob/main/docs/README.md)
covers configuration, reports, and design. Use
[SUPPORT.md](https://github.com/fly1d/repomin/blob/main/SUPPORT.md) for other
help and [SECURITY.md](https://github.com/fly1d/repomin/blob/main/SECURITY.md)
for private vulnerability reports.

Apache-2.0 licensed. See [LICENSE](LICENSE).
Apache-2.0 licensed. See
[LICENSE](https://github.com/fly1d/repomin/blob/main/LICENSE).
8 changes: 4 additions & 4 deletions docs/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ the shortest network-free demonstration of structured manifest reduction.

The host-backend examples are self-contained and use only Python. Run them from
a scratch directory after installing ReproMin from the GitHub Release wheel as
described in the [README](../README.md#install), or from an editable checkout
when contributing to the project. The Docker and semantic examples near the
end use the repository fixtures so their trust boundaries and provider
contract are explicit.
described in the [README](../README.md#try-a-real-reduction), or from an
editable checkout when contributing to the project. The Docker and semantic
examples near the end use the repository fixtures so their trust boundaries
and provider contract are explicit.

## Shrink a Python failure to its required files

Expand Down
33 changes: 33 additions & 0 deletions tests/test_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ def _setup_config() -> configparser.ConfigParser:
return config


def _markdown_link_targets(text: str) -> list[str]:
inline = re.findall(r"\]\(\s*<?([^\s>)]+)>?", text)
references = []
for match in re.finditer(
r"(?m)^[ ]{0,3}\[[^\]\n]+\]:[ \t]*(?:\n[ \t]+)?(?:<([^>\n]+)>|([^\s\n]+))",
text,
):
references.append(match.group(1) or match.group(2))
return inline + references


class PackagingContractTests(unittest.TestCase):
def test_explicit_manifest_entries_exist_in_a_clean_checkout(self) -> None:
manifest = (ROOT / "MANIFEST.in").read_text(encoding="utf-8")
Expand Down Expand Up @@ -113,6 +124,28 @@ def test_metadata_exposes_project_links_and_platform_support(self) -> None:
self.assertIn("Programming Language :: Python :: 3.13", metadata["classifiers"])
self.assertIn("Programming Language :: Python :: 3.14", metadata["classifiers"])

def test_package_long_description_has_portable_links(self) -> None:
config = _setup_config()
long_description = config["metadata"]["long_description"].strip()
self.assertEqual("file: README.md", long_description)

readme = (ROOT / "README.md").read_text(encoding="utf-8")
link_targets = _markdown_link_targets(readme)
relative_targets = [
target
for target in link_targets
if not target.startswith(("https://", "http://", "mailto:", "#"))
]
self.assertEqual(
[],
relative_targets,
"README links must resolve when rendered as the PyPI long description",
)

def test_package_link_scan_covers_reference_style_links(self) -> None:
readme = "[Quick start][guide]\n\n[guide]: docs/QUICKSTART.md\n"
self.assertEqual(["docs/QUICKSTART.md"], _markdown_link_targets(readme))

def test_development_extra_contains_release_and_test_tools(self) -> None:
config = _setup_config()
development_requirements = config["options.extras_require"]["dev"]
Expand Down