steward-cli 0.3.2__tar.gz → 0.5.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.
Files changed (63) hide show
  1. steward_cli-0.5.0/.claude/skills/discord-notify/SKILL.md +59 -0
  2. steward_cli-0.5.0/.claude/skills/discord-notify/scripts/send-discord.sh +100 -0
  3. steward_cli-0.5.0/.claude/skills/gh-issues/SKILL.md +45 -0
  4. steward_cli-0.5.0/.claude/skills/gh-issues/scripts/gh-issues.sh +52 -0
  5. steward_cli-0.5.0/.claude/skills/jekyll-test/SKILL.md +57 -0
  6. steward_cli-0.5.0/.claude/skills/jekyll-test/scripts/test-site.sh +232 -0
  7. steward_cli-0.5.0/.claude/skills/notebooklm/SKILL.md +47 -0
  8. steward_cli-0.5.0/.claude/skills/notebooklm/scripts/get-repo-sources.sh +200 -0
  9. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/SKILL.md +8 -4
  10. steward_cli-0.5.0/.claude/skills/pr-review/scripts/_resolve-nick.sh +43 -0
  11. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/pr-reply.sh +16 -5
  12. steward_cli-0.5.0/.claude/skills/pypi-maintainer/SKILL.md +75 -0
  13. steward_cli-0.5.0/.claude/skills/pypi-maintainer/scripts/switch-source.sh +102 -0
  14. steward_cli-0.5.0/.claude/skills/run-tests/SKILL.md +50 -0
  15. steward_cli-0.5.0/.claude/skills/run-tests/scripts/test.sh +52 -0
  16. steward_cli-0.5.0/.claude/skills/sonarclaude/SKILL.md +84 -0
  17. steward_cli-0.5.0/.claude/skills/sonarclaude/scripts/sonar.sh +263 -0
  18. {steward_cli-0.3.2 → steward_cli-0.5.0}/CHANGELOG.md +30 -0
  19. {steward_cli-0.3.2 → steward_cli-0.5.0}/PKG-INFO +1 -1
  20. steward_cli-0.5.0/culture.yaml +3 -0
  21. steward_cli-0.5.0/docs/perfect-patient.md +61 -0
  22. {steward_cli-0.3.2 → steward_cli-0.5.0}/docs/skill-sources.md +9 -2
  23. {steward_cli-0.3.2 → steward_cli-0.5.0}/pyproject.toml +1 -1
  24. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_commands/_corpus.py +12 -0
  25. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/test_corpus.py +2 -0
  26. steward_cli-0.5.0/tests/test_pr_reply_signature.py +52 -0
  27. steward_cli-0.5.0/tests/test_resolve_nick.py +82 -0
  28. {steward_cli-0.3.2 → steward_cli-0.5.0}/uv.lock +1 -1
  29. steward_cli-0.3.2/docs/perfect-patient.md +0 -48
  30. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/agent-config/SKILL.md +0 -0
  31. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
  32. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  33. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  34. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/portability-lint.sh +0 -0
  35. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/pr-batch.sh +0 -0
  36. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/pr-comments.sh +0 -0
  37. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/pr-status.sh +0 -0
  38. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/pr-review/scripts/workflow.sh +0 -0
  39. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/version-bump/SKILL.md +0 -0
  40. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  41. {steward_cli-0.3.2 → steward_cli-0.5.0}/.claude/skills.local.yaml.example +0 -0
  42. {steward_cli-0.3.2 → steward_cli-0.5.0}/.flake8 +0 -0
  43. {steward_cli-0.3.2 → steward_cli-0.5.0}/.github/workflows/publish.yml +0 -0
  44. {steward_cli-0.3.2 → steward_cli-0.5.0}/.github/workflows/tests.yml +0 -0
  45. {steward_cli-0.3.2 → steward_cli-0.5.0}/.gitignore +0 -0
  46. {steward_cli-0.3.2 → steward_cli-0.5.0}/.markdownlint-cli2.yaml +0 -0
  47. {steward_cli-0.3.2 → steward_cli-0.5.0}/CLAUDE.md +0 -0
  48. {steward_cli-0.3.2 → steward_cli-0.5.0}/LICENSE +0 -0
  49. {steward_cli-0.3.2 → steward_cli-0.5.0}/README.md +0 -0
  50. {steward_cli-0.3.2 → steward_cli-0.5.0}/docs/sibling-pattern.md +0 -0
  51. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/__init__.py +0 -0
  52. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/__main__.py +0 -0
  53. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/__init__.py +0 -0
  54. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_commands/__init__.py +0 -0
  55. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_commands/doctor.py +0 -0
  56. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_commands/show.py +0 -0
  57. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_errors.py +0 -0
  58. {steward_cli-0.3.2 → steward_cli-0.5.0}/steward/cli/_output.py +0 -0
  59. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/__init__.py +0 -0
  60. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/test_cli.py +0 -0
  61. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/test_cli_doctor.py +0 -0
  62. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/test_cli_doctor_siblings.py +0 -0
  63. {steward_cli-0.3.2 → steward_cli-0.5.0}/tests/test_skills_convention.py +0 -0
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: discord-notify
3
+ description: >
4
+ Send notifications to Discord via webhook. Use when: a long task completes,
5
+ an error needs attention, the user says "notify me", "ping me", "let me know",
6
+ "send to discord", or "update me when done".
7
+ ---
8
+
9
+ # Discord Notify
10
+
11
+ Send a message to a Discord channel using a webhook embed.
12
+
13
+ ## When to Use
14
+
15
+ - A long-running task finishes (build, deploy, migration)
16
+ - An error occurs that the user should know about
17
+ - The user explicitly asks to be notified
18
+
19
+ ## Prerequisites
20
+
21
+ The script requires the following tools on `PATH`:
22
+
23
+ - `bash`
24
+ - `curl` — sends the webhook POST
25
+ - `jq` — builds the JSON payload safely
26
+
27
+ ## Environment
28
+
29
+ Set `DISCORD_WEBHOOK_URL` to a Discord webhook URL before use.
30
+
31
+ ## Usage
32
+
33
+ ```bash
34
+ # Basic info message
35
+ bash .claude/skills/discord-notify/scripts/send-discord.sh "Build passed"
36
+
37
+ # Completion (green)
38
+ bash .claude/skills/discord-notify/scripts/send-discord.sh --type completion "Deploy finished"
39
+
40
+ # Error (red)
41
+ bash .claude/skills/discord-notify/scripts/send-discord.sh --type error "Tests failed on main"
42
+
43
+ # Status update (yellow)
44
+ bash .claude/skills/discord-notify/scripts/send-discord.sh --type status "Migration running — 3/10 tables done"
45
+
46
+ # Custom title
47
+ bash .claude/skills/discord-notify/scripts/send-discord.sh --type completion --title "CI Pipeline" "All checks green"
48
+
49
+ # Different sender identity
50
+ bash .claude/skills/discord-notify/scripts/send-discord.sh --username "Codex" "Task complete"
51
+ ```
52
+
53
+ ## Options
54
+
55
+ | Flag | Short | Default | Description |
56
+ |------|-------|---------|-------------|
57
+ | `--type` | `-t` | `info` | `info` (blue), `status` (yellow), `completion` (green), `error` (red) |
58
+ | `--title` | `-T` | auto | Override the embed title |
59
+ | `--username` | `-u` | `Claude Code` | Sender name shown in Discord |
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Discord webhook notification sender using embeds.
5
+ # Requires DISCORD_WEBHOOK_URL environment variable.
6
+
7
+ # --- Defaults ---
8
+ TYPE="info"
9
+ TITLE=""
10
+ USERNAME="Claude Code"
11
+ MESSAGE=""
12
+
13
+ # --- Color map ---
14
+ color_for_type() {
15
+ case "$1" in
16
+ info) echo 3447003 ;; # blue
17
+ status) echo 16776960 ;; # yellow
18
+ completion) echo 3066993 ;; # green
19
+ error) echo 15158332 ;; # red
20
+ *) echo "Unknown type: $1" >&2; exit 1 ;;
21
+ esac
22
+ }
23
+
24
+ # --- Default title ---
25
+ title_for_type() {
26
+ case "$1" in
27
+ info) echo "Info" ;;
28
+ status) echo "Status" ;;
29
+ completion) echo "Completed" ;;
30
+ error) echo "Error" ;;
31
+ esac
32
+ }
33
+
34
+ # --- Parse args ---
35
+ require_value() {
36
+ local flag="$1" remaining="$2"
37
+ if [[ "$remaining" -lt 2 ]]; then
38
+ echo "Error: $flag requires a value" >&2
39
+ echo "Usage: send-discord.sh [--type info|status|completion|error] [--title TITLE] [--username NAME] MESSAGE" >&2
40
+ exit 1
41
+ fi
42
+ }
43
+
44
+ while [[ $# -gt 0 ]]; do
45
+ case "$1" in
46
+ --type|-t) require_value "$1" "$#"; TYPE="$2"; shift 2 ;;
47
+ --title|-T) require_value "$1" "$#"; TITLE="$2"; shift 2 ;;
48
+ --username|-u) require_value "$1" "$#"; USERNAME="$2"; shift 2 ;;
49
+ -*) echo "Unknown option: $1" >&2; exit 1 ;;
50
+ *) MESSAGE="$1"; shift ;;
51
+ esac
52
+ done
53
+
54
+ # --- Validate ---
55
+ if [[ -z "${DISCORD_WEBHOOK_URL:-}" ]]; then
56
+ echo "Error: DISCORD_WEBHOOK_URL environment variable is not set." >&2
57
+ exit 1
58
+ fi
59
+
60
+ if [[ -z "$MESSAGE" ]]; then
61
+ echo "Error: No message provided." >&2
62
+ echo "Usage: send-discord.sh [--type info|status|completion|error] [--title TITLE] [--username NAME] MESSAGE" >&2
63
+ exit 1
64
+ fi
65
+
66
+ COLOR=$(color_for_type "$TYPE")
67
+ EMBED_TITLE="${TITLE:-$(title_for_type "$TYPE")}"
68
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
69
+
70
+ # --- Build JSON safely with jq ---
71
+ PAYLOAD=$(jq -n \
72
+ --arg username "$USERNAME" \
73
+ --arg title "$EMBED_TITLE" \
74
+ --arg description "$MESSAGE" \
75
+ --argjson color "$COLOR" \
76
+ --arg footer "Sent by $USERNAME" \
77
+ --arg timestamp "$TIMESTAMP" \
78
+ '{
79
+ username: $username,
80
+ embeds: [{
81
+ title: $title,
82
+ description: $description,
83
+ color: $color,
84
+ footer: { text: $footer },
85
+ timestamp: $timestamp
86
+ }]
87
+ }')
88
+
89
+ # --- Send ---
90
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
91
+ -H "Content-Type: application/json" \
92
+ -d "$PAYLOAD" \
93
+ "$DISCORD_WEBHOOK_URL")
94
+
95
+ if [[ "$HTTP_CODE" -ge 200 && "$HTTP_CODE" -lt 300 ]]; then
96
+ echo "Sent ($HTTP_CODE)"
97
+ else
98
+ echo "Error: Discord returned HTTP $HTTP_CODE" >&2
99
+ exit 1
100
+ fi
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: gh-issues
3
+ description: >
4
+ Fetch GitHub issues with full body and comments. Use when checking issues,
5
+ reviewing bug reports, or the user says "check issues", "fetch issues",
6
+ "issue #N", or references GitHub issue numbers.
7
+ triggers:
8
+ - check issues
9
+ - fetch issues
10
+ - issue #
11
+ - github issues
12
+ - verify issues
13
+ ---
14
+
15
+ # GitHub Issues Skill
16
+
17
+ Fetch one or more GitHub issues with full body text and all comments.
18
+
19
+ ## Usage
20
+
21
+ ### Single issue
22
+
23
+ ```bash
24
+ bash .claude/skills/gh-issues/scripts/gh-issues.sh 191
25
+ ```
26
+
27
+ ### Range
28
+
29
+ ```bash
30
+ bash .claude/skills/gh-issues/scripts/gh-issues.sh 191-197
31
+ ```
32
+
33
+ ### Specific list
34
+
35
+ ```bash
36
+ bash .claude/skills/gh-issues/scripts/gh-issues.sh 191 195 197
37
+ ```
38
+
39
+ ### Explicit repo
40
+
41
+ ```bash
42
+ bash .claude/skills/gh-issues/scripts/gh-issues.sh --repo owner/repo 42-50
43
+ ```
44
+
45
+ Output is JSON per issue with: number, title, state, labels, body, and comments array.
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+ # Fetch GitHub issues with full body and comments
3
+ # Usage: gh-issues.sh [RANGE|NUMBER] [--repo OWNER/REPO]
4
+ # gh-issues.sh 191-197 # range
5
+ # gh-issues.sh 191 # single
6
+ # gh-issues.sh 191 192 195 # list
7
+ # gh-issues.sh --repo foo/bar 5 # explicit repo
8
+
9
+ set -euo pipefail
10
+
11
+ REPO_FLAG=""
12
+ NUMBERS=()
13
+
14
+ while [[ $# -gt 0 ]]; do
15
+ case "$1" in
16
+ --repo)
17
+ if [[ $# -lt 2 || -z "$2" ]]; then
18
+ echo "Error: --repo requires a value (OWNER/REPO)" >&2
19
+ echo "Usage: gh-issues.sh [RANGE|NUMBER...] [--repo OWNER/REPO]" >&2
20
+ exit 1
21
+ fi
22
+ REPO_FLAG="--repo $2"
23
+ shift 2 ;;
24
+ *-*) # range like 191-197
25
+ IFS='-' read -r start end <<< "$1"
26
+ for ((i=start; i<=end; i++)); do NUMBERS+=("$i"); done
27
+ shift ;;
28
+ *) NUMBERS+=("$1"); shift ;;
29
+ esac
30
+ done
31
+
32
+ if [[ ${#NUMBERS[@]} -eq 0 ]]; then
33
+ echo "Usage: gh-issues.sh [RANGE|NUMBER...] [--repo OWNER/REPO]" >&2
34
+ exit 1
35
+ fi
36
+
37
+ for num in "${NUMBERS[@]}"; do
38
+ echo "========================================"
39
+ echo "ISSUE #${num}"
40
+ echo "========================================"
41
+ # shellcheck disable=SC2086
42
+ gh issue view "$num" $REPO_FLAG --json number,title,state,labels,body,comments \
43
+ --jq '{
44
+ number: .number,
45
+ title: .title,
46
+ state: .state,
47
+ labels: [.labels[].name],
48
+ body: .body,
49
+ comments: [.comments[] | {author: .author.login, body: .body}]
50
+ }' 2>/dev/null || echo "ERROR: Could not fetch issue #${num}"
51
+ echo
52
+ done
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: jekyll-test
3
+ description: >
4
+ Build a Jekyll site (GitHub Pages / Cloudflare Pages) and validate the
5
+ output: build succeeds, custom color scheme is applied, permalinked pages
6
+ exist, just-the-docs navigation is consistent. Use after editing
7
+ `_config.yml`, theme files, SCSS, or page front matter; or when the user
8
+ says "test the site", "did the site build", "check jekyll", or
9
+ "verify pages".
10
+ ---
11
+
12
+ # Jekyll Test
13
+
14
+ Conditional skill — only meaningful when the sibling repo ships a Jekyll
15
+ site. Detected by the presence of `_config.yml` somewhere in the repo.
16
+
17
+ The original version of this skill was a ten-step manual checklist. The
18
+ script does all ten steps in one shot and prints a single-screen summary;
19
+ follow the script, not a manual procedure.
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ # Test the site whose _config.yml is at or above the current directory
25
+ bash .claude/skills/jekyll-test/scripts/test-site.sh
26
+
27
+ # Test a specific site (path to repo root)
28
+ bash .claude/skills/jekyll-test/scripts/test-site.sh /path/to/jekyll-site
29
+ ```
30
+
31
+ ## What the script checks
32
+
33
+ The script walks up to find `_config.yml`, runs `bundle install --quiet`
34
+ and `bundle exec jekyll build` (the only hard-fail step), then reports
35
+ non-fatal validation findings:
36
+
37
+ - Build status and elapsed time.
38
+ - For `color_scheme: <name>` declarations, every hex from
39
+ `_sass/color_schemes/<name>.scss` is grep'd for in the built
40
+ `_site/assets/css/*` — missing colors are listed.
41
+ - Every `permalink:` in front matter is checked against the generated
42
+ `<permalink>/index.html` — missing pages are listed.
43
+ - For `just-the-docs` sites, every `parent:` value is matched against
44
+ parent pages' `title:` — orphans (children whose parent is not found)
45
+ are listed. Parent counts and child counts are printed.
46
+ - `_includes/footer_custom.html` and `_includes/head_custom.html`, if
47
+ they exist, are checked for inclusion in `_site/index.html`.
48
+
49
+ The output is a single summary block plus per-category failure detail.
50
+
51
+ ## Requirements
52
+
53
+ - `bundle` (Bundler) on PATH.
54
+ - `ruby` on PATH (whatever the site's `Gemfile` requires).
55
+ - `python3` on PATH (used to parse `_config.yml`; PyYAML preferred,
56
+ regex fallback if it is not installed).
57
+ - A Jekyll project (must contain `_config.yml`).
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env bash
2
+ # test-site.sh — Build a Jekyll site and validate the output.
3
+ # Replaces the manual ten-step checklist that lived in the original
4
+ # jekyll-test SKILL.md.
5
+ #
6
+ # Usage:
7
+ # test-site.sh # tests the site at/above $PWD
8
+ # test-site.sh /path/to/site
9
+ #
10
+ # Exits non-zero only if the Jekyll project cannot be found or the build
11
+ # itself fails. Validation findings (missing colors, missing permalinks,
12
+ # orphan navigation children, missing includes) are reported but do not
13
+ # fail the run — the agent reading the output decides what to do.
14
+
15
+ set -euo pipefail
16
+
17
+ START_DIR="${1:-$PWD}"
18
+
19
+ # --- Locate Jekyll root (walk up from START_DIR looking for _config.yml) ---
20
+ SITE_ROOT=""
21
+ dir="$(cd "$START_DIR" && pwd)"
22
+ while [[ "$dir" != "/" && "$dir" != "" ]]; do
23
+ if [[ -f "$dir/_config.yml" ]]; then
24
+ SITE_ROOT="$dir"
25
+ break
26
+ fi
27
+ dir="$(dirname "$dir")"
28
+ done
29
+
30
+ if [[ -z "$SITE_ROOT" ]]; then
31
+ echo "Error: no _config.yml found at or above $START_DIR — not a Jekyll project" >&2
32
+ exit 1
33
+ fi
34
+
35
+ cd "$SITE_ROOT"
36
+ echo "Site root: $SITE_ROOT"
37
+
38
+ # --- Read selected _config.yml keys via Python (PyYAML if available, else regex) ---
39
+ if ! command -v python3 >/dev/null 2>&1; then
40
+ echo "Error: python3 is required to parse _config.yml but was not found on PATH" >&2
41
+ exit 1
42
+ fi
43
+
44
+ read_config() {
45
+ python3 - <<'PY' 2>/dev/null
46
+ import os, sys, re
47
+ path = "_config.yml"
48
+ try:
49
+ import yaml
50
+ with open(path) as f:
51
+ cfg = yaml.safe_load(f) or {}
52
+ except Exception:
53
+ cfg = {}
54
+ line_re = re.compile(r"^(\w+):\s*(.*)$")
55
+ with open(path) as f:
56
+ for line in f:
57
+ m = line_re.match(line)
58
+ if m:
59
+ cfg[m.group(1)] = m.group(2).strip().strip('"').strip("'")
60
+ for key in ("color_scheme", "theme", "remote_theme", "baseurl", "url"):
61
+ val = cfg.get(key, "")
62
+ print(f"{key}={val}")
63
+ PY
64
+ }
65
+
66
+ declare -A CFG=()
67
+ while IFS='=' read -r k v; do
68
+ [[ -n "$k" ]] && CFG["$k"]="$v"
69
+ done < <(read_config)
70
+
71
+ THEME="${CFG[theme]:-${CFG[remote_theme]:-}}"
72
+ COLOR_SCHEME="${CFG[color_scheme]:-}"
73
+
74
+ echo "Theme: ${THEME:-<none>}"
75
+ echo "Color scheme: ${COLOR_SCHEME:-<none>}"
76
+
77
+ # --- Bundler dependencies ---
78
+ if ! command -v bundle >/dev/null 2>&1; then
79
+ echo "Error: bundle (Bundler) is not on PATH — install Ruby + bundler first" >&2
80
+ exit 1
81
+ fi
82
+
83
+ if ! bundle check >/dev/null 2>&1; then
84
+ echo "Installing gem dependencies via 'bundle install'..."
85
+ bundle install --quiet
86
+ fi
87
+
88
+ # --- just-the-docs search index init (only when used as a gem theme) ---
89
+ if [[ "$THEME" == "just-the-docs" && ! -f "assets/js/zzzz-search-data.json" ]]; then
90
+ echo "Initialising just-the-docs search index..."
91
+ bundle exec just-the-docs rake search:init >/dev/null 2>&1 || true
92
+ fi
93
+
94
+ # --- Build ---
95
+ echo
96
+ echo "Building site..."
97
+ BUILD_LOG="$(mktemp)"
98
+ trap 'rm -f "$BUILD_LOG"' EXIT
99
+ BUILD_OK=1
100
+ BUILD_TIME=""
101
+ if bundle exec jekyll build >"$BUILD_LOG" 2>&1; then
102
+ BUILD_TIME="$(grep -oE 'done in [0-9.]+ seconds' "$BUILD_LOG" | tail -1 || echo)"
103
+ else
104
+ BUILD_OK=0
105
+ fi
106
+
107
+ if [[ "$BUILD_OK" -eq 0 ]]; then
108
+ echo "Build: FAILED"
109
+ echo "--- last 40 lines of build log ---"
110
+ tail -40 "$BUILD_LOG"
111
+ exit 1
112
+ fi
113
+ echo "Build: OK ${BUILD_TIME:+($BUILD_TIME)}"
114
+
115
+ # --- Color scheme verification ---
116
+ COLOR_FOUND=0
117
+ COLOR_TOTAL=0
118
+ COLOR_MISSING=()
119
+ if [[ -n "$COLOR_SCHEME" ]]; then
120
+ SCSS_FILE="_sass/color_schemes/${COLOR_SCHEME}.scss"
121
+ if [[ -f "$SCSS_FILE" ]]; then
122
+ # Pull every `#abcdef` hex from the SCSS file
123
+ mapfile -t HEXES < <(grep -ohE '#[0-9a-fA-F]{3,8}' "$SCSS_FILE" | sort -u)
124
+ COLOR_TOTAL=${#HEXES[@]}
125
+ if [[ "$COLOR_TOTAL" -gt 0 ]]; then
126
+ CSS_BLOB="$(cat _site/assets/css/*.css 2>/dev/null || true)"
127
+ for hex in "${HEXES[@]}"; do
128
+ if grep -qiF "$hex" <<<"$CSS_BLOB"; then
129
+ ((COLOR_FOUND++)) || true
130
+ else
131
+ COLOR_MISSING+=("$hex")
132
+ fi
133
+ done
134
+ fi
135
+ fi
136
+ fi
137
+
138
+ # --- Permalink verification ---
139
+ PERMA_TOTAL=0
140
+ PERMA_OK=0
141
+ PERMA_MISSING=()
142
+ while IFS= read -r mdfile; do
143
+ perma="$(awk '
144
+ /^---$/ {fm = !fm; next}
145
+ fm && /^permalink:/ {sub(/^permalink:[ \t]*/, ""); gsub(/["'\'']/, ""); print; exit}
146
+ ' "$mdfile")"
147
+ [[ -z "$perma" ]] && continue
148
+ ((PERMA_TOTAL++)) || true
149
+ perma_clean="${perma#/}"
150
+ perma_clean="${perma_clean%/}"
151
+ if [[ -f "_site/${perma_clean}/index.html" || -f "_site/${perma_clean}.html" ]]; then
152
+ ((PERMA_OK++)) || true
153
+ else
154
+ PERMA_MISSING+=("$perma")
155
+ fi
156
+ done < <(find . -type f -name '*.md' -not -path './_site/*' -not -path './vendor/*' -not -path './node_modules/*' 2>/dev/null)
157
+
158
+ # --- just-the-docs navigation consistency ---
159
+ NAV_PARENTS=0
160
+ NAV_CHILDREN=0
161
+ NAV_ORPHANS=()
162
+ if [[ "$THEME" == "just-the-docs" ]]; then
163
+ declare -A PARENT_TITLES=()
164
+ while IFS= read -r mdfile; do
165
+ has_kids="$(awk '/^---$/{fm=!fm;next} fm && /^has_children:[ \t]*true/{print "yes";exit}' "$mdfile")"
166
+ title="$(awk '/^---$/{fm=!fm;next} fm && /^title:/{sub(/^title:[ \t]*/,"");gsub(/["'\'']/,"");print;exit}' "$mdfile")"
167
+ if [[ "$has_kids" == "yes" && -n "$title" ]]; then
168
+ PARENT_TITLES["$title"]=1
169
+ ((NAV_PARENTS++)) || true
170
+ fi
171
+ done < <(find . -type f -name '*.md' -not -path './_site/*' -not -path './vendor/*' 2>/dev/null)
172
+
173
+ while IFS= read -r mdfile; do
174
+ parent="$(awk '/^---$/{fm=!fm;next} fm && /^parent:/{sub(/^parent:[ \t]*/,"");gsub(/["'\'']/,"");print;exit}' "$mdfile")"
175
+ [[ -z "$parent" ]] && continue
176
+ ((NAV_CHILDREN++)) || true
177
+ if [[ -z "${PARENT_TITLES[$parent]:-}" ]]; then
178
+ NAV_ORPHANS+=("$mdfile -> parent:$parent")
179
+ fi
180
+ done < <(find . -type f -name '*.md' -not -path './_site/*' -not -path './vendor/*' 2>/dev/null)
181
+ fi
182
+
183
+ # --- Custom includes ---
184
+ INC_FOOTER="-"
185
+ INC_HEAD="-"
186
+ if [[ -f _includes/footer_custom.html ]]; then
187
+ if grep -qF "$(head -3 _includes/footer_custom.html)" _site/index.html 2>/dev/null; then
188
+ INC_FOOTER="ok"
189
+ else
190
+ INC_FOOTER="missing"
191
+ fi
192
+ fi
193
+ if [[ -f _includes/head_custom.html ]]; then
194
+ if grep -qF "$(head -3 _includes/head_custom.html)" _site/index.html 2>/dev/null; then
195
+ INC_HEAD="ok"
196
+ else
197
+ INC_HEAD="missing"
198
+ fi
199
+ fi
200
+
201
+ # --- Summary ---
202
+ echo
203
+ echo "Jekyll Site Test Results"
204
+ echo "========================"
205
+ echo "Theme: ${THEME:-<none>}"
206
+ echo "Color scheme: ${COLOR_SCHEME:-<none>}"
207
+ echo "Build: OK ${BUILD_TIME:+($BUILD_TIME)}"
208
+ if [[ -n "$COLOR_SCHEME" && "$COLOR_TOTAL" -gt 0 ]]; then
209
+ echo "Colors: $COLOR_FOUND/$COLOR_TOTAL custom colors found in CSS"
210
+ fi
211
+ echo "Pages: $PERMA_OK/$PERMA_TOTAL permalinked pages built"
212
+ if [[ "$THEME" == "just-the-docs" ]]; then
213
+ echo "Navigation: $NAV_PARENTS parents, $NAV_CHILDREN children, ${#NAV_ORPHANS[@]} orphans"
214
+ fi
215
+ echo "Includes: footer=$INC_FOOTER, head=$INC_HEAD"
216
+
217
+ # --- Failure detail (reported, not fatal) ---
218
+ if [[ ${#COLOR_MISSING[@]} -gt 0 ]]; then
219
+ echo
220
+ echo "Missing colors:"
221
+ printf ' %s\n' "${COLOR_MISSING[@]}"
222
+ fi
223
+ if [[ ${#PERMA_MISSING[@]} -gt 0 ]]; then
224
+ echo
225
+ echo "Missing permalinked pages:"
226
+ printf ' %s\n' "${PERMA_MISSING[@]}"
227
+ fi
228
+ if [[ ${#NAV_ORPHANS[@]} -gt 0 ]]; then
229
+ echo
230
+ echo "Orphan nav children (parent not found):"
231
+ printf ' %s\n' "${NAV_ORPHANS[@]}"
232
+ fi
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: notebooklm
3
+ description: >
4
+ Generate GitHub links to repo documentation for NotebookLM ingestion.
5
+ Use when: the user wants to create a NotebookLM notebook about a project,
6
+ needs doc links for a repo, or says "notebooklm", "notebook sources",
7
+ "get repo sources", or "doc links".
8
+ ---
9
+
10
+ # NotebookLM — Repo Source Links
11
+
12
+ Generate GitHub blob URLs for all documentation in the current repo, ready to paste into Google NotebookLM as sources.
13
+
14
+ ## When to Use
15
+
16
+ - Creating a NotebookLM notebook about a project
17
+ - Gathering all doc links for a repo
18
+ - Exporting documentation URLs for any external tool
19
+
20
+ ## Usage
21
+
22
+ ```bash
23
+ # Categorized output (default)
24
+ bash .claude/skills/notebooklm/scripts/get-repo-sources.sh
25
+
26
+ # Plain URLs only (for copy-paste)
27
+ bash .claude/skills/notebooklm/scripts/get-repo-sources.sh --plain
28
+
29
+ # Include plans and specs
30
+ bash .claude/skills/notebooklm/scripts/get-repo-sources.sh --all
31
+
32
+ # Override branch
33
+ bash .claude/skills/notebooklm/scripts/get-repo-sources.sh --branch develop
34
+ ```
35
+
36
+ ## Options
37
+
38
+ | Flag | Default | Description |
39
+ |------|---------|-------------|
40
+ | `--all` | off | Include plans, specs, and changelogs |
41
+ | `--plain` | off | Output only URLs, one per line (no headers) |
42
+ | `--branch NAME` | auto-detect | Override the git branch used in URLs |
43
+
44
+ ## Requirements
45
+
46
+ - Must be run inside a git repository with a GitHub remote
47
+ - `git` CLI available