S2b: the nudge that arrives at the sweep moment, carrying the command - #32
Conversation
… command The meter's first 12 hours said two things at once. The one-time nudges FIRE — 455 of them — and convert at zero: substitution after a nudge was 0.8%, indistinguishable from before it. And the dominant behaviour is the SAME-CLASS SWEEP: grep->grep->grep 357 times as a trigram, read x3 187, git-diff x3 119. Generic advice at the first grep does not change the next choice. So: at the Nth call of a class in a session (N=3), replace the verb-and-an- ellipsis tip with the exact one-call substitute, built from what was observed. A grep sweep gets a runnable --for= carrying the agent's own last patterns; a read sweep gets --pack-task/--expand scoped to the directory of the file just read; a git-history sweep gets --situ; a glob sweep gets --for or the flagless map. Once per class per session, advisory only, never a blocker, recorded on the row (nudge=sweep3, post_sweep on everything after) because an unmeasurable nudge is one nobody can ever turn off on evidence. The verdict is NOT assumed. docs/EVALS.md §4 pre-registers the one-week readout, its band (KEEP >=16.9%, REWORD 8.0-16.8%, DISABLE <8.0%), its minimum data, and the rule that a null readout disables the escalation — which is why RIPWIRE_SWEEP=0 was built before the measurement rather than after it. Along the way the instrument turned out to be broken in the direction that flattered the finding. 924 of a frozen 2,155-row log were `unclassified`, and 742 of those were multi-line or `cd <dir> && ...` command lines: jq's @TSV escapes newlines, so `cd /a/b\ngit diff` arrived as one token whose basename is `b\ngit`, matching no rule. Un-escaping for the readers, stripping cd/pushd and their operand like any other transparent prefix, and skipping git's own pre-subcommand options takes unclassified 924 -> 160 (-82.7%, 42.9% -> 7.4% of the log) on replay over that same frozen log. ripwire's own calls were undercounted 8x (9 -> 73) — the corrected substitution baseline is 5.62%, not 0.8%, and the registration states both numbers and sets its band against the corrected one. The correction sharpens the motivating finding rather than dissolving it: under v2 the post-nudge rate (0.79%) is ~8x LOWER than the pre-nudge rate (6.14%). Schema v2 adds post_sweep and the sweep<N> nudge value, and widens the classifier with build / gate-run / git-remote / git-misc / shell-misc. Those never enter the substitution rate — their families are other/meta/git — they exist because S4 ranks the absorption queue from the command mix an agent actually runs, and a class that writes no row is one that survey can never see. Row counts are therefore NOT comparable across the v1/v2 boundary, which is what the version field is for. Cost: one byte appended to a per-class counter plus a fork-free $(<file) read, on the nudgeable path only. +1 ms or under, below the harness's ±2 ms noise floor. No call that was already logged got slower; more calls are logged. Gates: test/hookcheck.sh section (12), arms S1-S14 and C1-C3b — 20 of them red against the pre-change hook. Fires at N and not before; two calls do not trigger; a fourth is silent; classes dedup independently; the row carries the marker; RIPWIRE_SWEEP=0 and the control arm leave calls 1-2 BYTE-IDENTICAL to a run with the feature on; silence off its preconditions and nothing on stderr; and fixtures for the cd strip (including `cd x && VAR=y grep` and the multi-line form) and every new class. 395 gates green, quality-delta gating=0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 34 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. 📝 WalkthroughSummary by CodeRabbit
WalkthroughThe substitution meter now uses schema v2, expands command classification, and adds configurable per-class sweep-escalation nudges. Reporting groups sweep exposure and mixed schemas. Documentation defines the S2b evaluation and decision thresholds. Tests cover classification, escalation, gating, and degradation. ChangesSubstitution meter sweep escalation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ToolCall
participant ripwire-nudge.sh
participant SweepState
participant MeterLog
participant RipwireCommand
ToolCall->>ripwire-nudge.sh: Send retrieval call
ripwire-nudge.sh->>SweepState: Update session/class count
SweepState-->>ripwire-nudge.sh: Return threshold state
ripwire-nudge.sh->>MeterLog: Write sweep metadata
ripwire-nudge.sh->>RipwireCommand: Emit class-specific advice
ripwire-nudge.sh-->>ToolCall: Allow original call
```}
</details>
<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->
<details>
<summary>🚥 Pre-merge checks | ✅ 5</summary>
<details>
<summary>✅ Passed checks (5 passed)</summary>
| Check name | Status | Explanation |
| :------------------------: | :------- | :-------------------------------------------------------------------------------------------------------------------------- |
| Description check | ✅ Passed | The description directly explains sweep detection, classifier changes, evaluation thresholds, testing, and safety controls. |
| Title check | ✅ Passed | The title clearly identifies the S2b sweep-moment nudge and its command payload. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
</details>
</details>
<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->
<details>
<summary>✨ Finishing Touches</summary>
<details>
<summary>📝 Generate docstrings</summary>
- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> Create stacked PR
- [ ] <!-- {"checkboxId": "3e1879ae-f29b-4d0d-8e06-d12b7ba33d98"} --> Commit on current branch
</details>
<details>
<summary>🧪 Generate unit tests (beta)</summary>
- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `s2b-sweep-nudge`
</details>
</details>
<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->
---
Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=redhat-et/ripwire&utm_content=32)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
<details>
<summary>❤️ Share</summary>
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)
</details>
<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>
<!-- tips_end -->
<!-- internal state start -->
<!-- N4IgzgxgFgpgtgQwGowE5gJYHsB2IBcAjADTgAuqArhGZajACYDKZCZMBoYF1t9K6bHiKkADqgDyAIwBWMGhgBuMMARABidQAIACgCUtYSnESoAngB0cVgJJxRAG3gwcZMIYDuMGKK0MY7Aq4WgBmWKhacAFoALQA5myMWjiUDHEqAHRaACqwWmRQGKgMhghRMRAOCGDuEAgODloYOFoIhiqYwRQYcenoWrgwrQyKGGDhZloqdVVkQlqiaFqV1WDEy7iszc1xrQvV7DH0CAyTRlLcGLTsWlLVScFYF2jKJWAwCKjQ+Whw7uEbVwwAAeZCyuSGIQ+fCGRlEonCbi0AAM9DYdAB1Gx6ACiAH0mBicTidABeAAMyPW9Ag4QY7mRYC8PgAPAA5AB8yNaOBKyIR3DxTO8oipPJKrFQ6SROCwkXCQwKCBahEi/2UqFgJwyVisAFVRAxErUqjUMCEMEtRJ9MDhdmQ5VBlQwnFNIAhFiU4JQHHMHM0hrSTM61n4ivIHeZxVMcKNULgoq4FvQLcCVOsAOJXAaiOa4UPO4YMK5CeobYO85am95gLIAMXjAC8XFp6I4EJN6AxqCotJQcCszRakvGPO4QvG4FoAJwAJgALPk5YQAGzk6MqVhSf1gWDuNq01A09hvSgXObXeZ3d7+nBDLAhLQAVgyK9nAFIddYcAARGAWu93HENAYDiMZ2C7KYQgtOoIEmAp6F3LAHHpfAtAAaWJHRWjILRAFMiVcMmnd91lxDEJD0H8cK0AAODJyUAZAJCJokjox/GwmAAQQAIQAGRxW4YAcLAPFo+jWPOOQaCXSJtm9KcwDKRwhnoABHShw0TNxwTyaZ6jYeYxmGUZxijQsPAwBpBLDRTtweFo2hSKzjgYLBKDBXUcE4hh6S0KAsCwABrCpYAgQKNg1BB0nWVMYVDSBYEQZYnTtdMq1Wc1LQiShDWNdZC0CyyHBiJkrmgAB6WlXHjYrPindhuFrHI8jbREkiMK40vU+orjMGJ/F9NoEjmO11n8CC4G2MA4HyysAA0AFleK0RQeqNPMWmtGoMhAUhUAQDwmGMUwzAWj1OBADJUAwUQLPoPFuv9MgzDxBAwtUfANG0TibHiFw0ESU9gyjB9kuVdIwE8iEtEe3qYje8KLVdE5fMwYEUSQ1AyBifzrsbXAQroHBuQR2UPCcNJnFcccASiCDQn7IIcFDApYTPS5LwJumln8oLIjYaA0Fmkp6FmEd5BcXDGCuJqcWBcCdlaMKyYp9ItP3ehWxgOkQJKQtu0cDA6huSXrt7T4VPgLBXhkxBmi2FpTJPLRApgSYddQL8rE0LRON9AGNvcB18jyfwVn2wOBkfEEESxh4IlEM9/QgGML0tSHvzZQZPN4gNahS9IGDQgBqJ9ypiclPJxS5EGd2l/C10YYFE/8wixtDeJE3aQCkFwKvODn3KEPFWqxjJRDMNQfZ+v67wj9rjs+d3H2gcGVE8g11qSVyIGMSWDOCcPMt7JVcORMCyDFZEsFZ1AxULZE6YQbkQjKSz09aTWQUqVIkgnLB6p5AHheIewQI7YGFiHNgrRnLyB1nrVAfxP6KmOGQLSWgnDKAcO4COsAIhKhaHUSgilGhBmtNdcYzMsjeX8CLHwiJFZt08CKGIelZjzBjlgIw9B1hsIPoQty1NbhnA6EISBk00xvEFklDUnRmbrGaD/Ysdo9geE+DgRWp8VqEHKooWcrZjTIOSDfMMx4HCTDIZ8BAdkvY4Gnv7cB+YZKsz8PIKojjmZRymMCWOzsASJ23EbVOJZ16Z2zt+XOgEwapSLloYuABmck5d5xVxroDDYDd6BNxbtBREaEFrS2MN3HeYByo4iQJxXiTAMhwAYFPb6v10hz3SUYYGy9okQ08jQpIbRgJHFAuBXWWgmCzikFMVaDhKD8PaEzUIAJhQ+FYe6dhwQUiUyajYXC/gAIn10ss6ZvcnSjHCOsQ8x53DXiEgGQw7MQEbUiB8bhVMkTEM0XkPR6UhxZXWGARYEBj5BzyAKbGCzfDiAwCdB53QU6FkwiScqZEKI/nKuxLifEBIIRUP5FCoZJoaPkqUewro1IaXoOrH5cDeRLy1icHYoYw5jHmFQJwoYqphH7PSH5tJFgYIhTLSBbR3jkMSK4qER4/7IWEh4GIwQmHNnjP0owvotBxDbK4wIG1bH2IgvwoOcoXFh3cbqrxnC44lH8UnIJksQkZysFnO8Oc84dMYCXQg5IdEV1SXMWuSR66W2yVBNuZAO5d1ICU8qTA9TcSYNkGw2Q9SxokGyPEC0cTZBxHoGpdTPrT0af9eeQNIWg1XqlW1OBobAKuKAlo3MIg7z3q4aZRkcpbxKP/BS0i2iKFVMHPRWRNl+CwLvdWOYNpllrYCC0cQ6D8J+cyXwfD7nvDICNOIoY7yiWRGs9IJNKz8i4WQIU86X6WhxZArJYwkggiUsSkSTVoaDkwMOCIZM/LOhZW6OonpIg+j9NcoMiBeShjbNCJIwFUzm0rB4fa8I0ChmRBABgyJyr8mIVAJDmZsxYFzEIAslYUYllwGWKQGkULrAamQTDlHoy7iEqQgBgGSiPsyFoNkzcZmR38JAa6vdmE+EEkc7AqAfnKhLI2WdCw0Bt0AxAGApzwjHiSIUbg4QjbjoCNdCAeGJR5Gse8Ac94V6bBqvDRBfg2AICyBmEVtJIrpGMaJRRkyuN8YXfs+5hYXEx2dL66sx9PaeW1QHXDzjQ5uKsZHUGpq/EJ0tSna1cxQl2vCVYSJvYS2F1dfElc5dCAAHYvUQvSX6xuloclBpDR4buvNAqlOurdcMMRt0wAyLuepvs83NOdq0otK8C5Ja8j5X1uAp0zrsq5pZMxpnNcBdA7ovQlgIBCPTED6T6DdBgBM5Y9RsGSYiI+6kcDiiucMKwG4zQoVLGEmuyB8BszXukvVu6gYGMhiyAUlbR3fKvuIbCTtK04PzH0RZAoKJgVHpFMiLI3FqhQH2IIFRr6Uoul7AhpDKHE67gw+0YVkZQwX1Hbh27oJ9o0EBZCIo3BjE4BiCEKouxPjTq0lkAAwn5mC0y1HuG87yJIwcnO/xVVcdYJHLIMHI5ucqw05OGFgA0cRYxZMNGVNrYh5ZGOfJrFoDwhRXTAXeKgUYKj1tmwmUcEVUhBFGjNk1GHu51f6zgco3Yr7ZSIJ6s2bn7pv0btvJBiUenBJtyGLXaAitCyPsysbIQWQmDzo2P2CCoZrQrrQIQj0MIxqMBysnCTEfqwlT+VH4yYwJgPJqFFXsXhNYo0YAAbhgY0NyZBE64TJQgZo+4Ril7Mvhhod6Q73mumBHAZYHTIW2w0LV30HHGuDga8LHj/jRx8W1c1sXAnxdcDazy9qYCOqiRll1cT4nxOnOXWcNFCs+qY1gTJm2yuBryVoAAEj0KA3cKPlTDoFQWYVXr97kzgQZBkCgjtYzxNIBwLxtJeJH5lrdJtpuQRAXz9JiwShBQuB6qD6uJhR/6Iz1DvAxACgljKCN4iQ7jBoogxDxBXD9RFBXzUEeDhDBQUDeD3x7rUGyhEGV53ytDuAE59LnAAaFjYaBzrCOBq7IjUGDB+4kz7hC64TXaE64DT6+yz6Rzz5hbhzGpRar5moDAb7JzBKJZlp74H7pb9axLFzzjlyVzfjVzerFZ37+qP6tzP6dxVakBf41Z4GtYf45oNKzxQGFrUrFr9ZlpyzsC858g+GhSBR+HcgUZYEkrhjYH7qCigrcgTrDgoTRgtrpIuLN4yohAlTcovYVhtoYCgh0CKhygajmiTD9ij5RC34VE4LwAd4tD9jXaFzUJDatHASwDMxKCwjzqTb6T3JJERRoBvKITYolCHIIDHLCb7DcAwD9InAWKvZAbiGxCPquIGy54bTUgiRQonAWaHYnBS7CRSBS73buZiKAgUAT6eZQBzHITmoajXRcZZ6qonBgY0i4DFhiGySSJaB25QDlQZhqrNCt7aYl6mR9S4DmIDDuSt59G0Ka7+Y/CNRzL7bbEMBEEphVGnb1aiA7DrDei+jvx3gO47G3CkYMDlRf5ko3wwDlSTSQB0lMbVhpSFj64vDTKgxlBSA9CUBuRAQ3SMDxBqqR4c6aq+z9GDrDr7z3J4E0z4J5Abonb54ZTPpPGk7aSBYz46oaH6paFGqRYr6+LxwLBxbGHpyeQxBaB1iMweb9FoSMjzojz9gAAUvEEgGYdYNg/E6w2QC0Og7EegFSvE6wAAUkwEmusAANoVJ6CkgxlaAZDZkAC6AAlNyBdsiN4QFL/nEQkVYM6a6QOO6bQp6aqj4DIJQr6UwDiEwEwDYEmniDYD+OsDoJxNkOmnoGyAWU0C0MWZLrEfIPEbuMiJWS6W6fMLXrEsiC5E2bgC2W2R2V2T2esMGfxHiP2dkC/qOUWSWUFL4bOfOdWbMsufWTceuTgJue2Z2cmruboAOUOSOYWeOeeWWdORWREk6kflYbONOPEuXAVvYWknXM4aVuxm4e3K/u/iAAAL5hoBAd4Uws7OHcTCRhRHRtJ6BrwfTJmgD7SpQ2DZogAUXpB4in4rg0QICEAMCzhPizgwBSDdwp7+GXRPbhgPRTJPQvQIyqCkDcCfBkBpYEB5YkAgAuAMDSX4B5bzjiWLzmBqAIGy6Ig4yqb4w07QBExKyBQqyMBqySwamXaoC06LnBDSxIgXYuIjJjKgrjErItBVB3g7SkB+p4VDqBQ4VEogi9RqBSpoXEDkVrxUVqC0UwCvSEDTgwDzjxJvQQArgIDkjcVsC8VXQ3TPaCU9TPSvTvTdwSVYxKV5ZPikAKUVVVXgDqWTyfRaXKjGWmWUzoJMIWT+AaIqIuKVqcw04To1b8xkCCwRDmRFCKyrn/hzF4g1Z4ih54K+mnmuByjIid6sANBzWllQ7dy+X4UBUALKTyzPRqAtEYBFLoWRWUXUWxV4gMA0QhBSAPUQDTjkiIYQBZUFBqC5UNb3SwxFWiWlWShSUBgEA0TkjVW8hKU0QrhqVtKaVKkhB0C3zaVYy6V4wEyGWoAOTKzkFmXPKWW1o2U1kcLAn7iVjradF85AJr6tX43tWSwGH+DXR2jeUgD7X+WBXHUhWfRhVXU0VRW3Vrx4jkjzh5ZvXxKzgrgrgQB5Y0RfW8W9wDiQn9XVojz0JjwTzA2SVKWEB1U1Vg34Czizjw0nRqByzWjRHYH1paRXrAhKJ/xvz+j+7pTXTDg6ZzYtSa24RIRjj5CoLoKYJCT/A4DmLrCyi4SsFsDoKtwRj/D7YIDEJljFjQQgQGa1h7W4UHXc1OAnWNUgD80RWC03UxUi1SArhSCEALhPjpUMBPjziK1qDK39y3JVobQa2+LjyTziUg163xI0RQ2KVG363Thm1LyI2YnN6t4qrxg5SKyjgXKdhfZJDpGHqZHeICg1HyaJ7uCgqfoTEhaFhLZQg0DtSiL5jno+3uASLtT/ayIhYg5w5tBqI41vLQLdrRgfK0i71GKR3ljCo2JZ3+B+VhS53BWnWfTnWXXF2xXRWfR3UQALiEAQBS0IDxLi11JiDZVqDhrlKVLVK1I63lVG1Pjkhj3yXQ2kOziQ31UI1NVKlOWjJaxgTcAeKuLcYYCikqJsikjxInaLqPE65Gxw5thVCyb8H5pBIzba5XBw6PqF7yDF78WazCFAZ4mz0+CXHi4KE4zgQTCQJxA3GuZgAN4uJRAlpjBTjt6d4Ill6Fiyg07bj+U7Ds2c1gNHV5280gDQNwDhXXXpDwMl10VPi13ziEA0RSB5ZSAhBPhcXYPfWfR4MxmENYPkC63UOm2UPD13gEAN15bj0aWfQ/hDoNrOwuJnIRhJAfKXJ+5aztjuwajYGKRRChBNgtjXYKIDjOYL3Z6yYlCMzs6WgiwD6FgXrvAlB9LlTApNapD2Zq33LzyhjCPEqYXbC9VAJCQRhCAVAjZW6Kx1DKBsBuPZ1c2eMQMF2FBxAf4C1wPC2pR4jTioNgUQAQ3khgUIBN1JNDqlL4NVJZrEOg25P4AN0UOG3Au10FN0Pm3FP/gBg6ZDDgqQozOCPBALPzB0yabRjAT0CsMQRJBwo6CkQ4jkSUSQKoo8T8QhzvE4qtAJAbXYGVNn0lAvhvjvi3D3B+4nMgM53nP51nWFJ+O3NC1l0PPZYxNSDkjsU0SX6fUJO8XJMEMAu90ZMQsrhgtUMQs0RQs9YT0MOYl4oQrGCErKQ0YX0tApFkoWXrAcpoAIjV7SkuTN7eJRFyICZLFCYUpVTW6TCOPxAGQqJRDVA1HkrRiFF3gbGuTuQ4GMqypSpdNKKKzFi2S3i7CjAHgjZikeLcswCgOHVBX8tQOCv+PBMwBBN3WEAJVV2EDzgwCJKxNfMgCKv/NEMqskNasas5McD4Bri0O6tFMgB6Ar3mrPCG78L1CnJDOxAP24DyaoCY6QK2hGPrHYYBwAhspW7wn+iTTlO6QTJTJLplHOIBSkL+RGwqTZVLAEL5DVDhRGAQASOZ0+WnMeMFveO+Mlt3Oit0UIDTiJXuqzj5ZpUcDyu4M/NlIpPKvpPtvdtrhZPguwfkOFMF1/hiqQTypYCKq/qaO+DjTbNdByiCo+ARZDA6AHrZAnt6iEGXIlCbb1AHtMpW4GKo3XtBjcOKzZhP3NNjGosWsfBRtgjAO5u8tvuQOF1dzCul0IMi2IbMXxLPVvhPjTgriNvhqRrRqxrxqJrJqppDlQdlVAvdvzi0MIcEDJXIdqAPqZvTrsNbjIw+Q33RARDLqrqWUuDWKpv5RmY3j4c4BzoihKxzCrTHFhtALx6YpIQoQ5t5vgOFvidVaSeBP3N0V5aMCziIZSAD0rgMDxMgA8VgdaYRpRoxpxoJqvkpppoZr6d92kNw3ZNKXqsWefTQy22SwjinEJQdHGTKgSNtMALaIyR6L5Q+SKyuWizpKLHLHRiR0HNTsRBdUuDh6VgQDxg1AxAzsCL2BWKinCVazqSaQWXRcic81icfuJdlvJdxXzgMAhCy1zjZfoPxKqfgfqcldafle6dVetvQeGcyWdsw2D3Qt6sgDQyjiGD/aFjXpBUOZjmO0nYeL1Ay7grzLx6cJPKQIuIfI5ElD7uZBCcxd8vvvFvnflsi15aJK10oPkiVXPXPeFeveadlddmfeZrfcGd63kiA+mdEBPhyX9sF1Wc4DsqViteNq1kMjg4b2qpuTkkqKFj2zxjdi9eDAxDeqIt7HVgCMPGX2w89MqJqO37Mw8BMxZ6HFqYhdVTPGNBjP0KYCRiTDDQUmlAaJzDiYW8HoPLBtWvUyQJspZvTKlSjV7hHdnOieXMoUk+Xd4gPv5ZupsVvjU90+lIM+lfacVd6ds81fAv5YG2avdsJVZP89qAQlYnynzA/aARfq9hUl/q0nWhmDCQnAU10KLCAwolsM3T7hmhxA4ChvQYeiLDoAUq47hD0rhg0Bl5wHUhkDhTgZVF8mVhZi4SCFngG/KGeK9zB6l9mBvLlGMY6RDCi9nZMpfbk7JgP4SkomckTMoiIZSFz9glr+KDIR7zRiIS/qKy2tfCCKCfPs8uh8ndw+1zT9iK2k4PMaI/4FcPEnJ55ZL8bFJPkVw06p8PulXVnmk3Z5G0aGXPPPgQGlp9sGqlnPIHKSygw9ASxQdonADZLRhOSSuTyqrncBL9uSoYUXLkU8ybgmBi7OXI0BoF0YVcEpJgf2i2SlMR0XmHxD5h5J6lze8wD2PJm3wpBqmQ6axD6GpSvwGgdwMKL7wUxVMSgymSMGpkaCDNJBw2X+oWHRYEx54k+XeO5SfYc0X2+bQAWoCuY3NYGoA0tqLRCCAcnwiGEIHLTuAICU+73ZnqgOq6qtu2UteDjgPwBS06qRfZrnkE4jlRuIqvLAL0FdBH8A+Z2XZNAh2wYIUhhcVsAPmDhbw+wN/FxNHTQRM06oPyc0iHic71NEQ8hYOo0FwRXsUoewIhCQjDBp16ABmEPq+wcF80JOLgqTm4IrohB5aUTWAddzyz+DiujPNPizxCEwcCA8SMhkPSUrZZ8B9DEANZhuC2YAY9mV9ALhcxr0IcPgMUPvV47utlivCbXi0GTYecluhvK3qZinDNBVo10HrjLkwBOADMAwLoqPlWiWQPOiLegCkTt4L9Ki1RRCBo1EFW1MSa/YgWgD6H2CvGp3YnsMKS7fs4q7FQgHcHdQysaI4tRtjVjqx5VGszWPwoCxhr/cR6lVJriAC0p9UeOdw0INCBqKGAi8ZfYIPLxd4YAPcjASqNZxqJvB48EldgAmz167B3OdkdBK8RpZvAAgrnPrlOBcBxgEwTND4fyLsgJ0UQtaDIGymRAN53ha0allig+LuBtkSdZVJoXoCBgdsNg9xqiIuYCtiwMDAJhd2xGi0Za5IJKgwBXDzgE+JI0smSL+rrFKRbWNtr92NrxI5K3PWcNAIZGbwWkbdAarkN2CL0VR4PRKF2kBzBAe0dRPMS0H0TH1GGeQU4RvWx5jlbgN8OHDIFUjRhVBDgdQeFATJJoVU+afhCiNi5E83RQrTEZ6LAF0Ua6jATnvOBoiIYFaoHT6KSPKgqNwxczFrJGJ+5KU2KqlerpgKgEMjIiClYbBUXhxLtTsIqYOFTUcp5ALQ6AXCH6zpxRRP4TOSWD8hyi+JFYYsZzvHhTwQR08uYGot2MJ5ici6Ho0ng82y7eBa604EINT2SrBigooY57LM0phUioxq48nusKNpn46usQkAJbXEHglYc3JYxO7n9Bu95gJ4q2KQWLDHgJgIUcGIrAf5pQhUEWUfoY2zBGMngZYUQrhgbzLldGvyJRjBFL5SCeRlYBiRYJYE6NpcRwfsD8i4ExAaBkCWsUsERG8kmoOgC9Jf0aI4BASPfDAM2BKB+sTcloLbAb3cAOsOxzSBoO7B3YngzGsASYBbBh5IjEC+JCorJJJKjxV0v4sPo4Ij4DigJdFKQLOGggZVye04diplWnEgBZx84+CekEQkrija4TOMZEPCaF8CBn0FnJYS1i7xBApBZENgm5DI5U2tsT4OFH0nyA6AmAUghQTpR8FZIkAXgXeH4EbV+OXiJwB6w2aBghm0eYIDxT7Aq014DATyQMPi4gCRhFbQKU+BgDpdZweWFSmk3y4ziQxc48kfQBilLiP8SEhKTNNQnAtkq8SBkUO3bD9NsC0mJYM0DqYoEhCBJG9uNi44DRQI6SAnMQO6kOR8MSpA3q5PRjPTpkTYlsa0GWxLADJdHYqM/zqAkZ3EZwOoDgB6pxAhpaIgumd18lR9HuUA5ihNJ8jQTasy0sMWtLikYDdp84CIV2zM5KcGRWlWjA0FclclfpCMASS9I3CghdxbaZ2pMEQDwhRucoAnKyXYAclFc0YCSVQE26MYNYQwHokkC/6D4igWsXiQoFIL6SRUr8SaC7UdF2Cex6IvsaNKxFDi4q5IckKfhCA+QIAUgQMU+ExmwSKRi4vGVn27ZPgaI2A4mT2xNoMis4hEnSUkCegAxGgekH3M3D9zN8bp7gC7CXzX7sBQQQeBUFrA2xm4PxaeEamHlGhkELIgbD/nU2MkyQ5SWxcVDQBRIrNLYDsXfgYR6DNAU6azRoEwh6KuN8ex3eGa6Iur9jAJUfFSm9Bmk5dye5IeaTg0WkwTsZcEiMRtPinAsoB647nlAMB6YTiKLQOEThKRERBVk4QRAERL3Ea5Q5uEY+oARppDBms22dgHEDLzBw4QjgeCEQM1464Ww30+5EZHgC5h3YznGSTQLhkuii2GsyPl6NiZStXmq4PaSpwilRSVpC4hCcuPxmwd2KO04BTELSkgAMpA01EtjAfClFV2b6XkEVPGBZSUhGiXSQyTFzrBpc2C4XDRi4FMCnizQSgLUSsra5dcQwfsCZREhCyQwp2IqN4k45yNnWFclRACG3SVy/+wnAATXKfl1zNZg4twYxXep1tT8CABAPIDNk9yLZAC/uUApko0NQF4NecOuMwlaVB+JUc1rsWsr7F96P9IEP0BEIRs1eB9dyvzFQCux0AWQCQJPKIHCjIIEXeYuRjyDDUyBvkNoF6RFBshuQzWU5BnhqLtFZMSYBsmCjYCfj4oT4xCFrhcReAEAlisyTMRTi+KNwO7E0KsEUb/J+JW0Q4C5E7B/yS8smDRiEu0b44bi8JAnLoImBZBq4U2SODYxaDS4dGJwEyFRORJmBIEg/HdtgS/7mIDmO2B+XFycECK/JcVacDRGyziK7g3geJHKzy6dyQAX+H/HgQAJSoKCIBMAptOBYoSNxWyjCRAuaqAEKCqcG3EUquCABMAgZDUEUCFEhgjECYIWLVedo25VwWtB9B2CfIaQneFkLr9QwHwb4Fx0cjmD8lydezDHE8pdiq5PCx+SNJfnay8Q1dYzilVeZV0EAs4Rtn+UvJyLrZZnaukovwDhMdWEC6GNkVPSEkBSfwvAqQJgD7cYRFY49Ga1xxCRJgEyDAFvEDlIhyVhS+oLgDXSsqhgGHdbvR1XrNZ0cpw5rLulo72BnoKIcaFhV2pcKCeXkwYQlyRlejApPg8WoFMCn5Z0Vk5UspiupGkMpWeK3nqoqJV5AFo+WUIFURhAw9yh7gKhWTBaDByCSe9agM/QZA4BRAX01BOsQKA7AJVKIKQPQFEg5Q/i/gOQoy1dVQJcI3oKnOIDvw9hjEZCxeodiOkHM4illBDIgFdhaBqCYkwNefGzDijiE8q2wf/36G8KfGGIhuWqp9Gw15aa4J6rqu4DlQpyYUK2aEIICKc8VK4UJmTKVKuUKMY5CcAcCoA0AOREeYzG9Fwj7D9o9mJhH7xs4gjtFmis0Gi1R53DJRqQWYuaNyLeone2S9YrkvwmW8Hx9Qu3hMGmbZVwe2GJ3irxMW8d1gLKvWIARlRh1JgbYtkOehEgxAmhGMedPEmQx0rIcAdBGJwvLXcLK10KoZbCrcFpUGKRoKQFICYqEAW1ZANtfqvLKALsVPbWunivJ77SgeA7LSnLkH7+ypiTCFyNgpuLMTsYqdR8JcLuGhh6iIQHfh1KlkKMZZyjHwOI2eR3iym/siiRGDLyQA71bNSFdBri6Iza1cKmiAwHJBrhtWjFeJAwCe4RSMV2GrFV2uUqrCCNENAdZiWaD+BFgvOJMBot0VijMhOJNwCLjMCHA+V2+GYOf1V5vE91CxGAIJhOQog0QmIbEPiEJBYQKQYoS3iZjqg3J4QUSx4lOqF7+9xsjij4tcKEwrR+RPm9EFiFxAEgiQJIPEN4oGXeNYNqquFXlggChMYA1dBcK83ClzLEmCyvVReS02GqtlMrPFTRDdSGbt4oEfaOtCXLCSyALNayj8L7iBhM15ClsGUMZwBAmg/wdyJgAbhtBGBrUS9SDAiDzjptfUpYlhRXULBJkN9efiUBL40gKpIxGUvxkLDQlFk4+a3r0FxZNpVq/w0YiKHy1idCtsmtwW6gQDi15NSDT7dVoWl1bW17amctpuWH4A2tRMmGuZ2I0F0tKM8mzZZSO05SmVpJG6LL12Bo5kMGUHvlpBQxYxAo3IOif7KZZkAUSGcxWDXxpJ786F1QB7emPyGjhntQA5wW9ruoqLpwhM6xBAAiZ/t0NmGhrQBRw06aiRufB2XbIoZqL3pXU6ZHOsrwaMxJ2CxIJJL85aBFtVsHmXJPwV0YqZKcYyesFzkxhuEu/d4JrnNiqMf+SQJ+s6xkb8kpSJQEJYQvqV9THJjO2ue6NLYjL7qs0trasNgFPNTZGm+rf+Q7WC7QdNEacElIdlvVwF2wrSukI8w1A0AdS6laSlG7x4n460BALINGweII67GJSasDSgP9EFLoJ3q8VBHHqBkaxSCK5VbhqY4IxyswC7uVVoUcye0B/M3EYCBUd2VFUiiABXAhBxlpWjijRC8EhBpwDAVLv+AwZJVUVYcKJlK1tmzgFND1MfSAFb15d6ABSKUDAAynTkPooAMYBIC+KsruqBAVQe8FIBjB9AebTvQxklhkc1i2ac/XJnAD+QfQDAPNvoDP0EEX9xYBgHoH7AlMIALAVmmul31hQCAPAX/ayoAPlorgTgcA4FEgNUAX9fqYishquAYh4w7AVSdkHgPdtn9YaGA4AemD1YNoiB5AyQtIC3hXYDAGwDUBIVgAQDagbuKaDICIGh2SqNwAQDIoc04ibIMoN2xAB/hOGOGQ+HER1q0APoUB6qj4nBUbRCBh/UgzdHuTCbs5kwMFZ0T3rx48OJvASYpPCK8J920yBLWehs2l7hJS2AIFsWqjIQbBiEF/gofwBOQHApASgf4DUCv0YZ3cQErFps4EGf9pAVTCPnqCIGBDUQXBsobEN4ABaeBcI0IbwMk6Rt05SQ8QkoMv7NDo+JwyDzyAXhXQlQD4KgBRKOa5gw4M/s5QmyUD0EW8+XkiDX719G+g0nwyoEcNCACALhtw84U8PqIdgzRpdTUW/3YIX9wR4uQ4DCOCG1AeRjgLEf4MTHimPzboCohwp2YQO6TKQ+kdkPtgsjbRz6FnAZik0nEwvEoGeJG3QKkYJ8OUMDIPaH8FjoB6YvOpazDJCo7MlRCUkWO7AZd9mXws0fGCTJsjWBzqMqQ752hLKLiZGgcc8TX9d+9UOUIpDmBgA2NUalY2aMi5NHOjHhz6F4d6NBHh8ox8YxEe+ZaZ3jqgGY9OXiNqBIktBrQPQaMAWEUjKrdY/gBkPyU5DyofhGoEQOGBnj36XuB0M3lygaDSQMYLSZMkgQ5kHKWEcpjtKwJ1Im4dmu4aENYm7Q3cEY6PjGOzGCThdZoLQZpOMHOICemoFpBLZxG5jIACQNG1BhMAj2UC0tMlHpNrG0jTJlA5sfkM7HIFcRLk6jqSC8mk6xu2ULyhwBUnhTjB7XGKaOOSmjIicGU4wd/4+MujmJno8qZxNFy1T+JoQ83gkAhArTq7G0xDH1M1hpoksFvdQYOD6BEjTgNQM5TQguIt5WiT4NdGUD7go6YXALlUfPV1Ajw7G+0HYoqKsHSzlEKI9kehgXiqcxNRpUloBBz1eQIuUjLhHbRaBq6cOUGP6HIkWY4k2BSga4CgClFEefkfRlGDxQtZPIAAKmPPErHkIo5ME8CcBwBTz1ZoBIUFgx6TFx1qmEb6XnChNJ82CPMtGCqgagkQ0CDDloEAAoBNGCWz0wKmc3DYFnPuS9x42CwA9GtJuTnh268wX0uSAyAS13wP5oyAAD8aIAAda0ABkiQBga9n0i3m+kVwGQGtthasxSMYU3eLlc2aGDQYeV8oZnCebPN5B7YLwa1LgDvMnZdD9yUCy4niTHYWm6xfYjMEaAXYiO66loL6RCVzj+O1xJ4HcWxiVLzADeCEqdt8Bl6VdaqK7QniTA06k0AkR9D+fmx9BQ6QwRdEkC3mD9Nce2doApaeKdEC5R6yNu7AjYyXkLg8G4CwLnOThsCTwA3DbBjk40tAvpKQrTnCCkgLAIAFkC4kryuAAA5P8A8COxCj3wCaGAA5CJXbl1oMKKr1va3K7elAZEHmT6ItKQYH63PU02cbvQG8qIdLf5qy1BbKQLsBhYH2+B9IgrDeQACZExcQgEgi6AuLSyYGbKrYlPMPooLxOoQIJcMFfIkgc4RcIACTCBc2uGiuAAkIhlaYXsL/wvYP/GbB8cGmIFgoSYj5Pa4ad9YrQAAAE3AigZIL7IDDjE0dtwY4IVGTnUk/11yNHFoEABkBFoAABkIN5YLUm5AuRk8u25YEyUxzoZyoaowVagA0sypojKOl4wzkrDakxJUuRXYLLRvczOpBepqHoD/kZWBgWVr86Kc1hf99FzsQi9FenBaBNr5Paq1oBwowWF4KFtMbUwDBoRTzrLD8KeZmvHnVJFevFkMlr2wRl6JwZ1r6T+ZMAtAAAcvnB5lBLSLalKSH8t3JpBm0A9GcNECkhVQmYxQGf2J1JBhb74BvIS3wiERiI0VvCPEgIs/nyoWgRFJRDEiMRmI7Ld2xS3RRaAWQdEckDbfwg0N1wVyMCONkzFvRVu7gAiOuALMhYAQX/e1rrHWsggoi5qAzOtYeE2JfYyQH0M0P47Ot87H6LzKyNEthcyocOYKriU34RzzGF573mCE5t7MOUloxXMJBv6+kwrgpMdK4YXO6z3wjy6EEHRSE/IdgTgdG2u1QAc2AAWmgEw6FBsY9u6y0sAGhcMoCKJbZGgEgi+k7wjAdwA/rIAUdkIVHGAGYyYIB0egNlvqSzVp1Oto2TBd/dZH7BhKeM7kEEdVc8hDtCSI5ygjQ0/hIJIIUULQyxdlxemdBpZBvEDt9i8Rlo/ZdsjWNBzgXkRC5KyO2AuwdQbglSJB5xHbIN4AafUAaKwBVQBs4gFIaKxqEtx29JgEGBYmcENgroC5M8iOiYgRiMA8yDePDogimhwByowIOAA0HthVgPgOAWxIAD4NwAGi7Kuzsc7C47Jk2cSdBuDhX8A5lfSUAFdKIDAD4ByolUKoL/ANEAJDHqjqS84TzLFJbjOwZYwcLLYGK1TLARIJwFQroUQASdB0DoF9MwBnH7AC6Gwe8e/YGAnEMgEO2yS36TAVwHCongIDkh3H4zHY6AGgydQgm7qcCSEA/M0QYgjFBMTEBUp9qYg4+pKqwiQYQ0w9E4j8yEDQpuOgAA== -->
<!-- internal state end -->
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
test/hookcheck.sh (1)
891-899: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe
cdneedle makes the C3 doc assertion vacuous.
grep -Fq "cd"matches any word that contains those two letters, for example "recorded" or "included". The check passes even if thecd-prefix rule is removed from the document. Use a distinctive string from the rule, such ascd/pushdorcd x && VAR=y grep.♻️ Proposed change
- for needle in 'post_sweep' 'RIPWIRE_SWEEP' 'sweep3' 'shell-misc' 'gate-run' 'git-remote' 'cd'; do + for needle in 'post_sweep' 'RIPWIRE_SWEEP' 'sweep3' 'shell-misc' 'gate-run' 'git-remote' '`cd`/`pushd`'; do🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/hookcheck.sh` around lines 891 - 899, Update the needle list in the C3 documentation check to replace the ambiguous `cd` substring with a distinctive rule example such as `cd`/`pushd` or `cd x && VAR=y grep`, while preserving the existing checks and pass/fail behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/EVALS.md`:
- Around line 569-573: Align the underpowered-readout timing in the “Minimum
data, and what happens below it” section and the readout schedule at “One
readout, at one week” so both describe the same maximum window. Either change
the DISABLE justification from three weeks to two weeks or revise the
extension/schedule to permit three weeks; ensure the registration has only one
unambiguous interpretation.
In `@docs/SUBSTITUTION_METER.md`:
- Around line 246-260: Normalize all frozen-log statistics to the authoritative
pair: 924 total unclassified rows and 742 cd-prefixed rows. Update
docs/SUBSTITUTION_METER.md lines 175-192 and 246-260, hooks/ripwire-nudge.sh
lines 254-260 and 588-599, test/hookcheck.sh lines 812-813, and docs/EVALS.md
lines 528-533; reconcile every conflicting 927, 916, 890, 816, or 784 value
while preserving the 160 corrected total and derived percentages.
- Around line 108-111: Update the documentation reference in
hooks/ripwire-nudge.sh associated with the post_sweep description from
docs/EVALS.md §8 to docs/EVALS.md §4, leaving the surrounding explanation
unchanged.
In `@hooks/ripwire-nudge.sh`:
- Around line 786-795: Sanitize or safely quote the `sweep_dir` value before it
is interpolated into the paste-ready command. Apply this consistently to both
command-generation paths around the `sweep_dir` assignment and the later
emission block at lines 815-832, while preserving the repository-root default
and read-sweep directory behavior.
- Around line 160-174: Resolve meter_arm from RIPWIRE_METER_ARM before the
meter_file early return in meter_init, alongside sweep_on and sweep_n. Preserve
the documented treatment default when the setting is absent, and ensure the
control value is available to the sweep gate even when no writable log path
exists.
---
Nitpick comments:
In `@test/hookcheck.sh`:
- Around line 891-899: Update the needle list in the C3 documentation check to
replace the ambiguous `cd` substring with a distinctive rule example such as
`cd`/`pushd` or `cd x && VAR=y grep`, while preserving the existing checks and
pass/fail behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 82e042ec-4220-4b6f-a0bb-15daaf117c3a
📒 Files selected for processing (7)
.ripwire_quality_acksbench/substitution_report.pydocs/EVALS.mddocs/SUBSTITUTION_METER.mdhooks/ripwire-nudge.shtest/deckcheck_allowlist.txttest/hookcheck.sh
| **Minimum data, and what happens below it.** ≥ 200 rate-eligible `post_sweep=1` calls across ≥ 10 | ||
| distinct sessions that saw an escalation. Below that the readout is declared **underpowered** — not | ||
| null — the escalation stays on, and the clock extends by one week, once. A second underpowered | ||
| readout is a DISABLE: a nudge that cannot accumulate 200 observations in three weeks of daily use is | ||
| not reaching enough moments to matter. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
The extension window contradicts the DISABLE justification.
Line 571 grants one extension of one week. Line 581 confirms the schedule: "One readout, at one week (or two, under the extension)." Line 572 then justifies the second-underpowered DISABLE with "three weeks of daily use". The maximum elapsed time under the stated rule is two weeks. Correct one of the two statements so the registration cannot be read two ways after the readout.
📝 Proposed fix
-readout is a DISABLE: a nudge that cannot accumulate 200 observations in three weeks of daily use is
+readout is a DISABLE: a nudge that cannot accumulate 200 observations in two weeks of daily use is
not reaching enough moments to matter.Also applies to: 581-582
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/EVALS.md` around lines 569 - 573, Align the underpowered-readout timing
in the “Minimum data, and what happens below it” section and the readout
schedule at “One readout, at one week” so both describe the same maximum window.
Either change the DISABLE justification from three weeks to two weeks or revise
the extension/schedule to permit three weeks; ensure the registration has only
one unambiguous interpretation.
| - `post_sweep=1` is the same idea one level up, for the sweep escalation only: everything after an | ||
| escalation fired in that session. It is the grouping variable of the pre-registered efficacy | ||
| readout in `docs/EVALS.md` §4, and it is recorded at observation time rather than reconstructed, | ||
| so the analysis reads an assignment instead of inferring one. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# List the numbered sections of docs/EVALS.md and every cross-reference to them.
rg -n '^#{2,3} ' docs/EVALS.md
echo '--- references ---'
rg -n 'EVALS\.md §[0-9]+' -g '!docs/EVALS.md' .Repository: redhat-et/ripwire
Length of output: 9397
🏁 Script executed:
#!/bin/bash
set -eu
echo '--- docs/EVALS.md: section 4 and sweep readout ---'
sed -n '210,235p;500,620p' docs/EVALS.md
echo '--- docs/SUBSTITUTION_METER.md: cited ranges ---'
sed -n '100,160p' docs/SUBSTITUTION_METER.md
echo '--- hooks/ripwire-nudge.sh: cited range ---'
sed -n '108,126p' hooks/ripwire-nudge.sh
echo '--- bench/substitution_report.py: cited range ---'
sed -n '128,150p' bench/substitution_report.py
echo '--- test/hookcheck.sh: cited range ---'
sed -n '624,640p' test/hookcheck.sh
echo '--- exact section-8 references near the documented readouts ---'
rg -n -C 2 '§8|section 8|Section 8|task success|success' docs/EVALS.md hooks/ripwire-nudge.sh bench/substitution_report.py test/hookcheck.sh docs/SUBSTITUTION_METER.mdRepository: redhat-et/ripwire
Length of output: 22513
Change docs/EVALS.md §8 to docs/EVALS.md §4 in hooks/ripwire-nudge.sh. Section 4 registers the sweep-escalation readout. Section 8 covers task-success claims that remain unpublished.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/SUBSTITUTION_METER.md` around lines 108 - 111, Update the documentation
reference in hooks/ripwire-nudge.sh associated with the post_sweep description
from docs/EVALS.md §8 to docs/EVALS.md §4, leaving the surrounding explanation
unchanged.
| ### What the correction did to the headline number | ||
|
|
||
| Replaying the v2 classifier over a frozen 2,155-row v1 log: | ||
|
|
||
| | | v1, as logged | v2, replayed | | ||
| | --- | --- | --- | | ||
| | `unclassified` | 924 (42.9% of the log) | **160** (7.4%) — **−82.7%** | | ||
| | substitution rate, overall | 1.05% (9/859) | **5.62%** (73/1298) | | ||
| | pre-nudge (`post_nudge=0`) | 1.09% | **6.14%** | | ||
| | post-nudge (`post_nudge=1`) | 0.79% | **0.79%** | | ||
|
|
||
| ripwire's own calls were undercounted **8×** (9 → 73), because `cd <worktree> && ./build/ripwire …` | ||
| is exactly the form the prefix strip was missing. Any analysis that quotes the 0.8% headline is | ||
| quoting a broken instrument; `docs/EVALS.md` §4 states both numbers and registers its band against | ||
| the corrected one. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
The frozen-log statistics are transcribed with different values in four files. One measurement produced the unclassified total and the cd-prefixed subset, but the total appears as 924, 927, 916, and 890, and the subset appears as 742, 816, and 784. Only 924 is consistent with the derived percentages (924/2155 = 42.9%, (924−160)/924 = −82.7%). Fix each site to the single authoritative pair.
docs/SUBSTITUTION_METER.md#L246-L260: keep 924 and 160 as the authoritative totals, and make every other site agree with this table.docs/SUBSTITUTION_METER.md#L175-L192: reconcile "924" on Line 179 with "927" on Line 190, and reconcile the 742 multi-line subset with the 816cd-prefixed subset.hooks/ripwire-nudge.sh#L254-L260: change "784 of 890unclassifiedrows" to the authoritative total andcd-prefixed count.hooks/ripwire-nudge.sh#L588-L599: change "742 of the live log's 916unclassifiedrows" to the authoritative total.test/hookcheck.sh#L812-L813: change "816 of the live log's 927 unclassified rows" to the authoritative total and subset.docs/EVALS.md#L528-L533: confirm "924 ... 742 of those" matches the authoritative pair, since this registration is the document the readout will be audited against.
🧰 Tools
🪛 LanguageTool
[style] ~258-~258: Consider an alternative for the overused word “exactly”.
Context: ...cd <worktree> && ./build/ripwire … is exactly the form the prefix strip was missing. ...
(EXACTLY_PRECISELY)
📍 Affects 4 files
docs/SUBSTITUTION_METER.md#L246-L260(this comment)docs/SUBSTITUTION_METER.md#L175-L192hooks/ripwire-nudge.sh#L254-L260hooks/ripwire-nudge.sh#L588-L599test/hookcheck.sh#L812-L813docs/EVALS.md#L528-L533
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/SUBSTITUTION_METER.md` around lines 246 - 260, Normalize all frozen-log
statistics to the authoritative pair: 924 total unclassified rows and 742
cd-prefixed rows. Update docs/SUBSTITUTION_METER.md lines 175-192 and 246-260,
hooks/ripwire-nudge.sh lines 254-260 and 588-599, test/hookcheck.sh lines
812-813, and docs/EVALS.md lines 528-533; reconcile every conflicting 927, 916,
890, 816, or 784 value while preserving the 160 corrected total and derived
percentages.
| # The sweep escalation is resolved even when the LOG is unavailable: it is a nudge, not a | ||
| # measurement, and it must not silently switch itself off on a machine with no writable HOME. | ||
| case "${RIPWIRE_SWEEP:-$_conf_sweep}" in | ||
| 0|off|no|false) sweep_on=0 ;; | ||
| *) sweep_on=1 ;; | ||
| esac | ||
| # An N that is not a plain positive integer reads as the default rather than disabling the | ||
| # feature by accident or escalating on the first call. | ||
| case "${RIPWIRE_SWEEP_N:-$_conf_sweepn}" in | ||
| ''|*[!0-9]*) sweep_n=3 ;; | ||
| 0) sweep_n=3 ;; | ||
| *) sweep_n="${RIPWIRE_SWEEP_N:-$_conf_sweepn}" ;; | ||
| esac | ||
|
|
||
| [ -n "$meter_file" ] || return 0 # no HOME and no explicit log path — nothing to write to |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
The control arm is not resolved before the sweep gate when no log path exists.
meter_init resolves sweep_on and sweep_n above Line 174, then returns early when meter_file is empty. meter_arm is assigned after that return, so it keeps the treatment default. The sweep gate at Line 729 tests meter_arm != "control". A session that sets RIPWIRE_METER_ARM=control but has no writable log path therefore still escalates. The documented contract says the escalation stays silent in the control arm.
Resolve meter_arm before the early return, next to the sweep settings, for the same reason the comment gives for sweep_on.
🛠️ Proposed fix
+ # The arm is resolved with the sweep settings, and for the same reason: it GATES the nudge, so
+ # it must not depend on whether a log is writable.
+ case "${RIPWIRE_METER_ARM:-$_conf_arm}" in
+ control) meter_arm="control" ;;
+ *) meter_arm="treatment" ;;
+ esac
+
[ -n "$meter_file" ] || return 0 # no HOME and no explicit log path — nothing to write to
case "${RIPWIRE_METER:-$_conf_enabled}" in
0|off|no|false) meter_enabled=0 ;;
*) meter_enabled=1 ;;
esac
- # Only the literal `control` selects the control arm. An unrecognized value must not silently
- # invent a third arm — it reads as the default, which is what the row then honestly records.
- case "${RIPWIRE_METER_ARM:-$_conf_arm}" in
- control) meter_arm="control" ;;
- *) meter_arm="treatment" ;;
- esac🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/ripwire-nudge.sh` around lines 160 - 174, Resolve meter_arm from
RIPWIRE_METER_ARM before the meter_file early return in meter_init, alongside
sweep_on and sweep_n. Preserve the documented treatment default when the setting
is absent, and ensure the control value is available to the sweep gate even when
no writable log path exists.
| # The directory the pasted command should be run against: the repo root, except for a read sweep, | ||
| # where the directory of the file just read is the tighter and more useful scope. Only an absolute | ||
| # path is trusted — a relative one would produce a command that is wrong from anywhere else. | ||
| sweep_dir="$meter_repo" | ||
| if [ "$mclass" = "read" ] | ||
| then | ||
| case "$mdetail" in | ||
| /*/*) sweep_dir="${mdetail%/*}" ;; | ||
| esac | ||
| fi |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
sweep_dir is interpolated without the sanitization the grep pattern gets.
Lines 749-759 sanitize the grep pattern at capture time. sweep_dir gets no equivalent treatment. For a read sweep it is ${mdetail%/*}, taken straight from the tool payload, so a path with a space, a quote, or a backtick produces a "paste-ready" command that is not pasteable. The JSON stays valid in both the jq and the fallback branch, so this is a message-quality defect, not an escaping defect.
Consider applying the same character filter to sweep_dir, or quoting the path inside the emitted command.
Also applies to: 815-832
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/ripwire-nudge.sh` around lines 786 - 795, Sanitize or safely quote the
`sweep_dir` value before it is interpolated into the paste-ready command. Apply
this consistently to both command-generation paths around the `sweep_dir`
assignment and the later emission block at lines 815-832, while preserving the
repository-root default and read-sweep directory behavior.
… live in the local ledger, the public band is defined as multiples of B Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first meter-gated behavior round, built from 12h of live data + the month-scale history mine.
The measured problem: the shipped nudge fires (455 calls) and converts at zero — and after the classifier correction below, post-nudge substitution (0.79%) is ~8× LOWER than pre-nudge (6.14%). Generic advice at the wrong moment.
The intervention: sweep detection — the 3rd same-class call in a session (grep/read/glob/git-history; Bash-grep and the Grep tool count as ONE class) triggers one escalated nudge per class per session containing the paste-ready one-call substitute built from the observed pattern (
--for="<the agent's own search terms>",--pack-task,--situ). Advisory only, never blocks;RIPWIRE_SWEEP=0kill switch pre-built; ≤+1ms on the hooked path.The classifier correction: unclassified 924 → 160 (−82.7%) on a frozen replay — root cause was jq @TSV newline-escaping breaking multi-line
cd … && cmdreads, plus cd/pushd/env-var/git-option stripping and new build/gate-run/git-remote classes. Ripwire's own calls were undercounted 8× (9 → 73). Corrected substitution baseline: 5.62%.Pre-registered efficacy readout (EVALS §4): primary = substitution on post_sweep=1 rows vs the corrected 5.62%; KEEP ≥16.9% (≥3×) / REWORD 8.0–16.8% / DISABLE <8.0%; ≥200 eligible rows across ≥10 sessions or underpowered→extend once→disable. A null readout disables the escalation — the switch exists before the measurement. Confounds disclosed (observational, 100%-treatment log, single-operator). Zero-hit-grep trigger deliberately deferred (needs PostToolUse; two triggers under one readout would be unattributable).
Red-first: 20 arms red against the shipped hook; hookcheck ALL PASS both after. Full plain suite ALL PASS; quality-delta gating=0 (verbosity fixed by splitting the classifier, not acked); determinism/xmllint clean.
🤖 Generated with Claude Code