repowarden 4.9.3 → 4.10.0-next.4
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.
- package/README.md +3 -2
- package/bin/agents +103 -0
- package/bin/app +2 -2
- package/bin/bot +1 -1
- package/bin/bots +3 -3
- package/bin/code-mort +5 -3
- package/bin/commit +12 -15
- package/bin/garde +237 -0
- package/bin/migrer +4 -1
- package/bin/npm-publication +1 -1
- package/bin/pr-checks +2 -8
- package/bin/pr-label +6 -12
- package/bin/proteger +1 -1
- package/bin/repowarden +78 -5
- package/bin/run-list +2 -13
- package/bin/run-rerun +2 -15
- package/bin/statut +3 -2
- package/bin/ticket +26 -4
- package/bin/ticket-comment +7 -10
- package/bin/ticket-label +7 -14
- package/bin/tickets +3 -4
- package/hooks/agents/repowarden-garde.js +16 -0
- package/hooks/lang/node.sh +14 -2
- package/hooks/lang/python.sh +14 -2
- package/hooks/lib/common.sh +3 -1
- package/hooks/lib/deadcode.sh +46 -9
- package/hooks/lib/forge.sh +21 -0
- package/hooks/lib/i18n/en.sh +48 -0
- package/hooks/lib/i18n/fr.sh +49 -0
- package/hooks/pre-push +22 -0
- package/install.sh +2 -1
- package/package.json +1 -1
package/bin/repowarden
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
# repowarden npm-publication publication npm automatique
|
|
22
22
|
# repowarden app init GitHub App des workflows (une fois)
|
|
23
23
|
# repowarden bot [init|rapport] bot d'organisation (dépôt de pilotage)
|
|
24
|
+
# repowarden agents init [--claude] [--opencode] garde-fou des agents IA
|
|
25
|
+
# repowarden garde [--format claude|opencode] vérifie une action d'agent
|
|
24
26
|
# repowarden --version
|
|
25
27
|
set -euo pipefail
|
|
26
28
|
|
|
@@ -38,11 +40,55 @@ source "$ROOT/hooks/lib/ui.sh"
|
|
|
38
40
|
# shellcheck source=../hooks/lib/i18n.sh
|
|
39
41
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
# Clé d'aide d'une commande, alias compris ; vide si la commande est inconnue.
|
|
44
|
+
help_key_r() {
|
|
45
|
+
case "$1" in
|
|
46
|
+
install) REPLY=help.install ;;
|
|
47
|
+
uninstall) REPLY=help.uninstall ;;
|
|
48
|
+
bots) REPLY=help.bots ;;
|
|
49
|
+
bot) REPLY=help.bot ;;
|
|
50
|
+
agents) REPLY=help.agents ;;
|
|
51
|
+
garde | guard) REPLY=help.garde ;;
|
|
52
|
+
cc | commit) REPLY=help.cc ;;
|
|
53
|
+
code-mort | deadcode) REPLY=help.code-mort ;;
|
|
54
|
+
ticket) REPLY=help.ticket ;;
|
|
55
|
+
tickets) REPLY=help.tickets ;;
|
|
56
|
+
pr) REPLY=help.pr ;;
|
|
57
|
+
run) REPLY=help.run ;;
|
|
58
|
+
app) REPLY=help.app ;;
|
|
59
|
+
migrer | migrate) REPLY=help.migrer ;;
|
|
60
|
+
proteger | protect) REPLY=help.proteger ;;
|
|
61
|
+
npm-publication | npm-publish) REPLY=help.npm-publication ;;
|
|
62
|
+
"" | statut | status) REPLY=help.statut ;;
|
|
63
|
+
*) REPLY="" ;;
|
|
64
|
+
esac
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
aide() { _tr help.main; printf '%b\n' "$_T" >&2; }
|
|
42
68
|
|
|
43
69
|
commande="${1:-}"
|
|
70
|
+
cmd="$commande"
|
|
44
71
|
[ $# -eq 0 ] || shift
|
|
45
|
-
|
|
72
|
+
|
|
73
|
+
# Une seule interception : le premier argument de la sous-commande, testé
|
|
74
|
+
# avant l'exécution (code 0, rien n'est fait). Seul ce premier argument
|
|
75
|
+
# compte : cc -m "--help" reste un message. pr et run gardent leurs
|
|
76
|
+
# sous-commandes (label, checks, rerun, list), dispatchées plus bas.
|
|
77
|
+
case "${1:-}" in
|
|
78
|
+
-h | --help | help)
|
|
79
|
+
help_key_r "$cmd"
|
|
80
|
+
if [ -n "$REPLY" ]; then
|
|
81
|
+
_tr "$REPLY"
|
|
82
|
+
printf '%b\n' "$_T"
|
|
83
|
+
exit 0
|
|
84
|
+
fi
|
|
85
|
+
err_t install.unknown_arg "$cmd"
|
|
86
|
+
aide
|
|
87
|
+
exit 1
|
|
88
|
+
;;
|
|
89
|
+
esac
|
|
90
|
+
|
|
91
|
+
case "$cmd" in
|
|
46
92
|
install)
|
|
47
93
|
# npx : paquet dans un cache temporaire, effaçable à tout moment ;
|
|
48
94
|
# des hooks globaux y pointeraient vers un dossier disparu
|
|
@@ -59,6 +105,28 @@ case "$commande" in
|
|
|
59
105
|
ticket) exec bash "$ROOT/bin/ticket" "$@" ;;
|
|
60
106
|
ticket-comment) exec bash "$ROOT/bin/ticket-comment" "$@" ;;
|
|
61
107
|
ticket-label) exec bash "$ROOT/bin/ticket-label" "$@" ;;
|
|
108
|
+
pr)
|
|
109
|
+
if [ $# -ge 1 ]; then
|
|
110
|
+
case "$1" in
|
|
111
|
+
label) exec bash "$ROOT/bin/pr-label" "${@:2}" ;;
|
|
112
|
+
checks) exec bash "$ROOT/bin/pr-checks" "${@:2}" ;;
|
|
113
|
+
*) err_t install.unknown_arg "$1"; _tr help.pr; printf '%b\n' "$_T" >&2; exit 1 ;;
|
|
114
|
+
esac
|
|
115
|
+
else
|
|
116
|
+
_tr help.pr; printf '%b\n' "$_T"; exit 0
|
|
117
|
+
fi
|
|
118
|
+
;;
|
|
119
|
+
run)
|
|
120
|
+
if [ $# -ge 1 ]; then
|
|
121
|
+
case "$1" in
|
|
122
|
+
rerun) exec bash "$ROOT/bin/run-rerun" "${@:2}" ;;
|
|
123
|
+
list) exec bash "$ROOT/bin/run-list" "${@:2}" ;;
|
|
124
|
+
*) err_t install.unknown_arg "$1"; _tr help.run; printf '%b\n' "$_T" >&2; exit 1 ;;
|
|
125
|
+
esac
|
|
126
|
+
else
|
|
127
|
+
_tr help.run; printf '%b\n' "$_T"; exit 0
|
|
128
|
+
fi
|
|
129
|
+
;;
|
|
62
130
|
pr-label) exec bash "$ROOT/bin/pr-label" "$@" ;;
|
|
63
131
|
run-rerun) exec bash "$ROOT/bin/run-rerun" "$@" ;;
|
|
64
132
|
run-list) exec bash "$ROOT/bin/run-list" "$@" ;;
|
|
@@ -69,15 +137,20 @@ case "$commande" in
|
|
|
69
137
|
app) exec bash "$ROOT/bin/app" "$@" ;;
|
|
70
138
|
bots) exec bash "$ROOT/bin/bots" "$@" ;;
|
|
71
139
|
bot) exec bash "$ROOT/bin/bot" "$@" ;;
|
|
140
|
+
agents) exec bash "$ROOT/bin/agents" "$@" ;;
|
|
141
|
+
garde | guard) exec bash "$ROOT/bin/garde" "$@" ;;
|
|
72
142
|
-v | --version | version)
|
|
73
143
|
repowarden_version_r "$ROOT"
|
|
74
144
|
echo "$REPLY"
|
|
75
145
|
;;
|
|
76
146
|
"" | statut | status) exec bash "$ROOT/bin/statut" "$@" ;;
|
|
77
|
-
-h | --help | help)
|
|
147
|
+
-h | --help | help)
|
|
148
|
+
_tr help.main
|
|
149
|
+
printf '%b\n' "$_T"
|
|
150
|
+
;;
|
|
78
151
|
*)
|
|
79
|
-
err_t install.unknown_arg "$
|
|
80
|
-
aide
|
|
152
|
+
err_t install.unknown_arg "$cmd"
|
|
153
|
+
aide
|
|
81
154
|
exit 1
|
|
82
155
|
;;
|
|
83
156
|
esac
|
package/bin/run-list
CHANGED
|
@@ -10,19 +10,8 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Liste les runs de workflows récents.
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
--workflow <nom> Filtre par nom de workflow
|
|
20
|
-
--limit N Nombre max de runs (défaut: 20)
|
|
21
|
-
|
|
22
|
-
Exemples:
|
|
23
|
-
repowarden run list
|
|
24
|
-
repowarden run list --workflow "CI" --limit 10
|
|
25
|
-
EOF
|
|
13
|
+
_tr help.run
|
|
14
|
+
printf '%b\n' "$_T"
|
|
26
15
|
}
|
|
27
16
|
|
|
28
17
|
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
package/bin/run-rerun
CHANGED
|
@@ -10,21 +10,8 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Relance un workflow GitHub Actions.
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
<run-id> ID du run à relancer
|
|
20
|
-
--failed Relance le dernier run échoué du repo
|
|
21
|
-
--workflow <nom> Relance le dernier run du workflow spécifié
|
|
22
|
-
|
|
23
|
-
Exemples:
|
|
24
|
-
repowarden run rerun 123456789
|
|
25
|
-
repowarden run rerun --failed
|
|
26
|
-
repowarden run rerun --workflow "CI"
|
|
27
|
-
EOF
|
|
13
|
+
_tr help.run
|
|
14
|
+
printf '%b\n' "$_T"
|
|
28
15
|
}
|
|
29
16
|
|
|
30
17
|
[ $# -ge 1 ] || { aide >&2; exit 1; }
|
package/bin/statut
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# Usage : repowarden statut (ou repowarden, sans argument)
|
|
3
|
+
#
|
|
2
4
|
# État de repowarden sur ce poste et dans le dépôt courant, puis la commande
|
|
3
|
-
# suivante à lancer (l'équivalent de « gh auth status » ou « brew doctor »)
|
|
4
|
-
# repowarden statut (ou repowarden, sans argument)
|
|
5
|
+
# suivante à lancer (l'équivalent de « gh auth status » ou « brew doctor »).
|
|
5
6
|
# Lecture seule : rien n'est modifié.
|
|
6
7
|
set -euo pipefail
|
|
7
8
|
|
package/bin/ticket
CHANGED
|
@@ -18,16 +18,36 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
18
18
|
# shellcheck source=../hooks/lib/tickets.sh
|
|
19
19
|
source "$ROOT/hooks/lib/tickets.sh"
|
|
20
20
|
|
|
21
|
-
aide() {
|
|
21
|
+
aide() { _tr help.ticket; printf '%b\n' "$_T" >&2; }
|
|
22
22
|
|
|
23
23
|
[ -n "$GIT_TOPLEVEL" ] || { err_t install.not_repo; exit 1; }
|
|
24
24
|
cd "$GIT_TOPLEVEL"
|
|
25
25
|
|
|
26
|
+
# Vrai si remote.origin.fetch couvre déjà la branche $1 : ligne exacte, ou
|
|
27
|
+
# refspec générale d'un clone normal. Évite d'empiler la même ligne à chaque
|
|
28
|
+
# appel (la config de l'utilisateur est laissée intacte quand elle suffit).
|
|
29
|
+
refspec_covers() {
|
|
30
|
+
local ligne
|
|
31
|
+
while IFS= read -r ligne; do
|
|
32
|
+
case "$ligne" in
|
|
33
|
+
"+refs/heads/$1:refs/remotes/origin/$1" | "+refs/heads/*:refs/remotes/origin/*") return 0 ;;
|
|
34
|
+
esac
|
|
35
|
+
done < <(git config --get-all remote.origin.fetch)
|
|
36
|
+
return 1
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
# Se place sur la branche $1 (locale, ou suivie depuis origin)
|
|
27
40
|
switch_to() {
|
|
28
41
|
if git show-ref -q --verify "refs/heads/$1"; then
|
|
29
42
|
git switch -q "$1"
|
|
30
43
|
else
|
|
44
|
+
# Clone mono-branche : la ref du ticket existe sans être suivie, et
|
|
45
|
+
# « switch --track » la refuse (« … is not a branch ») tant que la
|
|
46
|
+
# refspec ne la couvre pas. On la couvre une seule fois, puis on suit.
|
|
47
|
+
if ! refspec_covers "$1"; then
|
|
48
|
+
git config --add remote.origin.fetch "+refs/heads/$1:refs/remotes/origin/$1"
|
|
49
|
+
fi
|
|
50
|
+
git fetch -q origin
|
|
31
51
|
git switch -q --track -c "$1" "origin/$1"
|
|
32
52
|
fi
|
|
33
53
|
}
|
|
@@ -37,7 +57,7 @@ prendre() { gh issue edit "$1" --add-assignee @me >/dev/null 2>&1 || true; }
|
|
|
37
57
|
|
|
38
58
|
cmd_ticket() {
|
|
39
59
|
local n="$1" json etat titre etiquettes base
|
|
40
|
-
|
|
60
|
+
gh_ready || exit 1
|
|
41
61
|
step_t tk.cli.fetch "$n"
|
|
42
62
|
git fetch -q origin --prune
|
|
43
63
|
ticket_remote_branch_r "$n"
|
|
@@ -83,7 +103,7 @@ cmd_nouveau() {
|
|
|
83
103
|
shift
|
|
84
104
|
done
|
|
85
105
|
[ -n "$titre" ] || { err_t tk.cli.title_required; exit 1; }
|
|
86
|
-
|
|
106
|
+
gh_ready || exit 1
|
|
87
107
|
if tickets_managed; then
|
|
88
108
|
etiquettes+=(--label "$S_AVALIDER")
|
|
89
109
|
[ -z "$type" ] || etiquettes+=(--label "type: $type")
|
|
@@ -119,7 +139,9 @@ case "${1:-}" in
|
|
|
119
139
|
if [ -n "$REPLY" ]; then
|
|
120
140
|
info_t tk.cli.current "$branche" "$REPLY"
|
|
121
141
|
else
|
|
122
|
-
|
|
142
|
+
err_t tk.cli.no_ticket_here
|
|
143
|
+
aide >&2
|
|
144
|
+
exit 1
|
|
123
145
|
fi
|
|
124
146
|
;;
|
|
125
147
|
*)
|
package/bin/ticket-comment
CHANGED
|
@@ -10,19 +10,16 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Ajoute un commentaire sur le ticket #<n>.
|
|
17
|
-
|
|
18
|
-
Exemples:
|
|
19
|
-
repowarden ticket comment 123 "Conception retenue : ..."
|
|
20
|
-
repowarden ticket comment 456 "PR prête pour review"
|
|
21
|
-
EOF
|
|
13
|
+
_tr help.ticket
|
|
14
|
+
printf '%b\n' "$_T"
|
|
22
15
|
}
|
|
23
16
|
|
|
17
|
+
case "${1:-}" in
|
|
18
|
+
-h | --help) aide; exit 0 ;;
|
|
19
|
+
esac
|
|
20
|
+
|
|
24
21
|
[ $# -ge 2 ] || { aide >&2; exit 1; }
|
|
25
|
-
|
|
22
|
+
gh_ready || exit 1
|
|
26
23
|
|
|
27
24
|
n="${1}"
|
|
28
25
|
texte="${2}"
|
package/bin/ticket-label
CHANGED
|
@@ -10,23 +10,16 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Ajoute ou retire un label sur le ticket #<n>.
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
--remove Retire le label au lieu de l'ajouter
|
|
20
|
-
|
|
21
|
-
Exemples:
|
|
22
|
-
repowarden ticket label 123 "validé"
|
|
23
|
-
repowarden ticket label 123 "statut: backlog"
|
|
24
|
-
repowarden ticket label 123 "wip" --remove
|
|
25
|
-
EOF
|
|
13
|
+
_tr help.ticket
|
|
14
|
+
printf '%b\n' "$_T"
|
|
26
15
|
}
|
|
27
16
|
|
|
17
|
+
case "${1:-}" in
|
|
18
|
+
-h | --help) aide; exit 0 ;;
|
|
19
|
+
esac
|
|
20
|
+
|
|
28
21
|
[ $# -ge 2 ] || { aide >&2; exit 1; }
|
|
29
|
-
|
|
22
|
+
gh_ready || exit 1
|
|
30
23
|
|
|
31
24
|
n="${1}"
|
|
32
25
|
label="${2}"
|
package/bin/tickets
CHANGED
|
@@ -34,7 +34,7 @@ done
|
|
|
34
34
|
if [ "$commande" = sync ]; then
|
|
35
35
|
# shellcheck source=../hooks/lib/tickets.sh
|
|
36
36
|
source "$ROOT/hooks/lib/tickets.sh"
|
|
37
|
-
|
|
37
|
+
gh_ready || exit 1
|
|
38
38
|
[ -n "$GIT_TOPLEVEL" ] || { err_t install.not_repo; exit 1; }
|
|
39
39
|
cd "$GIT_TOPLEVEL"
|
|
40
40
|
tickets_sync force
|
|
@@ -42,12 +42,11 @@ if [ "$commande" = sync ]; then
|
|
|
42
42
|
exit 0
|
|
43
43
|
fi
|
|
44
44
|
if [ "$commande" != init ]; then
|
|
45
|
-
|
|
46
|
-
[ "$commande" = "" ] || [ "$commande" = -h ] || [ "$commande" = --help ]
|
|
45
|
+
_tr help.tickets; printf '%b\n' "$_T"
|
|
47
46
|
exit
|
|
48
47
|
fi
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
gh_ready || exit 1
|
|
51
50
|
[ -n "$GIT_TOPLEVEL" ] || { err_t install.not_repo; exit 1; }
|
|
52
51
|
cd "$GIT_TOPLEVEL"
|
|
53
52
|
[ -n "$REPO" ] || REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Garde-fou repowarden pour opencode (écrit par repowarden agents init) :
|
|
2
|
+
// chaque outil est soumis à « repowarden garde » avant de s'exécuter. Refus
|
|
3
|
+
// (code 2) → erreur rendue à l'agent, avec la commande à lancer. repowarden
|
|
4
|
+
// absent ou en panne : rien n'est bloqué.
|
|
5
|
+
// Plugins opencode : https://opencode.ai/docs/plugins/ (tool.execute.before)
|
|
6
|
+
import { spawnSync } from "node:child_process"
|
|
7
|
+
|
|
8
|
+
export const RepowardenGarde = async ({ directory }) => ({
|
|
9
|
+
"tool.execute.before": async (input, output) => {
|
|
10
|
+
const r = spawnSync("repowarden", ["garde"], {
|
|
11
|
+
input: JSON.stringify({ tool: input.tool, args: output.args, cwd: directory }),
|
|
12
|
+
encoding: "utf8",
|
|
13
|
+
})
|
|
14
|
+
if (r.status === 2) throw new Error((r.stderr || "").trim())
|
|
15
|
+
},
|
|
16
|
+
})
|
package/hooks/lang/node.sh
CHANGED
|
@@ -44,15 +44,17 @@ node_test() {
|
|
|
44
44
|
# inaccessible : prouvé) ; knip s'il est installé dans le projet (fichiers,
|
|
45
45
|
# exports, dépendances non référencés : candidats)
|
|
46
46
|
node_deadcode() {
|
|
47
|
-
local ran=""
|
|
47
|
+
local ran="" a_tsc=0 a_knip=0
|
|
48
48
|
if [ -f tsconfig.json ] && [ -x node_modules/.bin/tsc ]; then
|
|
49
49
|
ran=1
|
|
50
|
+
a_tsc=1
|
|
50
51
|
node_modules/.bin/tsc --noEmit -p . --noUnusedLocals --noUnusedParameters \
|
|
51
52
|
--allowUnreachableCode false --pretty false 2>/dev/null |
|
|
52
53
|
sed -nE 's/^(.+)\(([0-9]+),[0-9]+\): error (TS6133|TS6138|TS6192|TS6196|TS6198|TS7027): (.*)$/prouve\t\1\t\2\t\4/p'
|
|
53
54
|
fi
|
|
54
55
|
if [ -x node_modules/.bin/knip ] && has node; then
|
|
55
56
|
ran=1
|
|
57
|
+
a_knip=1
|
|
56
58
|
_tr dc.knip_file
|
|
57
59
|
local m_file="$_T"
|
|
58
60
|
_tr dc.knip_export
|
|
@@ -71,5 +73,15 @@ node_deadcode() {
|
|
|
71
73
|
for (const d of i[k] || []) out(i.file, 0, process.env.M_DEP + " " + d.name);
|
|
72
74
|
}'
|
|
73
75
|
fi
|
|
74
|
-
[ -
|
|
76
|
+
if [ -z "$ran" ]; then
|
|
77
|
+
deadcode_tool_missing "JavaScript / TypeScript" "typescript / knip"
|
|
78
|
+
elif [ "$a_tsc" = 0 ]; then
|
|
79
|
+
# knip seul : les variables, paramètres et imports inutilisés restent à analyser
|
|
80
|
+
_tr dc.scope.locals
|
|
81
|
+
deadcode_partial "JavaScript / TypeScript" typescript "$_T" "npm i -D typescript"
|
|
82
|
+
elif [ "$a_knip" = 0 ]; then
|
|
83
|
+
# tsc seul : les fichiers, exports et dépendances non référencés restent à analyser
|
|
84
|
+
_tr dc.scope.files
|
|
85
|
+
deadcode_partial "JavaScript / TypeScript" knip "$_T" "npm i -D knip"
|
|
86
|
+
fi
|
|
75
87
|
}
|
package/hooks/lang/python.sh
CHANGED
|
@@ -63,17 +63,29 @@ python_test() {
|
|
|
63
63
|
# vulture (confiance 100 % : prouvé, en dessous : candidat — les frameworks
|
|
64
64
|
# appellent des fonctions par leur nom)
|
|
65
65
|
python_deadcode() {
|
|
66
|
-
local ran=""
|
|
66
|
+
local ran="" a_ruff=0 a_vulture=0
|
|
67
67
|
if python_has ruff; then
|
|
68
68
|
ran=1
|
|
69
|
+
a_ruff=1
|
|
69
70
|
python_run ruff check --select F401,F811,F841 --output-format concise --quiet --exit-zero . 2>/dev/null |
|
|
70
71
|
sed -nE 's/^(.+):([0-9]+):[0-9]+: F[0-9]+ (\[\*\] )?(.*)$/prouve\t\1\t\2\t\4/p'
|
|
71
72
|
fi
|
|
72
73
|
if python_has vulture; then
|
|
73
74
|
ran=1
|
|
75
|
+
a_vulture=1
|
|
74
76
|
python_run vulture . --min-confidence 60 --exclude ".venv,venv,node_modules,build,dist,site-packages" 2>/dev/null |
|
|
75
77
|
sed -nE -e 's/^(.+):([0-9]+): (.*) \(100% confidence\)$/prouve\t\1\t\2\t\3/p' \
|
|
76
78
|
-e 's/^(.+):([0-9]+): (.*) \(([0-9]+)% confidence\)$/candidat\t\1\t\2\t\3 (\4 %)/p'
|
|
77
79
|
fi
|
|
78
|
-
[ -
|
|
80
|
+
if [ -z "$ran" ]; then
|
|
81
|
+
deadcode_tool_missing Python "ruff / vulture"
|
|
82
|
+
elif [ "$a_ruff" = 0 ]; then
|
|
83
|
+
# vulture seul : les imports et variables inutilisés restent à analyser
|
|
84
|
+
_tr dc.scope.imports
|
|
85
|
+
deadcode_partial Python ruff "$_T" "pip install ruff"
|
|
86
|
+
elif [ "$a_vulture" = 0 ]; then
|
|
87
|
+
# ruff seul : les fonctions et classes inutilisées restent à analyser
|
|
88
|
+
_tr dc.scope.functions
|
|
89
|
+
deadcode_partial Python vulture "$_T" "pip install vulture"
|
|
90
|
+
fi
|
|
79
91
|
}
|
package/hooks/lib/common.sh
CHANGED
|
@@ -370,7 +370,9 @@ check_version() {
|
|
|
370
370
|
root="${HOOKS_DIR%/hooks}"
|
|
371
371
|
repowarden_version_r "$root"
|
|
372
372
|
installed="$REPLY"
|
|
373
|
-
|
|
373
|
+
# 0.0.0-dev : version inconnue (clone sans tags, git clone --depth) ;
|
|
374
|
+
# aucune comparaison possible, pas de fausse alerte à chaque commit
|
|
375
|
+
[ -n "$installed" ] && [ "$installed" != 0.0.0-dev ] || return 0
|
|
374
376
|
local IFS=.
|
|
375
377
|
# shellcheck disable=SC2206 # découpage voulu sur les points
|
|
376
378
|
w=($wanted) i=($installed)
|
package/hooks/lib/deadcode.sh
CHANGED
|
@@ -17,11 +17,23 @@
|
|
|
17
17
|
# Code mort introduit depuis $1 (base) dans les fichiers lus sur stdin.
|
|
18
18
|
# Retour : 1 si un élément bloque selon le réglage deadcode.
|
|
19
19
|
deadcode_projects() {
|
|
20
|
-
local base="$1" changed added found dir p plugins niveau f l msg path proven=0 cand=0 mode ignore pat code var
|
|
21
|
-
local ran="" file
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
local base="$1" changed added found partial dir p plugins niveau f l msg path proven=0 cand=0 mode ignore pat code var
|
|
21
|
+
local ran="" file tmp partiel=0
|
|
22
|
+
# Un dossier temporaire unique : les fichiers de l'analyse, dont le
|
|
23
|
+
# fichier témoin de l'analyse partielle (voir deadcode_partial). Créés
|
|
24
|
+
# vides tout de suite : sans plugin ni fichier non suivi, rien ne les
|
|
25
|
+
# ouvrirait en écriture, et leur lecture (« done < found ») échouerait.
|
|
26
|
+
tmp="$(mktemp -d)"
|
|
27
|
+
changed="$tmp/changed"
|
|
28
|
+
added="$tmp/added"
|
|
29
|
+
found="$tmp/found"
|
|
30
|
+
partial="$tmp/partial"
|
|
31
|
+
: >"$changed"
|
|
32
|
+
: >"$added"
|
|
33
|
+
: >"$found"
|
|
34
|
+
: >"$partial"
|
|
35
|
+
DEADCODE_PARTIAL_FILE="$partial"
|
|
36
|
+
export DEADCODE_PARTIAL_FILE
|
|
25
37
|
cat >"$changed"
|
|
26
38
|
|
|
27
39
|
# Lignes ajoutées ou modifiées (fichier:ligne), du commit de base à
|
|
@@ -109,14 +121,18 @@ deadcode_projects() {
|
|
|
109
121
|
attention_t dc.candidate "$path" "$msg"
|
|
110
122
|
fi
|
|
111
123
|
done <"$found"
|
|
112
|
-
|
|
124
|
+
# Une analyse partielle (outil absent) interdit tout feu vert sans réserve
|
|
125
|
+
[ ! -s "$partial" ] || partiel=1
|
|
126
|
+
rm -rf "$tmp"
|
|
113
127
|
|
|
114
128
|
if [ -z "$ran" ]; then
|
|
115
129
|
info_t dc.nothing
|
|
116
130
|
return 0
|
|
117
131
|
fi
|
|
118
132
|
if [ "$proven" = 0 ] && [ "$cand" = 0 ]; then
|
|
119
|
-
|
|
133
|
+
if [ "$partiel" = 1 ]; then attention_t dc.none_partial
|
|
134
|
+
else ok_t dc.none
|
|
135
|
+
fi
|
|
120
136
|
return 0
|
|
121
137
|
fi
|
|
122
138
|
[ "$cand" = 0 ] || info_t dc.summary_candidates "$cand"
|
|
@@ -137,8 +153,29 @@ deadcode_projects() {
|
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
# Outil d'analyse absent : signalé, sans faire échouer le mode strict
|
|
140
|
-
# (la détection de code mort reste une aide, pas un prérequis du projet)
|
|
141
|
-
|
|
156
|
+
# (la détection de code mort reste une aide, pas un prérequis du projet).
|
|
157
|
+
# Un outil totalement absent compte comme une analyse partielle.
|
|
158
|
+
deadcode_tool_missing() {
|
|
159
|
+
attention_t dc.tool_missing "$1" "$2"
|
|
160
|
+
deadcode_partial_note "$1"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# Analyse partielle : $1 langage, $2 outil absent, $3 ce qui n'est pas analysé
|
|
164
|
+
# (déjà traduit, clé dc.scope.*), $4 installation à donner.
|
|
165
|
+
# Un des outils du langage manque : ce qu'il couvre n'est pas analysé, et la
|
|
166
|
+
# fin de l'analyse ne dira pas que tout va bien (voir deadcode_projects).
|
|
167
|
+
deadcode_partial() {
|
|
168
|
+
attention_t dc.partial "$1" "$2" "$3" "$4"
|
|
169
|
+
deadcode_partial_note "$1"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# Note l'analyse partielle : les plugins tournent dans un sous-shell de tube
|
|
173
|
+
# ({ … } |), une variable ne reviendrait pas — le signal passe par un fichier
|
|
174
|
+
# témoin sous le dossier temporaire de l'analyse
|
|
175
|
+
deadcode_partial_note() {
|
|
176
|
+
[ -n "${DEADCODE_PARTIAL_FILE:-}" ] || return 0
|
|
177
|
+
printf '%s\n' "$1" >>"$DEADCODE_PARTIAL_FILE"
|
|
178
|
+
}
|
|
142
179
|
|
|
143
180
|
# Java (Maven, Gradle) : règles PMD dont le résultat est prouvé — import,
|
|
144
181
|
# champ, méthode ou variable privés jamais utilisés dans leur portée
|
package/hooks/lib/forge.sh
CHANGED
|
@@ -45,3 +45,24 @@ github_sans_rulesets() {
|
|
|
45
45
|
local reponse
|
|
46
46
|
! reponse="$(gh api "repos/$1/rulesets" 2>&1)" && [[ "$reponse" == *"403"* ]]
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
# gh présent (rien n'est affiché)
|
|
50
|
+
gh_present() { command -v gh >/dev/null 2>&1; }
|
|
51
|
+
|
|
52
|
+
# gh présent et connecté : gh auth status réussi
|
|
53
|
+
gh_connected() { gh_present && gh auth status >/dev/null 2>&1; }
|
|
54
|
+
|
|
55
|
+
# Contrôle partagé des commandes qui parlent à GitHub (bin/ticket, bin/tickets,
|
|
56
|
+
# bin/app) : gh installé ET connecté, sinon le message du problème et un échec.
|
|
57
|
+
# Sans gh : bot.no_gh ; sans connexion : gh.not_logged (la commande de
|
|
58
|
+
# connexion, le scope workflow étant requis pour pousser .github/workflows/).
|
|
59
|
+
gh_ready() {
|
|
60
|
+
if ! gh_present; then
|
|
61
|
+
err_t bot.no_gh
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
if ! gh_connected; then
|
|
65
|
+
err_t gh.not_logged
|
|
66
|
+
return 1
|
|
67
|
+
fi
|
|
68
|
+
}
|
package/hooks/lib/i18n/en.sh
CHANGED
|
@@ -63,6 +63,7 @@ _msg_en() {
|
|
|
63
63
|
tk.cli.issue_created_branch) _M="Ticket #%s created." ;;
|
|
64
64
|
tk.cli.title_required) _M="Ticket title required: repowarden ticket nouveau \"<title>\"" ;;
|
|
65
65
|
tk.cli.current) _M="Branch %s: ticket #%s." ;;
|
|
66
|
+
tk.cli.no_ticket_here) _M="No ticket for this branch." ;;
|
|
66
67
|
cc.ticket_offer) _M="No ticket for this branch. Create one now (title: the description)? [y/N]: " ;;
|
|
67
68
|
cc.ticket_created) _M="Ticket #%s created and referenced in the message." ;;
|
|
68
69
|
cc.preview) _M="Message" ;;
|
|
@@ -106,6 +107,25 @@ _msg_en() {
|
|
|
106
107
|
install.keys_migrated) _M="repogarde.* settings (%s) renamed to repowarden.*" ;;
|
|
107
108
|
help.alias.feat) _M="(branch: feature/ accepted)" ;;
|
|
108
109
|
help.alias.fix) _M="(branch: bugfix/, hotfix/ accepted)" ;;
|
|
110
|
+
# Help texts for commands (--help): single source shown by bin/repowarden
|
|
111
|
+
help.main) _M="Usage: repowarden <command> [options] · detailed help: repowarden <command> --help\n\n repowarden post status and next step\n repowarden statut (same)\n repowarden install [--global] [--lang fr|en] activate hooks (install.sh)\n repowarden uninstall [--global] [--purge] remove them (before npm uninstall -g)\n repowarden bots GitHub repo bots (CI, releases, tickets…)\n repowarden cc commit assistant\n repowarden code-mort new dead code in branch\n repowarden ticket ticket of the current branch\n repowarden ticket <n> branch of ticket (created, linked if needed)\n repowarden ticket nouveau \"<title>\" new ticket\n repowarden ticket comment <n> \"<text>\" add a comment\n repowarden ticket label <n> <label> [--remove] manage ticket labels\n repowarden pr label <n> <label> [--remove] manage PR labels\n repowarden pr checks <n> show PR checks\n repowarden run rerun <id|--failed|--workflow> rerun a workflow\n repowarden run list [--workflow <name>] list recent runs\n repowarden tickets init set up ticket tracking (GitHub)\n repowarden tickets sync my assigned tickets → local branches\n repowarden proteger [options] protect GitHub branches\n repowarden migrer [--pr] [--hooks] migrate from repogarde to repowarden\n repowarden npm-publication automate npm publication\n repowarden app init GitHub App for workflows (once)\n repowarden bot [init|rapport] org bot (pilot repo)\n repowarden agents init [--claude] [--opencode] AI agent guard (Claude Code, opencode)\n repowarden garde checks an agent action (called by its hook)\n repowarden --version installed version" ;;
|
|
112
|
+
help.statut) _M="Usage: repowarden statut (or repowarden, no args)\n\nRead-only status of repowarden on this machine and in the current repo,\nplus the next command to run (like \"gh auth status\" or \"brew doctor\")." ;;
|
|
113
|
+
help.install) _M="Usage: repowarden install [--global] [--lang fr|en] [--bots | --sans-bots]\n\nActivate repowarden hooks (install.sh).\n --global all repos (and commit assistant: git cc)\n --lang fr|en message language (asked once if unset)\n --bots then propose repo bots (repowarden bots)\n --sans-bots never propose bots" ;;
|
|
114
|
+
help.uninstall) _M="Usage: repowarden uninstall [--global] [--purge] [--scan FOLDER]\n\nRemove repowarden hooks (only if owned). Do before npm uninstall -g.\n --global also remove global installation\n --purge remove caches and list repos still pointing to repowarden\n --scan FOLDER check repos in FOLDER still using repowarden (with --purge)" ;;
|
|
115
|
+
help.bots) _M="Usage: repowarden bots\n\nSet up GitHub repo bots (CI, releases, cleanup, tickets, App, protection,\nnpm): one global question, per-bot confirmation, preview, final confirmation.\nNothing done without consent. Can be rerun. Also via install --bots.\nNeeds a terminal, gh logged in and admin rights on the repo." ;;
|
|
116
|
+
help.bot) _M="Usage: repowarden bot [--repo o/r]… [--dry-run] [--rapport FILE]\n repowarden bot rapport FILE\n repowarden bot init\n\nOrg bot: nightly (and on demand) updates adopted projects (protection,\nmigration), publishes a report to the \"Rapport du bot repowarden\" issue.\n--dry-run shows without changes. init writes .github/workflows/bot.yml.\nUses installation token of the bot App (repowarden app init --bot)." ;;
|
|
117
|
+
help.cc) _M="Usage: repowarden cc [git commit options] (alias: git cc)\n repowarden cc -m \"description\" [--type T] [--scope S] [--breaking NOTE] [--body TEXT] [--refs \"Ticket: #12\"]\n repowarden cc --dry-run\n\nConventional commit assistant: guides header, body and footer, runs hooks.\nBatch mode (-m etc.): same checks, type/scope inferred from branch if omitted.\n --strict any refused answer stops (nothing committed)\n --dry-run show message without committing" ;;
|
|
118
|
+
help.code-mort) _M="Usage: repowarden code-mort [base]\n\nDead code introduced by your branch (like CI): only added/changed lines\nsince base (commits, staged/uncommitted, new files). Default: merge-base\nwith origin/main. See docs/code-mort.md (proven vs candidates)." ;;
|
|
119
|
+
help.ticket) _M="Usage: repowarden ticket <n> branch for ticket (created, linked if needed)\n repowarden ticket ticket of current branch\n repowarden ticket nouveau \"<title>\" [--type fix] [--description \"…\"]\n repowarden ticket comment <n> \"<text>\" add comment\n repowarden ticket label <n> <label> [--remove] manage labels\n\nTicket first: taking <n> assigns to you and switches to its branch\n(created from develop if needed). \"nouveau\" creates a ticket (\"à valider\"\nif tracking is managed). Needs gh connected (https://cli.github.com)." ;;
|
|
120
|
+
help.tickets) _M="Usage: repowarden tickets init [--repo owner/name] [--sans-validation-auto]\n repowarden tickets sync\n\nSets up ticket tracking: labels, issue template, workflow; classifies\nexisting tickets; records PR branches. sync checks out local branches for\ntickets assigned to you (auto with ticketSync=auto, manual by default)." ;;
|
|
121
|
+
help.pr) _M="Usage: repowarden pr label <n> <label> [--remove]\n repowarden pr checks <n>\n\nlabel adds or removes a label from PR #<n>; checks shows its checks\n(name, conclusion, status, link).\nExamples:\n repowarden pr label 123 \"ready-for-review\"\n repowarden pr label 123 \"needs-changes\" --remove\n repowarden pr checks 123" ;;
|
|
122
|
+
help.run) _M="Usage: repowarden run rerun <run-id|--failed|--workflow <name>>\n repowarden run list [--workflow <name>] [--limit N]\n\nrerun restarts a GitHub Actions workflow. list shows recent runs\n(default limit 20).\nExamples:\n repowarden run rerun --failed\n repowarden run list --workflow \"CI\" --limit 10" ;;
|
|
123
|
+
help.proteger) _M="Usage: repowarden proteger [--repo owner/name] [--checks \"repowarden,tests (ubuntu-latest)\"]\n [--relecteurs N] [--codeowners] [--environnement NAME] [--approbateurs \"login …\"]\n [--sans-tags] [--dry-run] [--verifier]\n\nProtects GitHub repo per .repowarden.conf: required PR, required checks,\nno force push/deletion, ruleset, squash merges, v* tags reserved to\nworkflows, optional human approvals. --verifier checks online rules\nwithout changes. Needs gh and admin rights." ;;
|
|
124
|
+
help.migrer) _M="Usage: repowarden migrer [--pr] [--hooks]\n\nMigrates from repogarde to repowarden (docs/migration-v4.md): configs,\nworkflows, renames, lists manual steps left. Safe to rerun.\n --pr on chore/migration-repowarden-vN: commit, push and PR\n --hooks also move leftover lefthook hooks to .git/hooks-lefthook/" ;;
|
|
125
|
+
help.npm-publication) _M="Usage: repowarden npm-publication [--repo owner/name] [--workflow release.yml]\n [--environnement NAME] [--dry-run]\n\nSets up automatic npm publishing per release via OIDC (trusted publishing,\nprovenance). Needs npm logged in, package exists; if interrupted resumes.\nWorkflow: release.yml publishes via npm-publish.yml." ;;
|
|
126
|
+
help.garde) _M="Usage: repowarden garde [--format claude|opencode] (reads the action on standard input)\n\nAI agent guard, called by the agent's hook before each action (repowarden\nagents init wires it): exit code 0 allowed, 2 refused with the command to\nrun. In a repowarden repository: no change on a detached HEAD, on a\nprotected branch, or outside a ticket branch when the repository tracks its\ntickets; branches created by repowarden ticket <n>, commits by repowarden\ncc; no --no-verify, no git add . / -A / --all. Requires jq." ;;
|
|
127
|
+
help.agents) _M="Usage: repowarden agents init [--claude] [--opencode] [--projet | --global]\n\nWires the guard (repowarden garde) into AI agents: Claude Code PreToolUse\nhook (.claude/settings.json), opencode plugin\n(.opencode/plugins/repowarden-garde.js). Without --claude or --opencode:\nboth. --projet (default): repository files, to commit; --global: user\nconfiguration. Re-runnable: existing files are completed, never\noverwritten." ;;
|
|
128
|
+
help.app) _M="Usage: repowarden app init [--repo owner/name] [--nom NAME] [--administration]\n repowarden app init --bot\n\nCreates/sets up a GitHub App for repowarden workflows (Actions token doesn't\ntrigger other workflows; App token does). Browser-based manifest, minimal\npermissions, credentials stored securely, installed on repo. --bot for org\nbot (pilot repo). Needs gh and node. Rerunnable." ;;
|
|
109
129
|
# Hooks and language plugins
|
|
110
130
|
hook.pre_commit.1) _M="Commit refused: branch name does not follow the convention." ;;
|
|
111
131
|
hook.pre_commit.2) _M="Direct commit on '%s' forbidden. Create a branch: git switch -c feat/my-feature" ;;
|
|
@@ -127,6 +147,7 @@ _msg_en() {
|
|
|
127
147
|
hook.pre_push.5) _M="%s: no changed file, nothing to test." ;;
|
|
128
148
|
hook.pre_push.6) _M="Nothing to test (branch deletion only)." ;;
|
|
129
149
|
hook.pre_push.7) _M="Pre-push OK" ;;
|
|
150
|
+
hook.pre_push.workflow_scope) _M="gh token without the 'workflow' scope: GitHub will refuse a push touching .github/workflows/. Allow it (then sign in again): gh auth refresh -h github.com -s workflow" ;;
|
|
130
151
|
hook.pre_push.lint.missing) _M="%s not installed, %s not checked (install: %s)." ;;
|
|
131
152
|
hook.pre_push.lint.run) _M="%s: %s" ;;
|
|
132
153
|
hook.branch_hint.1) _M="Branch name \"%s\" does not follow the convention: commits and pushes will be refused. Rename:" ;;
|
|
@@ -310,6 +331,7 @@ _msg_en() {
|
|
|
310
331
|
ci.proteger.tags_none) _M="not protected (--sans-tags)" ;;
|
|
311
332
|
ci.proteger.unknown_team) _M="Unknown or inaccessible team: %s (format @organisation/team)" ;;
|
|
312
333
|
ci.proteger.unknown_user) _M="Unknown user: %s" ;;
|
|
334
|
+
mig.unknown_version) _M="repowarden version unknown (clone without tags): git -C %s fetch --tags, or REPOWARDEN_MAJEURE=4 repowarden migrer." ;;
|
|
313
335
|
mig.no_major) _M="repowarden major version not found (%s): REPOWARDEN_MAJEURE=4 repowarden migrer." ;;
|
|
314
336
|
mig.dirty) _M="Uncommitted changes: commit or stash before repowarden migrer --pr." ;;
|
|
315
337
|
mig.pr_open) _M="Migration PR already open (%s): nothing to do." ;;
|
|
@@ -376,6 +398,12 @@ _msg_en() {
|
|
|
376
398
|
dc.candidate) _M="%s: %s (candidate: check for dynamic usage)" ;;
|
|
377
399
|
dc.nothing) _M="No file in an analysable language among the changes: nothing to check." ;;
|
|
378
400
|
dc.none) _M="No new dead code." ;;
|
|
401
|
+
dc.none_partial) _M="No new dead code in what was analysed: partial analysis, see above." ;;
|
|
402
|
+
dc.partial) _M="%s: %s not installed: %s (%s)." ;;
|
|
403
|
+
dc.scope.functions) _M="unused functions and classes not analysed" ;;
|
|
404
|
+
dc.scope.imports) _M="unused imports and variables not analysed" ;;
|
|
405
|
+
dc.scope.locals) _M="unused variables, parameters and imports not analysed" ;;
|
|
406
|
+
dc.scope.files) _M="unreferenced files, exports and dependencies not analysed" ;;
|
|
379
407
|
dc.summary_candidates) _M="%s candidate(s) to check: not blocking (reflection, framework or public API calls are possible)." ;;
|
|
380
408
|
dc.summary_proven) _M="%s proven dead code item(s): remove them, or ignore them (deadcodeIgnore)." ;;
|
|
381
409
|
dc.summary_strict) _M="%s dead code item(s) (deadcode = strict mode)." ;;
|
|
@@ -397,6 +425,7 @@ _msg_en() {
|
|
|
397
425
|
ci.notify.failure) _M="❌ %s: release workflow failed: %s" ;;
|
|
398
426
|
# GitHub CLI
|
|
399
427
|
bot.no_gh) _M="GitHub CLI (gh) required: https://cli.github.com" ;;
|
|
428
|
+
gh.not_logged) _M="gh not logged in: gh auth login -s workflow" ;;
|
|
400
429
|
# npm package
|
|
401
430
|
npm.npx_global) _M="npx uses a temporary folder: global hooks would point to a deleted folder. Install the package first: npm install -g repowarden, then repowarden install --global." ;;
|
|
402
431
|
npm.no_npm) _M="npm required: https://nodejs.org" ;;
|
|
@@ -641,6 +670,25 @@ _msg_en() {
|
|
|
641
670
|
run.listing.workflow) _M="Listing runs for workflow \"%s\"..." ;;
|
|
642
671
|
# PR checks
|
|
643
672
|
pr.checks.checking) _M="Checking checks for PR #%s..." ;;
|
|
673
|
+
# AI agent guard (repowarden garde, repowarden agents)
|
|
674
|
+
garde.format) _M="Unknown format \"%s\": claude or opencode." ;;
|
|
675
|
+
garde.no_jq) _M="repowarden garde: jq missing, action not checked (install jq: https://jqlang.org)." ;;
|
|
676
|
+
garde.json) _M="repowarden garde: unreadable JSON input, action not checked." ;;
|
|
677
|
+
garde.detache) _M="change refused: detached HEAD in %s.\n → Switch to a ticket's branch: repowarden ticket <n>" ;;
|
|
678
|
+
garde.protegee) _M="change refused: \"%s\" is a protected branch.\n → Work on a ticket's branch: repowarden ticket <n>" ;;
|
|
679
|
+
garde.protegee_libre) _M="change refused: \"%s\" is a protected branch.\n → Create a work branch: git switch -c <type>/<topic>" ;;
|
|
680
|
+
garde.hors_ticket) _M="change refused: branch \"%s\" is not a ticket's branch (<type>/<n>-<topic>).\n → Take the ticket: repowarden ticket <n>" ;;
|
|
681
|
+
garde.branche) _M="command refused: \"%s\" creates a branch; here, branches come from tickets.\n → repowarden ticket <n>" ;;
|
|
682
|
+
garde.commit) _M="command refused: \"%s\"; commits go through the assistant (only --amend --no-edit is allowed).\n → repowarden cc -m \"<description>\" --refs \"Ticket : #<n>\"" ;;
|
|
683
|
+
garde.no_verify) _M="command refused: \"%s\" bypasses the repowarden hooks.\n → Run it again without --no-verify and fix what the hooks report." ;;
|
|
684
|
+
garde.add_tout) _M="command refused: \"%s\" adds the whole repository.\n → Add files one by one: git add <files>" ;;
|
|
685
|
+
agents.added) _M="%s: guard added (%s)." ;;
|
|
686
|
+
agents.present) _M="%s: guard already in place (%s)." ;;
|
|
687
|
+
agents.kept) _M="%s: %s exists and differs from the template; kept as is (template: %s)." ;;
|
|
688
|
+
agents.bad_json) _M="%s: %s is not valid JSON; nothing was changed." ;;
|
|
689
|
+
agents.no_jq) _M="jq is required to update %s (https://jqlang.org)." ;;
|
|
690
|
+
agents.versionner) _M="To commit: git add %s" ;;
|
|
691
|
+
agents.no_repowarden) _M="The guard calls \"repowarden garde\": repowarden must be on the PATH (npm install -g repowarden)." ;;
|
|
644
692
|
*) _M="" ;;
|
|
645
693
|
esac
|
|
646
694
|
}
|