diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d78c30..ad71f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## Unreleased + +Release candidate for **v2.3.0**. + +- Adds `project/1.1`, an additive optional `profile` field with `general`, + `engineering`, `software`, and `research` values. The field selects a + presentation template; it does not change project identity or core state. +- Keeps `project/1.0` valid for existing projects. Producers that emit `profile` + must identify the record as `project/1.1` or a later compatible minor. +- Broadens the product wording from research-only to long-running projects while + retaining research as the flagship reference profile. Experimental run and + claim-evidence contracts are not part of this stable-core candidate. + ## v2.2.0 — 2026-07-20 - Replaces all public worked examples and domain-bearing invalid fixtures with a diff --git a/README.md b/README.md index acd6c70..e6ae1a0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ English | [中文](README.zh.md) > The shared data contracts that let the Scriptorium suite's tools exchange files. > **Product status: Public Alpha contract baseline.** The Public Alpha -> target is Windows-first and requires at least one agent host. Codex and Claude +> target is Windows-first and requires at least one agent host. The core contracts +> support general, engineering, software, and research projects. Experimental run +> and claim-evidence contracts are outside this stable baseline. Codex and Claude > Code are the two first-class target choices; canonical installers now exist, while > Claude Code live `SessionEnd` golden-path parity remains a release gap. The user's Markdown workspace, > PDFs, and code remain authoritative; Provenance supplies local capture, search, @@ -28,9 +30,11 @@ See the contracts run through a real-interface, synthetic-data workflow in the ## Overview Scriptorium Spec defines the file formats used by the **Scriptorium** suite — a -local-first research workflow designed for GitHub-comfortable researchers using -at least one of its two target hosts, Codex or Claude Code, on Windows. Its core works -over an ordinary project directory: +local-first project context and continuity product for GitHub-comfortable users of +long-running work. Research is the flagship reference profile, while the same core +project, note, and session contracts support engineering maintenance and personal +software development. The Windows-first core uses at least one of its two target +hosts, Codex or Claude Code, and works over an ordinary project directory: Markdown, PDFs, and code remain user-owned sources of truth. Provenance records derived project context and high-value claims through an approval-backed memory workflow; optional tools add reference-library governance and slide output. It @@ -156,12 +160,13 @@ the entrypoint ownership ADR defines that Public Alpha release boundary. ## Status -**Public Alpha contract baseline: v2.2.0.** This baseline targets compatibility with -Scriptorium v0.1.0; it does not claim that every component tag is already published. -Cross-repository and Windows CI golden paths cover +**Stable-core contract candidate: v2.3.0.** The latest published baseline remains +v2.2.0 until the candidate is committed, reviewed, tagged, and released. +Cross-repository and Windows acceptance paths cover the `init`/`doctor`/`status`/`inventory`/`demo`/`pull` entry and canonical host -installers, but adapter-specific reviewed migration execution, a packaged suite -installer, and external beta evidence remain product gaps. +installers. The umbrella candidate now also exposes pinned component profiles and a +preview-first source installer; fresh remote CI and external beta evidence remain +release gaps. The event/sync-layer contracts (`note/1.0`, `session-summary/1.0`) are implemented in Provenance; Provenance ingestion of parsed-paper/reading-note/review/ lineage is not yet implemented. diff --git a/README.zh.md b/README.zh.md index ebd77ce..3aae38a 100644 --- a/README.zh.md +++ b/README.zh.md @@ -5,7 +5,8 @@ > 让 Scriptorium 套件各工具彼此交换文件的共享数据契约。 > **产品状态:Public Alpha 契约基线。** Public Alpha 目标以 Windows -> 为首发平台,并要求至少选择一个 agent 宿主;Codex 与 Claude Code 是地位相同的一等 +> 为首发平台,并要求至少选择一个 agent 宿主。核心契约支持通用、工程、软件和科研 +> 项目;实验运行与论断证据契约不进入本轮稳定基线。Codex 与 Claude Code 是地位相同的一等 > 目标宿主;canonical installer 已实现,但 Claude Code 的 live `SessionEnd` golden > path 对等验证仍是 release gap。用户的 > Markdown 工作区、PDF 与代码保持权威;Provenance 提供 @@ -148,11 +149,11 @@ Steward 的源码包名为 `scriptorium-steward`,CLI 为 `steward`。Provenanc ## 状态 -**Public Alpha 契约基线:v2.2.0。** 该基线以 Scriptorium v0.1.0 为兼容目标, -不表示所有组件 tag 已经发布。跨仓与 Windows CI golden path 已覆盖 +**稳定核心契约候选:v2.3.0。** 在候选内容提交、复审、打标签并发布前,最近的已发布 +基线仍是 v2.2.0。跨仓与 Windows 验收路径已覆盖 `init`/`doctor`/`status`/`inventory`/`demo`/ -`pull` 入口及 canonical host installer,但适配器级的人审迁移执行、套件安装包与 -外部 beta 证据仍是产品缺口。事件/同步层契约 +`pull` 入口及 canonical host installer;umbrella 候选也已提供固定组件组合与默认预览 +的源码安装器。重新运行远端 CI 与外部 beta 证据仍是发布缺口。事件/同步层契约 (`note/1.0`、`session-summary/1.0`)已在 Provenance 实现;parsed-paper/reading-note/ review/lineage 摄取尚未实现。 diff --git a/examples/project.v1.example.json b/examples/project.v1.example.json index 5f5db39..8231bb2 100644 --- a/examples/project.v1.example.json +++ b/examples/project.v1.example.json @@ -1,7 +1,8 @@ { - "schema_version": "project/1.0", + "schema_version": "project/1.1", "project_id": "synthetic-xq17-calibration", "title": "[SYNTHETIC] XQ-17 calibration demo", + "profile": "research", "status": "active", "stage": "synthetic validation", "priority": "medium", diff --git a/pyproject.toml b/pyproject.toml index 99232dc..ac2d726 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "scriptorium-spec" -version = "2.2.0" +version = "2.3.0" description = "Shared data contracts for the Scriptorium suite" requires-python = "==3.12.*" dependencies = [] diff --git a/schemas/project/v1.json b/schemas/project/v1.json index efc393e..e1963af 100644 --- a/schemas/project/v1.json +++ b/schemas/project/v1.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/scriptorium-suite/scriptorium-spec/blob/main/schemas/project/v1.json", "title": "Scriptorium Project Record v1", - "description": "One research project in the user-owned Markdown workspace. The reference adapter materializes it as Projects/.md whose YAML frontmatter conforms to this schema; the body remains human-authored Markdown plus the separately owned append-only progress-log region. Obsidian is an optional editor. Provenance ingests supported frontmatter for portfolio and context retrieval without becoming the owner of the source file.", + "description": "One long-running project in the user-owned Markdown workspace. Research, engineering, and personal software work are supported profiles over the same project contract. The reference adapter materializes it as Projects/.md whose YAML frontmatter conforms to this schema; the body remains human-authored Markdown plus the separately owned append-only progress-log region. Obsidian is an optional editor. Provenance ingests supported frontmatter for portfolio and context retrieval without becoming the owner of the source file.", "type": "object", "required": ["schema_version", "project_id", "title", "status"], "properties": { @@ -13,6 +13,11 @@ "description": "Stable kebab-case id; should match the repo dir name when there is one." }, "title": { "type": "string" }, + "profile": { + "type": "string", + "enum": ["general", "research", "engineering", "software"], + "description": "Optional presentation template introduced in project/1.1. It does not change project identity or the core state contract." + }, "status": { "type": "string", "enum": ["planned", "active", "paused", "done", "archived"] @@ -42,5 +47,15 @@ "description": "Provenance attribution key (usually the repo dir name) so the hub can tie this project's AI sessions to it." }, "updated": { "type": "string", "description": "ISO date of last update." } - } + }, + "allOf": [ + { + "if": { "required": ["profile"] }, + "then": { + "properties": { + "schema_version": { "type": "string", "pattern": "^project/1\\.(?:[1-9][0-9]*)$" } + } + } + } + ] } diff --git a/tests/fixtures/invalid/project.invalid-profile.json b/tests/fixtures/invalid/project.invalid-profile.json new file mode 100644 index 0000000..b131431 --- /dev/null +++ b/tests/fixtures/invalid/project.invalid-profile.json @@ -0,0 +1,7 @@ +{ + "schema_version": "project/1.1", + "project_id": "demo-project", + "title": "Synthetic project", + "profile": "unsupported", + "status": "planned" +} diff --git a/tests/fixtures/invalid/project.profile-with-v1.0.json b/tests/fixtures/invalid/project.profile-with-v1.0.json new file mode 100644 index 0000000..97f82c3 --- /dev/null +++ b/tests/fixtures/invalid/project.profile-with-v1.0.json @@ -0,0 +1,7 @@ +{ + "schema_version": "project/1.0", + "project_id": "demo-project", + "title": "Synthetic project", + "profile": "software", + "status": "planned" +} diff --git a/tools/validate.py b/tools/validate.py index fa1f6de..7d1b1af 100644 --- a/tools/validate.py +++ b/tools/validate.py @@ -70,6 +70,7 @@ def validate_handoff(doc, errors): PROJECT_STATUS = {"planned", "active", "paused", "done", "archived"} +PROJECT_PROFILES = {"general", "research", "engineering", "software"} NOTE_SOURCES = {"obsidian", "openclaw", "agent"} APPROVAL_STATES = {"draft", "approved", "applied"} READING_STATUSES = {"New", "To Read", "In Progress", "Read", "Not Reading"} @@ -90,6 +91,10 @@ def validate_project(doc, errors): err(errors, "title", "missing title") if doc.get("status") not in PROJECT_STATUS: err(errors, "status", f"invalid status: {doc.get('status')!r}") + if "profile" in doc and doc["profile"] not in PROJECT_PROFILES: + err(errors, "profile", f"invalid profile: {doc.get('profile')!r}") + if "profile" in doc and doc.get("schema_version") == "project/1.0": + err(errors, "schema_version", "profile requires project/1.1 or later") def validate_note(doc, errors): diff --git a/uv.lock b/uv.lock index 8600d09..4bfd46c 100644 --- a/uv.lock +++ b/uv.lock @@ -128,7 +128,7 @@ wheels = [ [[package]] name = "scriptorium-spec" -version = "2.2.0" +version = "2.3.0" source = { virtual = "." } [package.dev-dependencies]