Skip to content

Commit f8a93c2

Browse files
authored
(#98) 소크라테스 spec coverage와 phase kickoff 계약 강화
* feat: 소크라테스 spec coverage와 phase kickoff 계약 강화 - clarification coverage category와 kickoff gate를 runtime에 추가 - phase bootstrap metadata와 doctor consistency 검증을 보강 - docs, skills, tests, workflow task artifact를 새 계약에 맞춤 * chore: git-ranker 서브모듈 포인터를 리뷰 브랜치에 반영 - workflow task를 reopen하고 follow-up phase로 범위를 재잠금 - git-ranker gitlink를 backend PR #89 커밋으로 맞춤 - review_ready evidence를 다시 남기고 PR 리뷰 준비 상태로 복구 * fix: legacy 빈 inputs phase plan 호환성을 유지 - bootstrap default가 빈 required_reads를 저장하지 않도록 보정 - legacy empty-input phase planning 회귀 테스트를 추가 - PR review follow-up을 task evidence와 함께 다시 review_ready로 기록
1 parent 814b1e2 commit f8a93c2

39 files changed

Lines changed: 1340 additions & 81 deletions

.codex/skills/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
1. `request-intake`
3030
2. `socratic-spec-authoring`
3131
3. `phase-planner`
32-
4. `boundary-check -> phase-executor -> verification-runner`를 active phase마다 반복
32+
4. `boundary-check -> phase-executor -> verification-runner`를 active phase마다 반복한다. 단, `task.json.kickoff_required_for_phase`가 active phase와 같으면 새 세션이 먼저 `kickoff`를 실행해야 한다.
3333
5. 모든 phase가 끝나면 `review-closeout`
3434
6. 실패, block, follow-up이면 `repair-reopen`
3535

36-
새 workflow에서는 markdown spec과 JSON state를 분리한다. `spec.md`는 사람용 요구사항 초안이고, `approve`가 이를 `task.json.intake`로 잠근다. `task.json`/`phases.json`/`runs/*.json`은 자동화용 canonical source다.
36+
새 workflow에서는 markdown spec과 JSON state를 분리한다. `spec.md`는 사람용 요구사항 초안이고, `approve`가 이를 `task.json.intake`로 잠근다. 새 spec contract에서는 clarification coverage category를 모두 채워야 승인된다. `task.json`/`phases.json`/`runs/*.json`은 자동화용 canonical source고, phase boundary kickoff proof도 여기 남긴다.

.codex/skills/phase-executor/SKILL.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ description: 현재 active phase 하나만 실행하고 hook을 통과시켜 pha
1919

2020
## 작업 방식
2121

22-
1. `python3 scripts/workflow.py run <task-id> --start`로 phase를 시작한다.
23-
2. phase의 허용 write path 안에서만 구현한다.
24-
3. phase를 닫을 때는 `python3 scripts/workflow.py run <task-id> --complete --changed-path ...`를 사용한다.
25-
4. TDD Guard가 막히면 테스트를 추가하거나 `test_policy.mode=evidence_only``test_policy.evidence`를 먼저 보강한다.
22+
1. `task.json.kickoff_required_for_phase`가 active phase와 같으면 새 세션이 먼저 `python3 scripts/workflow.py kickoff <task-id>`를 실행해 bootstrap proof를 남긴다.
23+
2. `python3 scripts/workflow.py run <task-id> --start`로 phase를 시작한다.
24+
3. phase의 허용 write path 안에서만 구현한다.
25+
4. phase를 닫을 때는 `python3 scripts/workflow.py run <task-id> --complete --changed-path ...`를 사용한다.
26+
5. TDD Guard가 막히면 테스트를 추가하거나 `test_policy.mode=evidence_only``test_policy.evidence`를 먼저 보강한다.
2627

2728
## 결과
2829

.codex/skills/phase-planner/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ description: 승인된 task를 executable phase 집합으로 쪼개고 `phases.j
2020
## 작업 방식
2121

2222
1. task를 작은 phase들로 쪼갠다.
23-
2. 각 phase에 `allowed_write_paths`, `acceptance.commands`, `test_policy` 채운 JSON을 작성한다.
23+
2. 각 phase에 `allowed_write_paths`, `acceptance.commands`, `test_policy`, `required_reads`, `starting_points`, `deliverables`, `completion_signal` 채운 JSON을 작성한다.
2424
3. 추가 요구사항으로 spec을 바꿨다면 `approve`를 다시 실행해 intake를 재잠근 뒤 `python3 scripts/workflow.py plan <task-id> --from <phase-json>` 또는 `--stdin`을 실행한다.
2525
4. `phases.json`은 오직 `plan` 명령만 canonical write owner다.
2626

2727
## 결과
2828

2929
- `workflows/tasks/<task-id>/phases.json`
3030
- `task.json.active_phase_id`
31+
- 다음 세션 kickoff가 읽을 bootstrap metadata
3132
- 다음 stage: `phase-executor`

.codex/skills/socratic-spec-authoring/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ description: 소크라테스 질문으로 `spec.md`를 잠그고, 사용자 명
2020
## 작업 방식
2121

2222
1. 질문으로 request, problem, goals, non-goals, constraints, acceptance를 `spec.md`에 기록한다.
23-
2. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet으로만 적는다.
24-
3. blocker가 없어질 때까지 질문 루프를 반복한다.
23+
2. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet으로만 적고, 새 contract에서는 각 `Q:``[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage category를 붙인다.
24+
3. `status`에서 `coverage_missing`이 비고 unresolved clarification이 없어질 때까지 질문 루프를 반복한다.
2525
4. placeholder가 남아 있지 않은지 확인한다.
2626
5. 사용자가 현재 `spec.md` 초안에 명시적으로 동의했을 때만 `python3 scripts/workflow.py approve <task-id> --note ...`를 실행한다.
2727
6. `approve``spec.md``task.json.intake`로 잠근다는 점을 전제로, 승인 전에는 phase 생성이나 구현을 시작하지 않는다.

.githooks/pre-commit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/bin/sh
22
set -eu
33

4+
# Phase-boundary kickoff proof is enforced by workflow runtime, not by git hooks.
5+
46
task_id="${WORKFLOW_TASK_ID:-}"
57
if [ -z "$task_id" ]; then
68
task_id="$(python3 scripts/workflow.py status --infer-active-task 2>/dev/null || true)"

.githooks/pre-push

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/bin/sh
22
set -eu
33

4+
# Phase-boundary kickoff proof is enforced by workflow runtime, not by git hooks.
5+
46
python3 scripts/workflow.py doctor
57
python3 scripts/workflow.py hook pre_command --command-text "git push $*"
68

AGENTS.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,20 @@ NEVER: control plane 문서를 앱 source-of-truth보다 우선시하지 않는
3737
## Workflow Contract
3838

3939
1. `new``workflows/tasks/<task-id>/spec.md``task.json` skeleton을 만든다.
40-
2. 소크라테스 질문으로 `spec.md`를 잠근다. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet만 사용한다.
40+
2. 소크라테스 질문으로 `spec.md`를 잠근다. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet만 사용하고, 새 spec contract에서는 `[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage를 모두 채운다.
4141
3. 사용자가 동의하면 `approve`가 같은 task 디렉터리의 `spec.md`에 Approval block을 추가하고, `spec.md` 내용을 `task.json.intake`로 잠근 뒤 `task.json``approved`로 전이한다.
4242
4. 추가 요구사항으로 spec을 다시 잠그면 `approve`를 다시 실행해 `task.json.intake`를 재잠근다.
43-
5. `plan --from <json>` 또는 `plan --stdin`이 phase 초안을 읽어 `phases.json`으로 적재한다. `spec.md``task.json.intake`가 어긋나 있으면 plan을 시작하지 않는다.
44-
6. `run --start`가 active phase를 시작한다.
45-
7. 구현 후 `run --complete --changed-path ...`가 write scope와 TDD guard를 통과해야 한다.
46-
8. `verify`가 completed phase의 acceptance command를 실행하고 `runs/*.json`에 evidence를 남긴다.
47-
9. 모든 phase가 완료되면 `review`가 review readiness를 기록한다.
48-
10. `review --close --user-validation-note ...`만 최종 완료를 닫을 수 있다.
49-
11. 실패, block, 추가 요구사항이 생기면 `reopen`으로 target phase를 `pending`으로 되돌리고 repair loop를 재개한다.
50-
12. `pre_push`의 branch-aware 예외는 현재 브랜치가 `main`이고 로컬 `main` tip이 로컬 `develop` tip과 같을 때의 동기화 publish에만 허용한다.
43+
5. `plan --from <json>` 또는 `plan --stdin`이 phase 초안을 읽어 `phases.json`으로 적재한다. 각 phase는 `required_reads`, `starting_points`, `deliverables`, `completion_signal` bootstrap 정보를 가져야 하며, `spec.md``task.json.intake`가 어긋나 있으면 plan을 시작하지 않는다.
44+
6. phase-1은 `run --start`로 바로 시작할 수 있다.
45+
7. 이전 phase verification이 통과해 다음 pending phase가 활성화되면, 새 세션이 먼저 `kickoff`를 실행해 bootstrap proof를 남겨야 한다.
46+
8. 그 다음 `run --start`가 active phase를 시작한다.
47+
9. 구현 후 `run --complete --changed-path ...`가 write scope와 TDD guard를 통과해야 한다.
48+
10. `verify`가 completed phase의 acceptance command를 실행하고 `runs/*.json`에 evidence를 남긴다.
49+
11. verification이 다음 pending phase를 활성화하면 `task.json.kickoff_required_for_phase`를 기록하고 task를 다시 `approved`로 전이한다.
50+
12. 모든 phase가 완료되면 `review`가 review readiness를 기록한다.
51+
13. `review --close --user-validation-note ...`만 최종 완료를 닫을 수 있다.
52+
14. 실패, block, 추가 요구사항이 생기면 `reopen`으로 target phase를 `pending`으로 되돌리고 repair loop를 재개한다. reopened phase가 2번째 이상 phase면 kickoff를 다시 요구한다.
53+
15. `pre_push`의 branch-aware 예외는 현재 브랜치가 `main`이고 로컬 `main` tip이 로컬 `develop` tip과 같을 때의 동기화 publish에만 허용한다.
5154

5255
## TDD Contract
5356

@@ -68,6 +71,7 @@ python3 scripts/workflow.py new <task-id> --title "..." --primary-repo <repo>
6871
python3 scripts/workflow.py approve <task-id> --note "..."
6972
python3 scripts/workflow.py plan <task-id> --from /path/to/phases.json
7073
python3 scripts/workflow.py plan <task-id> --stdin
74+
python3 scripts/workflow.py kickoff <task-id>
7175
python3 scripts/workflow.py run <task-id> --start
7276
python3 scripts/workflow.py run <task-id> --complete --changed-path ...
7377
python3 scripts/workflow.py verify <task-id>
@@ -85,6 +89,7 @@ python3 scripts/workflow.py hook pre_push --command-text "..."
8589
- `init``.githooks/*``workflows/system/hooks.json`을 source 기준으로 다시 동기화하고, `doctor`는 drift를 실패로 취급한다.
8690
- 실제 실행 엔진은 `scripts/workflow_runtime/cli.py`, `engine.py`, `models.py`, `guards.py`, `doctor.py`, `git_ops.py`가 분담한다.
8791
- `workflow.py`를 유지하는 이유는 사람과 AI가 하나의 안정적인 명령 surface만 기억하면 되기 때문이다.
92+
- `status`는 새 spec contract에서 `coverage_missing`과 active phase bootstrap summary를 노출해 다음 세션 시작점을 복원한다.
8893

8994
## Source Of Truth Order
9095

docs/artifact-model.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ workflows/
1818

1919
## Artifact Roles
2020

21-
- `workflows/tasks/<task-id>/spec.md`: 사람용 requirement artifact. 요청, 문제, 목표, 비목표, 제약, acceptance, 소크라테스 질문 로그, 승인 기록을 담는다.
22-
- `workflows/tasks/<task-id>/task.json`: mutable task state이자 승인 시점의 locked intake source다. approval, active phase, latest run, latest verified run, blocked reason, user validation과 `intake`를 담는다.
23-
- `workflows/tasks/<task-id>/phases.json`: 승인 이후 생성된 executable phase 집합이다. phase 목표, write scope, acceptance command, test policy, retry count를 담는다.
24-
- `workflows/tasks/<task-id>/runs/*.json`: phase completion, verification, review, reopen evidence다.
21+
- `workflows/tasks/<task-id>/spec.md`: 사람용 requirement artifact. 요청, 문제, 목표, 비목표, 제약, acceptance, 소크라테스 질문 로그, 승인 기록을 담는다. 새 spec contract에서는 clarification question마다 coverage category를 잠근다.
22+
- `workflows/tasks/<task-id>/task.json`: mutable task state이자 승인 시점의 locked intake source다. approval, active phase, latest run, latest verified run, kickoff requirement, blocked reason, user validation과 `intake`를 담는다.
23+
- `workflows/tasks/<task-id>/phases.json`: 승인 이후 생성된 executable phase 집합이다. phase 목표, write scope, acceptance command, test policy, retry count와 다음 세션 kickoff용 bootstrap metadata를 담는다.
24+
- `workflows/tasks/<task-id>/runs/*.json`: phase completion, phase kickoff, verification, review, reopen evidence다.
2525
- `workflows/system/hooks.json`: 전역 hook/guard/breaker 정책이다.
2626
- `workflows/system/circuit-breaker.json`: 반복 실패 fingerprint 메모리다.
2727

2828
## Spec And Phase Loading Flow
2929

3030
1. `new`가 task 디렉터리와 `spec.md`, `task.json`, `phases.json` skeleton을 만든다.
31-
2. 소크라테스 질문으로 `spec.md`를 채운다. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet만 허용한다.
31+
2. 소크라테스 질문으로 `spec.md`를 채운다. `Socratic Clarification Log``Q:`, `A:`, `Decision:` triplet만 허용하고, 새 contract에서는 `[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage를 모두 채운다.
3232
3. 사용자가 현재 spec 초안에 명시적으로 동의하면 `approve`가 같은 `spec.md`에 Approval block을 추가하고, 내용을 `task.json.intake`로 잠근 뒤 `task.json``approved`로 전이한다.
3333
4. 추가 요구사항으로 spec을 다시 잠그면 `approve`를 다시 실행해 `task.json.intake`를 갱신한다.
3434
5. `plan --from` 또는 `plan --stdin`이 외부 phase 초안을 읽어 같은 task 디렉터리의 `phases.json`으로 적재한다.
@@ -40,6 +40,7 @@ workflows/
4040

4141
- `id`
4242
- `title`
43+
- `contract_version`
4344
- `state`
4445
- `primary_repo`
4546
- `created_at`
@@ -48,6 +49,8 @@ workflows/
4849
- `active_phase_id`
4950
- `latest_run_id`
5051
- `last_verified_run_id`
52+
- `kickoff_required_for_phase`
53+
- `last_kickoff_run_id`
5154
- `blocked_reason`
5255
- `user_validated`
5356
- `user_validation_note`
@@ -62,6 +65,7 @@ workflows/
6265
`intake.clarifications`의 각 항목은 아래 필드를 가진다.
6366

6467
- `question`
68+
- `category`
6569
- `answer`
6670
- `decision`
6771
- `resolved`
@@ -75,6 +79,10 @@ workflows/
7579
- `title`
7680
- `goal`
7781
- `inputs`
82+
- `required_reads`
83+
- `starting_points`
84+
- `deliverables`
85+
- `completion_signal`
7886
- `allowed_write_paths`
7987
- `acceptance.commands`
8088
- `test_policy.mode`
@@ -87,6 +95,8 @@ workflows/
8795
- `require_tests`: 구현 변경이 있으면 대응 테스트 변경이 필요하다.
8896
- `evidence_only`: 테스트 delta 대신 명시적 evidence 배열을 근거로 허용한다.
8997

98+
`required_reads`, `starting_points`, `deliverables`, `completion_signal`은 다음 phase를 새 세션에서 시작할 때 `task.json`/`phases.json`/`spec.md`만으로 bootstrap할 수 있게 만드는 canonical metadata다.
99+
90100
## Validation Ownership
91101

92102
- JSON schema 파일은 사용하지 않는다.

docs/hooks.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
- `.github/workflows/workflow-control-plane.yml`
6262

6363
git hook만으로는 충분하지 않다. 로컬 CLI와 phase runner가 같은 hook 설정을 읽어야 guard가 유지된다.
64+
phase boundary의 fresh-session kickoff proof는 git hook이 아니라 workflow runtime이 `kickoff``run --start` 사이에서 직접 강제한다.
6465
`python3 scripts/workflow.py init`는 로컬 git 저장소의 `core.hooksPath``.githooks`로 맞추고, `doctor`는 이 설정이 빠지면 실패한다.
6566
`init``.githooks/pre-commit`, `.githooks/pre-push`, `workflows/system/hooks.json`을 source 기준으로 다시 동기화한다.
6667
`doctor`는 위 runtime surface가 source와 drift하면 실패하고 `python3 scripts/workflow.py init`를 다시 요구한다.

docs/runbook.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ python3 -m unittest discover -s tests -v
1616
python3 scripts/workflow.py new task-001 --title "..." --primary-repo git-ranker-workflow
1717
```
1818

19-
이후 `workflows/tasks/task-001/spec.md`를 소크라테스 질문으로 잠근다. `Socratic Clarification Log` 아래처럼 `Q/A/Decision` triplet만 사용한다.
19+
이후 `workflows/tasks/task-001/spec.md`를 소크라테스 질문으로 잠근다. 새 spec contract에서는 `Socratic Clarification Log` 아래처럼 coverage category를 포함한 `Q/A/Decision` triplet을 모두 채워야 한다.
2020

2121
```md
22-
- Q: phase canonical source는 무엇인가?
22+
- Q: [scope] phase canonical source는 무엇인가?
2323
- A: executable plan은 prose가 아니라 JSON이어야 한다.
2424
- Decision: `phases.json`만 canonical plan으로 쓴다.
2525
```
@@ -39,14 +39,18 @@ python3 scripts/workflow.py plan task-001 --from /tmp/task-001-phases.json
3939
cat /tmp/task-001-phases.json | python3 scripts/workflow.py plan task-001 --stdin
4040
```
4141

42+
새 phase JSON은 `required_reads`, `starting_points`, `deliverables`, `completion_signal`을 포함해 다음 세션 kickoff 시작점을 잠가야 한다.
43+
4244
## 실행과 검증
4345

44-
`verify``run --complete`로 닫힌 phase에 대해서만 실행한다.
46+
`verify``run --complete`로 닫힌 phase에 대해서만 실행한다. verification이 다음 pending phase를 활성화하면, 그 phase는 새 세션 kickoff를 거쳐야만 시작할 수 있다.
4547

4648
```bash
4749
python3 scripts/workflow.py run task-001 --start
4850
python3 scripts/workflow.py run task-001 --complete --changed-path scripts/workflow.py --changed-path tests/test_workflow_cli.py
4951
python3 scripts/workflow.py verify task-001
52+
python3 scripts/workflow.py kickoff task-001
53+
python3 scripts/workflow.py run task-001 --start
5054
python3 scripts/workflow.py review task-001 --note "review ready"
5155
python3 scripts/workflow.py review task-001 --close --user-validation-note "validated"
5256
```
@@ -74,3 +78,4 @@ python3 scripts/workflow.py hook pre_push --command-text "git push origin featur
7478
`pre_commit`은 active task가 여러 개라면 자동 추론을 중단하고 실패한다. 이 경우 `WORKFLOW_TASK_ID` 또는 `--task-id`로 명시적으로 task binding을 넣는다.
7579
`pre_push`는 먼저 현재 브랜치가 `main`인지와 로컬 `main`/`develop` tip이 같은지 확인한다. 이 조건을 만족하면 `develop` 동기화 publish로 보고 task-bound guard를 건너뛴다.
7680
그 외 경우에는 기존처럼 unpushed diff를 task scope에 매핑한다. active task가 없어도 completed task scope 하나로 매핑되면 그 task를 재사용하고, 단일 task로 정해지지 않으면 실패한다.
81+
다음 phase kickoff는 git hook이 아니라 `task.json.kickoff_required_for_phase``phase_kickoff` evidence로 강제된다.

0 commit comments

Comments
 (0)