# State Schema: `state/projects/PRJ-*.json` Owned by: `claw-project-tracker` (write); read by all other skills. ## Identifier convention `PRJ-YYYY-NNN-` where: - `YYYY` = year project first detected - `NNN` = zero-padded sequence within that year - `` = ≤ 24 chars, kebab-case, derived from most-frequent project keyword Examples: `PRJ-2025-001-客户A官网改版`, `PRJ-2026-014-supply-chain-rebuild` ## Top-level shape ```jsonc { "id": "PRJ-2025-001-客户A官网改版", // string, unique "name": "客户A 官网改版", // string, human-readable "客户方": "CUST-clientco", // string | null, FK → customers/ "raci": { // object "responsible": ["张三"], // array, internal people "accountable": "李四", // string | null "consulted": ["设计部"], // array "informed": ["Boss"] // array }, "gtd": { // object — GTD layer "next_action": "等张三发出修改稿 v3", // string | null "waiting_for": { // object | null "who": "张三", "since": "2026-04-28", // ISO date "days_overdue": 11 // int, computed daily }, "状态": "Stalled" // enum: Active | Stalled | Completed | Someday | Dropped }, "落地率判定": { // object "结论": "Stalled", // mirrors gtd.状态 "依据": [ // array "GTD-WF: 11 天无回复(阈值 5)", "R-37: 客户主动催办 2 次" ], "rule_refs": ["GTD-WF", "R-37"], // array, machine-readable "置信度": 0.82, // float [0,1] "source_email_ids": ["msg-abc@...", "msg-def@..."] // array }, "时间线": [ // array, append-only event log { "date": "2026-03-12", "event": "项目启动", "source_email_ids": ["msg-001@..."], "actor": "Boss" } ], "金额": 120000, // number | null, currency in 客户方's region "currency": "CNY", // ISO 4217 "下一步建议": "Boss 亲自 ping 张三 + cc 李四,表明 deadline", // string "_meta": { // internal Atlas bookkeeping "created_at": "2026-03-12T08:30:00Z", "updated_at": "2026-05-09T07:30:12Z", "atlas_version": "v0.4", "last_state_transition": { "from": "Active", "to": "Stalled", "at": "2026-05-08T07:30:00Z", "rule_refs": ["GTD-WF", "R-12"] }, "merged_from": null // string | null, set when project was merged from another id } } ``` ## Field rules ### Required vs optional **Required at creation:** `id`, `name`, `gtd.状态`, `_meta.created_at`, `_meta.atlas_version` **Required at first state-transition:** `落地率判定.结论`, `落地率判定.rule_refs`, `落地率判定.source_email_ids` **Optional:** `金额` / `currency` (if money never mentioned in thread), `下一步建议` (only set when state is Stalled or Active) ### Enum: `gtd.状态` | Value | Definition | Transitions | |-------|-----------|-------------| | `Active` | Has Next Action; recent activity within stall threshold | → Stalled, Completed, Someday | | `Stalled` | Waiting-For days_overdue > stall_threshold; no closure | → Active (resumed), Completed, Dropped | | `Completed` | Terminal keyword detected OR boss explicit close | → (none — terminal) | | `Someday` | Boss said "先放放" / "稍后" type closure | → Active (resumed), Dropped | | `Dropped` | 60+ days no signal AND was Stalled or Someday | → Active (rare resurrection) | ### Audit log Every state transition writes a row to `state/audit/project_transitions.csv`: ```csv timestamp,project_id,from_state,to_state,rule_refs,source_email_ids 2026-05-08T07:30:00Z,PRJ-2025-001,Active,Stalled,"GTD-WF;R-12","msg-abc;msg-def" ``` ### Boss override format Boss replies to Brief with: `OVERRIDE PRJ-2025-001 状态=Active reason="正在线下沟通,下周一交"` — Atlas applies, logs to `state/audit/boss_overrides.csv`, and downgrades the rule that produced the wrong call. ## Validation JSON Schema at `state-schemas/project.schema.json` (TBD — write when implementing claw-project-tracker code). Atlas validates every write against the schema; invalid writes go to `state/.invalid/` for debugging.