@minakoto00/skills 0.1.0

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.
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
5
+ # shellcheck source=./common.sh
6
+ source "$SCRIPT_DIR/common.sh"
7
+
8
+ input_path=
9
+
10
+ usage() {
11
+ cat <<'USAGE'
12
+ Usage: plan_review_validation_dispatch.sh [--input <path>]
13
+
14
+ Read clustered review issues and emit a bounded subagent dispatch plan.
15
+ USAGE
16
+ }
17
+
18
+ while [[ $# -gt 0 ]]; do
19
+ case "$1" in
20
+ --input)
21
+ input_path=$2
22
+ shift 2
23
+ ;;
24
+ --help|-h)
25
+ usage
26
+ exit 0
27
+ ;;
28
+ *)
29
+ die "unknown argument: $1"
30
+ ;;
31
+ esac
32
+ done
33
+
34
+ require_cmd jq
35
+
36
+ if [[ -n "$input_path" ]]; then
37
+ input_json=$(cat "$input_path")
38
+ else
39
+ input_json=$(cat)
40
+ fi
41
+
42
+ jq -cn --argjson payload "$input_json" '
43
+ def cluster_items:
44
+ $payload.issue_clusters.items // [];
45
+
46
+ def planned_subagents($cluster_count):
47
+ if $cluster_count <= 0 then 0
48
+ elif $cluster_count <= 2 then 1
49
+ elif $cluster_count <= 4 then 2
50
+ elif $cluster_count <= 6 then 3
51
+ else 4
52
+ end;
53
+
54
+ cluster_items as $clusters
55
+ | ($clusters | length) as $cluster_count
56
+ | planned_subagents($cluster_count) as $subagent_count
57
+ | {
58
+ issue_cluster_count: $cluster_count,
59
+ subagent_count: $subagent_count,
60
+ assignments: [
61
+ range(0; $subagent_count)
62
+ | . as $index
63
+ | {
64
+ subagent_id: ("validation-" + (($index + 1) | tostring)),
65
+ cluster_ids: [
66
+ range(0; $cluster_count)
67
+ | select(. % $subagent_count == $index)
68
+ | $clusters[.].cluster_id
69
+ ]
70
+ }
71
+ | .cluster_count = (.cluster_ids | length)
72
+ ]
73
+ }
74
+ '
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
5
+ # shellcheck source=./common.sh
6
+ source "$SCRIPT_DIR/common.sh"
7
+
8
+ repo=.
9
+ platform=
10
+ number=
11
+ body_file=
12
+ dry_run=false
13
+
14
+ usage() {
15
+ cat <<'USAGE'
16
+ Usage: post_review_comment.sh --repo <path> --number <id> --body-file <file> [--platform <github|gitlab>] [--dry-run]
17
+
18
+ Post a change plan and patch guidance comment to a GitHub PR or GitLab MR.
19
+ USAGE
20
+ }
21
+
22
+ while [[ $# -gt 0 ]]; do
23
+ case "$1" in
24
+ --repo)
25
+ repo=$2
26
+ shift 2
27
+ ;;
28
+ --platform)
29
+ platform=$2
30
+ shift 2
31
+ ;;
32
+ --number)
33
+ number=$2
34
+ shift 2
35
+ ;;
36
+ --body-file)
37
+ body_file=$2
38
+ shift 2
39
+ ;;
40
+ --dry-run)
41
+ dry_run=true
42
+ shift
43
+ ;;
44
+ --help|-h)
45
+ usage
46
+ exit 0
47
+ ;;
48
+ *)
49
+ die "unknown argument: $1"
50
+ ;;
51
+ esac
52
+ done
53
+
54
+ repo=$(resolve_repo_root "$repo")
55
+ [[ -n "$number" ]] || die "--number is required"
56
+ [[ -n "$body_file" ]] || die "--body-file is required"
57
+ [[ -f "$body_file" ]] || die "body file not found: $body_file"
58
+
59
+ if [[ -z "$platform" ]]; then
60
+ platform=$("$SCRIPT_DIR/detect_platform.sh" --repo "$repo")
61
+ fi
62
+
63
+ if [[ "$dry_run" == true ]]; then
64
+ print_kv platform "$platform"
65
+ print_kv repo_root "$repo"
66
+ print_kv number "$number"
67
+ print_kv body_file "$body_file"
68
+ exit 0
69
+ fi
70
+
71
+ cd "$repo"
72
+
73
+ case "$platform" in
74
+ github)
75
+ require_cmd gh
76
+ gh pr comment "$number" --body-file "$body_file"
77
+ ;;
78
+ gitlab)
79
+ require_cmd glab
80
+ glab mr note "$number" --message "$(cat "$body_file")"
81
+ ;;
82
+ *)
83
+ die "unsupported platform: $platform"
84
+ ;;
85
+ esac
86
+
87
+ print_kv platform "$platform"
88
+ print_kv number "$number"
89
+ print_kv body_file "$body_file"
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
5
+ # shellcheck source=./common.sh
6
+ source "$SCRIPT_DIR/common.sh"
7
+
8
+ repo=.
9
+
10
+ usage() {
11
+ cat <<'USAGE'
12
+ Usage: repo_policy.sh [--repo <path>]
13
+
14
+ Inspect AGENTS.md and CLAUDE.md, if present, and print the resolved worktree root policy.
15
+ USAGE
16
+ }
17
+
18
+ while [[ $# -gt 0 ]]; do
19
+ case "$1" in
20
+ --repo)
21
+ repo=$2
22
+ shift 2
23
+ ;;
24
+ --help|-h)
25
+ usage
26
+ exit 0
27
+ ;;
28
+ *)
29
+ die "unknown argument: $1"
30
+ ;;
31
+ esac
32
+ done
33
+
34
+ repo=$(resolve_repo_root "$repo")
35
+
36
+ extract_from_line() {
37
+ local line=$1
38
+ local token=
39
+ local root_token=
40
+
41
+ while IFS= read -r token; do
42
+ [[ -n "$token" ]] || continue
43
+ root_token=$token
44
+ if [[ "$token" == ../*/* ]]; then
45
+ root_token="../${token#../}"
46
+ root_token="${root_token%%/*}"
47
+ fi
48
+ if [[ "$root_token" == *worktree* || "$root_token" == *worktrees* ]]; then
49
+ printf '%s\n' "$(expand_path "$root_token" "$repo")"
50
+ return 0
51
+ fi
52
+ done < <(printf '%s\n' "$line" | grep -oE '\.\./[^[:space:]`]+|\./[^[:space:]`]+|/[^[:space:]`]+' || true)
53
+
54
+ while IFS= read -r token; do
55
+ token=${token#\`}
56
+ token=${token%\`}
57
+ if [[ "$token" == *worktree* || "$token" == *worktrees* ]]; then
58
+ printf '%s\n' "$(expand_path "$token" "$repo")"
59
+ return 0
60
+ fi
61
+ done < <(printf '%s\n' "$line" | grep -oE '\`[^\`]+\`' || true)
62
+
63
+ if [[ "$line" =~ ([A-Za-z0-9._-]+worktree[A-Za-z0-9._-]*)[[:space:]]+folder ]]; then
64
+ printf '%s\n' "$(expand_path "../${BASH_REMATCH[1]}" "$repo")"
65
+ return 0
66
+ fi
67
+
68
+ if [[ "$line" =~ \.[/]?worktrees ]]; then
69
+ printf '%s\n' "$(expand_path .worktrees "$repo")"
70
+ return 0
71
+ fi
72
+
73
+ if [[ "$line" =~ (^|[^.[:alnum:]_])worktrees([^[:alnum:]_]|$) ]]; then
74
+ printf '%s\n' "$(expand_path worktrees "$repo")"
75
+ return 0
76
+ fi
77
+
78
+ return 1
79
+ }
80
+
81
+ extract_policy() {
82
+ local file=$1
83
+ local match
84
+ while IFS= read -r line; do
85
+ match=$(extract_from_line "$line") || continue
86
+ printf '%s\n' "$match"
87
+ return 0
88
+ done < <(grep -i 'worktree' "$file" || true)
89
+ return 1
90
+ }
91
+
92
+ agents_file="$repo/AGENTS.md"
93
+ claude_file="$repo/CLAUDE.md"
94
+ agents_root=
95
+ claude_root=
96
+
97
+ if [[ -f "$agents_file" ]]; then
98
+ agents_root=$(extract_policy "$agents_file" || true)
99
+ fi
100
+
101
+ if [[ -f "$claude_file" ]]; then
102
+ claude_root=$(extract_policy "$claude_file" || true)
103
+ fi
104
+
105
+ if [[ -n "$agents_root" && -n "$claude_root" && "$agents_root" != "$claude_root" ]]; then
106
+ die "conflicting worktree roots: AGENTS.md=$agents_root CLAUDE.md=$claude_root"
107
+ fi
108
+
109
+ policy_root=${agents_root:-$claude_root}
110
+ policy_source=default
111
+
112
+ if [[ -n "$agents_root" ]]; then
113
+ policy_source=AGENTS.md
114
+ fi
115
+
116
+ if [[ -n "$claude_root" && -z "$agents_root" ]]; then
117
+ policy_source=CLAUDE.md
118
+ fi
119
+
120
+ if [[ -n "$claude_root" && -n "$agents_root" ]]; then
121
+ policy_source=AGENTS.md+CLAUDE.md
122
+ fi
123
+
124
+ if [[ -z "$policy_root" ]]; then
125
+ policy_root=$(expand_path .worktrees "$repo")
126
+ fi
127
+
128
+ print_kv repo_root "$repo"
129
+ print_kv policy_worktree_root "$policy_root"
130
+ print_kv policy_source "$policy_source"
131
+ print_kv agents_file "$agents_file"
132
+ print_kv claude_file "$claude_file"
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
5
+ # shellcheck source=./common.sh
6
+ source "$SCRIPT_DIR/common.sh"
7
+
8
+ repo=.
9
+ platform=
10
+ number=
11
+ mode=
12
+ json_output=false
13
+
14
+ usage() {
15
+ cat <<'USAGE'
16
+ Usage: resolve_review_target.sh --repo <path> (--latest | --number <id>) [--platform <github|gitlab>] [--json]
17
+
18
+ Resolve the latest open MR/PR or a specific MR/PR number and print normalized metadata.
19
+ Default output is shell-safe key=value lines.
20
+ USAGE
21
+ }
22
+
23
+ while [[ $# -gt 0 ]]; do
24
+ case "$1" in
25
+ --repo)
26
+ repo=$2
27
+ shift 2
28
+ ;;
29
+ --platform)
30
+ platform=$2
31
+ shift 2
32
+ ;;
33
+ --number)
34
+ number=$2
35
+ mode=number
36
+ shift 2
37
+ ;;
38
+ --latest)
39
+ mode=latest
40
+ shift
41
+ ;;
42
+ --json)
43
+ json_output=true
44
+ shift
45
+ ;;
46
+ --help|-h)
47
+ usage
48
+ exit 0
49
+ ;;
50
+ *)
51
+ die "unknown argument: $1"
52
+ ;;
53
+ esac
54
+ done
55
+
56
+ repo=$(resolve_repo_root "$repo")
57
+ require_cmd jq
58
+
59
+ if [[ -z "$mode" ]]; then
60
+ die "choose exactly one of --latest or --number"
61
+ fi
62
+
63
+ if [[ -z "$platform" ]]; then
64
+ platform=$("$SCRIPT_DIR/detect_platform.sh" --repo "$repo")
65
+ fi
66
+
67
+ remote_url=$(origin_url "$repo")
68
+ repository=$(repository_slug_from_remote "$remote_url")
69
+
70
+ select_latest_number() {
71
+ local field=$1
72
+ jq -r --arg field "$field" 'sort_by(.updatedAt // .updated_at) | last | .[$field] // empty'
73
+ }
74
+
75
+ emit_kv() {
76
+ local number_value=$1
77
+ local title=$2
78
+ local source_branch=$3
79
+ local target_branch=$4
80
+ local author=$5
81
+ local head_sha=$6
82
+ local updated_at=$7
83
+ local web_url=$8
84
+
85
+ print_kv platform "$platform"
86
+ print_kv repository "$repository"
87
+ print_kv number "$number_value"
88
+ print_kv title "$title"
89
+ print_kv source_branch "$source_branch"
90
+ print_kv target_branch "$target_branch"
91
+ print_kv author "$author"
92
+ print_kv head_sha "$head_sha"
93
+ print_kv updated_at "$updated_at"
94
+ print_kv web_url "$web_url"
95
+ }
96
+
97
+ cd "$repo"
98
+
99
+ case "$platform" in
100
+ github)
101
+ require_cmd gh
102
+
103
+ if [[ "$mode" == latest ]]; then
104
+ prs=$(gh pr list --state open --limit 100 --json number,updatedAt)
105
+ number=$(printf '%s' "$prs" | select_latest_number number)
106
+ fi
107
+
108
+ [[ -n "$number" ]] || die "no open GitHub pull requests found"
109
+
110
+ view=$(gh pr view "$number" --json number,title,headRefName,baseRefName,author,headRefOid,updatedAt,url)
111
+ number_value=$(printf '%s' "$view" | jq -r '.number')
112
+ title=$(printf '%s' "$view" | jq -r '.title')
113
+ source_branch=$(printf '%s' "$view" | jq -r '.headRefName')
114
+ target_branch=$(printf '%s' "$view" | jq -r '.baseRefName')
115
+ author=$(printf '%s' "$view" | jq -r '.author.login // .author.name // "unknown"')
116
+ head_sha=$(printf '%s' "$view" | jq -r '.headRefOid')
117
+ updated_at=$(printf '%s' "$view" | jq -r '.updatedAt')
118
+ web_url=$(printf '%s' "$view" | jq -r '.url')
119
+ ;;
120
+ gitlab)
121
+ require_cmd glab
122
+
123
+ if [[ "$mode" == latest ]]; then
124
+ mrs=$(glab mr list --state opened --per-page 100 --output json)
125
+ number=$(printf '%s' "$mrs" | select_latest_number iid)
126
+ fi
127
+
128
+ [[ -n "$number" ]] || die "no open GitLab merge requests found"
129
+
130
+ view=$(glab mr view "$number" --output json)
131
+ number_value=$(printf '%s' "$view" | jq -r '.iid')
132
+ title=$(printf '%s' "$view" | jq -r '.title')
133
+ source_branch=$(printf '%s' "$view" | jq -r '.source_branch')
134
+ target_branch=$(printf '%s' "$view" | jq -r '.target_branch')
135
+ author=$(printf '%s' "$view" | jq -r '.author.username // .author.name // "unknown"')
136
+ head_sha=$(printf '%s' "$view" | jq -r '.sha')
137
+ updated_at=$(printf '%s' "$view" | jq -r '.updated_at')
138
+ web_url=$(printf '%s' "$view" | jq -r '.web_url')
139
+ ;;
140
+ *)
141
+ die "unsupported platform: $platform"
142
+ ;;
143
+ esac
144
+
145
+ if [[ "$json_output" == true ]]; then
146
+ jq -cn \
147
+ --arg platform "$platform" \
148
+ --arg repository "$repository" \
149
+ --arg number "$number_value" \
150
+ --arg title "$title" \
151
+ --arg source_branch "$source_branch" \
152
+ --arg target_branch "$target_branch" \
153
+ --arg author "$author" \
154
+ --arg head_sha "$head_sha" \
155
+ --arg updated_at "$updated_at" \
156
+ --arg web_url "$web_url" \
157
+ '{platform:$platform,repository:$repository,number:$number,title:$title,source_branch:$source_branch,target_branch:$target_branch,author:$author,head_sha:$head_sha,updated_at:$updated_at,web_url:$web_url}'
158
+ else
159
+ emit_kv "$number_value" "$title" "$source_branch" "$target_branch" "$author" "$head_sha" "$updated_at" "$web_url"
160
+ fi
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
5
+ # shellcheck source=./common.sh
6
+ source "$SCRIPT_DIR/common.sh"
7
+
8
+ repo=.
9
+ remote=origin
10
+ source_branch=
11
+ head_sha=
12
+ dry_run=false
13
+
14
+ usage() {
15
+ cat <<'USAGE'
16
+ Usage: worktree_sync.sh --repo <path> --source-branch <branch> [--head-sha <sha>] [--remote <name>] [--dry-run]
17
+
18
+ Reuse or create a worktree for the source branch, using AGENTS.md / CLAUDE.md policy when present.
19
+ USAGE
20
+ }
21
+
22
+ while [[ $# -gt 0 ]]; do
23
+ case "$1" in
24
+ --repo)
25
+ repo=$2
26
+ shift 2
27
+ ;;
28
+ --source-branch)
29
+ source_branch=$2
30
+ shift 2
31
+ ;;
32
+ --head-sha)
33
+ head_sha=$2
34
+ shift 2
35
+ ;;
36
+ --remote)
37
+ remote=$2
38
+ shift 2
39
+ ;;
40
+ --dry-run)
41
+ dry_run=true
42
+ shift
43
+ ;;
44
+ --help|-h)
45
+ usage
46
+ exit 0
47
+ ;;
48
+ *)
49
+ die "unknown argument: $1"
50
+ ;;
51
+ esac
52
+ done
53
+
54
+ [[ -n "$source_branch" ]] || die "--source-branch is required"
55
+ repo=$(resolve_repo_root "$repo")
56
+
57
+ policy_output=$("$SCRIPT_DIR/repo_policy.sh" --repo "$repo")
58
+ load_kv_output "$policy_output"
59
+
60
+ worktree_name=$(sanitize_branch_name "$source_branch")
61
+ worktree_path="$policy_worktree_root/$worktree_name"
62
+ action=reused
63
+
64
+ worktree_exists=false
65
+ if git -C "$repo" worktree list --porcelain | grep -F "worktree $worktree_path" >/dev/null 2>&1; then
66
+ worktree_exists=true
67
+ elif [[ -d "$worktree_path" && -e "$worktree_path/.git" ]]; then
68
+ worktree_exists=true
69
+ fi
70
+
71
+ if [[ "$worktree_exists" == true ]]; then
72
+ if [[ -n "$(git -C "$worktree_path" status --porcelain)" ]]; then
73
+ die "existing worktree has uncommitted changes: $worktree_path"
74
+ fi
75
+ else
76
+ action=created
77
+ fi
78
+
79
+ if [[ "$dry_run" == true ]]; then
80
+ print_kv repo_root "$repo"
81
+ print_kv worktree_path "$worktree_path"
82
+ print_kv worktree_action "$action"
83
+ print_kv source_branch "$source_branch"
84
+ print_kv remote "$remote"
85
+ print_kv head_sha "$head_sha"
86
+ exit 0
87
+ fi
88
+
89
+ mkdir -p "$policy_worktree_root"
90
+
91
+ git -C "$repo" fetch "$remote" "$source_branch"
92
+
93
+ git -C "$repo" rev-parse --verify "$remote/$source_branch" >/dev/null 2>&1 || die "remote branch not found: $remote/$source_branch"
94
+
95
+ if [[ "$worktree_exists" == true ]]; then
96
+ git -C "$worktree_path" checkout "$source_branch"
97
+ git -C "$worktree_path" pull --ff-only "$remote" "$source_branch"
98
+ else
99
+ if git -C "$repo" show-ref --verify --quiet "refs/heads/$source_branch"; then
100
+ git -C "$repo" worktree add "$worktree_path" "$source_branch"
101
+ else
102
+ git -C "$repo" worktree add -b "$source_branch" "$worktree_path" "$remote/$source_branch"
103
+ fi
104
+ fi
105
+
106
+ if [[ -n "$head_sha" ]]; then
107
+ git -C "$worktree_path" fetch "$remote" "$source_branch"
108
+ git -C "$worktree_path" cat-file -e "$head_sha^{commit}" >/dev/null 2>&1 || die "head sha not available after fetch: $head_sha"
109
+ git -C "$worktree_path" reset --hard "$head_sha"
110
+ else
111
+ git -C "$worktree_path" reset --hard "$remote/$source_branch"
112
+ fi
113
+
114
+ print_kv repo_root "$repo"
115
+ print_kv worktree_path "$worktree_path"
116
+ print_kv worktree_action "$action"
117
+ print_kv source_branch "$source_branch"
118
+ print_kv current_head "$(git -C "$worktree_path" rev-parse HEAD)"