housebroken-cli 0.6.3__tar.gz → 0.6.4__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.3 → housebroken_cli-0.6.4}/PKG-INFO +3 -1
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/README.md +2 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/bin/housebroken +2 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/pyproject.toml +1 -1
- housebroken_cli-0.6.4/scripts/file-issue.sh +168 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/skills/housebroken/SKILL.md +3 -1
- housebroken_cli-0.6.4/src/housebroken/__init__.py +1 -0
- housebroken_cli-0.6.3/src/housebroken/__init__.py +0 -1
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/.gitignore +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/LICENSE +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/hatch_build.py +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/branch-check.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/check-ai-policy.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/claim-check.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/comment-census.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/comment-check.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/diff-defaults.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/distinct-outside.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/file-pr.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/fork-hygiene.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/inbox.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/notes.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/pr-sweep.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/prior-art.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/review.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/scripts/verify-filed-pr.sh +0 -0
- {housebroken_cli-0.6.3 → housebroken_cli-0.6.4}/src/housebroken/cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: housebroken-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4
|
|
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
|
|
@@ -79,6 +79,7 @@ A memory-safety, remote-abort, injection or path-escape finding goes by the proj
|
|
|
79
79
|
`branch-check.sh` refuses a dirty working tree, a file whose mode disagrees with its siblings, a file the repository's own `.gitignore` excludes, a working artifact, a commit carrying a tool trailer, a session link or a tool identity, a sign-off naming a username, a branch not on top of its base, and any comment added to code; it prints every absolute claim in added prose for falsification, and stamps the head it passed.
|
|
80
80
|
`review.sh` names the adversarial reviewer: a different model from the one that wrote the change, one tier down, never below Sonnet. The reviewer gets a fresh context, hard read-only limits and an attack list that starts with every claim the prose makes and includes the form of the code: the reviewer writes the changed block the way the strongest engineer in that language would, in the repository's own idioms, and a smaller or clearer version is a finding; every finding carries evidence it produced itself, and its report is bound to the head and the text it read. A fix is a new head and gets a new review.
|
|
81
81
|
`file-pr.sh` is the only way a pull request is opened. It refuses without a prior-art printout under a day old, a policy printout under a day old that does not read BAN, a body that discloses when the policy asks, a branch stamp for the exact head, and a POST AS IS review of that head and that body.
|
|
82
|
+
`file-issue.sh` is the only way an issue is opened. It refuses without the same prior-art and policy printouts, refuses the same prose, and refuses a body that mentions a fix, a patch or a pull request without a GitHub link to the branch or commit, so work that exists is attributable to whoever did it.
|
|
82
83
|
|
|
83
84
|
**10. Watch it land.**
|
|
84
85
|
`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. `inbox.sh` prints every event on your threads since the last acknowledged cursor, bodies included, with a census of failing, blocked and conflicting checks. Every maintainer comment gets a same-day answer in the contributor's voice, checked by `claim-check.sh` and, when it concedes, disagrees or rides on a code change, by the adversarial review. Replies to one repository are spaced ten minutes apart. When the maintainer is right, concede in one sentence. A silent maintainer is never nudged.
|
|
@@ -123,6 +124,7 @@ uv tool install git+https://github.com/lenamonj/housebroken
|
|
|
123
124
|
| `scripts/branch-check.sh` | the branch's mechanical facts: clean tree, modes, artifacts, trailers, sign-offs, comments, absolute claims |
|
|
124
125
|
| `scripts/review.sh` | the adversarial review: a different model attacks the change, and the filing is held to exactly what it read |
|
|
125
126
|
| `scripts/file-pr.sh` | the only way a pull request gets filed: five gates in front of `gh pr create` |
|
|
127
|
+
| `scripts/file-issue.sh` | the only way an issue gets filed: the same printouts and prose, and a fix offered is a fix linked |
|
|
126
128
|
| `scripts/verify-filed-pr.sh` | the filed pull request is what was meant, and CI settled |
|
|
127
129
|
| `scripts/pr-sweep.sh` | every open pull request where the ball is in your court |
|
|
128
130
|
| `scripts/inbox.sh` | what GitHub has to tell you since you last looked, bodies included, with a census of every open pull request |
|
|
@@ -67,6 +67,7 @@ A memory-safety, remote-abort, injection or path-escape finding goes by the proj
|
|
|
67
67
|
`branch-check.sh` refuses a dirty working tree, a file whose mode disagrees with its siblings, a file the repository's own `.gitignore` excludes, a working artifact, a commit carrying a tool trailer, a session link or a tool identity, a sign-off naming a username, a branch not on top of its base, and any comment added to code; it prints every absolute claim in added prose for falsification, and stamps the head it passed.
|
|
68
68
|
`review.sh` names the adversarial reviewer: a different model from the one that wrote the change, one tier down, never below Sonnet. The reviewer gets a fresh context, hard read-only limits and an attack list that starts with every claim the prose makes and includes the form of the code: the reviewer writes the changed block the way the strongest engineer in that language would, in the repository's own idioms, and a smaller or clearer version is a finding; every finding carries evidence it produced itself, and its report is bound to the head and the text it read. A fix is a new head and gets a new review.
|
|
69
69
|
`file-pr.sh` is the only way a pull request is opened. It refuses without a prior-art printout under a day old, a policy printout under a day old that does not read BAN, a body that discloses when the policy asks, a branch stamp for the exact head, and a POST AS IS review of that head and that body.
|
|
70
|
+
`file-issue.sh` is the only way an issue is opened. It refuses without the same prior-art and policy printouts, refuses the same prose, and refuses a body that mentions a fix, a patch or a pull request without a GitHub link to the branch or commit, so work that exists is attributable to whoever did it.
|
|
70
71
|
|
|
71
72
|
**10. Watch it land.**
|
|
72
73
|
`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. `inbox.sh` prints every event on your threads since the last acknowledged cursor, bodies included, with a census of failing, blocked and conflicting checks. Every maintainer comment gets a same-day answer in the contributor's voice, checked by `claim-check.sh` and, when it concedes, disagrees or rides on a code change, by the adversarial review. Replies to one repository are spaced ten minutes apart. When the maintainer is right, concede in one sentence. A silent maintainer is never nudged.
|
|
@@ -111,6 +112,7 @@ uv tool install git+https://github.com/lenamonj/housebroken
|
|
|
111
112
|
| `scripts/branch-check.sh` | the branch's mechanical facts: clean tree, modes, artifacts, trailers, sign-offs, comments, absolute claims |
|
|
112
113
|
| `scripts/review.sh` | the adversarial review: a different model attacks the change, and the filing is held to exactly what it read |
|
|
113
114
|
| `scripts/file-pr.sh` | the only way a pull request gets filed: five gates in front of `gh pr create` |
|
|
115
|
+
| `scripts/file-issue.sh` | the only way an issue gets filed: the same printouts and prose, and a fix offered is a fix linked |
|
|
114
116
|
| `scripts/verify-filed-pr.sh` | the filed pull request is what was meant, and CI settled |
|
|
115
117
|
| `scripts/pr-sweep.sh` | every open pull request where the ball is in your court |
|
|
116
118
|
| `scripts/inbox.sh` | what GitHub has to tell you since you last looked, bodies included, with a census of every open pull request |
|
|
@@ -53,6 +53,7 @@ usage: housebroken <subcommand> [args...]
|
|
|
53
53
|
9 branch the mechanical facts about the branch: tree, modes, artifacts, claims
|
|
54
54
|
9 review a different model attacks the change before it is filed
|
|
55
55
|
9 file the only way a pull request gets filed
|
|
56
|
+
9 issue the only way an issue gets filed
|
|
56
57
|
10 verify the filed pull request is what was meant, and CI settled
|
|
57
58
|
10 sweep every open pull request where the ball is in your court
|
|
58
59
|
10 inbox what GitHub has to tell you since you last looked, bodies included
|
|
@@ -98,6 +99,7 @@ case "$cmd" in
|
|
|
98
99
|
branch) script=branch-check.sh ;;
|
|
99
100
|
review) script=review.sh ;;
|
|
100
101
|
file) script=file-pr.sh ;;
|
|
102
|
+
issue) script=file-issue.sh ;;
|
|
101
103
|
verify) script=verify-filed-pr.sh ;;
|
|
102
104
|
sweep) script=pr-sweep.sh ;;
|
|
103
105
|
inbox) script=inbox.sh ;;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# file-issue.sh - the only way an issue gets filed: gh issue create behind four
|
|
3
|
+
# gates.
|
|
4
|
+
#
|
|
5
|
+
# Gate one is prior art: prior-art-<owner>-<repo>.md exists under
|
|
6
|
+
# $HOUSEBROKEN_HOME/prior-art/ and is under 24 hours old.
|
|
7
|
+
# Gate two is the policy: policy-<owner>-<repo>.md exists under
|
|
8
|
+
# $HOUSEBROKEN_HOME/policy/ (check-ai-policy.sh --out), is under 24 hours old,
|
|
9
|
+
# does not read BAN, and when it reads DISCLOSE the body discloses.
|
|
10
|
+
# Gate three is the prose: no tool footer, session trailer, co-author trailer,
|
|
11
|
+
# em dash or en dash in the body or the title.
|
|
12
|
+
# Gate four is the link: a body that offers a fix, a patch or a pull request
|
|
13
|
+
# names a branch or commit on GitHub. On 2026-09-09 an issue that described a
|
|
14
|
+
# fix without linking one was answered by another contributor's pull request
|
|
15
|
+
# seven hours later; on 2026-09-23 it happened again. Work that exists is
|
|
16
|
+
# linked so it is attributable to whoever did it.
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# bash file-issue.sh owner/repo --title ... --body-file ...
|
|
20
|
+
# FILE_ISSUE_DRY=1 bash file-issue.sh owner/repo ... # print, run nothing
|
|
21
|
+
# bash file-issue.sh --help
|
|
22
|
+
#
|
|
23
|
+
# Environment:
|
|
24
|
+
# HOUSEBROKEN_HOME work directory, default $HOME/.housebroken; the prior
|
|
25
|
+
# art and policy printouts are read from it.
|
|
26
|
+
# FILE_ISSUE_DRY set to 1 to print the gh command instead of running it.
|
|
27
|
+
#
|
|
28
|
+
# Assumes gh is installed and authenticated. It writes to GitHub only after all
|
|
29
|
+
# four gates pass, and only when FILE_ISSUE_DRY is not 1.
|
|
30
|
+
set -u
|
|
31
|
+
|
|
32
|
+
usage() {
|
|
33
|
+
cat <<'EOF'
|
|
34
|
+
usage: file-issue.sh owner/repo --title ... --body-file ... [gh issue create args...]
|
|
35
|
+
file-issue.sh --help
|
|
36
|
+
|
|
37
|
+
owner/repo the upstream repository the issue is filed on
|
|
38
|
+
the remaining arguments go to gh issue create, and only these are accepted:
|
|
39
|
+
--title (required), --body-file (required), --label, --assignee,
|
|
40
|
+
--milestone and --project, each value as its own argument or after an
|
|
41
|
+
equals sign
|
|
42
|
+
|
|
43
|
+
gates:
|
|
44
|
+
prior art $HOUSEBROKEN_HOME/prior-art/prior-art-<owner>-<repo>.md must
|
|
45
|
+
exist and be under 24 hours old
|
|
46
|
+
policy $HOUSEBROKEN_HOME/policy/policy-<owner>-<repo>.md must exist,
|
|
47
|
+
be under 24 hours old and not read RESULT: BAN; when it reads
|
|
48
|
+
RESULT: DISCLOSE the body must name the AI use
|
|
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
|
|
51
|
+
link a body that mentions a fix, a patch or a pull request must
|
|
52
|
+
carry a github.com URL to a branch, commit or comparison, so
|
|
53
|
+
the work it describes is attributable
|
|
54
|
+
|
|
55
|
+
environment:
|
|
56
|
+
HOUSEBROKEN_HOME work directory, default $HOME/.housebroken
|
|
57
|
+
FILE_ISSUE_DRY 1 prints the gh command and files nothing
|
|
58
|
+
EOF
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if [ "$#" -eq 0 ] || [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
|
|
62
|
+
usage
|
|
63
|
+
[ "$#" -eq 0 ] && exit 2
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
command -v gh >/dev/null 2>&1 || { echo "REFUSED: gh is not on PATH" >&2; exit 2; }
|
|
68
|
+
|
|
69
|
+
repo="$1"
|
|
70
|
+
shift
|
|
71
|
+
case "$repo" in
|
|
72
|
+
*/*) : ;;
|
|
73
|
+
*) echo "REFUSED: first argument must be owner/repo" >&2; exit 2 ;;
|
|
74
|
+
esac
|
|
75
|
+
[ "$#" -gt 0 ] || { echo "REFUSED: no gh issue create arguments given" >&2; exit 2; }
|
|
76
|
+
|
|
77
|
+
home="${HOUSEBROKEN_HOME:-$HOME/.housebroken}"
|
|
78
|
+
art="$home/prior-art/prior-art-${repo%%/*}-${repo##*/}.md"
|
|
79
|
+
if [ ! -f "$art" ]; then
|
|
80
|
+
echo "REFUSED: no prior art at $art - run prior-art.sh $repo <terms> --out first" >&2
|
|
81
|
+
exit 2
|
|
82
|
+
fi
|
|
83
|
+
now=$(date +%s)
|
|
84
|
+
made=$(date -r "$art" +%s) || { echo "REFUSED: cannot read the age of $art" >&2; exit 2; }
|
|
85
|
+
if [ $((now - made)) -gt 86400 ]; then
|
|
86
|
+
echo "REFUSED: prior art $art is $(( (now - made) / 3600 ))h old - rerun prior-art.sh --out" >&2
|
|
87
|
+
exit 2
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
policy="$home/policy/policy-${repo%%/*}-${repo##*/}.md"
|
|
91
|
+
if [ ! -f "$policy" ]; then
|
|
92
|
+
echo "REFUSED: no policy printout at $policy - run check-ai-policy.sh $repo --out first" >&2
|
|
93
|
+
exit 2
|
|
94
|
+
fi
|
|
95
|
+
made=$(date -r "$policy" +%s) || { echo "REFUSED: cannot read the age of $policy" >&2; exit 2; }
|
|
96
|
+
if [ $((now - made)) -gt 86400 ]; then
|
|
97
|
+
echo "REFUSED: policy printout $policy is $(( (now - made) / 3600 ))h old - rerun check-ai-policy.sh --out" >&2
|
|
98
|
+
exit 2
|
|
99
|
+
fi
|
|
100
|
+
policy_result=$(grep -m1 '^RESULT: ' "$policy" | awk '{print $2}')
|
|
101
|
+
case "$policy_result" in
|
|
102
|
+
BAN) echo "REFUSED: $repo forbids AI-written contributions ($policy); never file here" >&2; exit 2 ;;
|
|
103
|
+
DISCLOSE|MENTION|CLEAN) ;;
|
|
104
|
+
*) echo "REFUSED: $policy has no RESULT line - rerun check-ai-policy.sh --out" >&2; exit 2 ;;
|
|
105
|
+
esac
|
|
106
|
+
|
|
107
|
+
em=$(printf '\xe2\x80\x94') # em dash U+2014, built at runtime to keep this file ASCII
|
|
108
|
+
en=$(printf '\xe2\x80\x93') # en dash U+2013
|
|
109
|
+
banned_re="Generated with|Claude-Session|claude\.ai/code/session_|Co-Authored-By|$em|$en|&[mn]dash;|̵[12];|ȁ[34];"
|
|
110
|
+
check_text() {
|
|
111
|
+
local what="$1" text="$2" hit
|
|
112
|
+
hit=$(printf '%s' "$text" | grep -ioE "$banned_re" | head -1) || true
|
|
113
|
+
if [ -n "$hit" ]; then
|
|
114
|
+
echo "REFUSED: $what contains '$hit' - strip it before filing" >&2
|
|
115
|
+
exit 2
|
|
116
|
+
fi
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# gh issue create also takes a body from --body, --template, --recover, --web
|
|
120
|
+
# and stdin, and obeys the last -R it is given. Each of those files something
|
|
121
|
+
# no gate read, so only these flags pass.
|
|
122
|
+
bodyfile=""
|
|
123
|
+
title=""
|
|
124
|
+
pass=()
|
|
125
|
+
while [ "$#" -gt 0 ]; do
|
|
126
|
+
case "$1" in
|
|
127
|
+
-F|--body-file) bodyfile="${2:-}"; pass+=("$1" "${2:-}"); shift ;;
|
|
128
|
+
--body-file=*) bodyfile="${1#--body-file=}"; pass+=("$1") ;;
|
|
129
|
+
-t|--title) title="${2:-}"; pass+=("$1" "${2:-}"); shift ;;
|
|
130
|
+
--title=*) title="${1#--title=}"; pass+=("$1") ;;
|
|
131
|
+
-l|--label|-a|--assignee|-m|--milestone|-p|--project) pass+=("$1" "${2:-}"); shift ;;
|
|
132
|
+
--label=*|--assignee=*|--milestone=*|--project=*) pass+=("$1") ;;
|
|
133
|
+
*)
|
|
134
|
+
echo "REFUSED: file-issue.sh does not pass $1 to gh issue create: the body comes from one --body-file, the repository is the first argument" >&2
|
|
135
|
+
exit 2
|
|
136
|
+
;;
|
|
137
|
+
esac
|
|
138
|
+
shift
|
|
139
|
+
done
|
|
140
|
+
[ -n "$title" ] || { echo "REFUSED: pass --title" >&2; exit 2; }
|
|
141
|
+
[ -n "$bodyfile" ] || { echo "REFUSED: pass the body as --body-file so the gates can read it" >&2; exit 2; }
|
|
142
|
+
if [ "$bodyfile" = "-" ] || [ ! -f "$bodyfile" ]; then
|
|
143
|
+
echo "REFUSED: body file $bodyfile does not exist" >&2
|
|
144
|
+
exit 2
|
|
145
|
+
fi
|
|
146
|
+
body=$(cat "$bodyfile")
|
|
147
|
+
check_text "body file $bodyfile" "$body"
|
|
148
|
+
check_text "--title" "$title"
|
|
149
|
+
if [ "$policy_result" = "DISCLOSE" ] && ! grep -qiE '\bAI\b|LLM|Claude|Copilot|ChatGPT|language model|assist' "$bodyfile"; then
|
|
150
|
+
echo "REFUSED: $repo requires AI use to be disclosed ($policy) and the body does not name it" >&2
|
|
151
|
+
exit 2
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
offer_re='\b(fix|fixed|fixes|patch|patched|patches|pull request|PR)\b'
|
|
155
|
+
link_re='https://github\.com/[^/[:space:]]+/[^/[:space:]]+/(tree|commit|compare|blob)/[^[:space:])]+'
|
|
156
|
+
offer=$(printf '%s' "$body" | grep -ioE "$offer_re" | head -1) || true
|
|
157
|
+
if [ -n "$offer" ] && ! printf '%s' "$body" | grep -qE "$link_re"; then
|
|
158
|
+
echo "REFUSED: the body says '$offer' and links no branch or commit - push the work to your fork and link it, or take it out of the body" >&2
|
|
159
|
+
exit 2
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if [ "${FILE_ISSUE_DRY:-0}" = "1" ]; then
|
|
163
|
+
printf 'DRY RUN, not filed:\ngh issue create -R %s' "$repo"
|
|
164
|
+
for arg in "${pass[@]}"; do printf ' %q' "$arg"; done
|
|
165
|
+
printf '\n'
|
|
166
|
+
exit 0
|
|
167
|
+
fi
|
|
168
|
+
gh issue create -R "$repo" "${pass[@]}"
|
|
@@ -70,7 +70,9 @@ report it in one line and do not proceed to the next step.
|
|
|
70
70
|
says behavior changes need discussion first, and a runtime behavior
|
|
71
71
|
change on a stable major that the project's own compatibility promise
|
|
72
72
|
forbids. Even then the patch is pushed to a branch and linked from the
|
|
73
|
-
issue, so the work is attributable to whoever did it
|
|
73
|
+
issue, so the work is attributable to whoever did it; `housebroken issue
|
|
74
|
+
owner/repo --title ... --body-file ...` is the only way an issue is
|
|
75
|
+
opened, and it refuses a body that offers a fix without that link. Classify every
|
|
74
76
|
patch before writing a test for it. A finding whose only red evidence is a measurement, such
|
|
75
77
|
as peak memory or elapsed time, is a hold: a pull request needs a test
|
|
76
78
|
that fails on the default branch for a wrong value, a crash or an
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.4"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.6.3"
|
|
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
|
|
File without changes
|