@tw93/waza 3.28.0 → 3.29.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.
- package/README.md +10 -2
- package/package.json +1 -1
- package/rules/anti-patterns.md +18 -18
- package/scripts/build_metadata.py +214 -21
- package/scripts/check-update.sh +39 -0
- package/scripts/dispatcher-template.md +2 -0
- package/scripts/dispatcher.md +2 -0
- package/scripts/setup-rule.sh +1 -1
- package/scripts/setup-statusline.sh +1 -1
- package/scripts/skill_checks.py +184 -3
- package/scripts/statusline.sh +98 -11
- package/skills/check/SKILL.md +19 -3
- package/skills/check/references/project-context.md +16 -1
- package/skills/check/references/public-reply.md +3 -2
- package/skills/design/SKILL.md +5 -1
- package/skills/health/SKILL.md +3 -1
- package/skills/hunt/SKILL.md +4 -1
- package/skills/hunt/references/failure-patterns.md +9 -0
- package/skills/learn/SKILL.md +3 -1
- package/skills/read/SKILL.md +3 -1
- package/skills/think/SKILL.md +7 -1
- package/skills/write/SKILL.md +3 -1
- package/skills/write/references/write-zh-release-notes.md +2 -0
package/scripts/skill_checks.py
CHANGED
|
@@ -46,6 +46,7 @@ FORCED_GITHUB_TOOL_RE = re.compile(
|
|
|
46
46
|
r'for\s+all\s+GitHub\s+interactions,\s+not\s+MCP\s+or\s+raw\s+API)',
|
|
47
47
|
re.IGNORECASE,
|
|
48
48
|
)
|
|
49
|
+
CJK_RE = re.compile(r"[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]")
|
|
49
50
|
|
|
50
51
|
DURABLE_CONTEXT_SKILLS = {"think", "check", "hunt", "design", "write", "health"}
|
|
51
52
|
|
|
@@ -59,6 +60,19 @@ ATTRIBUTION_PATTERNS = (
|
|
|
59
60
|
"noreply@anthropic.com",
|
|
60
61
|
"cursoragent@cursor.com",
|
|
61
62
|
)
|
|
63
|
+
CODEX_MIRROR_IGNORED_DIRS = {
|
|
64
|
+
"__pycache__",
|
|
65
|
+
".mypy_cache",
|
|
66
|
+
".pytest_cache",
|
|
67
|
+
".ruff_cache",
|
|
68
|
+
}
|
|
69
|
+
CODEX_MIRROR_IGNORED_NAMES = {
|
|
70
|
+
".DS_Store",
|
|
71
|
+
}
|
|
72
|
+
CODEX_MIRROR_IGNORED_SUFFIXES = {
|
|
73
|
+
".pyc",
|
|
74
|
+
".pyo",
|
|
75
|
+
}
|
|
62
76
|
|
|
63
77
|
|
|
64
78
|
def pipe_count(s: str) -> int:
|
|
@@ -75,6 +89,14 @@ def pipe_count(s: str) -> int:
|
|
|
75
89
|
return n
|
|
76
90
|
|
|
77
91
|
|
|
92
|
+
def should_include_codex_mirror_file(path: Path) -> bool:
|
|
93
|
+
if any(part in CODEX_MIRROR_IGNORED_DIRS for part in path.parts):
|
|
94
|
+
return False
|
|
95
|
+
if path.name in CODEX_MIRROR_IGNORED_NAMES:
|
|
96
|
+
return False
|
|
97
|
+
return path.suffix not in CODEX_MIRROR_IGNORED_SUFFIXES
|
|
98
|
+
|
|
99
|
+
|
|
78
100
|
def check_skill_files(root: Path):
|
|
79
101
|
skill_files = sorted((root / "skills").glob("*/SKILL.md"))
|
|
80
102
|
if not skill_files:
|
|
@@ -105,7 +127,14 @@ def check_skill_files(root: Path):
|
|
|
105
127
|
|
|
106
128
|
|
|
107
129
|
def check_marketplace(root: Path, expected_version: str, skill_names: set[str], skill_descriptions: dict[str, str]):
|
|
108
|
-
"""Validate marketplace.
|
|
130
|
+
"""Validate generated Claude Code and Codex marketplace metadata."""
|
|
131
|
+
check_claude_marketplace(root, expected_version, skill_names, skill_descriptions)
|
|
132
|
+
check_codex_plugin(root, expected_version)
|
|
133
|
+
check_codex_marketplace(root)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def check_claude_marketplace(root: Path, expected_version: str, skill_names: set[str], skill_descriptions: dict[str, str]):
|
|
137
|
+
"""Validate Claude Code marketplace.json shape:
|
|
109
138
|
|
|
110
139
|
- One bundle entry: name == "waza", source == "./".
|
|
111
140
|
- Per-skill entries: name == "waza-<skill>", source == "./skills/<skill>".
|
|
@@ -202,6 +231,138 @@ def check_marketplace(root: Path, expected_version: str, skill_names: set[str],
|
|
|
202
231
|
print(f"ok: all versions in lock-step with VERSION={expected_version}")
|
|
203
232
|
|
|
204
233
|
|
|
234
|
+
def check_codex_plugin(root: Path, expected_version: str):
|
|
235
|
+
"""Validate Codex plugin manifest shape."""
|
|
236
|
+
plugin_root = root / "plugins" / "waza"
|
|
237
|
+
manifest_path = plugin_root / ".codex-plugin" / "plugin.json"
|
|
238
|
+
if not manifest_path.exists():
|
|
239
|
+
fail(
|
|
240
|
+
"MISSING CODEX PLUGIN MANIFEST: expected "
|
|
241
|
+
"plugins/waza/.codex-plugin/plugin.json "
|
|
242
|
+
"so Codex can install Waza as a plugin from the repo marketplace"
|
|
243
|
+
)
|
|
244
|
+
manifest = json.loads(manifest_path.read_text())
|
|
245
|
+
required = {
|
|
246
|
+
"name": "waza",
|
|
247
|
+
"version": expected_version,
|
|
248
|
+
"skills": "./skills/",
|
|
249
|
+
"license": "MIT",
|
|
250
|
+
"homepage": "https://github.com/tw93/Waza",
|
|
251
|
+
"repository": "https://github.com/tw93/Waza",
|
|
252
|
+
}
|
|
253
|
+
for key, expected in required.items():
|
|
254
|
+
actual = manifest.get(key)
|
|
255
|
+
if actual != expected:
|
|
256
|
+
fail(
|
|
257
|
+
f"CODEX PLUGIN FIELD DRIFT: plugins/waza/.codex-plugin/plugin.json {key}="
|
|
258
|
+
f"{actual!r} expected {expected!r}"
|
|
259
|
+
)
|
|
260
|
+
if not (manifest.get("description") or "").strip():
|
|
261
|
+
fail("CODEX PLUGIN DESCRIPTION: plugins/waza/.codex-plugin/plugin.json needs description")
|
|
262
|
+
author = manifest.get("author")
|
|
263
|
+
if not isinstance(author, dict) or not author.get("name"):
|
|
264
|
+
fail("CODEX PLUGIN AUTHOR: plugins/waza/.codex-plugin/plugin.json needs author.name")
|
|
265
|
+
interface = manifest.get("interface")
|
|
266
|
+
if not isinstance(interface, dict):
|
|
267
|
+
fail("CODEX PLUGIN INTERFACE: plugins/waza/.codex-plugin/plugin.json needs interface object")
|
|
268
|
+
interface_required = {
|
|
269
|
+
"displayName": "Waza",
|
|
270
|
+
"developerName": "Tw93",
|
|
271
|
+
"category": "Developer Tools",
|
|
272
|
+
"websiteURL": "https://github.com/tw93/Waza",
|
|
273
|
+
}
|
|
274
|
+
for key, expected in interface_required.items():
|
|
275
|
+
actual = interface.get(key)
|
|
276
|
+
if actual != expected:
|
|
277
|
+
fail(
|
|
278
|
+
f"CODEX PLUGIN INTERFACE DRIFT: plugins/waza/.codex-plugin/plugin.json "
|
|
279
|
+
f"interface.{key}={actual!r} expected {expected!r}"
|
|
280
|
+
)
|
|
281
|
+
default_prompt = interface.get("defaultPrompt")
|
|
282
|
+
if (
|
|
283
|
+
not isinstance(default_prompt, list)
|
|
284
|
+
or not default_prompt
|
|
285
|
+
or len(default_prompt) > 3
|
|
286
|
+
or any(not isinstance(item, str) or len(item) > 128 for item in default_prompt)
|
|
287
|
+
):
|
|
288
|
+
fail(
|
|
289
|
+
"CODEX PLUGIN DEFAULT PROMPTS: interface.defaultPrompt must contain "
|
|
290
|
+
"1-3 strings, each <=128 chars"
|
|
291
|
+
)
|
|
292
|
+
if not (plugin_root / "skills").is_dir():
|
|
293
|
+
fail(
|
|
294
|
+
"CODEX PLUGIN SKILLS PATH: plugins/waza/.codex-plugin/plugin.json "
|
|
295
|
+
"points at missing plugins/waza/skills/"
|
|
296
|
+
)
|
|
297
|
+
for source_name in ("skills", "rules"):
|
|
298
|
+
source_root = root / source_name
|
|
299
|
+
mirror_root = plugin_root / source_name
|
|
300
|
+
for source_path in sorted(source_root.rglob("*")):
|
|
301
|
+
if not source_path.is_file():
|
|
302
|
+
continue
|
|
303
|
+
source_rel = source_path.relative_to(source_root)
|
|
304
|
+
if not should_include_codex_mirror_file(source_rel):
|
|
305
|
+
continue
|
|
306
|
+
mirror_path = mirror_root / source_rel
|
|
307
|
+
if not mirror_path.exists():
|
|
308
|
+
fail(
|
|
309
|
+
f"CODEX PLUGIN MIRROR MISSING: {mirror_path.relative_to(root)} "
|
|
310
|
+
f"must mirror {source_path.relative_to(root)}"
|
|
311
|
+
)
|
|
312
|
+
if mirror_path.read_bytes() != source_path.read_bytes():
|
|
313
|
+
fail(
|
|
314
|
+
f"CODEX PLUGIN MIRROR DRIFT: {mirror_path.relative_to(root)} "
|
|
315
|
+
f"differs from {source_path.relative_to(root)}"
|
|
316
|
+
)
|
|
317
|
+
print(f"ok: Codex plugin manifest pinned to {expected_version}")
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def check_codex_marketplace(root: Path):
|
|
321
|
+
"""Validate repo-local Codex marketplace shape."""
|
|
322
|
+
marketplace_path = root / ".agents" / "plugins" / "marketplace.json"
|
|
323
|
+
if not marketplace_path.exists():
|
|
324
|
+
fail(
|
|
325
|
+
"MISSING CODEX MARKETPLACE: expected .agents/plugins/marketplace.json "
|
|
326
|
+
"so `codex plugin marketplace add tw93/Waza` can discover Waza"
|
|
327
|
+
)
|
|
328
|
+
marketplace = json.loads(marketplace_path.read_text())
|
|
329
|
+
if marketplace.get("name") != "waza":
|
|
330
|
+
fail("CODEX MARKETPLACE NAME: .agents/plugins/marketplace.json name must be 'waza'")
|
|
331
|
+
interface = marketplace.get("interface")
|
|
332
|
+
if not isinstance(interface, dict) or interface.get("displayName") != "Waza":
|
|
333
|
+
fail(
|
|
334
|
+
"CODEX MARKETPLACE DISPLAY NAME: .agents/plugins/marketplace.json "
|
|
335
|
+
"must set interface.displayName to 'Waza'"
|
|
336
|
+
)
|
|
337
|
+
plugins = marketplace.get("plugins")
|
|
338
|
+
if not isinstance(plugins, list) or len(plugins) != 1:
|
|
339
|
+
fail("CODEX MARKETPLACE PLUGINS: expected exactly one Waza plugin entry")
|
|
340
|
+
entry = plugins[0]
|
|
341
|
+
expected_entry = {
|
|
342
|
+
"name": "waza",
|
|
343
|
+
"source": {
|
|
344
|
+
"source": "local",
|
|
345
|
+
"path": "./plugins/waza",
|
|
346
|
+
},
|
|
347
|
+
"policy": {
|
|
348
|
+
"installation": "AVAILABLE",
|
|
349
|
+
"authentication": "ON_INSTALL",
|
|
350
|
+
},
|
|
351
|
+
"category": "Developer Tools",
|
|
352
|
+
}
|
|
353
|
+
if entry != expected_entry:
|
|
354
|
+
fail(
|
|
355
|
+
"CODEX MARKETPLACE ENTRY DRIFT: .agents/plugins/marketplace.json "
|
|
356
|
+
f"plugins[0]={entry!r} expected {expected_entry!r}"
|
|
357
|
+
)
|
|
358
|
+
if not (root / "plugins" / "waza" / ".codex-plugin" / "plugin.json").exists():
|
|
359
|
+
fail(
|
|
360
|
+
"CODEX MARKETPLACE SOURCE: source.path './plugins/waza' must resolve to a plugin "
|
|
361
|
+
"root containing .codex-plugin/plugin.json"
|
|
362
|
+
)
|
|
363
|
+
print("ok: Codex marketplace exposes waza plugin")
|
|
364
|
+
|
|
365
|
+
|
|
205
366
|
def check_references(root: Path, skill_files: list[Path]):
|
|
206
367
|
for path in skill_files:
|
|
207
368
|
skill_dir = path.parent.name
|
|
@@ -245,6 +406,11 @@ def check_description_conformance(skill_descriptions: dict[str, str]):
|
|
|
245
406
|
f"DESCRIPTION MISSING EXCLUSION CLAUSE: {skill}\n"
|
|
246
407
|
f" Must contain a 'Not for ...' clause so the resolver learns when NOT to fire. Got: {clean[:120]!r}"
|
|
247
408
|
)
|
|
409
|
+
if CJK_RE.search(clean):
|
|
410
|
+
fail(
|
|
411
|
+
f"DESCRIPTION CONTAINS CJK: {skill}\n"
|
|
412
|
+
f" Keep public-facing description metadata English-only. Put multilingual trigger phrases in when_to_use."
|
|
413
|
+
)
|
|
248
414
|
print(f"ok: description {skill} ({length} chars)")
|
|
249
415
|
|
|
250
416
|
|
|
@@ -638,6 +804,21 @@ def check_readme_install_command(root: Path):
|
|
|
638
804
|
f"README INSTALL COMMAND: README.md must include {expected!r}\n"
|
|
639
805
|
f" Waza's public install path depends on this exact string."
|
|
640
806
|
)
|
|
807
|
+
expected_codex_marketplace = "codex plugin marketplace add tw93/Waza"
|
|
808
|
+
if expected_codex_marketplace not in text:
|
|
809
|
+
fail(
|
|
810
|
+
"README CODEX MARKETPLACE COMMAND: README.md must include "
|
|
811
|
+
f"{expected_codex_marketplace!r}\n"
|
|
812
|
+
f" Codex plugin installs should use the repo marketplace so users can "
|
|
813
|
+
f"upgrade without rerunning npx skills add."
|
|
814
|
+
)
|
|
815
|
+
expected_codex_install = "codex plugin add waza@waza"
|
|
816
|
+
if expected_codex_install not in text:
|
|
817
|
+
fail(
|
|
818
|
+
"README CODEX PLUGIN COMMAND: README.md must include "
|
|
819
|
+
f"{expected_codex_install!r}\n"
|
|
820
|
+
f" The Codex marketplace entry must document the plugin install selector."
|
|
821
|
+
)
|
|
641
822
|
expected_pi = "pi install npm:@tw93/waza"
|
|
642
823
|
if expected_pi not in text:
|
|
643
824
|
fail(
|
|
@@ -668,8 +849,8 @@ def check_readme_install_command(root: Path):
|
|
|
668
849
|
f"without per-release README churn."
|
|
669
850
|
)
|
|
670
851
|
print(
|
|
671
|
-
"ok: README installs nested skills,
|
|
672
|
-
"and latest installer assets"
|
|
852
|
+
"ok: README installs nested skills, Codex plugin marketplace, Pi package, "
|
|
853
|
+
"Antigravity, OpenCode, and latest installer assets"
|
|
673
854
|
)
|
|
674
855
|
|
|
675
856
|
|
package/scripts/statusline.sh
CHANGED
|
@@ -10,6 +10,7 @@ HIGHWATER_LOCK_DIR="$CACHE_DIR/highwater.lock"
|
|
|
10
10
|
CACHE_MAX_AGE=21600 # 6 hours: one full rate_limit window
|
|
11
11
|
HIGHWATER_LOCK_MAX_AGE=10
|
|
12
12
|
HIGHWATER_RESET_SKEW_MAX=7200 # tolerate session jitter, reject crossed windows
|
|
13
|
+
HIGHWATER_DROP_RESET_MIN=5 # fresh lower live values must drop by at least 5%
|
|
13
14
|
|
|
14
15
|
input=$(cat)
|
|
15
16
|
|
|
@@ -20,6 +21,9 @@ jq_full='[
|
|
|
20
21
|
+ (.context_window.current_usage.cache_creation_input_tokens // 0)
|
|
21
22
|
+ (.context_window.current_usage.cache_read_input_tokens // 0) | tostring),
|
|
22
23
|
(.context_window.context_window_size // 0 | tostring),
|
|
24
|
+
(.session_id // "null" | tostring),
|
|
25
|
+
(.cost.total_api_duration_ms // 0 | tonumber? // 0 | floor | tostring),
|
|
26
|
+
(.context_window.total_output_tokens // 0 | tonumber? // 0 | floor | tostring),
|
|
23
27
|
(.rate_limits.five_hour.used_percentage // null | if . then (. | round | tostring) else "null" end),
|
|
24
28
|
(.rate_limits.five_hour.resets_at // "" | tostring),
|
|
25
29
|
(.rate_limits.seven_day.used_percentage // null | if . then (. | round | tostring) else "null" end),
|
|
@@ -33,6 +37,16 @@ jq_rl='[
|
|
|
33
37
|
(.rate_limits.seven_day.resets_at // "" | tostring)
|
|
34
38
|
] | @tsv'
|
|
35
39
|
|
|
40
|
+
jq_hw='[
|
|
41
|
+
(.five_hour.used_percentage // null | if . then (. | round | tostring) else "null" end),
|
|
42
|
+
(.five_hour.resets_at // "null" | tostring),
|
|
43
|
+
(.seven_day.used_percentage // null | if . then (. | round | tostring) else "null" end),
|
|
44
|
+
(.seven_day.resets_at // "null" | tostring),
|
|
45
|
+
(._last.session_id // "null" | tostring),
|
|
46
|
+
(._last.api_duration_ms // 0 | tonumber? // 0 | floor | tostring),
|
|
47
|
+
(._last.output_tokens // 0 | tonumber? // 0 | floor | tostring)
|
|
48
|
+
] | @tsv'
|
|
49
|
+
|
|
36
50
|
cache_file_mtime() {
|
|
37
51
|
local path="$1"
|
|
38
52
|
local ts=""
|
|
@@ -79,11 +93,40 @@ read_highwater() {
|
|
|
79
93
|
hw_5h_reset=""
|
|
80
94
|
hw_7d_pct=""
|
|
81
95
|
hw_7d_reset=""
|
|
96
|
+
hw_last_session_id=""
|
|
97
|
+
hw_last_api_ms="0"
|
|
98
|
+
hw_last_output_tokens="0"
|
|
82
99
|
[ -f "$HIGHWATER_FILE" ] || return
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
highwater_data=$(jq -r "$jq_hw" "$HIGHWATER_FILE" 2>/dev/null)
|
|
101
|
+
IFS="$tab" read -r hw_5h_pct hw_5h_reset hw_7d_pct hw_7d_reset hw_last_session_id hw_last_api_ms hw_last_output_tokens <<EOF
|
|
102
|
+
$highwater_data
|
|
103
|
+
EOF
|
|
104
|
+
[ "$hw_5h_pct" = "null" ] && hw_5h_pct=""
|
|
105
|
+
[ "$hw_5h_reset" = "null" ] && hw_5h_reset=""
|
|
106
|
+
[ "$hw_7d_pct" = "null" ] && hw_7d_pct=""
|
|
107
|
+
[ "$hw_7d_reset" = "null" ] && hw_7d_reset=""
|
|
108
|
+
[ "$hw_last_session_id" = "null" ] && hw_last_session_id=""
|
|
109
|
+
is_uint "$hw_last_api_ms" || hw_last_api_ms=0
|
|
110
|
+
is_uint "$hw_last_output_tokens" || hw_last_output_tokens=0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
json_quote() {
|
|
114
|
+
printf '%s' "$1" | jq -Rs . 2>/dev/null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
compute_fresh_activity() {
|
|
118
|
+
fresh_activity=0
|
|
119
|
+
[ "$live_rate_limits_present" = "1" ] || return
|
|
120
|
+
[ -n "$live_session_id" ] && [ "$live_session_id" != "null" ] || return
|
|
121
|
+
[ "$live_session_id" = "$hw_last_session_id" ] || return
|
|
122
|
+
is_uint "$live_api_ms" || live_api_ms=0
|
|
123
|
+
is_uint "$live_output_tokens" || live_output_tokens=0
|
|
124
|
+
is_uint "$hw_last_api_ms" || hw_last_api_ms=0
|
|
125
|
+
is_uint "$hw_last_output_tokens" || hw_last_output_tokens=0
|
|
126
|
+
if [ "$live_api_ms" -gt "$hw_last_api_ms" ] 2>/dev/null \
|
|
127
|
+
|| [ "$live_output_tokens" -gt "$hw_last_output_tokens" ] 2>/dev/null; then
|
|
128
|
+
fresh_activity=1
|
|
129
|
+
fi
|
|
87
130
|
}
|
|
88
131
|
|
|
89
132
|
# apply_hw: compares live vs high-water marks for a single counter (5h or 7d).
|
|
@@ -132,28 +175,62 @@ apply_hw() {
|
|
|
132
175
|
applied_hw_reset="$hw_reset"
|
|
133
176
|
return
|
|
134
177
|
fi
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
178
|
+
if [ "$hw_ok" = "0" ] || [ "$live_pct" -gt "$hw_pct" ] 2>/dev/null; then
|
|
179
|
+
applied_pct="$live_pct"
|
|
180
|
+
applied_reset="$live_reset"
|
|
181
|
+
applied_hw_pct="$live_pct"
|
|
182
|
+
applied_hw_reset="$live_reset"
|
|
183
|
+
return
|
|
184
|
+
fi
|
|
185
|
+
if [ "$fresh_activity" = "1" ] \
|
|
186
|
+
&& is_uint "$live_reset" && is_uint "$hw_reset" \
|
|
187
|
+
&& [ "$live_pct" -lt "$hw_pct" ] 2>/dev/null \
|
|
188
|
+
&& [ $((hw_pct - live_pct)) -ge "$HIGHWATER_DROP_RESET_MIN" ] 2>/dev/null; then
|
|
189
|
+
applied_pct="$live_pct"
|
|
190
|
+
applied_reset="$live_reset"
|
|
191
|
+
applied_hw_pct="$live_pct"
|
|
192
|
+
applied_hw_reset="$live_reset"
|
|
193
|
+
return
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
applied_pct="$hw_pct"
|
|
197
|
+
applied_reset="${live_reset:-$hw_reset}"
|
|
198
|
+
applied_hw_pct="$hw_pct"
|
|
199
|
+
applied_hw_reset="$hw_reset"
|
|
139
200
|
}
|
|
140
201
|
|
|
141
202
|
write_highwater() {
|
|
142
203
|
is_uint "$new_hw_5h_pct" || is_uint "$new_hw_7d_pct" || return
|
|
143
204
|
mkdir -p "$CACHE_DIR" 2>/dev/null || return
|
|
144
205
|
local r5="${new_hw_5h_reset:-0}" r7="${new_hw_7d_reset:-0}"
|
|
206
|
+
local wrote=0 sid_json
|
|
145
207
|
is_uint "$r5" || r5=0
|
|
146
208
|
is_uint "$r7" || r7=0
|
|
147
209
|
if ! {
|
|
148
210
|
{
|
|
149
211
|
printf '{\n'
|
|
212
|
+
if [ "$live_rate_limits_present" = "1" ] \
|
|
213
|
+
&& [ -n "$live_session_id" ] && [ "$live_session_id" != "null" ]; then
|
|
214
|
+
sid_json=$(json_quote "$live_session_id")
|
|
215
|
+
printf ' "_last": {"session_id": %s, "api_duration_ms": %s, "output_tokens": %s}' \
|
|
216
|
+
"${sid_json:-\"\"}" "${live_api_ms:-0}" "${live_output_tokens:-0}"
|
|
217
|
+
wrote=1
|
|
218
|
+
elif [ -n "$hw_last_session_id" ]; then
|
|
219
|
+
sid_json=$(json_quote "$hw_last_session_id")
|
|
220
|
+
printf ' "_last": {"session_id": %s, "api_duration_ms": %s, "output_tokens": %s}' \
|
|
221
|
+
"${sid_json:-\"\"}" "${hw_last_api_ms:-0}" "${hw_last_output_tokens:-0}"
|
|
222
|
+
wrote=1
|
|
223
|
+
fi
|
|
150
224
|
if is_uint "$new_hw_5h_pct"; then
|
|
225
|
+
[ "$wrote" = "1" ] && printf ',\n'
|
|
151
226
|
printf ' "five_hour": {"used_percentage": %s, "resets_at": %s}' "$new_hw_5h_pct" "$r5"
|
|
152
|
-
|
|
153
|
-
printf '\n'
|
|
227
|
+
wrote=1
|
|
154
228
|
fi
|
|
155
229
|
if is_uint "$new_hw_7d_pct"; then
|
|
230
|
+
[ "$wrote" = "1" ] && printf ',\n'
|
|
156
231
|
printf ' "seven_day": {"used_percentage": %s, "resets_at": %s}\n' "$new_hw_7d_pct" "$r7"
|
|
232
|
+
else
|
|
233
|
+
printf '\n'
|
|
157
234
|
fi
|
|
158
235
|
printf '}\n'
|
|
159
236
|
} > "${HIGHWATER_FILE}.tmp" 2>/dev/null \
|
|
@@ -165,6 +242,7 @@ write_highwater() {
|
|
|
165
242
|
|
|
166
243
|
apply_highwater_all() {
|
|
167
244
|
read_highwater
|
|
245
|
+
compute_fresh_activity
|
|
168
246
|
|
|
169
247
|
apply_hw "$five_pct" "$five_reset" "$hw_5h_pct" "$hw_5h_reset"
|
|
170
248
|
five_pct="$applied_pct"
|
|
@@ -183,14 +261,23 @@ apply_highwater_all() {
|
|
|
183
261
|
parsed=""
|
|
184
262
|
[ -n "$input" ] && parsed=$(printf '%s' "$input" | jq -r "$jq_full" 2>/dev/null)
|
|
185
263
|
|
|
186
|
-
IFS="$tab" read -r used_tokens window_size live_five_pct live_five_reset live_seven_pct live_seven_reset <<EOF
|
|
264
|
+
IFS="$tab" read -r used_tokens window_size live_session_id live_api_ms live_output_tokens live_five_pct live_five_reset live_seven_pct live_seven_reset <<EOF
|
|
187
265
|
$parsed
|
|
188
266
|
EOF
|
|
189
267
|
|
|
268
|
+
live_session_id="${live_session_id:-}"
|
|
269
|
+
[ "$live_session_id" = "null" ] && live_session_id=""
|
|
270
|
+
live_api_ms="${live_api_ms:-0}"
|
|
271
|
+
live_output_tokens="${live_output_tokens:-0}"
|
|
190
272
|
five_pct="${live_five_pct:-}"
|
|
191
273
|
five_reset="${live_five_reset:-}"
|
|
192
274
|
seven_pct="${live_seven_pct:-}"
|
|
193
275
|
seven_reset="${live_seven_reset:-}"
|
|
276
|
+
live_rate_limits_present=0
|
|
277
|
+
if { [ "$five_pct" != "null" ] && [ -n "$five_pct" ]; } \
|
|
278
|
+
|| { [ "$seven_pct" != "null" ] && [ -n "$seven_pct" ]; }; then
|
|
279
|
+
live_rate_limits_present=1
|
|
280
|
+
fi
|
|
194
281
|
|
|
195
282
|
# If rate_limits missing from live input, read from cache
|
|
196
283
|
if [ "$five_pct" = "null" ] || [ -z "$five_pct" ]; then
|
package/skills/check/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: check
|
|
3
|
-
description: "Reviews code diffs, PRs, issue queues, release readiness, commits, pushes, publishing, and project audits. Use when users ask review
|
|
3
|
+
description: "Reviews code diffs, PRs, issue queues, release readiness, commits, pushes, publishing, and project audits. Use when users ask in any language for code review, issue or PR triage, release gates, publishing follow-through, or project audits. Not for debugging root causes or prose review."
|
|
4
4
|
when_to_use: "review, 看看代码, 检查一下, 有没有问题, 是否需要优化, 合并前, 继续优化, 优化代码, 看看issue, 看看PR, release, publish, push, release reaction, GitHub reaction, 发布, 提交, 关闭issue, 发布表情, release表情, close issue, issue close, review my code, check changes, before merge, before release, code review, code-review, audit, project audit, 项目体检, 项目评分, 给项目打分, 深入分析项目代码, 评估项目质量, 代码质量评分, scorecard, linus review, rate this codebase, score this project"
|
|
5
5
|
dispatch_intent: "Code review, before merge, release gates, generated artifacts, safety sinks, publish/push/reaction follow-through, triage issues/PRs, project-wide code-quality audit scorecard"
|
|
6
6
|
---
|
|
@@ -9,6 +9,8 @@ dispatch_intent: "Code review, before merge, release gates, generated artifacts,
|
|
|
9
9
|
|
|
10
10
|
Prefix your first line with 🥷 inline, not as its own paragraph.
|
|
11
11
|
|
|
12
|
+
**Update check (non-blocking).** Before starting, run `bash ../../scripts/check-update.sh` once; if it prints a line, relay it to the user, then continue. It runs at most once a day, only reads a public version file, sends no data, and fails silently.
|
|
13
|
+
|
|
12
14
|
> Note: `/review` is a built-in Anthropic plugin command for PR review. Waza uses `/check` (or the alias `code-review`) instead. Do not re-trigger `/review` from within this skill.
|
|
13
15
|
|
|
14
16
|
Read the diff, find the problems, fix what can be fixed safely, ask about the rest. Done means verification ran in this session and passed.
|
|
@@ -106,7 +108,7 @@ Activate when the user mentions: issue, PR, "review all", triage, "batch", or "
|
|
|
106
108
|
|
|
107
109
|
**Status answer order:** For "都解决了吗", "is this fixed", "is this ready", or similar status checks, answer in this order: code or commit state, branch or CI state, release artifact or registry state, then public issue or PR state. Do not collapse fixed-on-main, available in pre-release, next stable release, and already shipped.
|
|
108
110
|
|
|
109
|
-
**Flow:** First identify the project's issue/PR host from public context. For GitHub projects, pull open items with `gh issue list -R <repo> --state open --limit 20` and `gh pr list -R <repo> --state open`. For non-GitHub projects, use the platform CLI/API named by the project docs or user request; if none exists, stop and report the missing integration instead of pretending GitHub commands apply. For each item, check
|
|
111
|
+
**Flow:** First identify the project's issue/PR host from public context. For GitHub projects, pull open items with `gh issue list -R <repo> --state open --limit 20` and `gh pr list -R <repo> --state open`. For non-GitHub projects, use the platform CLI/API named by the project docs or user request; if none exists, stop and report the missing integration instead of pretending GitHub commands apply. For each item, check current state with the project's release boundary: latest public release, main branch, preview/nightly/beta channel, registry/appcast, and target issue/PR status. If the fix is already in the current public release or documented pre-release channel, close with that exact upgrade path. If fixed on `main` but unreleased, reply "已修复,等下一个版本 release" and close only when project convention or the current user request allows fixed-on-main closure; otherwise leave it open with the next-release note. If no fix exists, analyze and act. Fix now if possible (`fix: closes #N` commit); for valid-but-unreleased items acknowledge and leave open; for invalid items give one-two sentence reason and close.
|
|
110
112
|
|
|
111
113
|
Before final conclusions in a live queue, refresh the issue/PR list once more and re-read any item that changed during the run. If evidence is incomplete, hold the item instead of closing it on a guess.
|
|
112
114
|
|
|
@@ -141,7 +143,8 @@ This mode extends review; it does not skip review. Before any public or irrevers
|
|
|
141
143
|
1. Extract release rules from public project context: README, manifests, CI workflows, release notes, package scripts, changelogs, and explicit user instructions in the current thread.
|
|
142
144
|
2. Fill the Release Gate 2.0 matrix from `references/project-context.md`: review base, dirty/staged/untracked state, latest tag, origin sync, version fields, generated artifacts, package/archive contents, release assets, registry/appcast/CI, and public issue/PR state.
|
|
143
145
|
3. Verify generated or bundled outputs, version fields, release notes, package contents, and required artifacts are in sync. Prefer dry-run commands when the ecosystem provides them.
|
|
144
|
-
Generated deliverables include tracked archives, ignored dist files, appcasts, site/download copy, registry packages, checksums, and release assets. If project docs require them, regenerate, inspect, and stage or upload them explicitly even when they are ignored by git; do not infer readiness from source-only tests.
|
|
146
|
+
Generated deliverables include tracked archives, ignored dist files, appcasts, site/download copy, registry packages, checksums, and release assets. If project docs require them, regenerate, inspect, and stage or upload them explicitly even when they are ignored by git; do not infer readiness from source-only tests. For remote assets, prefer downloading or reading back the published artifact and comparing entries, checksums, or manifest contents; release page text, file size, or workflow success alone is not artifact proof.
|
|
147
|
+
If the project has preview, beta, nightly, stable, or App Store lanes, name the lane explicitly. Do not use a preview or beta artifact to claim stable release readiness, and do not touch stable appcast, registry, or download surfaces when the requested lane is preview-only unless project docs require it.
|
|
145
148
|
4. Commit only intended files. Preserve unrelated dirty work, serialize git operations so index locks or overlapping adds do not corrupt the workflow, and re-check HEAD/status before pushing so concurrent agent or maintainer commits are not swept into your ship action.
|
|
146
149
|
5. Push, publish, tag, or create a release only when the user has explicitly approved that action. If auth, OTP, CI, registry, or network state blocks the operation, pause and report the exact blocker.
|
|
147
150
|
6. For issue/PR follow-through, confirm the item identity with the host's read command before posting. On GitHub, use `gh issue view` or `gh pr view`; on other hosts, use the CLI/API named by project docs or the current request. Use `references/public-reply.md` for the maintainer reply template (mention, single thanks, facts, explicit next release or verification step) and its closure criteria.
|
|
@@ -229,6 +232,8 @@ Measure the diff and classify depth:
|
|
|
229
232
|
|
|
230
233
|
State the depth before proceeding.
|
|
231
234
|
|
|
235
|
+
Static content diffs can stay quick even when they touch several generated files: version strings, dates, release-copy mirrors, sitemap dates, or one-for-one localization copy changes usually need line-by-line readback plus grep consistency, not a specialist fleet. Escalate only when the diff changes logic, generation rules, public distribution behavior, or user-facing semantics beyond the literal text replacement.
|
|
236
|
+
|
|
232
237
|
## Did We Build What Was Asked?
|
|
233
238
|
|
|
234
239
|
Before reading code, check scope drift: do the diff and the stated goal match? Label: **on target** / **drift** / **incomplete**.
|
|
@@ -259,6 +264,16 @@ Check command contract and installed-runtime behavior, not just library tests: h
|
|
|
259
264
|
|
|
260
265
|
For mutating CLI commands, also run the Safety Sink Review: dry-run or confirmation path, operation log or rollback story, retry/idempotency, signal/partial-failure handling, and test-mode guards for auth prompts or real system changes. For cleanup, uninstall, prune, reset, or cache-removal commands, add two checks before approval: can a normal user verify each selected item is safe, and is the deleted content locally rebuildable rather than a downloaded dependency or user data? If either answer is no, require narrower matching, explicit user selection, or leave the item visible but non-destructive.
|
|
261
266
|
|
|
267
|
+
## Skill, Plugin, And Packaged Install Surface
|
|
268
|
+
|
|
269
|
+
When a diff touches a skill, plugin, marketplace entry, installer, package allowlist, package manifest, generated mirror, or published archive, verify the installed runtime contract, not just the source tree:
|
|
270
|
+
|
|
271
|
+
1. Identify the install path a real user will get: package manager, release archive, marketplace entry, plugin source path, or installer script default ref.
|
|
272
|
+
2. Build or regenerate the package exactly as project docs require, then inspect the archive or generated mirror for every new script, reference, template, rule, manifest, and executable bit.
|
|
273
|
+
3. Run an isolated install smoke when the surface is installable: fresh temp home/config/cache, add the marketplace or package, install the skill or plugin, list it, and invoke the smallest command or entrypoint that proves scripts and references resolve from the installed path.
|
|
274
|
+
4. Filter generated mirrors and archives for cache/noise files such as `__pycache__`, `*.pyc`, `.pytest_cache`, `.ruff_cache`, `.mypy_cache`, `.DS_Store`, local logs, and screenshots unless the project explicitly ships them.
|
|
275
|
+
5. If network, auth, or host tooling prevents the install smoke, state the missing layer as a blocker or gap. Do not replace installed-runtime proof with manifest JSON, source tests, or a successful local import.
|
|
276
|
+
|
|
262
277
|
## Hard Stops (fix before merging)
|
|
263
278
|
|
|
264
279
|
Examples, not exhaustive -- flag any diff that could cause irreversible harm if merged unreviewed.
|
|
@@ -271,6 +286,7 @@ Examples, not exhaustive -- flag any diff that could cause irreversible harm if
|
|
|
271
286
|
- **Generated artifact drift**: if source changes require generated or bundled outputs, verify the output was regenerated and included.
|
|
272
287
|
- **Verifier failure layer unclear**: if a verifier fails before assertions or due to missing optional dependencies, bootstrap noise, transient build-service crashes, unavailable simulators, or tool setup, classify setup versus product failure. Retry only with new evidence or a narrower environment. Do not call the repo broken until the intended test body or artifact check actually ran.
|
|
273
288
|
- **Tracked package omissions**: if a package script builds from tracked files, allowlists, or generated manifests, verify every new helper module, reference file, template, or script used by the diff is tracked and present in the built archive before sign-off.
|
|
289
|
+
- **Manifest-only install proof**: if a diff changes a skill, plugin, installer, marketplace entry, package wrapper, or installable archive, metadata and source tests are not enough. Build or install through the real user path in an isolated environment, or mark the install/runtime layer unverified.
|
|
274
290
|
- **Version skew**: release version fields across manifests, package metadata, app configs, changelogs, tags, or lockfiles must stay synchronized.
|
|
275
291
|
- **Unknown identifiers in diff**: any function, variable, or type introduced in the diff that does not exist in the codebase is a hard stop. Grep before writing or approving any reference: `grep -r "name" .` -- no results outside the diff = does not exist.
|
|
276
292
|
- **Dead-code or YAGNI deletion without proof**: any "zero callers" or "unused" claim must be checked across the whole repository, including top-level entrypoints, docs, tests, generated dispatch tables, scripts, CI, and dynamic lookup patterns. Treat sub-agent or tool reports as leads, not proof. Before deleting, batch-grep all candidates, classify test-only references separately from production references, and chase written variables or data tables that may become orphaned together. If the grep scope is partial, do not delete.
|
|
@@ -21,11 +21,14 @@ Use this template to compress repository context before running Waza `/check`. T
|
|
|
21
21
|
- Generated or bundled artifacts that must stay in sync with source changes.
|
|
22
22
|
- Packaging source of truth: whether archives are built from `git ls-files`, explicit allowlists, generated manifests, or source directories.
|
|
23
23
|
- Delivery surfaces: whether generated outputs are tracked, ignored, external release assets, registry uploads, appcasts, installer metadata, checksums, or site/download copy; how they are regenerated, inspected, staged, or uploaded.
|
|
24
|
+
- Distribution lanes: preview, beta, nightly, stable, App Store, or registry channels, and which generated artifacts belong to each lane.
|
|
24
25
|
- CLI command surfaces: entrypoints, subcommands, flags, help/version behavior, exit codes, stdout/stderr contract, TTY and non-interactive paths, config/env precedence, and installed-runtime checks.
|
|
25
26
|
- Runtime dependencies introduced by the diff: Python packages, CLIs, network services, package managers, or platform tools that are not already declared in CI/docs.
|
|
27
|
+
- Skill, plugin, marketplace, or package install surfaces: installer default ref, marketplace source path, generated mirror, package allowlist, archive root, executable bits, and the installed-runtime smoke command.
|
|
26
28
|
- Domain-specific safety rules.
|
|
27
29
|
- Release artifacts that must exist.
|
|
28
30
|
- GitHub release reactions or other public release follow-through expected by the project.
|
|
31
|
+
- Release-asset verification method: download, archive entry comparison, checksum manifest, package metadata readback, appcast readback, or registry query.
|
|
29
32
|
- Public issue or PR reply conventions.
|
|
30
33
|
- Known CI or test flakes documented by the project and how to distinguish them from real failures.
|
|
31
34
|
- Release, publish, push, or issue-closure prerequisites documented by the project.
|
|
@@ -56,6 +59,14 @@ Use this template to compress repository context before running Waza `/check`. T
|
|
|
56
59
|
- Install/run proof: built package, temp prefix, PATH shim, shebang/executable bit, or package-manager path checked with `<command>`.
|
|
57
60
|
- Mutating commands: dry-run/confirmation, operation log, rollback/retry behavior, signal/partial-failure handling.
|
|
58
61
|
|
|
62
|
+
## Skill Or Plugin Install Surface
|
|
63
|
+
|
|
64
|
+
- User install path: `<package manager / release archive / marketplace entry / plugin id / installer script>`.
|
|
65
|
+
- Source path and generated mirror: `<source dir>` -> `<installed dir>`.
|
|
66
|
+
- Package/archive inclusion: new scripts, references, templates, rules, manifests, and executable bits checked with `<command>`.
|
|
67
|
+
- Isolated install smoke: fresh temp home/config/cache plus `<install command>` and `<list or invoke command>`.
|
|
68
|
+
- Noise filtering: cache files, local logs, screenshots, and temp outputs excluded or intentionally shipped.
|
|
69
|
+
|
|
59
70
|
## Project Hard Stops
|
|
60
71
|
|
|
61
72
|
- Do not modify `<protected path>` unless explicitly requested.
|
|
@@ -78,7 +89,9 @@ See `public-reply.md` for the full reply template (language match, `@user` + tha
|
|
|
78
89
|
|
|
79
90
|
- Version fields to check: `<manifest>`, `<app config>`, `<lockfile>`.
|
|
80
91
|
- Generated artifacts to check: `<artifact>` from `<source>`.
|
|
92
|
+
- Distribution lane: `<preview/beta/nightly/stable/etc.>` and which public surfaces it is allowed to touch.
|
|
81
93
|
- Dry-run command before publishing: `<command>`.
|
|
94
|
+
- Remote asset proof: `<download/readback command>` that checks content, manifest, digest, appcast, or registry state.
|
|
82
95
|
- GitHub release reactions to add after asset verification: `<+1/laugh/heart/hooray/rocket/eyes or none>`.
|
|
83
96
|
- Public state to re-read after publishing or closing: `<registry/release/issue URL or command>`.
|
|
84
97
|
```
|
|
@@ -95,10 +108,12 @@ Fill this before claiming a change is release-ready. Use "n/a" only when the pro
|
|
|
95
108
|
| Worktree state | Dirty, staged, and untracked files accounted for |
|
|
96
109
|
| Remote state | `origin/main` or release branch sync checked |
|
|
97
110
|
| Version fields | Manifest, app config, changelog, appcast, and lockfile versions aligned |
|
|
111
|
+
| Distribution lane | Preview, beta, nightly, stable, registry, or app-store lane named, with unrelated lanes left untouched |
|
|
98
112
|
| Runtime dependencies | Newly introduced Python packages, CLIs, package managers, and network tools declared and available in CI |
|
|
99
113
|
| Generated artifacts | Tracked archives, ignored dist outputs, bundled/minified files, appcasts, installer metadata, checksums, and site/download copy regenerated or proven not needed |
|
|
100
114
|
| Package/archive contents | Built package inspected for required files, newly introduced helpers/references, and missing extras |
|
|
101
|
-
|
|
|
115
|
+
| Installed runtime | Package, skill, plugin, CLI, or marketplace install exercised from a clean environment when the diff changes installable surfaces |
|
|
116
|
+
| Release assets | GitHub release, appcast, download archive, checksum, or installer assets downloaded or read back and verified beyond page text or file size |
|
|
102
117
|
| Registry/appcast | npm/crates/Homebrew/appcast/App Store or equivalent state re-read after publish |
|
|
103
118
|
| CI status | Latest required checks passed or blocker named |
|
|
104
119
|
| Issue/PR state | Target issue or PR re-read before commenting, closing, merging, or saying shipped |
|
|
@@ -6,8 +6,9 @@ Reusable by both Triage Mode and Ship / Release Follow-through. Default to this
|
|
|
6
6
|
2. **Language:** Match the **opener's** language when it is Chinese or English. If the opener used Japanese or Korean, use English for the maintainer reply unless project docs override.
|
|
7
7
|
3. Open with `@<login>` and **at most one** short thanks (`感谢反馈`, `thank you for the report`, etc.). Do **not** add closing thanks stacks (`再次感谢`, `Thanks again`, long courtesy endings).
|
|
8
8
|
4. One or two short paragraphs: factual reason, what shipped or what is blocked, no ceremony.
|
|
9
|
-
5.
|
|
10
|
-
6.
|
|
9
|
+
5. Name the exact boundary: already released, fixed on `main` but unreleased, available in nightly/beta/preview, next release, not planned, duplicate, or still needs evidence. Do not write "shipped", "released", or "verified" unless that state was checked in the current turn.
|
|
10
|
+
6. Always give a **next step tied to releases or verification**: next App Store or GitHub release, nightly upgrade command, cache path to clear once, or exactly what info is still needed.
|
|
11
|
+
7. Prefer **editing** an existing maintainer comment (`PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}`) when updating wording; avoid delete plus repost unless the old text must disappear from history.
|
|
11
12
|
|
|
12
13
|
## When closing
|
|
13
14
|
|
package/skills/design/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design
|
|
3
|
-
description: "Produces distinctive, production-grade UI for pages, components, visual interfaces, typography, and screenshot-driven polish. Use when users ask
|
|
3
|
+
description: "Produces distinctive, production-grade UI for pages, components, visual interfaces, typography, and screenshot-driven polish. Use when users ask in any language for UI, page, component, frontend, typography, screenshot-grounded visual polish, or complaints that a screen looks unclear, ugly, inconsistent, or visually wrong. Not for backend logic or data pipelines."
|
|
4
4
|
when_to_use: "设计, 做页面, 做组件, 不好看, 不和谐, 不清晰, 很丑, 很怪, 很傻, 突兀, 不协调, 字体, 字形, 排印, 排版, 样式, 前端, UI, 截图, build page, create component, make it look good, style, design, screenshot with visual complaint, typography, font looks wrong"
|
|
5
5
|
dispatch_intent: "UI, component, page, visual interface, frontend, artifact-grounded screenshot aesthetic complaint"
|
|
6
6
|
---
|
|
@@ -9,6 +9,8 @@ dispatch_intent: "UI, component, page, visual interface, frontend, artifact-grou
|
|
|
9
9
|
|
|
10
10
|
Prefix your first line with 🥷 inline, not as its own paragraph.
|
|
11
11
|
|
|
12
|
+
**Update check (non-blocking).** Before starting, run `bash ../../scripts/check-update.sh` once; if it prints a line, relay it to the user, then continue. It runs at most once a day, only reads a public version file, sends no data, and fails silently.
|
|
13
|
+
|
|
12
14
|
If it could have been generated by a default prompt, it is not good enough.
|
|
13
15
|
|
|
14
16
|
## Outcome Contract
|
|
@@ -73,6 +75,8 @@ Activate when the user sends a screenshot or image alongside a complaint ("这
|
|
|
73
75
|
- Do not flatten specific taste feedback into generic UI adjectives. "More premium" is not a diagnosis; "caption baseline drifts above the Chinese line" is.
|
|
74
76
|
- If the screenshot exposes a regression, broken render, timing issue, or generated asset defect rather than taste, route to `/hunt` and preserve the visual evidence.
|
|
75
77
|
|
|
78
|
+
**Native screenshot handoff.** For native apps, once you have proven the app builds, runs, and can reach the target view, do not spend repeated cycles fighting focus, window ordering, or coordinate-click automation just to capture final visual proof. Make one bounded automation attempt. If it is flaky, name the exact screen and ask the user for the screenshot to iterate against. This is a visual QA boundary, not a substitute for build/run verification.
|
|
79
|
+
|
|
76
80
|
**Boundary**: if the fix requires changing 3 or more components, or if it reveals a direction problem rather than a specific bug, pause and run the full direction lock before continuing.
|
|
77
81
|
|
|
78
82
|
**Redesign priority order** (when reworking an existing UI rather than building from scratch): font replacement → color cleanup → hover/active states → layout and whitespace → replace generic components → add loading/empty/error states → typographic polish. This order maximizes visual lift while minimizing the blast radius of each pass. Full rules in `references/design-reference.md`. Common traps and absolute CSS bans: `references/design-traps.md`.
|
package/skills/health/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: health
|
|
3
|
-
description: "Runs a budget-aware agent-assisted engineering health audit for instruction/config drift, hooks/MCP, verifier surfaces, and AI maintainability. Use when users ask
|
|
3
|
+
description: "Runs a budget-aware agent-assisted engineering health audit for instruction/config drift, hooks/MCP, verifier surfaces, and AI maintainability. Use when users ask in any language to audit Claude, Codex, Pi, agent instructions, MCP or hooks, verifier coverage, or AI-maintainability drift. Not for debugging application code or reviewing PRs."
|
|
4
4
|
when_to_use: "检查claude, 检查codex, 检查pi, Codex 配置, Pi 配置, AGENTS.md, config.toml, agent instructions, 健康度, 配置检查, 配置对不对, AI coding 腐化, 代码变烂, 维护性, 上下文混乱, 验证缺失, 验证命令失真, Claude ignoring instructions, Pi coding agent, check config, settings not working, audit config"
|
|
5
5
|
dispatch_intent: "Codex/Claude/Pi ignoring instructions, agent config audit, hooks/MCP broken, health token usage, AI coding code rot, hotspot ownership, unclear context, missing verification, stale verifier output"
|
|
6
6
|
---
|
|
@@ -9,6 +9,8 @@ dispatch_intent: "Codex/Claude/Pi ignoring instructions, agent config audit, hoo
|
|
|
9
9
|
|
|
10
10
|
Prefix your first line with 🥷 inline, not as its own paragraph.
|
|
11
11
|
|
|
12
|
+
**Update check (non-blocking).** Before starting, run `bash ../../scripts/check-update.sh` once; if it prints a line, relay it to the user, then continue. It runs at most once a day, only reads a public version file, sends no data, and fails silently.
|
|
13
|
+
|
|
12
14
|
Audit the current project's agent setup and AI coding maintainability against this framework:
|
|
13
15
|
`agent config → instruction surfaces → tools/runtime → verifiers → maintainability`
|
|
14
16
|
|