Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 14 additions & 9 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# 双文件夹布局:Script_Writer/ = 交付物仓本体;Script_Writer_Lab/ = 质量契约与自优化实验场。
# 资产层必须由你本人 review。Agent 可以提 PR,但不能自动合并。
/spec/ @randypanding
/profiles/ @randypanding
/brands/ @randypanding
/cases/export/ @randypanding
/eval/thresholds.yaml @randypanding
/adr/ @randypanding
/.github/ @randypanding
/COMPLIANCE.md @randypanding
# src/ 与 tests/ 不设 owner:Agent 自主区
/Script_Writer/spec/ @randypanding
/Script_Writer/profiles/ @randypanding
/Script_Writer/brands/ @randypanding
/Script_Writer/cases/export/ @randypanding
/Script_Writer/eval/thresholds.yaml @randypanding
/Script_Writer/adr/ @randypanding
/.github/ @randypanding
/Script_Writer/COMPLIANCE.md @randypanding
# Lab 侧契约资产(ADR-0001:contract/ 改动需人类确认;spec/adr 需 ADR)
/Script_Writer_Lab/contract/ @randypanding
/Script_Writer_Lab/adr/ @randypanding
/Script_Writer_Lab/spec/ @randypanding
# src/ 与 tests/ 不设 owner:Agent 自主区
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,23 @@ concurrency: {group: "ci-${{ github.ref }}", cancel-in-progress: true}

permissions: {contents: read}

defaults:
run:
working-directory: Script_Writer

jobs:
lab:
name: Lab (lint/test/guard)
defaults:
run:
working-directory: Script_Writer_Lab
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- run: uv sync
- run: make ci # lint + pytest(llm默认跳过) + corpus泄漏守卫

# ---------- 阻塞:秒级,无 LLM ----------
quality:
name: lint & typecheck
Expand Down Expand Up @@ -54,7 +70,7 @@ jobs:
- run: uv run pytest -m "not llm" -n auto --cov --cov-report=term --cov-fail-under=80
- uses: actions/upload-artifact@v4
if: always()
with: {name: test-report, path: out/}
with: {name: test-report, path: Script_Writer/out/}

golden:
name: golden regression (结构+渲染快照)
Expand All @@ -77,5 +93,5 @@ jobs:
with: {fetch-depth: 0}
- name: 检查本 PR 是否新增/修改了 adr/
run: |
git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -q '^adr/' \
git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -q '^Script_Writer/adr/' \
|| { echo "::error::标记 asset-change 的 PR 必须包含 ADR(AGENTS.md §5)"; exit 1; }
3 changes: 3 additions & 0 deletions .github/workflows/judge-calibration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
workflow_dispatch:
permissions: {contents: write, issues: write, actions: write}

defaults:
run:
working-directory: Script_Writer
jobs:
calibrate:
runs-on: ubuntu-latest
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/llm-eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:

permissions: {contents: read, pull-requests: write}

defaults:
run:
working-directory: Script_Writer
jobs:
l1:
# 只在 PR 打了 affects-generation 标签、或 nightly 时跑(省钱)
Expand All @@ -32,8 +35,8 @@ jobs:
run: uv run python -m nsc.eval.gate --thresholds eval/thresholds.yaml
- uses: actions/upload-artifact@v4
if: always()
with: {name: l1-report, path: out/eval/}
with: {name: l1-report, path: Script_Writer/out/eval/}
- name: 在 PR 上贴报告
if: github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with: {path: out/eval/l1.md}
with: {path: Script_Writer/out/eval/l1.md}
5 changes: 4 additions & 1 deletion .github/workflows/metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ on:
schedule: [{cron: "0 3 * * 1"}]
workflow_dispatch:
permissions: {contents: write, issues: write}
defaults:
run:
working-directory: Script_Writer
jobs:
dash:
runs-on: ubuntu-latest
Expand All @@ -21,4 +24,4 @@ jobs:
continue-on-error: true
with:
issue-number: 1 # 固定一个"飞轮周报"Issue
body-path: docs/metrics/latest.md
body-path: Script_Writer/docs/metrics/latest.md
5 changes: 4 additions & 1 deletion .github/workflows/rule-promotion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
workflow_dispatch:
permissions: {contents: write, pull-requests: write}

defaults:
run:
working-directory: Script_Writer
jobs:
mine:
runs-on: ubuntu-latest
Expand All @@ -23,7 +26,7 @@ jobs:
with:
branch: bot/rule-candidates
title: "规则候选(自动挖掘 $(date +%F))"
body-path: out/mining/validation.md
body-path: Script_Writer/out/mining/validation.md
labels: |
rule-candidate
asset-change
Expand Down
35 changes: 17 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
# NSC · Narrative Spec Compiler
# Script_Writer · 组织仓(双文件夹布局)

把「写小说 / 写剧本」变成**编译**:`spec/` 是源码,小说、剧本、prompt、代码都是编译产物
本仓是组织级聚合仓,**已决策**:交付物项目与实验场项目分两个文件夹保存,各自保留完整的工程结构(各自的 pyproject/Makefile/AGENTS.md,独立 CI)

- 业务:为商家生成可直接发在自有短视频账号的**营销短剧**。先出**小说**(商家确认物),再出**剧本**(制作团队执行物)。
- 视频拍摄/剪辑由外部制作团队负责,本系统**不做视频生成**。
| 文件夹 | 项目 | 角色 |
|---|---|---|
| [`Script_Writer/`](Script_Writer/) | 交付物仓本体(SW) | spec 即源码的短剧编译器(`nsc`);治理完备,L0~L3 规则 + 判官协议 |
| [`Script_Writer_Lab/`](Script_Writer_Lab/) | 质量契约与自优化实验场(Lab) | 为 SW 提供退化锚/语料锚/判官考试,承载 M1/M2 优化循环(见其 `adr/0001-lab-constitution.md`) |

## 快速开始
```bash
uv sync
make db-rebuild # 从 cases/export/*.jsonl 重建 SQLite
make test-fast # 不调用 LLM 的全部门禁
nsc run --brief examples/demo_tea/brief.yaml --profile short_drama_v1
nsc check out/demo_tea/ir.json # L0 检查
nsc render out/demo_tea/ir.json --target novel_docx script_fountain
```
## 两仓关系(ADR: Lab L-D1 仓内外分离)

## 三条铁律
1. **`spec/` 是唯一真相。** 任何知识若不能落进 `spec/ir | spec/checks | spec/rubrics | spec/rules | profiles | brands`,视为不存在。
2. **`prompts/`、`src/`、`out/` 是生成物。** 手改 `prompts/` = CI 失败。重写 `src/` 必须能通过同一套 `tests/`。
3. **反馈必须锚定到节点 ID。** 无 `node_id` 的反馈不入库。
- Lab 对 SW 是 **pinned 只读依赖**:只能 subprocess 调 SW checkout 的 `uv run nsc ...`,禁止 import。
- 洞察回流只走对 `Script_Writer/` 的 PR(SW-xx 上游卡)。
- Lab 的 `corpus/`、`transcripts/` 永不入库(泄漏守卫拦截)。

详见 [AGENTS.md](AGENTS.md)、[docs/ENGINEERING_PLAN.md](docs/ENGINEERING_PLAN.md)、[docs/BORROW_MAP.md](docs/BORROW_MAP.md)。
## CI

- `Script_Writer/`:lint/typecheck/spec-guard/tests/golden(见 `.github/workflows/ci.yml`)。
- `Script_Writer_Lab/`:`make ci`(lint + pytest + corpus 泄漏守卫)。
- 周期任务(判官校准/规则挖掘/飞轮面板)均在 `Script_Writer/` 上下文执行。

各文件夹内的开发规矩见各自的 `AGENTS.md`。
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading