|
240 | 240 | "tier": "cheap", |
241 | 241 | "reasoning_level": "low" |
242 | 242 | } |
| 243 | + }, |
| 244 | + { |
| 245 | + "type": "Gene", |
| 246 | + "id": "gene_publish_feishu_doc", |
| 247 | + "category": "innovate", |
| 248 | + "signals_match": [ |
| 249 | + "publish_markdown_to_feishu", |
| 250 | + "create_feishu_doc", |
| 251 | + "export_report_to_feishu", |
| 252 | + "把结果发到飞书文档", |
| 253 | + "发布飞书文档", |
| 254 | + "把报告导出到飞书", |
| 255 | + "publish results to a feishu doc", |
| 256 | + "export notes to lark document", |
| 257 | + "飞书文档", |
| 258 | + "发布到飞书", |
| 259 | + "导出到飞书", |
| 260 | + "发到飞书", |
| 261 | + "lark文档", |
| 262 | + "飞书文档|lark doc|feishu doc" |
| 263 | + ], |
| 264 | + "strategy": [ |
| 265 | + "Verify the toolchain: run `lark-cli doctor` and require ok:true with at least one ready identity", |
| 266 | + "Always use the Docs v2 API (v1 is deprecated): pass `--api-version v2`", |
| 267 | + "Write the body as Lark-flavored Markdown to a temp file and pass `--content @file.md --doc-format markdown` to avoid shell-escaping bugs", |
| 268 | + "Create with the user identity so the doc is human-owned: `lark-cli docs +create --api-version v2 --as user --doc-format markdown --content @file.md`", |
| 269 | + "To place it in a folder or wiki add `--parent-token <token>` (use `--parent-position my_library` for the personal space)", |
| 270 | + "Parse data.document.url from the JSON response and return it to the user; use `docs +update --api-version v2` with the document_id to amend instead of recreating" |
| 271 | + ], |
| 272 | + "validation": [ |
| 273 | + "node --version" |
| 274 | + ], |
| 275 | + "constraints": { |
| 276 | + "max_files": 2, |
| 277 | + "forbidden_paths": [ |
| 278 | + ".git", |
| 279 | + "node_modules", |
| 280 | + "~/.lark-cli/config.json" |
| 281 | + ] |
| 282 | + }, |
| 283 | + "preconditions": [ |
| 284 | + "lark-cli installed and on PATH (npm i -g @larksuite/cli)", |
| 285 | + "lark-cli auth status reports a ready user or bot identity" |
| 286 | + ], |
| 287 | + "summary": "Publish Markdown content as a Feishu/Lark document via the official lark-cli (Docs v2). Use --as user for human-owned docs and @file content for long bodies; return the resulting document URL.", |
| 288 | + "schema_version": "1.6.0", |
| 289 | + "epigenetic_marks": [], |
| 290 | + "learning_history": [], |
| 291 | + "anti_patterns": [], |
| 292 | + "routing_hint": null, |
| 293 | + "tool_policy": null, |
| 294 | + "avoid": [ |
| 295 | + "using the deprecated Docs v1 API or the v1 --markdown flag", |
| 296 | + "passing long markdown inline (shell-escaping corrupts it) instead of --content @file", |
| 297 | + "overwriting ~/.lark-cli/config.json (holds the app secret and tokens)" |
| 298 | + ], |
| 299 | + "asset_id": "sha256:9ed275fd6394567d0eb6c0fda45193bbeaba7bd84941ea4e75eb7fc859fb0dcf" |
| 300 | + }, |
| 301 | + { |
| 302 | + "type": "Gene", |
| 303 | + "id": "gene_conventional_git_commit", |
| 304 | + "category": "optimize", |
| 305 | + "signals_match": [ |
| 306 | + "git_commit", |
| 307 | + "create_commit", |
| 308 | + "commit_changes", |
| 309 | + "conventional_commit", |
| 310 | + "提交代码", |
| 311 | + "生成提交信息", |
| 312 | + "write a commit message", |
| 313 | + "stage and commit" |
| 314 | + ], |
| 315 | + "strategy": [ |
| 316 | + "Inspect the change: `git diff --staged` if anything is staged, else `git diff`, plus `git status --porcelain`", |
| 317 | + "Pick a Conventional Commits type (feat/fix/docs/style/refactor/perf/test/build/ci/chore/revert) and optional scope from what actually changed", |
| 318 | + "Stage logically-grouped files explicitly (git add <paths>); NEVER stage or commit secrets (.env, credentials, private keys)", |
| 319 | + "Write a present-tense imperative description under 72 chars; add a body/footer for breaking changes (type! or BREAKING CHANGE:) and issue refs (Closes #N)", |
| 320 | + "Commit one logical change with `git commit -m` (heredoc for multi-line)", |
| 321 | + "Safety: never touch git config, never --force/hard-reset/--no-verify without explicit request, never force-push main; if a hook fails, fix and make a NEW commit (do not amend)" |
| 322 | + ], |
| 323 | + "validation": [ |
| 324 | + "node --version" |
| 325 | + ], |
| 326 | + "constraints": { |
| 327 | + "max_files": 50, |
| 328 | + "forbidden_paths": [ |
| 329 | + ".git", |
| 330 | + "node_modules" |
| 331 | + ] |
| 332 | + }, |
| 333 | + "preconditions": [ |
| 334 | + "a git repository with staged or unstaged changes" |
| 335 | + ], |
| 336 | + "summary": "Create a Conventional Commits-style git commit: analyze the diff to pick type/scope, stage logical groups (never secrets), and write an imperative <72-char message.", |
| 337 | + "schema_version": "1.6.0", |
| 338 | + "epigenetic_marks": [], |
| 339 | + "learning_history": [], |
| 340 | + "anti_patterns": [], |
| 341 | + "routing_hint": null, |
| 342 | + "tool_policy": null, |
| 343 | + "avoid": [ |
| 344 | + "committing secrets or unrelated changes in one commit", |
| 345 | + "amending or force-pushing to bypass a failing hook", |
| 346 | + "past-tense or vague messages like \"updated stuff\"" |
| 347 | + ], |
| 348 | + "asset_id": "sha256:505c207b9984c397255daed61c5f24fb3bfcadedb803d2a4eaa429457f08cd2f" |
| 349 | + }, |
| 350 | + { |
| 351 | + "type": "Gene", |
| 352 | + "id": "gene_poll_bugbot_review", |
| 353 | + "category": "optimize", |
| 354 | + "signals_match": [ |
| 355 | + "poll_bugbot", |
| 356 | + "bugbot_review", |
| 357 | + "wait_for_ci_review", |
| 358 | + "pr_review_gate", |
| 359 | + "等bugbot", |
| 360 | + "等待评审", |
| 361 | + "check bugbot", |
| 362 | + "review the pr", |
| 363 | + "pr opened" |
| 364 | + ], |
| 365 | + "strategy": [ |
| 366 | + "Poll the \"Cursor Bugbot\" check via `gh pr view --json statusCheckRollup` every ~60s until status=COMPLETED (cap ~10min); filter by name, not index", |
| 367 | + "On SUCCESS: safe to merge ONLY if no other required check is red AND zero open inline comments from the cursor[bot] login (note the [bot] suffix)", |
| 368 | + "On NEUTRAL: do NOT treat as pass — fetch inline comments `gh api repos/:o/:r/pulls/:n/comments` filtered to user.login==\"cursor[bot]\", surface path/line/severity, hand back to the human", |
| 369 | + "On FAILURE/ACTION_REQUIRED: surface findings, do not merge", |
| 370 | + "Auto-merge (squash + delete-branch) only when explicitly authorized AND conclusion is SUCCESS; merge conflicts/CI-red/required-review surface verbatim, never auto-fixed here" |
| 371 | + ], |
| 372 | + "validation": [ |
| 373 | + "node --version" |
| 374 | + ], |
| 375 | + "constraints": { |
| 376 | + "max_files": 1, |
| 377 | + "forbidden_paths": [ |
| 378 | + ".git", |
| 379 | + "node_modules" |
| 380 | + ] |
| 381 | + }, |
| 382 | + "preconditions": [ |
| 383 | + "an open GitHub PR in a repo where Cursor Bugbot runs" |
| 384 | + ], |
| 385 | + "summary": "Wait for Cursor Bugbot on a GitHub PR, then gate on the conclusion: SUCCESS may merge, NEUTRAL/FAILURE always pauses to surface inline findings to the human.", |
| 386 | + "schema_version": "1.6.0", |
| 387 | + "epigenetic_marks": [], |
| 388 | + "learning_history": [], |
| 389 | + "anti_patterns": [], |
| 390 | + "routing_hint": null, |
| 391 | + "tool_policy": null, |
| 392 | + "avoid": [ |
| 393 | + "treating NEUTRAL as pass (it has shipped real bugs before)", |
| 394 | + "filtering comments on \"cursor\" instead of \"cursor[bot]\" (silently returns nothing)", |
| 395 | + "auto-merging without explicit authorization or with CI red" |
| 396 | + ], |
| 397 | + "asset_id": "sha256:0f50f4cfecb0e6f3a9bd3c9c0a426e56f4f1c0230b4836a9471b38e499410ea9" |
| 398 | + }, |
| 399 | + { |
| 400 | + "type": "Gene", |
| 401 | + "id": "gene_gateway_timeout_recovery", |
| 402 | + "category": "repair", |
| 403 | + "signals_match": [ |
| 404 | + "gateway_timeout", |
| 405 | + "upstream_timeout", |
| 406 | + "http_524", |
| 407 | + "request_timed_out", |
| 408 | + "超时了", |
| 409 | + "网关超时", |
| 410 | + "遇到超时", |
| 411 | + "retry on timeout", |
| 412 | + "operation timed out" |
| 413 | + ], |
| 414 | + "strategy": [ |
| 415 | + "Treat it as transient or size-driven, not a logic failure; do not report it as a hard failure before recovering", |
| 416 | + "Retry the SAME operation verbatim exactly ONCE (a large fraction clear on immediate retry); do not loop", |
| 417 | + "If it times out again, STOP retrying the monolith: split the work along a natural seam (per-file/dir/endpoint/record/section/time-window) into small independent units", |
| 418 | + "Dispatch the units as parallel subagents in a single batch so each finishes under the gateway deadline; merge their results", |
| 419 | + "If one unit itself times out, apply this same procedure recursively to that slice" |
| 420 | + ], |
| 421 | + "validation": [ |
| 422 | + "node --version" |
| 423 | + ], |
| 424 | + "constraints": { |
| 425 | + "max_files": 1, |
| 426 | + "forbidden_paths": [ |
| 427 | + ".git", |
| 428 | + "node_modules" |
| 429 | + ] |
| 430 | + }, |
| 431 | + "preconditions": [ |
| 432 | + "a tool call / fetch / subagent / long command returned a gateway-class timeout (524/522/502/504)" |
| 433 | + ], |
| 434 | + "summary": "Recover from a gateway/upstream timeout: retry the same call once, and if it still times out, decompose the work into parallel subagents and merge — never loop the monolithic call.", |
| 435 | + "schema_version": "1.6.0", |
| 436 | + "epigenetic_marks": [], |
| 437 | + "learning_history": [], |
| 438 | + "anti_patterns": [], |
| 439 | + "routing_hint": null, |
| 440 | + "tool_policy": null, |
| 441 | + "avoid": [ |
| 442 | + "retrying the same large call more than once", |
| 443 | + "serial retries instead of parallel decomposition", |
| 444 | + "surfacing the timeout as a hard failure before recovering" |
| 445 | + ], |
| 446 | + "asset_id": "sha256:63c4251dcd8308030194f797051c08672691b52553e00b0eb33772c215712acc" |
| 447 | + }, |
| 448 | + { |
| 449 | + "type": "Gene", |
| 450 | + "id": "gene_github_webhook_listener", |
| 451 | + "category": "innovate", |
| 452 | + "signals_match": [ |
| 453 | + "github_webhook_listener", |
| 454 | + "bugbot_webhook", |
| 455 | + "passive_pr_notifications", |
| 456 | + "设置webhook", |
| 457 | + "部署webhook监听", |
| 458 | + "notify when bugbot finishes", |
| 459 | + "webhook tunnel" |
| 460 | + ], |
| 461 | + "strategy": [ |
| 462 | + "Run the idempotent deploy: a loopback Python listener (127.0.0.1:8644) validating GitHub X-Hub-Signature-256 HMAC via hmac.compare_digest, writing vetted payloads to ~/.claude/inbox/", |
| 463 | + "Expose it via a cloudflared quick tunnel (outbound-only, no inbound port); a path-watcher re-PATCHes the GitHub webhook config whenever the tunnel URL changes", |
| 464 | + "Keep listener + tunnel alive with systemd --user units hardened (ProtectSystem=strict, NoNewPrivileges, MemoryDenyWriteExecute); a SessionStart hook drains the inbox and re-validates PR state via gh api before surfacing", |
| 465 | + "Security invariants: HMAC on every request, X-GitHub-Delivery dedup against replay, write-only sink (never exec/template/deserialize payload), file modes secret 0600 / inbox 0700", |
| 466 | + "Add repos with deploy.sh --repos; rotate the secret every 90 days (rotate-secret.sh) and immediately on any leak; never trust the inbox payload without re-fetching" |
| 467 | + ], |
| 468 | + "validation": [ |
| 469 | + "node --version" |
| 470 | + ], |
| 471 | + "constraints": { |
| 472 | + "max_files": 20, |
| 473 | + "forbidden_paths": [ |
| 474 | + ".git", |
| 475 | + "node_modules" |
| 476 | + ] |
| 477 | + }, |
| 478 | + "preconditions": [ |
| 479 | + "a developer machine with systemd --user and cloudflared available" |
| 480 | + ], |
| 481 | + "summary": "Deploy a per-developer GitHub webhook listener (HMAC-validated, cloudflared tunnel, systemd-kept) that drops PR/Bugbot events into ~/.claude/inbox for the next session to surface.", |
| 482 | + "schema_version": "1.6.0", |
| 483 | + "epigenetic_marks": [], |
| 484 | + "learning_history": [], |
| 485 | + "anti_patterns": [], |
| 486 | + "routing_hint": null, |
| 487 | + "tool_policy": null, |
| 488 | + "avoid": [ |
| 489 | + "opening an inbound port instead of an outbound cloudflared tunnel", |
| 490 | + "trusting the webhook payload without HMAC validation and PR re-fetch", |
| 491 | + "execing or deserializing anything from the payload" |
| 492 | + ], |
| 493 | + "asset_id": "sha256:ac2a2f185390aef37996651ef21355f4beb437049e52a6ca3898619a8d648084" |
243 | 494 | } |
244 | 495 | ] |
245 | 496 | } |
0 commit comments