Skip to content

SW-05 p3 fragment 组成数据化:窗口/投影/Thread 注入进 profile.context(ADR-0017) - #13

Merged
randypanding merged 1 commit into
mainfrom
sw/sw-05-p3-context-config
Aug 22, 2026
Merged

SW-05 p3 fragment 组成数据化:窗口/投影/Thread 注入进 profile.context(ADR-0017)#13
randypanding merged 1 commit into
mainfrom
sw/sw-05-p3-context-config

Conversation

@randypanding

Copy link
Copy Markdown
Owner

这个 PR 改的是哪一层?(必选其一)

  • A 资产层spec/ profiles/ brands/ cases/export/)→ 必须打标签 asset-change 并附 ADR
  • B 生成物层src/ tests/)→ 无需 ADR
  • 文档 / CI

ADR:adr/0017-p3-context-profile-section.md(status: proposed,含 profiles/_schema.py 变更,等确认)
(编号说明:ADR-0016 已被 sw/sw-07 分支占用,本卡顺延 0017)

工单

Closes # · 工单号:SW-05(上游依赖卡,Lab 仓 docs/WORK_ORDERS.md §上游依赖卡)

问题

p3 的跨集上下文组成硬编码在 pipeline.pyprev_episode_summary 窗口恒 1、known_facts 投影恒五字段、p2 的 threads 表永不注入。弱/强模型需要不同窗口与投影面。

改动

缺省(=原行为) 说明
context.prev_summary_window 1 _window_join:近端在前、远端逐行追加;window=1 与原实现逐字节一致;recompile 同享
context.known_fact_fields 原五字段 白名单子集(schema field_validator 拦截白名单外字段)
context.inject_threads false Thread 投影 {id,title,status,state} 注入 fragment,p3 转发进 LLM 输入(同 revivable_ideas 模式)
  • profiles/_schema.py 新增 ContextSettings(extra=forbid);两个在库 profile 显式写入缺省值,行为零变化
  • 偏差记录:卡面称"profile 的 context.* 配置段已存在"——该段只存在于 delivery/30ep-song-hotel 分支(T-33),origin/main 上不存在;本卡在 main 上新建该段(字段名对齐 delivery 分支的 ADR 设计,SW-06 将在同段补预算旋钮)

验收命令(贴出你本地跑通的输出)

uv run pytest tests/test_p3_context_config.py -q   # 5 passed
uv run ruff format --check . && uv run ruff check .   # All checks passed
uv run pyright   # 0 errors
两个 profile 过 _schema.py 验证   # schema OK
make spec-guard 六项   # 全 OK
uv run pytest -m "not llm" -n auto   # 526 passed, 1 failed(test_db_export_fresh,本机未提交 cases.db 现场所致,干净 worktree 通过)

检查表

  • 测试先红后绿(4 例先红:投影/窗口/开关均未实现;window=1 回归用例除外——它是守护原行为的)
  • 没有在 Python 里写业务规则(旋钮读 profile;白名单是机制映射)
  • 未新增 check 规则(不适用)
  • 没有手改 prompts/
  • 手写行数仍在预算内(src 净增 ~55 行)
  • 未改 IR
  • 未改 rubric

影响生成结果吗?

  • 否(缺省 = 原行为;profile 显式改参才影响,届时 profile 版本进缓存键)

Copilot AI lite review requested due to automatic review settings August 21, 2026 21:07
@randypanding randypanding added the asset-change 改动 spec/profiles/brands,需 ADR + 人工 approve label Aug 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There is a confirmed config semantics bug (known_fact_fields: [] cannot be expressed) and an unresolved/contradictory definition of the window ordering (“near-first” vs current join order) across code/tests/ADR.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR makes p3 fragment cross-episode context composition configurable via profile.context.* (window size for prev_episode_summary, projection fields for known_facts, and an inject_threads switch), with defaults intended to preserve existing behavior, and adds schema/ADR/tests to formalize the change.

Changes:

  • Add ContextSettings to profiles/_schema.py and set Profile.context with defaults + whitelist validation.
  • Update pipeline.py (run + recompile) to build p3 fragments using context.prev_summary_window, context.known_fact_fields, and context.inject_threads.
  • Add end-to-end stubbed tests covering default behavior, window>1 behavior, and threads injection forwarding.
File summaries
File Description
tests/test_p3_context_config.py Adds regression + configuration tests for known_facts projection, prev_summary windowing, and threads injection.
src/nsc/passes/pipeline.py Implements the configurable window/projection/injection logic and helper utilities (_window_join, _threads_view, etc.).
src/nsc/passes/p3_beatsheet.py Forwards injected threads from fragment into the LLM inputs when present.
profiles/short_video_v1.yaml Adds explicit default context block (intended zero behavior change).
profiles/short_drama_v1.yaml Adds explicit default context block (intended zero behavior change).
profiles/_schema.py Introduces ContextSettings with extra=forbid and known_fact_fields whitelist validation.
adr/0017-p3-context-profile-section.md Documents the decision and intended semantics for the new profile.context section.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +650 to +653
def _known_fact_fields_of(profile: dict[str, Any]) -> tuple[str, ...]:
"""profile.context.known_fact_fields → 投影字段(白名单交集,缺省 = 原五字段)。"""
wanted = profile.get("context", {}).get("known_fact_fields") or list(_KNOWN_FACT_FIELDS)
return tuple(k for k in _KNOWN_FACT_FIELDS if k in wanted)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正(10227b0):_known_fact_fields_of 改为 is None 判定——显式 known_fact_fields: [] 现在是合法的空投影(有意隐藏全部字段),只有键缺失才回退五字段缺省。补了回归断言(tests/test_p3_context_config.py::test_known_facts_fields_from_profile)。

Comment on lines +670 to +676
def _window_join(summaries: list[str], window: int) -> str:
"""prev_episode_summary 窗口(SW-05):近端在前、远端追加在后,逐行拼接。

window=1 与原行为逐字节一致(单元素直接返回);window=0 即恒空串。
"""
n = max(0, int(window))
return "\n".join(summaries[-n:]) if n else ""

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正(10227b0):确认预期语义是时间序(远端在前、近端在后),与 compress_history 的【前情】→【上一集】布局一致——实现本身正确,初稿 docstring 表述反了。已统一 docstring、ADR-0017、测试注释三处表述;断言不变(窗口扩展只在前端追加远端集)。

Comment on lines +18 to +22
| 键 | 语义 | 缺省 | 消费点 |
|---|---|---|---|
| `context.prev_summary_window` | p3 `prev_episode_summary` 看近端 N 集(0=恒空) | 1 | `run_pipeline` p3 循环 + `recompile_episode`(`_window_join`:近端在前、远端逐行追加) |
| `context.known_fact_fields` | `known_facts` 投影字段(白名单子集) | `[id, content, episode_no, status, type]` | `_known_facts` |
| `context.inject_threads` | 是否把 p2 的 Thread 表注入 p3(投影 `{id,title,status,state}`) | false | `run_pipeline`/`recompile_episode` 组装 fragment,p3 转发进 LLM 输入 |

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正(10227b0):ADR 表述改为"按时间序逐行拼接,远端在前、近端在后,与 compress_history 布局一致",并在约束一节补记 review 的两处澄清(显式空投影合法、窗口时间序)。

Comment thread tests/test_p3_context_config.py Outdated
Comment on lines +113 to +115
# 窗口=2:第 3 集的窗口严格包含第 2 集的窗口(多了第 1 集摘要)
assert summaries[2].startswith(summaries[1]), "近端摘要在前,远端追加在后"
assert len(summaries[2]) > len(summaries[1])

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正(10227b0):注释改为"时间序拼接(远端在前、近端在后,同 compress_history 布局)——第 3 集的窗口以第 1 集摘要开头、第 2 集摘要收尾"。断言本身(startswith + 长度递增)在新旧表述下都成立于时间序实现,未改。

randypanding added a commit that referenced this pull request Aug 21, 2026
Copilot review(PR #13):
- _known_fact_fields_of 用 or 判断,显式 [] 与未配置混同 → 改为 is None 判定
- _window_join 实现是时间序(远端在前),初稿 docstring/ADR/测试注释写成
  "近端在前" → 统一改为时间序表述(与 compress_history【前情】→【上一集】布局一致)
randypanding added a commit that referenced this pull request Aug 21, 2026
Copilot review(PR #14):
- p3/p5 参考层(bible/profile/characters_json)超配额时原实现 pop 掉键,
  而 signature 把它们声明为必填 InputField → 改为保留键、置空值
- p3 装配抽成 _budgeted_inputs(与 p5 同形,可单测)
- 回归:test_p3_degradation_keeps_keys + test_p5_budgeted_inputs 增键存在断言
- 第 3 条意见(known_fact_fields 空列表)已在 rebase 自 PR #1310227b0 修复
@randypanding
randypanding enabled auto-merge (squash) August 22, 2026 04:32
@randypanding
randypanding force-pushed the sw/sw-05-p3-context-config branch 3 times, most recently from f9d4f85 to b4bd1a7 Compare August 22, 2026 04:59
@randypanding
randypanding force-pushed the sw/sw-05-p3-context-config branch from b4bd1a7 to 85cff88 Compare August 22, 2026 05:00
@randypanding
randypanding merged commit c8348f9 into main Aug 22, 2026
10 checks passed
@randypanding
randypanding deleted the sw/sw-05-p3-context-config branch August 22, 2026 05:02
randypanding added a commit that referenced this pull request Aug 26, 2026
* SW-05 p3 fragment 组成数据化:窗口/投影/Thread 注入进 profile.context(ADR-0017)

- context.prev_summary_window(缺省 1=原行为):run_pipeline 与 recompile_episode
  统一走 _window_join(近端在前、远端逐行追加;window=1 逐字节同原实现)
- context.known_fact_fields(缺省原五字段,白名单校验):_known_facts 投影可窄化
- context.inject_threads(缺省 false):p2 Thread 表按 {id,title,status,state}
  投影注入 p3 fragment,p3 转发进 LLM 输入
- profiles/_schema.py 新增 ContextSettings(extra=forbid + field_validator)
- 测试:tests/test_p3_context_config.py(5 例,先红后绿)

* SW-05 review 修正:known_fact_fields 显式空列表不再回退缺省;窗口序表述改为时间序

Copilot review(PR #13):
- _known_fact_fields_of 用 or 判断,显式 [] 与未配置混同 → 改为 is None 判定
- _window_join 实现是时间序(远端在前),初稿 docstring/ADR/测试注释写成
  "近端在前" → 统一改为时间序表述(与 compress_history【前情】→【上一集】布局一致)

* sync: 远端 main 快照(API tarball;解决 fetch 阻断)

* style: ruff format(union 解冲突文件)

* lab round10: p4 beat_to_scene 类型矫正(随机后端结构漂移)+lab_smoke_v1 三集评测切片+p3 指令 v2(round8/9:escalation/枚举/PENDING/钩子纪律)

* lab round10b: _to_int 宽容转换(字符串下标/嵌套值,TypeError 实证)

* lab round12: resolve_pending 降级语义(无 donor 解除契约不致命;随机后端 PENDING 悬空最高频死法实证)

* lab round12: resolve_pending 降级语义(无 donor 解除契约不致命)+修正最终返回输入;测试 8 绿

* lab round12b: p1 Prop sku_ref null 归一(NarrativeIR ValidationError 实证)

* lab round12c: 通用 null→字段默认值归一(characters/locations/motifs 同型错误一例多杀)

* lab round13b: present_character_ids 空表全集兜底(scenes.N=[] ValidationError 实证)

* lab round14: p3/p4 结构机械修复——STR-014 承重节拍兜底/BM-002 植入间距重排/STR-010 主角补位(attempt4/5 同门连死实证,相位重试只复述诊断不改结构)

* lab round15: est_duration_s 等比缩放到集目标时长(DLG-006 六集全灭根因)+_retry_pass 传输容错(APIConnectionError 杀死整轮实证)

* lab round16: p5 对白目标区间与 DLG-006 对齐(旧 lo=0.8x 全顺从也死)+_expand_if_thin 欠量当场定点扩写(系统性欠量 26% 实证)

* lab round16b: 对白瞄准线=门禁线+3pp(毫厘之死实证 341/342/344 vs 344.25)+扩写循环至达标(上限2次,只留更厚稿)

* lab round17: p6 prompt 瘦身(_slim_scenes/_slim_profile/_slim_bible_for_episode 投影,实证 46631 字符撞护栏;id 全保留 anchor_map 契约不动)

* lab round18: 暗线步进钳制(INV-19 机械前置,实证 8 章全产物死于 final 门 current_stage 5/7 超界)

* lab round19: CMP-001 绝对化用语机械替换(门禁 fix 要求的确定性执行)+p1 必填 str 空串占位(characters.4.need 实证)

* lab round20: 南浪仔(海南文旅 IP)brief+brand 资产(用户定稿故事五幕:雨林→浪尖→旅程→暗线→陪伴)

* lab round20b: DLG-006 瞄准余量 +3pp→+6pp+扩写上限 2→3(ep8 差 12 字实证)

* lab round20c: canonical_name 改为'南浪仔'(BM-009 系统性失败实证:slogan 本身就违规,'南浪仔 NOLAN'全名在叙事中永不自然;NOLAN 单用降级为偶发可重试)

* lab round20d: ir_io.save 用 mode='json'(datetime 序列化,实证全绿产物死于 ir.json 导出)

* test 修正:Project 必填字段补齐(provenance_id/logline)

* docs: README 快速开始修正(实际 CLI 语法)+独立使用说明(端点配置/新品牌/profile/测试/战役分支)

* lab round23: 战役实测版 prompts 入库(p3 v3.2/p5 round13,全绿产物复现所需;B1 生成物例外,PR 内声明)+ADR-0015/16/17 状态 accepted

* merge 收尾:ruff 全绿(pairwise/values()/去过期 noqa)

* merge 收尾2:ruff format+check 全仓合规(CI lint & typecheck 门禁)

* merge 收尾3:pyright 合规(测试替身 cast PassContext)+format

---------

Co-authored-by: sync <t@t>
Co-authored-by: cnb <cnb@example.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset-change 改动 spec/profiles/brands,需 ADR + 人工 approve

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants