@tw93/waza 3.25.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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/package.json +35 -0
  4. package/rules/anti-patterns.md +38 -0
  5. package/rules/chinese.md +18 -0
  6. package/rules/durable-context.md +27 -0
  7. package/rules/english.md +14 -0
  8. package/scripts/build_metadata.py +360 -0
  9. package/scripts/check_routing_drift.py +82 -0
  10. package/scripts/dispatcher-template.md +43 -0
  11. package/scripts/dispatcher.md +53 -0
  12. package/scripts/package-skill.sh +71 -0
  13. package/scripts/packaging_filter.py +55 -0
  14. package/scripts/setup-rule.sh +109 -0
  15. package/scripts/setup-statusline.sh +127 -0
  16. package/scripts/skill_checks.py +483 -0
  17. package/scripts/skill_frontmatter.py +110 -0
  18. package/scripts/statusline.sh +321 -0
  19. package/scripts/validate_package.py +66 -0
  20. package/scripts/verify_skills.py +100 -0
  21. package/skills/RESOLVER.md +91 -0
  22. package/skills/check/SKILL.md +338 -0
  23. package/skills/check/agents/reviewer-architecture.md +39 -0
  24. package/skills/check/agents/reviewer-security.md +39 -0
  25. package/skills/check/references/persona-catalog.md +56 -0
  26. package/skills/check/references/project-context.md +107 -0
  27. package/skills/check/references/public-reply.md +14 -0
  28. package/skills/check/scripts/audit_signals.py +485 -0
  29. package/skills/check/scripts/run-tests.sh +19 -0
  30. package/skills/design/SKILL.md +134 -0
  31. package/skills/design/references/design-aesthetic-quality.md +67 -0
  32. package/skills/design/references/design-data-viz.md +34 -0
  33. package/skills/design/references/design-reference.md +278 -0
  34. package/skills/design/references/design-tokens.md +53 -0
  35. package/skills/design/references/design-traps.md +43 -0
  36. package/skills/health/SKILL.md +231 -0
  37. package/skills/health/agents/inspector-context.md +119 -0
  38. package/skills/health/agents/inspector-control.md +84 -0
  39. package/skills/health/agents/inspector-maintainability.md +55 -0
  40. package/skills/health/scripts/check-agent-context.sh +5 -0
  41. package/skills/health/scripts/check-doc-refs.sh +8 -0
  42. package/skills/health/scripts/check-maintainability.sh +8 -0
  43. package/skills/health/scripts/check-verifier-output.sh +5 -0
  44. package/skills/health/scripts/check_agent_context.py +407 -0
  45. package/skills/health/scripts/check_doc_refs.py +110 -0
  46. package/skills/health/scripts/check_maintainability.py +629 -0
  47. package/skills/health/scripts/check_verifier_output.py +116 -0
  48. package/skills/health/scripts/collect-data.sh +760 -0
  49. package/skills/hunt/SKILL.md +197 -0
  50. package/skills/hunt/references/failure-patterns.md +75 -0
  51. package/skills/hunt/references/ime-unicode.md +58 -0
  52. package/skills/hunt/references/logging-techniques.md +72 -0
  53. package/skills/hunt/references/rendering-debug.md +34 -0
  54. package/skills/learn/SKILL.md +128 -0
  55. package/skills/read/SKILL.md +108 -0
  56. package/skills/read/references/read-methods.md +110 -0
  57. package/skills/read/references/save-paths.md +33 -0
  58. package/skills/read/scripts/fetch.sh +105 -0
  59. package/skills/read/scripts/fetch_feishu.py +246 -0
  60. package/skills/read/scripts/fetch_local.py +218 -0
  61. package/skills/read/scripts/fetch_weixin.py +107 -0
  62. package/skills/think/SKILL.md +155 -0
  63. package/skills/write/SKILL.md +129 -0
  64. package/skills/write/references/write-en.md +197 -0
  65. package/skills/write/references/write-zh-bilingual.md +60 -0
  66. package/skills/write/references/write-zh-prose.md +48 -0
  67. package/skills/write/references/write-zh-release-notes.md +38 -0
  68. package/skills/write/references/write-zh.md +645 -0
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+ # Install a Waza rule into Claude Code (~/.claude/rules/<rule>.md) or Codex
3
+ # (~/.codex/AGENTS.md, wrapped in markers so re-runs replace the block).
4
+ #
5
+ # Usage:
6
+ # setup-rule.sh <rule-name> [claude-code|codex]
7
+ #
8
+ # rule-name corresponds to a file at rules/<rule-name>.md in this repo. Marker
9
+ # label is derived from the rule slug (e.g. anti-patterns -> Anti-Patterns,
10
+ # english -> English Coaching), with explicit overrides for the established
11
+ # product names so existing AGENTS.md installs remain idempotent.
12
+ set -e
13
+
14
+ RULE="${1:-}"
15
+ TARGET="${2:-claude-code}"
16
+ WAZA_REF="${WAZA_REF:-v3.25.0}"
17
+
18
+ if [ -z "$RULE" ]; then
19
+ echo "Usage: setup-rule.sh <rule-name> [claude-code|codex]" >&2
20
+ echo "Examples: setup-rule.sh anti-patterns" >&2
21
+ echo " setup-rule.sh english codex" >&2
22
+ exit 1
23
+ fi
24
+
25
+ case "$RULE" in
26
+ *[!a-z0-9-]* | -* | *- | "")
27
+ echo "Error: rule-name must match [a-z0-9][a-z0-9-]*[a-z0-9]." >&2
28
+ exit 1
29
+ ;;
30
+ esac
31
+
32
+ case "$WAZA_REF" in
33
+ main|v[0-9]*.[0-9]*.[0-9]*) ;;
34
+ *)
35
+ echo "Error: WAZA_REF must be main or a release tag like v3.24.0." >&2
36
+ exit 1
37
+ ;;
38
+ esac
39
+
40
+ RAW="https://raw.githubusercontent.com/tw93/Waza/${WAZA_REF}/rules/${RULE}.md"
41
+
42
+ # Marker label = how the block appears in ~/.codex/AGENTS.md. Established names
43
+ # kept verbatim so existing installs keep matching their original start/end
44
+ # markers; new rules fall back to a Title Case rendering of the slug.
45
+ case "$RULE" in
46
+ english) MARKER_LABEL="English Coaching" ;;
47
+ anti-patterns) MARKER_LABEL="Anti-Patterns" ;;
48
+ *)
49
+ MARKER_LABEL="$(printf '%s' "$RULE" | tr '-' ' ' | awk '{ for (i=1;i<=NF;i++) $i = toupper(substr($i,1,1)) tolower(substr($i,2)); print }')"
50
+ ;;
51
+ esac
52
+
53
+ if ! command -v curl >/dev/null 2>&1; then
54
+ echo "Error: curl is required but not installed." >&2
55
+ exit 1
56
+ fi
57
+
58
+ case "$TARGET" in
59
+ claude-code|claude)
60
+ mkdir -p "$HOME/.claude/rules"
61
+ curl -fsSL "$RAW" -o "$HOME/.claude/rules/${RULE}.md"
62
+ echo "Waza ${MARKER_LABEL} installed for Claude Code."
63
+ ;;
64
+
65
+ codex)
66
+ if ! command -v python3 >/dev/null 2>&1; then
67
+ echo "Error: python3 is required but not installed." >&2
68
+ exit 1
69
+ fi
70
+
71
+ mkdir -p "$HOME/.codex"
72
+ tmp="$(mktemp)"
73
+ trap 'rm -f "$tmp"' EXIT
74
+ curl -fsSL "$RAW" -o "$tmp"
75
+
76
+ # Inline Python: this script is installed via `curl | bash` (no companion
77
+ # .py file on the user's machine), so the AGENTS.md edit logic stays self-
78
+ # contained here. py_compile cannot syntax-check it; bash -n catches
79
+ # quoting bugs in the shell layer.
80
+ MARKER_LABEL="$MARKER_LABEL" python3 - "$tmp" "$HOME/.codex/AGENTS.md" <<'PYEOF'
81
+ import os
82
+ import sys
83
+ from pathlib import Path
84
+
85
+ label = os.environ["MARKER_LABEL"]
86
+ source = Path(sys.argv[1]).read_text().strip()
87
+ target = Path(sys.argv[2])
88
+ start = f"<!-- Waza {label}: start -->"
89
+ end = f"<!-- Waza {label}: end -->"
90
+ block = f"{start}\n{source}\n{end}\n"
91
+ text = target.read_text() if target.exists() else ""
92
+
93
+ if start in text and end in text:
94
+ before = text.split(start, 1)[0].rstrip()
95
+ after = text.split(end, 1)[1].lstrip()
96
+ text = f"{before}\n\n{block}\n{after}".rstrip() + "\n"
97
+ else:
98
+ text = text.rstrip() + "\n\n" + block
99
+
100
+ target.write_text(text)
101
+ PYEOF
102
+ echo "Waza ${MARKER_LABEL} installed for Codex."
103
+ ;;
104
+
105
+ *)
106
+ echo "Usage: setup-rule.sh <rule-name> [claude-code|codex]" >&2
107
+ exit 1
108
+ ;;
109
+ esac
@@ -0,0 +1,127 @@
1
+ #!/bin/bash
2
+ # Install Waza statusline into Claude Code
3
+ set -e
4
+
5
+ CLAUDE_DIR="$HOME/.claude"
6
+ DEST="$CLAUDE_DIR/statusline.sh"
7
+ SETTINGS_FILE="$CLAUDE_DIR/settings.json"
8
+ WAZA_REF="${WAZA_REF:-v3.25.0}"
9
+
10
+ case "$WAZA_REF" in
11
+ main|v[0-9]*.[0-9]*.[0-9]*) ;;
12
+ *)
13
+ echo "Error: WAZA_REF must be main or a release tag like v3.24.0." >&2
14
+ exit 1
15
+ ;;
16
+ esac
17
+
18
+ RAW="https://raw.githubusercontent.com/tw93/Waza/${WAZA_REF}/scripts/statusline.sh"
19
+
20
+ if ! command -v curl &>/dev/null; then
21
+ echo "Error: curl is required but not installed." >&2
22
+ exit 1
23
+ fi
24
+
25
+ if ! command -v python3 &>/dev/null; then
26
+ echo "Error: python3 is required but not installed." >&2
27
+ exit 1
28
+ fi
29
+
30
+ if ! command -v jq &>/dev/null; then
31
+ if command -v brew &>/dev/null; then
32
+ echo "Installing jq via Homebrew..."
33
+ brew install jq
34
+ else
35
+ echo "Error: jq is required but not installed." >&2
36
+ echo " macOS: brew install jq" >&2
37
+ echo " Linux: sudo apt-get install jq or sudo dnf install jq" >&2
38
+ exit 1
39
+ fi
40
+ fi
41
+
42
+ mkdir -p "$CLAUDE_DIR"
43
+
44
+ # Refuse to modify an invalid settings file. Overwriting it would drop unrelated keys.
45
+ if [ -f "$SETTINGS_FILE" ]; then
46
+ SETTINGS_FILE="$SETTINGS_FILE" python3 - <<'PYEOF'
47
+ import json
48
+ import os
49
+ import sys
50
+
51
+ path = os.environ["SETTINGS_FILE"]
52
+ try:
53
+ with open(path) as f:
54
+ json.load(f)
55
+ except Exception as exc:
56
+ print(f"Error: {path} is not valid JSON. Refusing to modify it.", file=sys.stderr)
57
+ print(f"Reason: {exc}", file=sys.stderr)
58
+ sys.exit(1)
59
+ PYEOF
60
+ fi
61
+
62
+ # Check for existing statusLine (skip if already Waza)
63
+ EXISTING=$(SETTINGS_FILE="$SETTINGS_FILE" python3 -c "
64
+ import json, os
65
+ path = os.environ['SETTINGS_FILE']
66
+ if os.path.exists(path):
67
+ d = json.load(open(path))
68
+ sl = d.get('statusLine', {})
69
+ cmd = sl.get('command', '')
70
+ if cmd and cmd != 'bash ~/.claude/statusline.sh':
71
+ print(cmd)
72
+ " 2>/dev/null)
73
+
74
+ if [ -n "$EXISTING" ]; then
75
+ echo "Another statusline is already configured:"
76
+ echo " $EXISTING"
77
+ ans=""
78
+ prompted=0
79
+ if [ -t 0 ]; then
80
+ printf "Replace it with Waza statusline? [Y/n] "
81
+ if read -r ans; then prompted=1; fi
82
+ elif { printf "Replace it with Waza statusline? [Y/n] " >/dev/tty; } 2>/dev/null \
83
+ && read -r ans </dev/tty 2>/dev/null; then
84
+ prompted=1
85
+ fi
86
+ if [ "$prompted" -eq 0 ]; then
87
+ echo "Non-interactive shell with no controlling TTY; keeping existing statusline."
88
+ echo "Re-run interactively (or set WAZA_REPLACE_STATUSLINE=1) to replace it."
89
+ if [ "${WAZA_REPLACE_STATUSLINE:-}" != "1" ]; then
90
+ exit 0
91
+ fi
92
+ ans="y"
93
+ fi
94
+ if [ "$ans" = "n" ] || [ "$ans" = "N" ]; then
95
+ echo "Skipped. Existing statusline kept."
96
+ exit 0
97
+ fi
98
+ fi
99
+
100
+ # Download statusline script (after any confirmation prompt)
101
+ curl -fsSL "$RAW" -o "$DEST"
102
+ chmod +x "$DEST"
103
+
104
+ # Write statusLine into ~/.claude/settings.json
105
+ SETTINGS_FILE="$SETTINGS_FILE" python3 - <<'PYEOF'
106
+ import json
107
+ import os
108
+ import tempfile
109
+
110
+ path = os.environ["SETTINGS_FILE"]
111
+ d = {}
112
+ if os.path.exists(path):
113
+ with open(path) as f:
114
+ d = json.load(f)
115
+
116
+ d["statusLine"] = {"type": "command", "command": "bash ~/.claude/statusline.sh"}
117
+
118
+ directory = os.path.dirname(path)
119
+ fd, tmp_path = tempfile.mkstemp(prefix="settings.", suffix=".json.tmp", dir=directory)
120
+ with os.fdopen(fd, "w") as f:
121
+ json.dump(d, f, indent=2)
122
+ f.write("\n")
123
+ os.replace(tmp_path, path)
124
+ PYEOF
125
+
126
+ echo "Waza statusline installed. Restart Claude Code to activate."
127
+ echo "Tip: if you see a 513 error after switching Claude accounts, remove the statusLine entry from ~/.claude/settings.json, restart Claude Code, then re-run this script."