housebroken-cli 0.2.8__tar.gz → 0.4.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.
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/PKG-INFO +4 -2
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/README.md +3 -1
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/bin/housebroken +6 -2
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/pyproject.toml +1 -1
- housebroken_cli-0.4.0/scripts/branch-check.sh +140 -0
- housebroken_cli-0.4.0/scripts/claim-check.sh +67 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/skills/housebroken/SKILL.md +28 -6
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/.gitignore +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/LICENSE +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/hatch_build.py +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/check-ai-policy.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/comment-census.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/diff-defaults.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/distinct-outside.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/file-pr.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/fork-hygiene.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/inbox.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/notes.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/pr-sweep.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/prior-art.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/scripts/verify-filed-pr.sh +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/src/housebroken/__init__.py +0 -0
- {housebroken_cli-0.2.8 → housebroken_cli-0.4.0}/src/housebroken/cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: housebroken-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Agent-written pull requests that do not make a mess in someone else's house.
|
|
5
5
|
Project-URL: Repository, https://github.com/lenamonj/housebroken
|
|
6
6
|
License-Expression: MIT
|
|
@@ -109,7 +109,7 @@ Every organization gets a card before the first filing: CLA, DCO, signed-commit
|
|
|
109
109
|
A memory-safety or remote-abort finding in a library goes by the project's SECURITY.md route, privately, and never becomes a public pull request until the project answers.
|
|
110
110
|
|
|
111
111
|
**9. File through the gate.**
|
|
112
|
-
`file-pr.sh` wraps the pull request creation and refuses when the prior-art printout for that repository is missing or older than a day, or when the body carries a footer, a trailer, or a typographic dash.
|
|
112
|
+
`branch-check.sh` reads the branch before anything leaves the machine: it refuses a dirty working tree, a file whose mode disagrees with its own siblings, a committed file the repository's own `.gitignore` excludes, a working artifact, and a branch that is not on top of its base, and it prints every absolute claim the added prose makes so each can be falsified against the code. Three of those came from one review round on a single pull request. `file-pr.sh` wraps the pull request creation and refuses when the prior-art printout for that repository is missing or older than a day, or when the body carries a footer, a trailer, or a typographic dash.
|
|
113
113
|
|
|
114
114
|
**10. Watch it land.**
|
|
115
115
|
`verify-filed-pr.sh` re-derives from GitHub that the head is the intended commit, the diff is exactly the intended files, and CI settled green. `pr-sweep.sh` lists every open pull request where the ball is in your court: a maintainer's comment unanswered, a review requesting changes, a red check, a conflict. Every maintainer comment gets a same-day answer. A ruling in a closed issue is never argued with. When the maintainer is right, concede and let them close it.
|
|
@@ -146,6 +146,8 @@ uv tool install git+https://github.com/lenamonj/housebroken
|
|
|
146
146
|
| `scripts/prior-art.sh` | issues and pull requests on the touched files, type stated, rulings quoted |
|
|
147
147
|
| `scripts/comment-census.sh` | added code versus added comments, per branch |
|
|
148
148
|
| `scripts/diff-defaults.sh` | default arguments and one-line wrappers added to keep call sites untouched |
|
|
149
|
+
| `scripts/claim-check.sh` | every falsifiable claim in a body or a reply, listed to re-derive |
|
|
150
|
+
| `scripts/branch-check.sh` | the branch's mechanical facts: clean tree, file modes, artifacts, absolute claims |
|
|
149
151
|
| `scripts/file-pr.sh` | the only way a pull request gets filed |
|
|
150
152
|
| `scripts/verify-filed-pr.sh` | the filed pull request is what was meant, and CI settled |
|
|
151
153
|
| `scripts/pr-sweep.sh` | every open pull request where the ball is in your court |
|
|
@@ -97,7 +97,7 @@ Every organization gets a card before the first filing: CLA, DCO, signed-commit
|
|
|
97
97
|
A memory-safety or remote-abort finding in a library goes by the project's SECURITY.md route, privately, and never becomes a public pull request until the project answers.
|
|
98
98
|
|
|
99
99
|
**9. File through the gate.**
|
|
100
|
-
`file-pr.sh` wraps the pull request creation and refuses when the prior-art printout for that repository is missing or older than a day, or when the body carries a footer, a trailer, or a typographic dash.
|
|
100
|
+
`branch-check.sh` reads the branch before anything leaves the machine: it refuses a dirty working tree, a file whose mode disagrees with its own siblings, a committed file the repository's own `.gitignore` excludes, a working artifact, and a branch that is not on top of its base, and it prints every absolute claim the added prose makes so each can be falsified against the code. Three of those came from one review round on a single pull request. `file-pr.sh` wraps the pull request creation and refuses when the prior-art printout for that repository is missing or older than a day, or when the body carries a footer, a trailer, or a typographic dash.
|
|
101
101
|
|
|
102
102
|
**10. Watch it land.**
|
|
103
103
|
`verify-filed-pr.sh` re-derives from GitHub that the head is the intended commit, the diff is exactly the intended files, and CI settled green. `pr-sweep.sh` lists every open pull request where the ball is in your court: a maintainer's comment unanswered, a review requesting changes, a red check, a conflict. Every maintainer comment gets a same-day answer. A ruling in a closed issue is never argued with. When the maintainer is right, concede and let them close it.
|
|
@@ -134,6 +134,8 @@ uv tool install git+https://github.com/lenamonj/housebroken
|
|
|
134
134
|
| `scripts/prior-art.sh` | issues and pull requests on the touched files, type stated, rulings quoted |
|
|
135
135
|
| `scripts/comment-census.sh` | added code versus added comments, per branch |
|
|
136
136
|
| `scripts/diff-defaults.sh` | default arguments and one-line wrappers added to keep call sites untouched |
|
|
137
|
+
| `scripts/claim-check.sh` | every falsifiable claim in a body or a reply, listed to re-derive |
|
|
138
|
+
| `scripts/branch-check.sh` | the branch's mechanical facts: clean tree, file modes, artifacts, absolute claims |
|
|
137
139
|
| `scripts/file-pr.sh` | the only way a pull request gets filed |
|
|
138
140
|
| `scripts/verify-filed-pr.sh` | the filed pull request is what was meant, and CI settled |
|
|
139
141
|
| `scripts/pr-sweep.sh` | every open pull request where the ball is in your court |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# housebroken - one command name for the
|
|
2
|
+
# housebroken - one command name for the gate scripts.
|
|
3
3
|
#
|
|
4
4
|
# The skill file, and any future adapter for another agent host, must be able
|
|
5
5
|
# to say `housebroken prior-art owner/repo term` without knowing where the
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# housebroken version
|
|
14
14
|
#
|
|
15
15
|
# Environment:
|
|
16
|
-
# HOUSEBROKEN_SCRIPTS directory holding the
|
|
16
|
+
# HOUSEBROKEN_SCRIPTS directory holding the *.sh gate scripts. When
|
|
17
17
|
# unset, the scripts directory next to this file
|
|
18
18
|
# (../scripts), then this file's own directory, then
|
|
19
19
|
# $HOUSEBROKEN_HOME/scripts are tried in that order.
|
|
@@ -48,6 +48,8 @@ usage: housebroken <subcommand> [args...]
|
|
|
48
48
|
1 outside count outside contributors merged in the last 120 days
|
|
49
49
|
2 prior-art issues and pull requests on the touched files, rulings quoted
|
|
50
50
|
6 census added code lines against added comment lines, per branch
|
|
51
|
+
6 claims every falsifiable claim in outbound text, listed to re-derive
|
|
52
|
+
9 branch the mechanical facts about the branch: tree, modes, artifacts, claims
|
|
51
53
|
9 file the only way a pull request gets filed
|
|
52
54
|
10 verify the filed pull request is what was meant, and CI settled
|
|
53
55
|
10 sweep every open pull request where the ball is in your court
|
|
@@ -89,6 +91,8 @@ case "$cmd" in
|
|
|
89
91
|
outside) script=distinct-outside.sh ;;
|
|
90
92
|
prior-art) script=prior-art.sh ;;
|
|
91
93
|
census) script=comment-census.sh ;;
|
|
94
|
+
claims) script=claim-check.sh ;;
|
|
95
|
+
branch) script=branch-check.sh ;;
|
|
92
96
|
file) script=file-pr.sh ;;
|
|
93
97
|
verify) script=verify-filed-pr.sh ;;
|
|
94
98
|
sweep) script=pr-sweep.sh ;;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# branch-check.sh - the mechanical facts about the branch you are about to file.
|
|
3
|
+
#
|
|
4
|
+
# Three defects on PaloAltoNetworks/docusaurus-openapi-docs #1624 were facts
|
|
5
|
+
# about the branch rather than about the patch, and git could have printed all
|
|
6
|
+
# three before anything left the machine.
|
|
7
|
+
#
|
|
8
|
+
# A reviewer had just shown that a sentence in the added documentation
|
|
9
|
+
# overclaimed. The wording was corrected in the working tree, the branch was
|
|
10
|
+
# rebuilt with `git reset --soft <base>`, and the commits still carried the old
|
|
11
|
+
# sentence: a soft reset leaves the index at the previous commit, so the
|
|
12
|
+
# corrected file was never staged. The tree was dirty and nobody looked. A
|
|
13
|
+
# dirty tree is a refusal here, because what you tested is not what you file.
|
|
14
|
+
#
|
|
15
|
+
# The new test file was committed 100755 where every other test in that
|
|
16
|
+
# repository is 100644, which GitHub renders in the diff. A mode that disagrees
|
|
17
|
+
# with the file's own siblings is a refusal.
|
|
18
|
+
#
|
|
19
|
+
# The overclaiming sentence was an absolute: "removes only the files the plugin
|
|
20
|
+
# generated", which the code falsifies for two file names. Absolutes in added
|
|
21
|
+
# prose are printed for you to check one by one; they are not refused, because
|
|
22
|
+
# some of them are true.
|
|
23
|
+
#
|
|
24
|
+
# Usage:
|
|
25
|
+
# bash branch-check.sh [CLONE] [--base REF]
|
|
26
|
+
# bash branch-check.sh --help
|
|
27
|
+
#
|
|
28
|
+
# CLONE defaults to the current directory. REF defaults to the first of
|
|
29
|
+
# upstream/main, upstream/master, origin/main, origin/master that resolves.
|
|
30
|
+
#
|
|
31
|
+
# Exits 0 when nothing blocks, 1 on a refusal, 2 on a usage error.
|
|
32
|
+
set -u
|
|
33
|
+
|
|
34
|
+
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/, ""); print; next} NR>1 {exit}' "$0"; }
|
|
35
|
+
|
|
36
|
+
clone="."
|
|
37
|
+
base=""
|
|
38
|
+
while [ "$#" -gt 0 ]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--help|-h) usage; exit 0 ;;
|
|
41
|
+
--base)
|
|
42
|
+
shift
|
|
43
|
+
base="${1:-}"
|
|
44
|
+
[ -n "$base" ] || { echo "REFUSED: --base needs a ref" >&2; exit 2; }
|
|
45
|
+
;;
|
|
46
|
+
-*) echo "REFUSED: unknown option $1" >&2; exit 2 ;;
|
|
47
|
+
*) clone="$1" ;;
|
|
48
|
+
esac
|
|
49
|
+
shift
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
cd "$clone" 2>/dev/null || { echo "REFUSED: $clone is not a directory" >&2; exit 2; }
|
|
53
|
+
git rev-parse --git-dir >/dev/null 2>&1 || { echo "REFUSED: $clone is not a git clone" >&2; exit 2; }
|
|
54
|
+
|
|
55
|
+
if [ -z "$base" ]; then
|
|
56
|
+
for candidate in upstream/main upstream/master origin/main origin/master; do
|
|
57
|
+
if git rev-parse --verify -q "$candidate" >/dev/null 2>&1; then base="$candidate"; break; fi
|
|
58
|
+
done
|
|
59
|
+
fi
|
|
60
|
+
[ -n "$base" ] || { echo "REFUSED: no base ref resolved - pass --base REF" >&2; exit 2; }
|
|
61
|
+
git rev-parse --verify -q "$base" >/dev/null 2>&1 || { echo "REFUSED: base $base does not resolve" >&2; exit 2; }
|
|
62
|
+
|
|
63
|
+
blocked=0
|
|
64
|
+
block() { echo "REFUSED: $*"; blocked=1; }
|
|
65
|
+
|
|
66
|
+
echo "== branch check: $(git rev-parse --abbrev-ref HEAD) against $base =="
|
|
67
|
+
|
|
68
|
+
# What you tested is what you file, or you do not know what you are filing.
|
|
69
|
+
dirty=$(git status --porcelain)
|
|
70
|
+
if [ -n "$dirty" ]; then
|
|
71
|
+
block "the working tree is dirty, so the commits are not what you tested"
|
|
72
|
+
printf '%s\n' "$dirty" | sed 's/^/ /'
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
if ! git merge-base --is-ancestor "$base" HEAD 2>/dev/null; then
|
|
76
|
+
block "HEAD is not on top of $base - rebase before filing"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
files=$(git diff --name-only "$base..HEAD" 2>/dev/null)
|
|
80
|
+
if [ -z "$files" ]; then
|
|
81
|
+
block "no files differ from $base - there is nothing to file"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
while IFS= read -r f; do
|
|
85
|
+
[ -n "$f" ] || continue
|
|
86
|
+
entry=$(git ls-files -s -- "$f" 2>/dev/null)
|
|
87
|
+
[ -n "$entry" ] || continue
|
|
88
|
+
mode=$(printf '%s\n' "$entry" | awk '{print $1}')
|
|
89
|
+
|
|
90
|
+
# A mode is only wrong relative to the file's own neighbours.
|
|
91
|
+
if [ "$mode" = "100755" ]; then
|
|
92
|
+
case "$f" in
|
|
93
|
+
*.*) ext=".${f##*.}" ;;
|
|
94
|
+
*) ext="" ;;
|
|
95
|
+
esac
|
|
96
|
+
if [ -n "$ext" ]; then
|
|
97
|
+
sibs=$(git ls-files -s -- "*$ext" 2>/dev/null | awk -v self="$f" '$4 != self {print $1}')
|
|
98
|
+
norm=$(printf '%s\n' "$sibs" | grep -c '^100644$')
|
|
99
|
+
exec=$(printf '%s\n' "$sibs" | grep -c '^100755$')
|
|
100
|
+
if [ "$norm" -gt "$exec" ]; then
|
|
101
|
+
block "$f is committed 100755 but $norm of its $ext siblings are 100644"
|
|
102
|
+
fi
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# The repository's own .gitignore is the authority on what is build output.
|
|
107
|
+
if git check-ignore -q --no-index -- "$f" 2>/dev/null; then
|
|
108
|
+
block "$f is committed but the repository's .gitignore excludes it"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
case "$f" in
|
|
112
|
+
.jeffy/*|*/.jeffy/*|PLAN.md|*/PLAN.md|JOURNAL.md|*/JOURNAL.md|*.orig|*.rej)
|
|
113
|
+
block "$f is a working artifact and has no place in the diff" ;;
|
|
114
|
+
esac
|
|
115
|
+
done <<EOF
|
|
116
|
+
$files
|
|
117
|
+
EOF
|
|
118
|
+
|
|
119
|
+
# Absolutes in added prose are the claims a maintainer can falsify in one grep.
|
|
120
|
+
claims=$(git diff -U0 "$base..HEAD" -- '*.md' '*.mdx' '*.rst' '*.txt' 2>/dev/null \
|
|
121
|
+
| grep '^+' | grep -v '^+++' | sed 's/^+//' \
|
|
122
|
+
| grep -nEi '\b(only|exactly|always|never|guaranteed|nothing|everything)\b')
|
|
123
|
+
if [ -n "$claims" ]; then
|
|
124
|
+
echo "CHECK: added prose makes absolute claims - falsify each one against the code:"
|
|
125
|
+
printf '%s\n' "$claims" | sed 's/^/ /'
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
echo
|
|
129
|
+
echo "commits:"
|
|
130
|
+
git log --oneline "$base..HEAD" | sed 's/^/ /'
|
|
131
|
+
echo "diff:"
|
|
132
|
+
git diff --stat "$base..HEAD" | sed 's/^/ /'
|
|
133
|
+
|
|
134
|
+
if [ "$blocked" -ne 0 ]; then
|
|
135
|
+
echo
|
|
136
|
+
echo "branch-check: refused. Fix the causes above; a refusal is a result."
|
|
137
|
+
exit 1
|
|
138
|
+
fi
|
|
139
|
+
echo
|
|
140
|
+
echo "branch-check: nothing mechanical blocks this branch."
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# claim-check.sh - lists every claim in outbound text that a maintainer can
|
|
3
|
+
# falsify, so each one gets re-derived before it is sent.
|
|
4
|
+
#
|
|
5
|
+
# On microsoft/GSL #1272 a reply draft said "The five new static_asserts fail on
|
|
6
|
+
# main." A reviewer falsified it in one pass. The number had come from a red arm
|
|
7
|
+
# that grepped only for `static assertion failed`, so it counted five matches
|
|
8
|
+
# and never saw the twenty-one other errors beside them; and against the commit
|
|
9
|
+
# a maintainer would actually revert to, only four of the five fail. The
|
|
10
|
+
# sentence named a basis and was still wrong about it.
|
|
11
|
+
#
|
|
12
|
+
# So this does not try to judge a claim. Text checks cannot: the bad sentence
|
|
13
|
+
# named its revision and read perfectly. It lists them, and the rule in step 6
|
|
14
|
+
# is that every listed line is re-measured, at the moment of writing, against
|
|
15
|
+
# the exact revision the sentence names. The gap this closes is that until now
|
|
16
|
+
# every gate here read code and nothing read the prose, while the prose is what
|
|
17
|
+
# the maintainer reads first.
|
|
18
|
+
#
|
|
19
|
+
# Usage:
|
|
20
|
+
# bash claim-check.sh FILE
|
|
21
|
+
# bash claim-check.sh --help
|
|
22
|
+
#
|
|
23
|
+
# Exits 1 when it finds claims to re-derive, 0 when it finds none, 2 on a usage
|
|
24
|
+
# error. Exit 1 is not a refusal to send; it is a refusal to send unread.
|
|
25
|
+
set -u
|
|
26
|
+
|
|
27
|
+
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/, ""); print; next} NR>1 {exit}' "$0"; }
|
|
28
|
+
|
|
29
|
+
case "${1:-}" in
|
|
30
|
+
--help|-h) usage; exit 0 ;;
|
|
31
|
+
"") echo "REFUSED: name the file holding the text" >&2; exit 2 ;;
|
|
32
|
+
esac
|
|
33
|
+
file="$1"
|
|
34
|
+
[ -f "$file" ] || { echo "REFUSED: $file does not exist" >&2; exit 2; }
|
|
35
|
+
|
|
36
|
+
# Strip fenced code and quoted logs: a number inside pasted output is evidence,
|
|
37
|
+
# not a claim being made.
|
|
38
|
+
body=$(awk '/^```/ {fence = !fence; next} !fence && !/^ *[|>]/ {print NR": "$0}' "$file")
|
|
39
|
+
|
|
40
|
+
quantified=$(printf '%s
|
|
41
|
+
' "$body" | grep -nEi '[0-9]+ *(of|/) *[0-9]+|\b([0-9]+|one|two|three|four|five|six|seven|eight|nine|ten|no) +([a-z_-]+ +){0,3}(tests?|assertions?|static_asserts?|checks?|errors?|failures?|jobs?|files?|warnings?|projects?|commits?|suites?)\b' | cut -d: -f2-)
|
|
42
|
+
|
|
43
|
+
absolute=$(printf '%s\n' "$body" | grep -nEi \
|
|
44
|
+
'\b(only|exactly|always|never|every|all|none|nothing|everything|guaranteed|any)\b' \
|
|
45
|
+
| cut -d: -f2-)
|
|
46
|
+
|
|
47
|
+
found=0
|
|
48
|
+
if [ -n "$quantified" ]; then
|
|
49
|
+
found=1
|
|
50
|
+
echo "COUNTED: re-derive each, against the revision the sentence names, now:"
|
|
51
|
+
printf '%s\n' "$quantified" | sed 's/^/ /'
|
|
52
|
+
fi
|
|
53
|
+
if [ -n "$absolute" ]; then
|
|
54
|
+
found=1
|
|
55
|
+
echo "ABSOLUTE: falsify each against the code, not against your memory of it:"
|
|
56
|
+
printf '%s\n' "$absolute" | sed 's/^/ /'
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
if [ "$found" -eq 0 ]; then
|
|
60
|
+
echo "claim-check: no falsifiable claim found in $file"
|
|
61
|
+
exit 0
|
|
62
|
+
fi
|
|
63
|
+
echo
|
|
64
|
+
echo "claim-check: $file makes claims a maintainer can check. Re-measure each"
|
|
65
|
+
echo "one before sending. A sentence that names its revision can still be wrong"
|
|
66
|
+
echo "about it; that is the failure this exists for."
|
|
67
|
+
exit 1
|
|
@@ -81,8 +81,15 @@ report it in one line and do not proceed to the next step.
|
|
|
81
81
|
trusting a command's exit code, check the clone's line endings before the
|
|
82
82
|
first edit, export PATH explicitly in any detached script and report every
|
|
83
83
|
step's exit code. Two arms of an experiment that agree exactly have not
|
|
84
|
-
tested the variable.
|
|
85
|
-
|
|
84
|
+
tested the variable. Swap the file's content from `git show <base>:<path>`
|
|
85
|
+
rather than switching branches: a checkout refused because the tree is
|
|
86
|
+
dirty leaves the patched file in place, and the arm then reports success
|
|
87
|
+
under the label RED. Assert the two arms' hashes differ before believing
|
|
88
|
+
either result. Before filing, hash the changed file on disk against
|
|
89
|
+
the blob in the commit: a branch can carry the test and not the fix.
|
|
90
|
+
After rebuilding commits, grep the committed blob for the change, never
|
|
91
|
+
the file on disk: `git reset --soft` leaves the index at the previous
|
|
92
|
+
commit, so a correction made after that commit is not in the new one. When the
|
|
86
93
|
patched function serves several public entry points or has several
|
|
87
94
|
branches, the test is a grid: every entry point through every branch,
|
|
88
95
|
plus the zero, identity and signed-boundary rows. A reviewer lists the
|
|
@@ -94,7 +101,11 @@ report it in one line and do not proceed to the next step.
|
|
|
94
101
|
workflow file to find them. A gate you did not run is a red check the
|
|
95
102
|
maintainer sees before you do. When the repository ships a Dangerfile, a
|
|
96
103
|
pre-commit config or a commitlint config, those are its acceptance
|
|
97
|
-
criteria in machine-readable form; run them.
|
|
104
|
+
criteria in machine-readable form; run them. When the project's own lint
|
|
105
|
+
aborts on its own configuration, that is a fact to state, not permission
|
|
106
|
+
to skip yours: run the linter over the changed files directly, and
|
|
107
|
+
reproduce the global failure on a pristine base so the body says whose
|
|
108
|
+
it is.
|
|
98
109
|
|
|
99
110
|
6. **Match the house style.**
|
|
100
111
|
Run `housebroken notes owner/repo` before writing the pull request and
|
|
@@ -107,7 +118,11 @@ report it in one line and do not proceed to the next step.
|
|
|
107
118
|
you reproduced on the fresh clone in this session, never a line carried
|
|
108
119
|
from a journal. No tool footer, no session link, no
|
|
109
120
|
co-author trailer, no typographic dashes. When a template asks whether AI
|
|
110
|
-
was used, answer in one truthful sentence.
|
|
121
|
+
was used, answer in one truthful sentence. Run `housebroken claims` over
|
|
122
|
+
the body and re-measure every line it lists, now, against the exact
|
|
123
|
+
revision that sentence names. A claim that names its revision can still
|
|
124
|
+
be wrong about it, which is why the listing is the whole gate: the
|
|
125
|
+
re-derivation is yours to do.
|
|
111
126
|
|
|
112
127
|
7. **Know the paperwork.**
|
|
113
128
|
Before the first pull request to an organization, find its agreement: CLA,
|
|
@@ -124,7 +139,12 @@ report it in one line and do not proceed to the next step.
|
|
|
124
139
|
pull request until the project answers.
|
|
125
140
|
|
|
126
141
|
9. **File through the gate.**
|
|
127
|
-
`housebroken
|
|
142
|
+
`housebroken branch <clone>` first. It refuses a dirty working tree, a file
|
|
143
|
+
whose mode disagrees with its own siblings, a committed file the repository
|
|
144
|
+
ignores, and a branch that is not on top of its base, and it prints every
|
|
145
|
+
absolute claim your added prose makes so you can falsify each one against
|
|
146
|
+
the code. Then
|
|
147
|
+
`housebroken file owner/repo --title ... --body-file ...`, the only way a
|
|
128
148
|
pull request is opened. Never run the pull request creation command
|
|
129
149
|
directly. The gate refuses when the prior-art printout for that repository
|
|
130
150
|
is missing or older than a day, or when the body carries a footer, a
|
|
@@ -141,7 +161,9 @@ report it in one line and do not proceed to the next step.
|
|
|
141
161
|
on every open pull request. A list of who commented is not a read, and a
|
|
142
162
|
conversion to draft is a review. Act on every human item, then run
|
|
143
163
|
`housebroken inbox --ack`. Answer every maintainer comment the same day,
|
|
144
|
-
in the user's voice
|
|
164
|
+
in the user's voice, and run `housebroken claims` over the reply before
|
|
165
|
+
it is posted: the only claim that has gone out wrong here was in a
|
|
166
|
+
reply, not a body. Rework what is asked for as a second commit so the reviewer sees
|
|
145
167
|
the change. When the maintainer is
|
|
146
168
|
right, concede in one sentence and let them close it. Never nudge a
|
|
147
169
|
silent maintainer without the user's explicit word. After answering a
|
|
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
|