chore(ci): tune PR Agent config
- split per-model banners so two model jobs no longer overwrite each other - raise reviewer findings cap to 8, broaden /improve to readability/cleanup - enable dual-publishing for high-score suggestions (inline annotations) - switch Claude model from opus-4-7 to opus-4-6 (fallback sonnet-4-6) - raise reasoning_effort to high, response_language to zh-CN - drop two dead config keys silently ignored by upstream schema - add best_practices.md with 6 project-specific invariants for /improve
This commit is contained in:
@@ -9,38 +9,56 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
review-claude:
|
review-claude:
|
||||||
if: >
|
if: >
|
||||||
github.event_name == 'pull_request' ||
|
github.event.sender.type != 'Bot' &&
|
||||||
(github.event_name == 'issue_comment' &&
|
(
|
||||||
github.event.issue.pull_request &&
|
github.event_name == 'pull_request' ||
|
||||||
startsWith(github.event.comment.body, '/') &&
|
(github.event_name == 'issue_comment' &&
|
||||||
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
|
github.event.issue.pull_request &&
|
||||||
|
startsWith(github.event.comment.body, '/') &&
|
||||||
|
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
|
||||||
|
)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: PR Agent - Claude Opus 4.7
|
- name: PR Agent - Claude Opus 4.6
|
||||||
uses: the-pr-agent/pr-agent@main
|
uses: the-pr-agent/pr-agent@main
|
||||||
env:
|
env:
|
||||||
OPENAI.KEY: ${{ secrets.PR_REVIEW_API_KEY }}
|
OPENAI.KEY: ${{ secrets.PR_REVIEW_API_KEY }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
config.model: "openai/claude-opus-4-7"
|
config.model: "openai/claude-opus-4-6"
|
||||||
config.fallback_models: '["openai/claude-opus-4-6"]'
|
config.fallback_models: '["openai/claude-sonnet-4-6"]'
|
||||||
config.custom_model_max_tokens: 200000
|
config.custom_model_max_tokens: 200000
|
||||||
|
config.reasoning_effort: "high"
|
||||||
openai.api_base: ${{ secrets.PR_REVIEW_BASE_URL }}
|
openai.api_base: ${{ secrets.PR_REVIEW_BASE_URL }}
|
||||||
github_action_config.auto_review: "true"
|
github_action_config.auto_review: "true"
|
||||||
github_action_config.auto_describe: "true"
|
github_action_config.auto_describe: "true"
|
||||||
github_action_config.auto_improve: "true"
|
github_action_config.auto_improve: "true"
|
||||||
github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "synchronize"]'
|
github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "synchronize"]'
|
||||||
|
pr_reviewer.extra_instructions: |
|
||||||
|
在评审正文最顶部,单独一行以引用块格式输出:
|
||||||
|
> 🤖 Reviewed by **Claude Opus 4.6**
|
||||||
|
不要评论纯代码风格或格式问题。
|
||||||
|
pr_code_suggestions.extra_instructions: |
|
||||||
|
在建议表格上方,单独一行以引用块格式输出:
|
||||||
|
> 🤖 Suggested by **Claude Opus 4.6**
|
||||||
|
best_practices.md 已包含项目规则,请优先围绕规则违反给出建议。
|
||||||
|
pr_description.extra_instructions: |
|
||||||
|
在描述顶部以引用块单独一行输出:
|
||||||
|
> 🤖 Described by **Claude Opus 4.6**
|
||||||
|
|
||||||
review-gpt:
|
review-gpt:
|
||||||
if: >
|
if: >
|
||||||
github.event_name == 'pull_request' ||
|
github.event.sender.type != 'Bot' &&
|
||||||
(github.event_name == 'issue_comment' &&
|
(
|
||||||
github.event.issue.pull_request &&
|
github.event_name == 'pull_request' ||
|
||||||
startsWith(github.event.comment.body, '/') &&
|
(github.event_name == 'issue_comment' &&
|
||||||
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
|
github.event.issue.pull_request &&
|
||||||
|
startsWith(github.event.comment.body, '/') &&
|
||||||
|
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
|
||||||
|
)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
@@ -55,8 +73,17 @@ jobs:
|
|||||||
config.model: "openai/gpt-5.5"
|
config.model: "openai/gpt-5.5"
|
||||||
config.fallback_models: '["openai/gpt-5.4-mini"]'
|
config.fallback_models: '["openai/gpt-5.4-mini"]'
|
||||||
config.custom_model_max_tokens: 200000
|
config.custom_model_max_tokens: 200000
|
||||||
|
config.reasoning_effort: "high"
|
||||||
openai.api_base: ${{ secrets.PR_REVIEW_BASE_URL }}
|
openai.api_base: ${{ secrets.PR_REVIEW_BASE_URL }}
|
||||||
github_action_config.auto_review: "true"
|
github_action_config.auto_review: "true"
|
||||||
github_action_config.auto_describe: "false"
|
github_action_config.auto_describe: "false"
|
||||||
github_action_config.auto_improve: "true"
|
github_action_config.auto_improve: "true"
|
||||||
github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "synchronize"]'
|
github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "synchronize"]'
|
||||||
|
pr_reviewer.extra_instructions: |
|
||||||
|
在评审正文最顶部,单独一行以引用块格式输出:
|
||||||
|
> 🤖 Reviewed by **GPT 5.5**
|
||||||
|
不要评论纯代码风格或格式问题。
|
||||||
|
pr_code_suggestions.extra_instructions: |
|
||||||
|
在建议表格上方,单独一行以引用块格式输出:
|
||||||
|
> 🤖 Suggested by **GPT 5.5**
|
||||||
|
best_practices.md 已包含项目规则,请优先围绕规则违反给出建议。
|
||||||
|
|||||||
+27
-8
@@ -1,22 +1,41 @@
|
|||||||
|
# PR-Agent configuration for InfiPlot.
|
||||||
|
# Per-model banners and tool-specific extra_instructions live in
|
||||||
|
# .github/workflows/pr-agent.yml. Project-level coding rules live in
|
||||||
|
# best_practices.md (consumed by /improve). Keep this file structural only.
|
||||||
|
|
||||||
[config]
|
[config]
|
||||||
ai_timeout = 300
|
ai_timeout = 300
|
||||||
temperature = 0.2
|
temperature = 0.2
|
||||||
|
reasoning_effort = "high"
|
||||||
|
response_language = "zh-CN"
|
||||||
|
|
||||||
[pr_reviewer]
|
[pr_reviewer]
|
||||||
num_code_suggestions = 4
|
num_max_findings = 8
|
||||||
inline_code_comments = true
|
|
||||||
require_security_review = true
|
require_security_review = true
|
||||||
extra_instructions = """
|
require_tests_review = false # repo has no test framework
|
||||||
This is a Next.js 16 / React 19 / TypeScript interactive visual novel engine.
|
require_can_be_split_review = true
|
||||||
Focus on: logic errors, security vulnerabilities, missing error handling,
|
require_score_review = true
|
||||||
type safety issues, and architectural violations.
|
require_todo_scan = true
|
||||||
Do not comment on code style or formatting.
|
persistent_comment = false # two model jobs would otherwise overwrite each other
|
||||||
"""
|
|
||||||
|
|
||||||
[pr_description]
|
[pr_description]
|
||||||
generate_ai_title = true
|
generate_ai_title = true
|
||||||
publish_labels = true
|
publish_labels = true
|
||||||
use_bullet_points = true
|
use_bullet_points = true
|
||||||
|
enable_pr_diagram = true
|
||||||
|
|
||||||
|
[pr_code_suggestions]
|
||||||
|
num_code_suggestions_per_chunk = 6
|
||||||
|
max_number_of_calls = 4
|
||||||
|
parallel_calls = true
|
||||||
|
focus_only_on_problems = false # also surface readability/reuse cleanups, not only bugs
|
||||||
|
suggestions_score_threshold = 0
|
||||||
|
dual_publishing_score_threshold = 7 # high-scoring suggestions also appear as inline comments
|
||||||
|
persistent_comment = false # two model jobs would otherwise overwrite each other
|
||||||
|
|
||||||
|
[best_practices]
|
||||||
|
enable_global_best_practices = false
|
||||||
|
max_lines_allowed = 2000
|
||||||
|
|
||||||
[ignore]
|
[ignore]
|
||||||
glob = [
|
glob = [
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# InfiPlot Best Practices
|
||||||
|
|
||||||
|
PR-Agent 的 `/improve` 工具读本文件作为项目级规则。违反时会被打 `Organization best practice` 标签。
|
||||||
|
|
||||||
|
权威来源是 `AGENTS.md`;本文件只列由 PR-Agent 自动审查的高价值不变量。新增时两边同步。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 1: Server 必须无状态
|
||||||
|
|
||||||
|
引擎语义是 `Session + EngineConfig → SceneResult`。客户端持有完整 `Session` 并在每次请求时发回;服务端不引入按用户键的全局缓存、模块级会话存储或持久化层。
|
||||||
|
|
||||||
|
## Pattern 2: Writer 不得 patch `StoryState` 的 stable 字段
|
||||||
|
|
||||||
|
`StoryState` 分两区:stable 字段 `logline / genreTags / protagonist / castNotes` 由 Architect 在会话开始时写入,**Writer 永不覆盖**;volatile 字段(`synopsis / openThreads / relationships / nextHook`)每场景可重写。`applyStoryStatePatch` 必须过滤 patch 中的 stable 键。
|
||||||
|
|
||||||
|
## Pattern 3: LLM 输出必须经 `parseJsonLoose()` 解析
|
||||||
|
|
||||||
|
`parseJsonLoose`(`lib/engine/jsonParser.ts`)依次尝试 direct parse、fenced extraction、object slicing、jsonrepair。核心 agent 输出禁止裸 `JSON.parse`。
|
||||||
|
|
||||||
|
## Pattern 4: Writer prompt 的 stable prefix 不可重排或重排版
|
||||||
|
|
||||||
|
`buildWriterPlanUserMessage()` 与 `buildWriterBeatsUserMessage()` 的 stable prefix(world / style / story spine / archived history / known scene keys / character list)顺序与格式直接决定 prompt cache 命中率;重排、改 markdown 风格都会击穿缓存。dynamic suffix 可以变。
|
||||||
|
|
||||||
|
## Pattern 5: TTS 隐私 — 剥离 `referenceAudioBase64` 并尊重 `clientTts`
|
||||||
|
|
||||||
|
客户端在调用 `/api/scene`、`/api/vision`、`/api/insert-beat` 前必须从 `Session` 里 strip 掉 `voice.referenceAudioBase64`,请求返回后本地合并回去。当 `clientTts: true` 时,服务端路由必须 drop `config.tts`,确保用户 TTS 密钥永不触达服务器、服务端 TTS 不被意外触发。
|
||||||
|
|
||||||
|
## Pattern 6: `orientation` 在会话开始时锁定,缺省值统一回退 `"landscape"`
|
||||||
|
|
||||||
|
`orientation` 控制 prompt framing、生成尺寸、mock 图像与 PlayCanvas 布局,整个会话期间不变。所有进入 `scene.orientation` 的路径(Architect 输出、Prebaked firstact、fallback 分支、异常 / 缺失输入)都必须把无效或缺省值 coerce 成 `"landscape"`,不允许透传 undefined 或非法字符串。fallback 分支尤其容易漏归一化。
|
||||||
Reference in New Issue
Block a user