From 431f6a94b675585911bee66699d11e98d2fd0aa5 Mon Sep 17 00:00:00 2001 From: "David J. Kim" Date: Wed, 22 Jul 2026 16:14:04 -0400 Subject: [PATCH 1/4] feedback-capture: route low-friction feedback to Discussions - ISSUE_TEMPLATE/config.yml: add a Discussions contact link (ask a question or share a catch) ahead of the docs link, so the issue chooser offers the lower-friction path first. - first_catch.yml: trim required fields to stack, what-was-caught, and card or report (command/where/version now optional); restate share-safe; close by thanking and inviting a star. - .github/FUNDING.yml: commented template, no active sponsor handle. - CONTRIBUTING.md: add a 30-second smallest-useful-contribution path up top. --- .github/FUNDING.yml | 9 +++++++++ .github/ISSUE_TEMPLATE/config.yml | 3 +++ .github/ISSUE_TEMPLATE/first_catch.yml | 18 +++++++++++++----- CONTRIBUTING.md | 14 ++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c535311 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,9 @@ +# Sponsor button for the repo. This file is a template: every line is commented, +# so no sponsor button renders until a maintainer opts in. +# +# To turn it on, uncomment one line and set the real handle. The GitHub Sponsors +# handle below is a placeholder, not an active account: confirm the org has a +# Sponsors profile before uncommenting. +# +# github: [attenlabs] +# custom: ["https://hotato.dev/"] diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 34d5866..df02442 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: true contact_links: + - name: Ask a question or share a catch + url: https://github.com/attenlabs/hotato/discussions + about: Questions, a moment hotato caught, an integration you wired up, or an idea. Lower friction than an issue, and others can chime in. - name: Documentation url: https://hotato.dev/docs/ about: Guides for capture, scoring, CI gating, and the MCP server. diff --git a/.github/ISSUE_TEMPLATE/first_catch.yml b/.github/ISSUE_TEMPLATE/first_catch.yml index 9bb7e7d..0e8f19e 100644 --- a/.github/ISSUE_TEMPLATE/first_catch.yml +++ b/.github/ISSUE_TEMPLATE/first_catch.yml @@ -32,10 +32,10 @@ body: id: command attributes: label: Command you ran - description: The exact invocation, credentials removed. + description: The exact invocation, credentials removed. Optional, but it helps us reproduce. placeholder: "hotato investigate --stack vapi --call-id " validations: - required: true + required: false - type: textarea id: what_was_caught attributes: @@ -68,19 +68,27 @@ body: - Gating a branch in CI (contract verify) - Still a candidate, deciding validations: - required: true + required: false - type: input id: version attributes: label: hotato version - description: Output of `hotato --version`. + description: Output of `hotato --version`. Optional. placeholder: "hotato x.y.z" validations: - required: true + required: false - type: checkboxes id: share_safe attributes: label: Share-safe + description: The card and the text report carry timings and measurements only. Keep it that way. options: - label: No audio is attached, and the paste carries no call id, phone number, or name of any call participant. required: true + - type: markdown + attributes: + value: >- + Thank you. A first catch from a stack we did not operate is the + clearest signal this tool works. If it earned a place in your loop, + a [star on the repo](https://github.com/attenlabs/hotato) helps the + next person find it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6bb5614..9917346 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,20 @@ ever a single blended score. Every kind of contribution is welcome. This guide gets your first one merged with the least friction, then points you at the contribution that helps most. +## The 30-second contribution + +The smallest useful change, start to finish: + +- **A one-line doc fix.** A typo, a stale flag, a command that reads wrong. + Edit the file on GitHub, open the PR. Done. +- **A labeled synthetic fixture.** One JSON scenario that stresses a timing + edge the suites miss. Copy an existing label under + [`corpus/suites/`](corpus/suites/), change the timings, run + `python3 corpus/validate.py your_label.json` until it prints PASS. + +Both are reviewed quickly and merge without a release. If you have more time, +read on. + ## Ways to help Pick whatever fits the time you have: From e27c1db8a702a091d4a764e750f5a92b614078f8 Mon Sep 17 00:00:00 2001 From: "David J. Kim" Date: Wed, 22 Jul 2026 16:14:20 -0400 Subject: [PATCH 2/4] conversion: README star-ask + MIT badge + star-history + animated demo cast; CLI first-run star footer --- README.md | 18 +++++++- README.pypi.md | 18 +++++++- docs/assets/hotato-demo-cast.svg | 79 ++++++++++++++++++++++++++++++++ src/hotato/start.py | 5 ++ tests/test_start_cli.py | 14 ++++++ 5 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 docs/assets/hotato-demo-cast.svg diff --git a/README.md b/README.md index a4c1fc7..e09928f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ PyPI version Downloads per month Python versions -CI status

+CI status +MIT license

+ # hotato @@ -14,6 +16,8 @@ Your evals are green. Your agent still ships bugs they can't see: talk-over, dead air, a tool it swore it ran. hotato catches them on your machine and gates CI so they stay fixed. +uvx hotato start --demo catches a 2.66s talk-over and returns exit 1 + **[hotato.dev](https://hotato.dev)** @@ -30,6 +34,8 @@ Conversation failed: Agent did not yield; measured talk-over was 2.66 s. That transcript passed every text eval. The timing did not. hotato pins the catch as a CI contract that reproduces byte for byte, so a fixed bug stays fixed. It measures timing and say-do, not intent. +If hotato caught something your evals missed, a [star](https://github.com/attenlabs/hotato) helps other teams find it. + ## The loop Turn production failures into portable tests, run candidate releases against them, and carry evidence with every release. Five steps, one command each, nothing leaves your machine. @@ -164,10 +170,18 @@ Timing is measurable only when the two voices arrive on separate channels; a mon Issues and PRs welcome: [`CONTRIBUTING.md`](CONTRIBUTING.md) · [`SECURITY.md`](SECURITY.md) · [`CHANGELOG`](CHANGELOG.md) · [`docs/`](docs/) +## Star history + +hotato star history + ## License MIT ([`LICENSE`](LICENSE)) -
Know when to pass it on.
+
+If hotato caught something your evals missed, a star helps other teams find it. +
+Know when to pass it on. +
mcp-name: io.github.attenlabs/hotato diff --git a/README.pypi.md b/README.pypi.md index 3245b8e..9e11562 100644 --- a/README.pypi.md +++ b/README.pypi.md @@ -6,7 +6,9 @@ PyPI version Downloads per month Python versions -CI status

+CI status +MIT license

+ # hotato @@ -14,6 +16,8 @@ Your evals are green. Your agent still ships bugs they can't see: talk-over, dead air, a tool it swore it ran. hotato catches them on your machine and gates CI so they stay fixed. +uvx hotato start --demo catches a 2.66s talk-over and returns exit 1 + **[hotato.dev](https://hotato.dev)** @@ -30,6 +34,8 @@ Conversation failed: Agent did not yield; measured talk-over was 2.66 s. That transcript passed every text eval. The timing did not. hotato pins the catch as a CI contract that reproduces byte for byte, so a fixed bug stays fixed. It measures timing and say-do, not intent. +If hotato caught something your evals missed, a [star](https://github.com/attenlabs/hotato) helps other teams find it. + ## The loop Turn production failures into portable tests, run candidate releases against them, and carry evidence with every release. Five steps, one command each, nothing leaves your machine. @@ -164,10 +170,18 @@ Timing is measurable only when the two voices arrive on separate channels; a mon Issues and PRs welcome: [`CONTRIBUTING.md`](https://github.com/attenlabs/hotato/blob/main/CONTRIBUTING.md) · [`SECURITY.md`](https://github.com/attenlabs/hotato/blob/main/SECURITY.md) · [`CHANGELOG`](https://github.com/attenlabs/hotato/blob/main/CHANGELOG.md) · [`docs/`](https://github.com/attenlabs/hotato/blob/main/docs/) +## Star history + +hotato star history + ## License MIT ([`LICENSE`](https://github.com/attenlabs/hotato/blob/main/LICENSE)) -
Know when to pass it on.
+
+If hotato caught something your evals missed, a star helps other teams find it. +
+Know when to pass it on. +
mcp-name: io.github.attenlabs/hotato diff --git a/docs/assets/hotato-demo-cast.svg b/docs/assets/hotato-demo-cast.svg new file mode 100644 index 0000000..e8f24ba --- /dev/null +++ b/docs/assets/hotato-demo-cast.svg @@ -0,0 +1,79 @@ + + uvx hotato start --demo catches a 2.66s talk-over + A terminal types uvx hotato start --demo, then reveals that a transcript which passed every text eval failed on timing: the agent talked over the caller for 2.66 seconds, so the gate returns exit 1. + + + + + + + + + hotato + + + + $ uvx hotato start --demo + + + + + Conversation failed: Agent did not yield; + + + measured talk-over was 2.66 s. + + + + talk-over 2.66s the agent kept talking while + + + the caller held the floor + + + + That transcript passed every text eval. + + + The timing did not. hotato pins it as a CI + + + contract that reproduces byte for byte. + + + + $ echo $? → 1 the gate is red until it is fixed + + diff --git a/src/hotato/start.py b/src/hotato/start.py index 8807e43..bed75ee 100644 --- a/src/hotato/start.py +++ b/src/hotato/start.py @@ -848,6 +848,11 @@ def run_start(*, demo: bool = False, stereo: Optional[str] = None, event_wav_rel = (f"{contract_info['bundle_rel']}/audio/event.wav" if contract_written else None) print(_next_commands_text(event_wav_rel)) + # One quiet footer on the successful demo path only (never on errors or + # other subcommands): a star is how the next team finds this. + print("") + print("Useful? A star helps other teams find it: " + "github.com/attenlabs/hotato") return 0 diff --git a/tests/test_start_cli.py b/tests/test_start_cli.py index 427c775..508e1ce 100644 --- a/tests/test_start_cli.py +++ b/tests/test_start_cli.py @@ -118,6 +118,20 @@ def test_start_demo_prints_the_next_commands(tmp_path, capsys): not in joined) +def test_start_demo_prints_one_quiet_star_ask_footer(tmp_path, capsys): + """The successful --demo text path closes with exactly ONE quiet star-ask + footer -- printed once, on the success path only. A usage error (no mode) + never reaches it.""" + assert cli.main(["start", "--demo", "--dir", str(tmp_path)]) == 0 + out = capsys.readouterr().out + ask = "Useful? A star helps other teams find it: github.com/attenlabs/hotato" + assert ask in out + assert out.count(ask) == 1 + # not emitted on the mode-usage-error path (exit 2, nothing scored) + assert cli.main(["start"]) == 2 + assert ask not in capsys.readouterr().out + + def test_start_demo_json_format(tmp_path, capsys): rc = cli.main(["start", "--demo", "--dir", str(tmp_path), "--format", "json"]) From d98c395a0090e831b814c7136186d9a742dbfc47 Mon Sep 17 00:00:00 2001 From: "David J. Kim" Date: Wed, 22 Jul 2026 16:29:05 -0400 Subject: [PATCH 3/4] growth: drop the star-ask (operator decision) Removes the star solicitations (README top + bottom lines, the Star history section, the CLI first-run star footer, and its test) per operator direction. Keeps the MIT license badge and the animated demo cast: those are a factual badge and a product demo, not a star ask. Feedback-capture and the /use-cases inbound content stay. Claude-Session: https://claude.ai/code/session_01BqJW5Dey1DzqBeBCAJXrH9 --- README.md | 12 +----------- README.pypi.md | 12 +----------- src/hotato/start.py | 5 ----- tests/test_start_cli.py | 14 -------------- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index e09928f..f624b0e 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,6 @@ Conversation failed: Agent did not yield; measured talk-over was 2.66 s. That transcript passed every text eval. The timing did not. hotato pins the catch as a CI contract that reproduces byte for byte, so a fixed bug stays fixed. It measures timing and say-do, not intent. -If hotato caught something your evals missed, a [star](https://github.com/attenlabs/hotato) helps other teams find it. - ## The loop Turn production failures into portable tests, run candidate releases against them, and carry evidence with every release. Five steps, one command each, nothing leaves your machine. @@ -170,18 +168,10 @@ Timing is measurable only when the two voices arrive on separate channels; a mon Issues and PRs welcome: [`CONTRIBUTING.md`](CONTRIBUTING.md) · [`SECURITY.md`](SECURITY.md) · [`CHANGELOG`](CHANGELOG.md) · [`docs/`](docs/) -## Star history - -hotato star history - ## License MIT ([`LICENSE`](LICENSE)) -
-If hotato caught something your evals missed, a star helps other teams find it. -
-Know when to pass it on. -
+
Know when to pass it on.
mcp-name: io.github.attenlabs/hotato diff --git a/README.pypi.md b/README.pypi.md index 9e11562..2547550 100644 --- a/README.pypi.md +++ b/README.pypi.md @@ -34,8 +34,6 @@ Conversation failed: Agent did not yield; measured talk-over was 2.66 s. That transcript passed every text eval. The timing did not. hotato pins the catch as a CI contract that reproduces byte for byte, so a fixed bug stays fixed. It measures timing and say-do, not intent. -If hotato caught something your evals missed, a [star](https://github.com/attenlabs/hotato) helps other teams find it. - ## The loop Turn production failures into portable tests, run candidate releases against them, and carry evidence with every release. Five steps, one command each, nothing leaves your machine. @@ -170,18 +168,10 @@ Timing is measurable only when the two voices arrive on separate channels; a mon Issues and PRs welcome: [`CONTRIBUTING.md`](https://github.com/attenlabs/hotato/blob/main/CONTRIBUTING.md) · [`SECURITY.md`](https://github.com/attenlabs/hotato/blob/main/SECURITY.md) · [`CHANGELOG`](https://github.com/attenlabs/hotato/blob/main/CHANGELOG.md) · [`docs/`](https://github.com/attenlabs/hotato/blob/main/docs/) -## Star history - -hotato star history - ## License MIT ([`LICENSE`](https://github.com/attenlabs/hotato/blob/main/LICENSE)) -
-If hotato caught something your evals missed, a star helps other teams find it. -
-Know when to pass it on. -
+
Know when to pass it on.
mcp-name: io.github.attenlabs/hotato diff --git a/src/hotato/start.py b/src/hotato/start.py index bed75ee..8807e43 100644 --- a/src/hotato/start.py +++ b/src/hotato/start.py @@ -848,11 +848,6 @@ def run_start(*, demo: bool = False, stereo: Optional[str] = None, event_wav_rel = (f"{contract_info['bundle_rel']}/audio/event.wav" if contract_written else None) print(_next_commands_text(event_wav_rel)) - # One quiet footer on the successful demo path only (never on errors or - # other subcommands): a star is how the next team finds this. - print("") - print("Useful? A star helps other teams find it: " - "github.com/attenlabs/hotato") return 0 diff --git a/tests/test_start_cli.py b/tests/test_start_cli.py index 508e1ce..427c775 100644 --- a/tests/test_start_cli.py +++ b/tests/test_start_cli.py @@ -118,20 +118,6 @@ def test_start_demo_prints_the_next_commands(tmp_path, capsys): not in joined) -def test_start_demo_prints_one_quiet_star_ask_footer(tmp_path, capsys): - """The successful --demo text path closes with exactly ONE quiet star-ask - footer -- printed once, on the success path only. A usage error (no mode) - never reaches it.""" - assert cli.main(["start", "--demo", "--dir", str(tmp_path)]) == 0 - out = capsys.readouterr().out - ask = "Useful? A star helps other teams find it: github.com/attenlabs/hotato" - assert ask in out - assert out.count(ask) == 1 - # not emitted on the mode-usage-error path (exit 2, nothing scored) - assert cli.main(["start"]) == 2 - assert ask not in capsys.readouterr().out - - def test_start_demo_json_format(tmp_path, capsys): rc = cli.main(["start", "--demo", "--dir", str(tmp_path), "--format", "json"]) From 37a1c93dffb33d0724e6ae05939a4f0709900fb6 Mon Sep 17 00:00:00 2001 From: "David J. Kim" Date: Wed, 22 Jul 2026 16:51:17 -0400 Subject: [PATCH 4/4] chore: regenerate llms-full.txt (CONTRIBUTING 30-second-path edit) The feedback commit's CONTRIBUTING.md change feeds llms-full; regenerate so the committed copy matches (test_llms_full_txt_committed_copy_is_up_to_date). --- llms-full.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/llms-full.txt b/llms-full.txt index 05e4eef..13d9b20 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -10,7 +10,9 @@ FILE: README.md PyPI version Downloads per month Python versions -CI status

+CI status +MIT license

+ # hotato @@ -18,6 +20,8 @@ FILE: README.md Your evals are green. Your agent still ships bugs they can't see: talk-over, dead air, a tool it swore it ran. hotato catches them on your machine and gates CI so they stay fixed. +uvx hotato start --demo catches a 2.66s talk-over and returns exit 1 + **[hotato.dev](https://hotato.dev)**