retentioneering/retentioneering-contributing
> Help the user turn their Retentioneering ideas, friction reports, bug capturing and validating the idea, through minimal reproductions and issue drafts, to preparing, testing, and submitting a pull request that follows this repository's conventions. Use when the user says they found a bug, wants a feature, wrote a workaround worth upstreaming, or asks how to contribute, open an issue, or make a PR to retentioneering-tools.
npx skills add https://github.com/retentioneering/retentioneering-tools --skill retentioneering-contributing
Convert a user's observation — a bug, a paper cut, a missing capability, a workaround
they keep re-writing — into the smallest upstream change that would have prevented it,
packaged so maintainers can accept it quickly.
| File | Read it when |
|---|---|
| references/repo-conventions.md | before touching code — build/test/docs commands, architecture rules, naming, sync obligations |
| references/proposal-templates.md | when drafting — issue/feature/PR templates with worked examples |
Record four things while they are fresh:
that created the expectation, if any).
retentioneering.__version__, Python, OS, install source(pip wheel vs source checkout).
Field lesson: reports formatted as expectation/reality/cost/repro get acted on;
"X is broken" reports stall.
Many pain points are already fixed on v5-migration — verify before drafting:
git log --oneline -30 and CHANGELOG.md — search keywords from the observation.gh issue list --search "<keywords>", gh pr list ....contribution may become a docs clarification or a regression test instead — both welcome.
Build the smallest toy that shows the gap, e.g.:
import pandas as pd
from retentioneering import Eventstream
df = pd.DataFrame({"user_id": ["u1","u1","u2"], "event": ["a","b","a"],
"timestamp": pd.date_range("2026-01-01", periods=3, freq="1min")})
# EXPECTED: ... ACTUAL: ...
Rules: synthetic data only (never the user's real log); deterministic (fixed frames, no
randomness without seed); one behavior per repro; assert the expectation so the repro
doubles as a failing test.
| Situation | Shape |
|---|---|
| Clear defect with repro | Issue with repro; PR with fix + regression test if user wants to go further |
| Surprising-but-documented behavior | Docs PR (docstring is the source of truth — site pages regenerate from it) |
| Missing capability | Feature issue: use-case first, proposed signature second, evidence third (see templates) |
| Repeated workaround in user's code | Extract as proposed API: show the workaround, its cost, the proposed call replacing it |
| Wrong-conclusion trap (library was silent) | Frame as "missing signal": what the library knew and did not surface; propose the warning/field |
For API proposals, the accepted framing (from templates): problem → evidence of frequency
→ proposed signature → semantics incl. edge cases → acceptance criteria → migration notes.
Read references/repo-conventions.md first. Non-negotiables:
master-tracking v5-migration; one logical change per PR.make install-dev — installs deps (uv sync + npm install) and wires the git hook(a one-time-per-clone step) so commits are auto-checked; skip it and commits bypass the hooks
locally and CI's lint job flags the formatting on your PR. Add make build only when
touching widgets/JS.
path_col/event_col/timestamp_col/session_col,start_event/end_event, verb-first processors, noun widgets, <widget>_data twins.
duckdb.sql with replacement-scan idioms (superseded ADR-0002).
tests/...); a bug fix MUST include thefailing-before test from Stage 3.
house style; silent degradation (dropped rows, empty results without a signal) is an
auto-reject.
method names; JS metric editor consumes the Python metric schema; docstrings feed the
docs site — update all in the same PR (uv run python docs/scripts/render_pages.py).
uv run pre-commit run --all-files # ruff lint+format, gitleaks, hygiene
uv run pytest tests/ -v # full suite (CI runs 3.11–3.13)
uv run python docs/scripts/render_pages.py # if docstrings changed
Commit style: imperative, scoped, explaining WHY when non-obvious (see git log for the
house voice). Update CHANGELOG.md under the unreleased/current section for
user-visible changes.
Submit:
git push -u origin <branch>
gh pr create --title "<imperative summary>" --body-file pr_body.md
PR body (template in references/proposal-templates.md): what & why → linked issue →
repro/before-after → tests added → sync checklist (docs/MCP/JS if applicable) →
breaking-change note. CI must pass: lint + test (3.11/3.12/3.13). master is
PR-only; merging does not release (releases are tag-driven by maintainers).
Respond to review within the PR (avoid force-push after review starts; append commits).
If maintainers ask for direction changes, update the issue first, then the code — the
issue is the contract.
When the user accumulated a batch (e.g., a journal of friction from a project):
deduplicate → verify each against current version (Stage 2) → rank by
(frequency × silent-failure risk) → file the top 3–5 as separate issues with repros →
offer one PR for the cheapest verified fix to build credibility, referencing the issues
for the rest. Do not open one mega-issue.
Take retentioneering/retentioneering-contributing from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npm.
Without those the skill loads but fails at the first command.