redundo 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- redundo-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +51 -0
- redundo-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- redundo-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
- redundo-0.1.0/.github/pull_request_template.md +10 -0
- redundo-0.1.0/.github/workflows/ci.yml +29 -0
- redundo-0.1.0/.github/workflows/publish.yml +45 -0
- redundo-0.1.0/.gitignore +8 -0
- redundo-0.1.0/CODE_OF_CONDUCT.md +64 -0
- redundo-0.1.0/CONTRIBUTING.md +129 -0
- redundo-0.1.0/LICENSE +21 -0
- redundo-0.1.0/PKG-INFO +390 -0
- redundo-0.1.0/README.md +364 -0
- redundo-0.1.0/docs/claude-code.md +425 -0
- redundo-0.1.0/docs/cowork.md +179 -0
- redundo-0.1.0/docs/hashing.md +127 -0
- redundo-0.1.0/docs/openclaw.md +204 -0
- redundo-0.1.0/docs/openinference.md +73 -0
- redundo-0.1.0/examples/demo_report.html +83 -0
- redundo-0.1.0/examples/demo_trace.jsonl +31 -0
- redundo-0.1.0/pyproject.toml +47 -0
- redundo-0.1.0/src/redundo/__init__.py +10 -0
- redundo-0.1.0/src/redundo/adapter/__init__.py +13 -0
- redundo-0.1.0/src/redundo/adapter/cli.py +135 -0
- redundo-0.1.0/src/redundo/adapter/collector.py +171 -0
- redundo-0.1.0/src/redundo/adapter/detect.py +136 -0
- redundo-0.1.0/src/redundo/adapter/hashing.py +145 -0
- redundo-0.1.0/src/redundo/adapter/otlp.py +207 -0
- redundo-0.1.0/src/redundo/adapter/sources/__init__.py +6 -0
- redundo-0.1.0/src/redundo/adapter/sources/claude_code.py +830 -0
- redundo-0.1.0/src/redundo/adapter/sources/cowork.py +378 -0
- redundo-0.1.0/src/redundo/adapter/sources/openclaw.py +466 -0
- redundo-0.1.0/src/redundo/adapter/sources/openinference.py +482 -0
- redundo-0.1.0/src/redundo/adapter/writer.py +20 -0
- redundo-0.1.0/src/redundo/analyzer/__init__.py +37 -0
- redundo-0.1.0/src/redundo/analyzer/classify.py +241 -0
- redundo-0.1.0/src/redundo/analyzer/cli.py +104 -0
- redundo-0.1.0/src/redundo/analyzer/cycles.py +96 -0
- redundo-0.1.0/src/redundo/analyzer/ingest.py +121 -0
- redundo-0.1.0/src/redundo/analyzer/lineage.py +118 -0
- redundo-0.1.0/src/redundo/analyzer/metrics.py +244 -0
- redundo-0.1.0/src/redundo/analyzer/report.py +434 -0
- redundo-0.1.0/src/redundo/analyzer/schema.py +171 -0
- redundo-0.1.0/src/redundo/cli.py +58 -0
- redundo-0.1.0/tests/adapter/fixtures/sample_otlp.json +94 -0
- redundo-0.1.0/tests/adapter/helpers.py +113 -0
- redundo-0.1.0/tests/adapter/test_claude_code.py +383 -0
- redundo-0.1.0/tests/adapter/test_cli.py +124 -0
- redundo-0.1.0/tests/adapter/test_cowork.py +183 -0
- redundo-0.1.0/tests/adapter/test_detect.py +106 -0
- redundo-0.1.0/tests/adapter/test_hashing.py +192 -0
- redundo-0.1.0/tests/adapter/test_openclaw.py +305 -0
- redundo-0.1.0/tests/adapter/test_openinference.py +255 -0
- redundo-0.1.0/tests/adapter/test_otlp.py +70 -0
- redundo-0.1.0/tests/analyzer/fixtures/malformed.jsonl +4 -0
- redundo-0.1.0/tests/analyzer/fixtures/sample.jsonl +18 -0
- redundo-0.1.0/tests/analyzer/test_analyzer_cli.py +32 -0
- redundo-0.1.0/tests/analyzer/test_classify.py +254 -0
- redundo-0.1.0/tests/analyzer/test_coverage.py +152 -0
- redundo-0.1.0/tests/analyzer/test_cycles.py +92 -0
- redundo-0.1.0/tests/analyzer/test_end_to_end.py +71 -0
- redundo-0.1.0/tests/analyzer/test_hash_spec_guard.py +34 -0
- redundo-0.1.0/tests/analyzer/test_ingest.py +51 -0
- redundo-0.1.0/tests/analyzer/test_lineage.py +78 -0
- redundo-0.1.0/tests/analyzer/test_metrics.py +107 -0
- redundo-0.1.0/tests/analyzer/test_report_html.py +136 -0
- redundo-0.1.0/tests/analyzer/test_schema.py +74 -0
- redundo-0.1.0/tests/test_redundo_cli.py +94 -0
- redundo-0.1.0/uv.lock +194 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something in redundo produced a wrong, missing, or misleading result.
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting this. redundo's whole design point is "never guess past a genuine unknown" -- so a case where it guessed wrong, or where its degrade-honestly behavior is confusing, is exactly the kind of bug report that matters most.
|
|
9
|
+
|
|
10
|
+
- type: dropdown
|
|
11
|
+
id: component
|
|
12
|
+
attributes:
|
|
13
|
+
label: Where does this happen?
|
|
14
|
+
options:
|
|
15
|
+
- redundo adapt (a specific source: openinference, claude-code, cowork, openclaw)
|
|
16
|
+
- redundo analyze (classification, coverage, report output)
|
|
17
|
+
- redundo collect
|
|
18
|
+
- CLI / packaging
|
|
19
|
+
- Documentation
|
|
20
|
+
- Not sure
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
|
|
24
|
+
- type: textarea
|
|
25
|
+
id: what-happened
|
|
26
|
+
attributes:
|
|
27
|
+
label: What happened?
|
|
28
|
+
description: What you expected vs. what you actually got.
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
|
|
32
|
+
- type: textarea
|
|
33
|
+
id: repro
|
|
34
|
+
attributes:
|
|
35
|
+
label: Minimal reproduction
|
|
36
|
+
description: >
|
|
37
|
+
A small trace (JSONL for `analyze`, or a captured OTLP batch for `adapt`) that
|
|
38
|
+
reproduces this, plus the exact command you ran. Redact any real prompt/tool
|
|
39
|
+
content first -- content_hash exists so you never have to share raw content to
|
|
40
|
+
report a bug.
|
|
41
|
+
render: shell
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
|
|
45
|
+
- type: input
|
|
46
|
+
id: version
|
|
47
|
+
attributes:
|
|
48
|
+
label: redundo version
|
|
49
|
+
description: Output of `pip show redundo` (the Version line), or the commit/tag you installed from.
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: A new source, a new analysis, or a change to adapt/analyze's behavior.
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Before proposing a new adapter source or analysis, skim [CONTRIBUTING.md](../../CONTRIBUTING.md) --
|
|
9
|
+
both are held to specific discipline (real captured telemetry, honest coverage
|
|
10
|
+
reporting, never guessing past a genuine unknown) that shapes what a good PR
|
|
11
|
+
for either looks like.
|
|
12
|
+
|
|
13
|
+
- type: dropdown
|
|
14
|
+
id: kind
|
|
15
|
+
attributes:
|
|
16
|
+
label: What kind of change is this?
|
|
17
|
+
options:
|
|
18
|
+
- New adapter source (a new agent framework's OTLP)
|
|
19
|
+
- New analysis (something other than redundant-call detection)
|
|
20
|
+
- Change to an existing source or analysis
|
|
21
|
+
- CLI / packaging
|
|
22
|
+
- Other
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: problem
|
|
28
|
+
attributes:
|
|
29
|
+
label: What's the problem or gap?
|
|
30
|
+
description: What can't you do with redundo today that you want to?
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: proposal
|
|
36
|
+
attributes:
|
|
37
|
+
label: Proposed approach
|
|
38
|
+
description: >
|
|
39
|
+
If this is a new source: what does its real OTLP/telemetry shape look like,
|
|
40
|
+
and do you have a real capture to validate against? (See CONTRIBUTING.md --
|
|
41
|
+
every source in this project was built against actual captured data, not
|
|
42
|
+
just a framework's docs.)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## What changed and why
|
|
2
|
+
|
|
3
|
+
<!-- The "why" matters more than the "what" here -- see CONTRIBUTING.md. -->
|
|
4
|
+
|
|
5
|
+
## Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] `uv run pytest` passes locally
|
|
8
|
+
- [ ] New behavior has test coverage (a fixture, not just a real capture -- real captures are for validation, too brittle/large to be the actual test)
|
|
9
|
+
- [ ] If this touches an adapter source or the analyzer: coverage/known-gaps are still reported honestly, nothing silently guesses past an unknown
|
|
10
|
+
- [ ] Docs (`README.md`, `docs/*.md`) updated if this changes documented behavior
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: test (py${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v3
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: uv sync --extra collector
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
name: Build distribution
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v3
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
|
|
19
|
+
- name: Build sdist and wheel
|
|
20
|
+
run: uv build
|
|
21
|
+
|
|
22
|
+
- name: Upload build artifacts
|
|
23
|
+
uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
name: Publish
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment:
|
|
33
|
+
name: pypi
|
|
34
|
+
url: https://pypi.org/project/redundo/
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write # required for PyPI Trusted Publishing (OIDC) -- no API token stored anywhere
|
|
37
|
+
steps:
|
|
38
|
+
- name: Download build artifacts
|
|
39
|
+
uses: actions/download-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: dist
|
|
42
|
+
path: dist/
|
|
43
|
+
|
|
44
|
+
- name: Publish to PyPI
|
|
45
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
redundo-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes,
|
|
23
|
+
and learning from the experience
|
|
24
|
+
- Focusing on what is best not just for us as individuals, but for the overall
|
|
25
|
+
community
|
|
26
|
+
|
|
27
|
+
Examples of unacceptable behavior:
|
|
28
|
+
|
|
29
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
30
|
+
of any kind
|
|
31
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
32
|
+
- Public or private harassment
|
|
33
|
+
- Publishing others' private information, such as a physical or email address,
|
|
34
|
+
without their explicit permission
|
|
35
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
36
|
+
professional setting
|
|
37
|
+
|
|
38
|
+
## Enforcement Responsibilities
|
|
39
|
+
|
|
40
|
+
Project maintainers are responsible for clarifying and enforcing our standards
|
|
41
|
+
of acceptable behavior and will take appropriate and fair corrective action in
|
|
42
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
43
|
+
or harmful.
|
|
44
|
+
|
|
45
|
+
## Scope
|
|
46
|
+
|
|
47
|
+
This Code of Conduct applies within all community spaces, and also applies
|
|
48
|
+
when an individual is officially representing the community in public spaces.
|
|
49
|
+
|
|
50
|
+
## Enforcement
|
|
51
|
+
|
|
52
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
53
|
+
reported to the maintainers by opening a private security advisory or issue on
|
|
54
|
+
this repository. All complaints will be reviewed and investigated promptly and
|
|
55
|
+
fairly.
|
|
56
|
+
|
|
57
|
+
## Attribution
|
|
58
|
+
|
|
59
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
60
|
+
version 2.1, available at
|
|
61
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
62
|
+
|
|
63
|
+
[homepage]: https://www.contributor-covenant.org
|
|
64
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
By participating in this project you agree to abide by its
|
|
4
|
+
[Code of Conduct](CODE_OF_CONDUCT.md).
|
|
5
|
+
|
|
6
|
+
This is two packages under one name: `redundo.adapter` turns a
|
|
7
|
+
specific trace source into the schema, `redundo.analyzer` runs
|
|
8
|
+
analyses over that schema. They share the schema contract and nothing
|
|
9
|
+
else at runtime — contribute to either independently.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
- **Every change goes through a branch and a pull request against
|
|
14
|
+
`main`** — including maintainers' own changes. `main` is protected:
|
|
15
|
+
direct pushes are rejected, and CI must pass before a PR can merge.
|
|
16
|
+
- **Branch names**: `fix/…` for bug fixes, `feat/…` for new sources or
|
|
17
|
+
analyses, `chore/…` for anything else (docs, CI, tooling).
|
|
18
|
+
- **Bug reports and feature requests** go through the issue templates
|
|
19
|
+
(`.github/ISSUE_TEMPLATE/`) rather than an ad-hoc issue — the bug
|
|
20
|
+
report template in particular asks for a minimal reproduction (a
|
|
21
|
+
small fixture, not a real capture) and the redundo version, which is
|
|
22
|
+
most of what's needed to act on it.
|
|
23
|
+
- **CI** (`.github/workflows/ci.yml`) runs the full test suite on
|
|
24
|
+
Python 3.10–3.12 for every PR. A PR that doesn't pass CI doesn't get
|
|
25
|
+
merged, no exception for "it's just docs" — the workflow itself is
|
|
26
|
+
the only thing verifying that.
|
|
27
|
+
|
|
28
|
+
## Adding a new source (`redundo.adapter`)
|
|
29
|
+
|
|
30
|
+
Each source lives in its own module under `src/redundo/adapter/sources/`.
|
|
31
|
+
A good addition:
|
|
32
|
+
|
|
33
|
+
1. **Captures real telemetry first.** Every existing source's `docs/*.md`
|
|
34
|
+
was written against actual captured OTLP JSON, not just the source's
|
|
35
|
+
published documentation — several documented behaviors turned out to
|
|
36
|
+
be wrong or incomplete once checked against real data. Do the same:
|
|
37
|
+
enable the source's telemetry, point it at a local collector (see
|
|
38
|
+
`docs/` for examples), and look at what actually comes out before
|
|
39
|
+
writing conversion logic against it.
|
|
40
|
+
2. **Writes a `docs/<source>.md`** covering: how task/session grouping
|
|
41
|
+
works, what content is and isn't observable (and under which flags),
|
|
42
|
+
how tool calls and their results are represented, and a "known gaps"
|
|
43
|
+
section stating plainly what can't be recovered and why. Copy the
|
|
44
|
+
structure of an existing source doc.
|
|
45
|
+
3. **Adds a detection rule** in `detect.py` — something in the data
|
|
46
|
+
itself (a span name, an attribute, a resource attribute) that
|
|
47
|
+
reliably distinguishes this source from every other one already
|
|
48
|
+
supported. If nothing does, say so in the docstring and require
|
|
49
|
+
`--source` instead of guessing.
|
|
50
|
+
4. **Never fabricates content.** If a result or a piece of content isn't
|
|
51
|
+
observable, omit the record or mark it explicitly rather than
|
|
52
|
+
inventing a placeholder hash — see `hashing.py`'s module docstring and
|
|
53
|
+
any existing source's handling of unobservable content for why: a
|
|
54
|
+
placeholder hash that happens to match (or never match) another
|
|
55
|
+
record's hash reads as a real finding to everything downstream.
|
|
56
|
+
5. **Tests against hand-built fixtures**, not just real captures (which
|
|
57
|
+
are convenient for validation but too large/brittle to check in) --
|
|
58
|
+
see `tests/adapter/helpers.py` for the fixture builders every existing
|
|
59
|
+
source's tests use.
|
|
60
|
+
|
|
61
|
+
## Adding a new analysis (`redundo.analyzer`)
|
|
62
|
+
|
|
63
|
+
The schema and ingest layer (`schema.py`, `ingest.py`) and the reporting
|
|
64
|
+
infrastructure (`report.py`'s coverage plumbing, `to_text()`/`to_json()`/
|
|
65
|
+
`to_html()`) are not specific to waste detection. `classify.py`,
|
|
66
|
+
`cycles.py`, and the candidate-pair parts of `lineage.py` are — that's
|
|
67
|
+
today's one analysis, not the whole package.
|
|
68
|
+
|
|
69
|
+
A new analysis over the same schema should:
|
|
70
|
+
|
|
71
|
+
1. **Reuse `load_events()` and the `Event` dataclass** — never invent a
|
|
72
|
+
parallel ingestion path. The schema is the contract every adapter
|
|
73
|
+
targets; a second analysis reading something else defeats the point
|
|
74
|
+
of having one.
|
|
75
|
+
2. **Report coverage honestly**, the same way the waste analysis does:
|
|
76
|
+
what fraction of the loaded corpus this analysis can actually speak
|
|
77
|
+
to, before any headline number. See `metrics.py`'s `CoverageStats`
|
|
78
|
+
and `report.py`'s coverage lines for the pattern to follow.
|
|
79
|
+
3. **Never guess past a genuine unknown.** `classify.py`'s three-signal
|
|
80
|
+
model (waste-supporting / legit-supporting / unknown, never a forced
|
|
81
|
+
binary) and its module docstring are the reference for why: a
|
|
82
|
+
confident wrong answer is worse than an honest "the trace doesn't
|
|
83
|
+
say," because the first time someone spot-checks a confident answer
|
|
84
|
+
by hand and finds it wrong, the tool stops being trusted.
|
|
85
|
+
4. **Prints its rule next to its own counts**, not just a label — see
|
|
86
|
+
`RULE_TEXT` in `report.py`. A number without the rule that produced it
|
|
87
|
+
isn't checkable by anyone reading the report.
|
|
88
|
+
5. **Ships with a fixture-based validation**, the same discipline
|
|
89
|
+
`tests/analyzer/fixtures/sample.jsonl` follows: hand-built traces with
|
|
90
|
+
a known, intended classification for each case your new analysis
|
|
91
|
+
distinguishes, not just real captured examples (useful for demos, too
|
|
92
|
+
brittle/large to be the actual test).
|
|
93
|
+
|
|
94
|
+
## Running tests
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv sync
|
|
98
|
+
uv run pytest
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`tests/adapter/` and `tests/analyzer/` run independently — a change to
|
|
102
|
+
one package's tests should never need to touch the other's.
|
|
103
|
+
|
|
104
|
+
## Releasing to PyPI
|
|
105
|
+
|
|
106
|
+
Publishing uses [Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
|
|
107
|
+
(OIDC) via GitHub Actions — no API token is stored anywhere. To cut a release:
|
|
108
|
+
|
|
109
|
+
1. Bump `version` in `pyproject.toml`, merge that through the normal PR
|
|
110
|
+
workflow.
|
|
111
|
+
2. Tag the merge commit `vX.Y.Z` and push the tag, or create a GitHub
|
|
112
|
+
Release directly against `main` with that tag.
|
|
113
|
+
3. Publishing a GitHub Release triggers `.github/workflows/publish.yml`,
|
|
114
|
+
which builds the sdist/wheel with `uv build` and publishes them via
|
|
115
|
+
`pypa/gh-action-pypi-publish`.
|
|
116
|
+
|
|
117
|
+
The PyPI project must have this repository registered as a trusted
|
|
118
|
+
publisher first (PyPI account/org → Publishing settings → project name
|
|
119
|
+
`redundo`, repo `CogentWizards/redundo`, workflow `publish.yml`,
|
|
120
|
+
environment `pypi`) — a one-time setup step, done on pypi.org, not in
|
|
121
|
+
this repo.
|
|
122
|
+
|
|
123
|
+
## Reporting a documented behavior that turned out to be wrong
|
|
124
|
+
|
|
125
|
+
If you've captured real telemetry from a source and it disagrees with
|
|
126
|
+
what's written in `docs/`, that's a genuinely valuable bug report even
|
|
127
|
+
without a fix attached — open an issue (the bug report template) with
|
|
128
|
+
the captured data (redacted of any real content) or a description of
|
|
129
|
+
the discrepancy.
|
redundo-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cogent AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|