housebroken-cli 0.6.7__tar.gz → 0.6.8__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.
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/PKG-INFO +1 -1
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/pyproject.toml +1 -1
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/branch-check.sh +1 -1
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/file-pr.sh +30 -4
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/prior-art.sh +31 -3
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/verify-filed-pr.sh +1 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/skills/housebroken/SKILL.md +5 -2
- housebroken_cli-0.6.8/src/housebroken/__init__.py +1 -0
- housebroken_cli-0.6.7/src/housebroken/__init__.py +0 -1
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/.gitignore +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/LICENSE +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/README.md +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/bin/housebroken +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/hatch_build.py +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/check-ai-policy.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/claim-check.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/comment-census.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/comment-check.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/diff-defaults.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/distinct-outside.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/file-issue.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/fork-hygiene.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/inbox.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/notes.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/pr-sweep.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/scripts/review.sh +0 -0
- {housebroken_cli-0.6.7 → housebroken_cli-0.6.8}/src/housebroken/cli.py +0 -0
|
@@ -184,6 +184,6 @@ fi
|
|
|
184
184
|
# The stamp file-pr.sh reads: this head passed, against this base, at this time.
|
|
185
185
|
head=$(git rev-parse HEAD)
|
|
186
186
|
mkdir -p "$home/branch-checks"
|
|
187
|
-
printf 'head: %s\nbase: %s\nchecked: %s\n' "$head" "$(git rev-parse "$base")" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$home/branch-checks/$head"
|
|
187
|
+
printf 'head: %s\nbase: %s\nbase-ref: %s\nchecked: %s\n' "$head" "$(git rev-parse "$base")" "$base" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$home/branch-checks/$head"
|
|
188
188
|
echo
|
|
189
189
|
echo "branch-check: nothing mechanical blocks this branch."
|
|
@@ -47,9 +47,11 @@ gates:
|
|
|
47
47
|
be under 24 hours old and not read RESULT: BAN; when it reads
|
|
48
48
|
RESULT: DISCLOSE the body must name the AI use
|
|
49
49
|
prose no tool footer, session trailer, co-author trailer, em dash or
|
|
50
|
-
en dash, in any case, in the --body-file or the --title
|
|
50
|
+
en dash, in any case, in the --body-file or the --title; a
|
|
51
|
+
body of at most 120 words
|
|
51
52
|
branch $HOUSEBROKEN_HOME/branch-checks/<head> must exist, written by
|
|
52
|
-
branch-check.sh when this head passed
|
|
53
|
+
branch-check.sh when this head passed, against the branch this
|
|
54
|
+
files into (--base, or the repository's default branch)
|
|
53
55
|
review run from the clone being filed; the report at
|
|
54
56
|
$HOUSEBROKEN_HOME/reviews/review-<owner>-<repo>-<head12>.md must
|
|
55
57
|
pass review.sh check for this head and the --body-file, and an
|
|
@@ -128,6 +130,7 @@ check_text() {
|
|
|
128
130
|
# as its own argument or after an equals sign.
|
|
129
131
|
bodyfile=""
|
|
130
132
|
title=""
|
|
133
|
+
filebase=""
|
|
131
134
|
pass=()
|
|
132
135
|
while [ "$#" -gt 0 ]; do
|
|
133
136
|
case "$1" in
|
|
@@ -135,8 +138,10 @@ while [ "$#" -gt 0 ]; do
|
|
|
135
138
|
--body-file=*) bodyfile="${1#--body-file=}"; pass+=("$1") ;;
|
|
136
139
|
-t|--title) title="${2:-}"; pass+=("$1" "${2:-}"); shift ;;
|
|
137
140
|
--title=*) title="${1#--title=}"; pass+=("$1") ;;
|
|
138
|
-
-B|--base
|
|
139
|
-
--base
|
|
141
|
+
-B|--base) filebase="${2:-}"; pass+=("$1" "${2:-}"); shift ;;
|
|
142
|
+
--base=*) filebase="${1#--base=}"; pass+=("$1") ;;
|
|
143
|
+
-l|--label|-a|--assignee|-r|--reviewer|-m|--milestone|-p|--project) pass+=("$1" "${2:-}"); shift ;;
|
|
144
|
+
--label=*|--assignee=*|--reviewer=*|--milestone=*|--project=*) pass+=("$1") ;;
|
|
140
145
|
-d|--draft|--no-maintainer-edit) pass+=("$1") ;;
|
|
141
146
|
*)
|
|
142
147
|
echo "REFUSED: file-pr.sh does not pass $1 to gh pr create: the body comes from one --body-file, the head is the branch you are on, the repository is the first argument" >&2
|
|
@@ -152,6 +157,11 @@ if [ "$bodyfile" = "-" ] || [ ! -f "$bodyfile" ]; then
|
|
|
152
157
|
fi
|
|
153
158
|
check_text "body file $bodyfile" "$(cat "$bodyfile")"
|
|
154
159
|
check_text "--title" "$title"
|
|
160
|
+
words=$(wc -w < "$bodyfile" | tr -d ' ')
|
|
161
|
+
if [ "$words" -gt 120 ]; then
|
|
162
|
+
echo "REFUSED: the body is $words words - say what was wrong, what the change does and how it was verified in 120 or fewer" >&2
|
|
163
|
+
exit 2
|
|
164
|
+
fi
|
|
155
165
|
if [ "$policy_result" = "DISCLOSE" ] && ! grep -qiE '\bAI\b|LLM|Claude|Copilot|ChatGPT|language model|assist' "$bodyfile"; then
|
|
156
166
|
echo "REFUSED: $repo requires AI use to be disclosed ($policy) and the body does not name it" >&2
|
|
157
167
|
exit 2
|
|
@@ -162,6 +172,22 @@ if [ ! -f "$home/branch-checks/$head" ]; then
|
|
|
162
172
|
echo "REFUSED: branch-check.sh has not passed head ${head:0:12} - run it from this clone first" >&2
|
|
163
173
|
exit 2
|
|
164
174
|
fi
|
|
175
|
+
# Every diff gate read the diff against the stamp's base; it must be the branch this files into.
|
|
176
|
+
checked=$(sed -n 's/^base-ref: //p' "$home/branch-checks/$head" | tr -d '\r')
|
|
177
|
+
if [ -z "$checked" ]; then
|
|
178
|
+
echo "REFUSED: the branch-check stamp for head ${head:0:12} names no base - rerun branch-check.sh" >&2
|
|
179
|
+
exit 2
|
|
180
|
+
fi
|
|
181
|
+
target="$filebase"
|
|
182
|
+
if [ -z "$target" ]; then
|
|
183
|
+
target=$(gh repo view "$repo" --json defaultBranchRef --jq .defaultBranchRef.name 2>/dev/null | tr -d '\r')
|
|
184
|
+
[ -n "$target" ] || { echo "REFUSED: cannot read the default branch of $repo - pass --base" >&2; exit 2; }
|
|
185
|
+
fi
|
|
186
|
+
case "$checked" in
|
|
187
|
+
"$target"|*/"$target") ;;
|
|
188
|
+
*) echo "REFUSED: branch-check.sh measured this head against $checked, but it is filed into $target - rerun branch-check.sh --base <remote>/$target" >&2
|
|
189
|
+
exit 2 ;;
|
|
190
|
+
esac
|
|
165
191
|
review="$home/reviews/review-${repo%%/*}-${repo##*/}-${head:0:12}.md"
|
|
166
192
|
if [ ! -f "$review" ]; then
|
|
167
193
|
echo "REFUSED: no adversarial review at $review - run review.sh brief and have a different model attack this head" >&2
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
# 2026-09-04) argued against a ruling already made in CLOSED issue #98, which
|
|
10
10
|
# nobody read, so this script prints the last non-author comment on every closed
|
|
11
11
|
# item. A term containing a slash or a dot is treated as a file path and the
|
|
12
|
-
# commit history of that path is scanned for the PRs that touched it
|
|
12
|
+
# commit history of that path is scanned for the PRs that touched it, and
|
|
13
|
+
# every open PR that changes it is listed, which no text search finds
|
|
14
|
+
# (Shopify/ruby-lsp #4103 deleted the file a fix was written against).
|
|
13
15
|
# Written 2026-09-07.
|
|
14
16
|
#
|
|
15
17
|
# Usage:
|
|
@@ -34,7 +36,8 @@ usage: prior-art.sh owner/repo <term>... [--out]
|
|
|
34
36
|
|
|
35
37
|
owner/repo the upstream repository to search
|
|
36
38
|
<term> a symbol, phrase or file path; a term with a slash or a dot is
|
|
37
|
-
also treated as a path
|
|
39
|
+
also treated as a path: its commit history is scanned and
|
|
40
|
+
every open PR that changes it is listed
|
|
38
41
|
--out save the printout under $HOUSEBROKEN_HOME/prior-art/
|
|
39
42
|
|
|
40
43
|
environment:
|
|
@@ -70,7 +73,8 @@ calls=0
|
|
|
70
73
|
items=0
|
|
71
74
|
tmp=$(mktemp) || { echo "prior-art.sh: cannot create temp file" >&2; exit 1; }
|
|
72
75
|
row=$(mktemp) || { echo "prior-art.sh: cannot create temp file" >&2; exit 1; }
|
|
73
|
-
|
|
76
|
+
openfiles=$(mktemp) || { echo "prior-art.sh: cannot create temp file" >&2; exit 1; }
|
|
77
|
+
trap 'rm -f "$tmp" "$row" "$openfiles"' EXIT
|
|
74
78
|
|
|
75
79
|
# last comment on a closed item written by somebody other than its author
|
|
76
80
|
last_word() {
|
|
@@ -132,6 +136,30 @@ for term in "${terms[@]}"; do
|
|
|
132
136
|
printf '| PR | #%s | merged | %s | %s | %s | |\n' "$num" "$date" "$author" "$subject" >>"$tmp"
|
|
133
137
|
items=$((items+1))
|
|
134
138
|
done <"$row"
|
|
139
|
+
|
|
140
|
+
# an open PR that changes the path is prior art even when no title or body names it
|
|
141
|
+
if [ ! -s "$openfiles" ]; then
|
|
142
|
+
# shellcheck disable=SC2016 # $p is a jq variable
|
|
143
|
+
gh pr list -R "$repo" --state open --limit 200 --json number,createdAt,author,title,changedFiles,files \
|
|
144
|
+
--jq '.[] | . as $p | (if .changedFiles > (.files | length) then ["MORE"] else [.files[].path] end)[] |
|
|
145
|
+
[($p.number|tostring), $p.createdAt[0:10], $p.author.login,
|
|
146
|
+
($p.title|gsub("[|]";"/")|gsub("[\n\r\t]";" ")), .] | @tsv' >"$openfiles" ||
|
|
147
|
+
{ echo "prior-art.sh: open PR listing failed for $repo" >&2; exit 1; }
|
|
148
|
+
calls=$((calls+1))
|
|
149
|
+
# GitHub returns at most 100 files per PR here; a larger PR is read in full
|
|
150
|
+
awk -F'\t' '$5 == "MORE"' "$openfiles" | while IFS=$'\t' read -r num date author title _; do
|
|
151
|
+
gh api --paginate "repos/$repo/pulls/$num/files?per_page=100" --jq '.[].filename' |
|
|
152
|
+
while IFS= read -r f; do printf '%s\t%s\t%s\t%s\t%s\n' "$num" "$date" "$author" "$title" "$f"; done
|
|
153
|
+
done >"$row"
|
|
154
|
+
cat "$row" >>"$openfiles"
|
|
155
|
+
[ -s "$openfiles" ] || printf 'none\n' >"$openfiles"
|
|
156
|
+
fi
|
|
157
|
+
while IFS=$'\t' read -r num date author title path; do
|
|
158
|
+
case "$path" in "$term"|*/"$term") ;; *) continue ;; esac
|
|
159
|
+
grep -q "^| PR | #$num | open, changes this file |" "$tmp" && continue
|
|
160
|
+
printf '| PR | #%s | open, changes this file | %s | %s | %s | |\n' "$num" "$date" "$author" "$title" >>"$tmp"
|
|
161
|
+
items=$((items+1))
|
|
162
|
+
done <"$openfiles"
|
|
135
163
|
;;
|
|
136
164
|
esac
|
|
137
165
|
done
|
|
@@ -97,6 +97,7 @@ view comments '.comments[] | " " + .author.login + ": " + (.body | gsub("\n";
|
|
|
97
97
|
|
|
98
98
|
echo ""
|
|
99
99
|
if [ "$fail" -ne 0 ]; then echo "PR-VERIFY: PROBLEMS ABOVE"
|
|
100
|
+
elif [ "${waiting:-0}" -gt 0 ]; then echo "PR-VERIFY: NOT SETTLED ($waiting workflow run(s) wait for a maintainer to approve them; nothing settles until one does, so move on)"
|
|
100
101
|
elif [ "$unsettled" -ne 0 ]; then echo "PR-VERIFY: NOT SETTLED (CI has not run on this head)"
|
|
101
102
|
else echo "PR-VERIFY: OK"; fi
|
|
102
103
|
[ "$fail" -eq 0 ] && [ "$unsettled" -ne 0 ] && exit 3
|
|
@@ -179,8 +179,11 @@ report it in one line and do not proceed to the next step.
|
|
|
179
179
|
is missing or older than a day, when the policy printout is missing, older
|
|
180
180
|
than a day or reads BAN, when the policy reads DISCLOSE and the body does
|
|
181
181
|
not disclose, when the body carries a footer, a trailer or a dash
|
|
182
|
-
character, when `housebroken branch` has not
|
|
183
|
-
|
|
182
|
+
character or runs past 120 words, when `housebroken branch` has not
|
|
183
|
+
stamped the exact head against the branch it is filed into (`--base`
|
|
184
|
+
to both when the project takes pull requests on a branch other than its
|
|
185
|
+
default), or when there is no POST AS IS review of the exact head and
|
|
186
|
+
body being filed.
|
|
184
187
|
A refusal is a result; fix the cause.
|
|
185
188
|
|
|
186
189
|
10. **Watch it land.**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.8"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.6.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|