Notion Sprint Sync
Overview
로컬 metadata를 source of truth로 사용해 Notion Task 속성을 안전하게 동기화한다. 기본 동작은 dry-run이며, 전체 preflight가 성공한 경우에만 사용자가 명시한 속성을 수정한다.
작업 전 mapping-contract.md를 읽는다.
Required inputs
planning/sprint-assignments.json 경로와 대상 Sprint ID
- Notion 작업 Database URL
- 수정할 속성 목록:
상위 작업, 우선순위, 스프린트 중 하나 이상
스프린트를 수정한다면 정확한 Notion Sprint Page 또는 select 값
Sprint ID로 Notion 스프린트 값을 추론하지 않는다. 과거 매핑이나 번호 규칙도 명시 입력을 대체하지 못한다.
Workflow
1. Build the local manifest
- Sprint JSON에서 대상 Story 목록을 읽는다.
- 각 Story directory와
README.md를 찾아 epic_id, story_id, task_ids, target_sprint를 읽는다.
- 각 Task Markdown의
task_id, story_id, target_sprint를 교차검증한다.
- Story 목록을 Task 목록으로 전개한다. Story 수를 Task 수로 보고하지 않는다.
Epic directory > Story directory > Task filename과 metadata 관계가 다르면 중단한다.
2. Resolve Notion pages
- Story는
STORY-[A-Z]+-\d{3}, Task는 TASK-\d{4} prefix로 검색한다.
- title 전체가 아니라 정규화한 prefix를 exact match한다.
- 각 ID가 정확히 한 Page와 대응하는지 확인한다.
- Story Page의
분류=스토리, Task Page의 분류=태스크를 확인한다.
- 누락, 중복, 분류 불일치가 하나라도 있으면 write를 0건으로 중단한다.
3. Compute requested values
상위 작업: 각 Task metadata의 story_id에 대응하는 Notion Story Page
우선순위: 사용자가 명시한 값 또는 S01=P0, S02=P1, ..., S10=P9
스프린트: 사용자가 명시한 Notion Page/value만 사용
Notion schema에서 property type, relation target, select option을 확인한다. 기존 값이 요청값과 다르면 conflict로 보고하며, 사용자가 교체를 명시하지 않았다면 덮어쓰지 않는다.
4. Produce a dry-run
쓰기 전에 Sprint, Story/Task 수, Page 일치/누락/중복/분류 오류, 속성별 동일/공백/conflict, 변경 예정 before -> after, 쓰기 가능 여부를 보고한다.
5. Apply only explicit writes
사용자가 적용을 명시한 경우에만 실행한다.
- query/search 결과 URL에서 32자리 Page UUID를 추출해
update_page.page_id로 사용한다. Page URL 전체를 page_id에 전달하지 않는다.
- payload에는 요청된 allowlist 속성만 포함한다.
- 이미 같은 값은 skip한다.
- Page별 결과를 기록하며 실패를 숨기지 않는다.
- 생성, 삭제, 본문 수정, schema 변경은 수행하지 않는다.
6. Verify all targets
전체 대상 Page를 다시 읽어 요청값을 확인한다. 요청하지 않은 allowlist 속성과 Page 본문이 바뀌지 않았는지 비교한다. 성공, 실패, 불일치, 부수 변경 수를 각각 보고한다.
Stop conditions
다음 중 하나면 쓰지 않고 dry-run 결과만 반환한다.
- Notion
스프린트 값이 필요하지만 명시되지 않음
- local metadata 불일치
- Notion Page 누락, 중복 또는
분류 불일치
- relation target 또는 select option 검증 실패
- 기존 값 conflict에 대한 교체 권한 없음
Example
사용자 요청: S06 Task의 상위 작업과 우선순위를 동기화하고 스프린트 1에 넣어.
- S06 Story를 실제 Task 목록으로 전개한다.
- Priority를
P5로 계산한다.
- Notion의 정확한
스프린트 1 Page를 확인한다.
- dry-run 전체가 통과하면
상위 작업, 우선순위, 스프린트만 수정한다.
1---2name: notion-sprint-sync3description: Use when synchronizing a local planning/sprint-assignments.json Epic-Story-Task hierarchy to Notion 작업 pages, including dry-run mapping, duplicate detection, 상위 작업 relations, Sprint-derived 우선순위, or an explicitly selected 스프린트 relation.4---56# Notion Sprint Sync78## Overview910로컬 metadata를 source of truth로 사용해 Notion Task 속성을 안전하게 동기화한다. 기본 동작은 dry-run이며, 전체 preflight가 성공한 경우에만 사용자가 명시한 속성을 수정한다.1112작업 전 [mapping-contract.md](references/mapping-contract.md)를 읽는다.1314## Required inputs1516- `planning/sprint-assignments.json` 경로와 대상 Sprint ID17- Notion 작업 Database URL18- 수정할 속성 목록: `상위 작업`, `우선순위`, `스프린트` 중 하나 이상19- `스프린트`를 수정한다면 정확한 Notion Sprint Page 또는 select 값2021Sprint ID로 Notion `스프린트` 값을 추론하지 않는다. 과거 매핑이나 번호 규칙도 명시 입력을 대체하지 못한다.2223## Workflow2425### 1. Build the local manifest26271. Sprint JSON에서 대상 Story 목록을 읽는다.282. 각 Story directory와 `README.md`를 찾아 `epic_id`, `story_id`, `task_ids`, `target_sprint`를 읽는다.293. 각 Task Markdown의 `task_id`, `story_id`, `target_sprint`를 교차검증한다.304. Story 목록을 Task 목록으로 전개한다. Story 수를 Task 수로 보고하지 않는다.315. `Epic directory > Story directory > Task filename`과 metadata 관계가 다르면 중단한다.3233### 2. Resolve Notion pages34351. Story는 `STORY-[A-Z]+-\d{3}`, Task는 `TASK-\d{4}` prefix로 검색한다.362. title 전체가 아니라 정규화한 prefix를 exact match한다.373. 각 ID가 정확히 한 Page와 대응하는지 확인한다.384. Story Page의 `분류=스토리`, Task Page의 `분류=태스크`를 확인한다.395. 누락, 중복, 분류 불일치가 하나라도 있으면 write를 0건으로 중단한다.4041### 3. Compute requested values4243- `상위 작업`: 각 Task metadata의 `story_id`에 대응하는 Notion Story Page44- `우선순위`: 사용자가 명시한 값 또는 `S01=P0`, `S02=P1`, ..., `S10=P9`45- `스프린트`: 사용자가 명시한 Notion Page/value만 사용4647Notion schema에서 property type, relation target, select option을 확인한다. 기존 값이 요청값과 다르면 conflict로 보고하며, 사용자가 교체를 명시하지 않았다면 덮어쓰지 않는다.4849### 4. Produce a dry-run5051쓰기 전에 Sprint, Story/Task 수, Page 일치/누락/중복/분류 오류, 속성별 동일/공백/conflict, 변경 예정 `before -> after`, 쓰기 가능 여부를 보고한다.5253### 5. Apply only explicit writes5455사용자가 적용을 명시한 경우에만 실행한다.56571. query/search 결과 URL에서 32자리 Page UUID를 추출해 `update_page.page_id`로 사용한다. Page URL 전체를 `page_id`에 전달하지 않는다.582. payload에는 요청된 allowlist 속성만 포함한다.593. 이미 같은 값은 skip한다.604. Page별 결과를 기록하며 실패를 숨기지 않는다.615. 생성, 삭제, 본문 수정, schema 변경은 수행하지 않는다.6263### 6. Verify all targets6465전체 대상 Page를 다시 읽어 요청값을 확인한다. 요청하지 않은 allowlist 속성과 Page 본문이 바뀌지 않았는지 비교한다. 성공, 실패, 불일치, 부수 변경 수를 각각 보고한다.6667## Stop conditions6869다음 중 하나면 쓰지 않고 dry-run 결과만 반환한다.7071- Notion `스프린트` 값이 필요하지만 명시되지 않음72- local metadata 불일치73- Notion Page 누락, 중복 또는 `분류` 불일치74- relation target 또는 select option 검증 실패75- 기존 값 conflict에 대한 교체 권한 없음7677## Example7879사용자 요청: `S06 Task의 상위 작업과 우선순위를 동기화하고 스프린트 1에 넣어.`80811. S06 Story를 실제 Task 목록으로 전개한다.822. Priority를 `P5`로 계산한다.833. Notion의 정확한 `스프린트 1` Page를 확인한다.844. dry-run 전체가 통과하면 `상위 작업`, `우선순위`, `스프린트`만 수정한다.