Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codex/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
5. 모든 phase가 끝나면 `review-closeout`
6. 실패, block, follow-up이면 `repair-reopen`

새 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도 여기 남긴다.
새 workflow에서는 markdown spec과 JSON state를 분리한다. `spec.md`는 사람용 요구사항 초안이고, `approve`가 이를 `task.json.intake`로 잠근다. 새 spec contract에서는 `Socratic Clarification Log`의 열린 질문이 모두 닫혀야 승인된다. `task.json`/`phases.json`/`runs/*.json`은 자동화용 canonical source고, phase boundary kickoff proof도 여기 남긴다.
4 changes: 2 additions & 2 deletions .codex/skills/repair-reopen/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ description: failed, blocked, review follow-up, 추가 요구사항이 들어온

1. 왜 reopen이 필요한지 note를 한 줄로 잠근다.
2. 필요하면 target phase를 정한다.
3. `python3 scripts/workflow.py reopen <task-id> --note "..." [--phase-id ...]`로 task를 `approved` 상태로 되돌리고 target phase를 `pending`으로 복구한다.
3. `python3 scripts/workflow.py reopen <task-id> --note "..." [--phase-id ...]`로 task를 `approved` 상태로 되돌리고 target phase와 그 이후 downstream phase를 `pending`으로 복구한다.
4. 추가 요구사항이면 먼저 `spec.md`를 다시 잠근다.
5. spec이 바뀌었으면 `python3 scripts/workflow.py approve <task-id> --note "..."`로 `task.json.intake`를 다시 잠근다.
6. 필요하면 `plan`으로 phase를 다시 적재한다.
Expand All @@ -30,6 +30,6 @@ description: failed, blocked, review follow-up, 추가 요구사항이 들어온
## 결과

- `state=approved`인 `task.json`
- rerunnable target phase (`status=pending`)
- rerunnable target/downstream phases (`status=pending`)
- cleared `blocked_reason`
- new reopen run evidence
4 changes: 2 additions & 2 deletions .codex/skills/socratic-spec-authoring/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ description: 소크라테스 질문으로 `spec.md`를 잠그고, 사용자 명
## 작업 방식

1. 질문으로 request, problem, goals, non-goals, constraints, acceptance를 `spec.md`에 기록한다.
2. `Socratic Clarification Log`는 `Q:`, `A:`, `Decision:` triplet으로만 적고, 새 contract에서는 각 `Q:`에 `[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage category를 붙인다.
3. `status`에서 `coverage_missing`이 비고 unresolved clarification이 없어질 때까지 질문 루프를 반복한다.
2. `Socratic Clarification Log`는 clarification마다 `Q:`로 시작하고 마지막 줄에 `Status:`를 둔다. `open`은 `Q:`와 선택적 `A:`를 허용하고, `resolved`는 `Q:`/`A:`/`Decision:`/`Status: resolved`를 순서대로 가진다.
3. `status`에서 `open_clarification_count=0`이고 `validation_errors`가 비어 있을 때까지 질문 루프를 반복한다. 질문은 고정 목록이 아니며, spec 작성 중 새 애매점이 생기면 언제든 추가하거나 다시 연다.
4. placeholder가 남아 있지 않은지 확인한다.
5. 사용자가 현재 `spec.md` 초안에 명시적으로 동의했을 때만 `python3 scripts/workflow.py approve <task-id> --note ...`를 실행한다.
6. `approve`가 `spec.md`를 `task.json.intake`로 잠근다는 점을 전제로, 승인 전에는 phase 생성이나 구현을 시작하지 않는다.
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ NEVER: control plane 문서를 앱 source-of-truth보다 우선시하지 않는
## Workflow Contract

1. `new`가 `workflows/tasks/<task-id>/spec.md`와 `task.json` skeleton을 만든다.
2. 소크라테스 질문으로 `spec.md`를 잠근다. `Socratic Clarification Log`는 `Q:`, `A:`, `Decision:` triplet만 사용하고, 새 spec contract에서는 `[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage를 모두 채운다.
2. 소크라테스 질문으로 `spec.md`를 잠근다. `Socratic Clarification Log`는 각 clarification마다 `Q:`와 마지막 줄의 `Status:`를 가진다. `Status: open` 질문이 하나라도 남아 있으면 승인하지 않는다. `resolved` 항목만 `A:`와 `Decision:`으로 닫고, spec 작성 중 애매점이 생기면 언제든 질문을 추가하거나 다시 연다.
3. 사용자가 동의하면 `approve`가 같은 task 디렉터리의 `spec.md`에 Approval block을 추가하고, `spec.md` 내용을 `task.json.intake`로 잠근 뒤 `task.json`을 `approved`로 전이한다.
4. 추가 요구사항으로 spec을 다시 잠그면 `approve`를 다시 실행해 `task.json.intake`를 재잠근다.
5. `plan --from <json>` 또는 `plan --stdin`이 phase 초안을 읽어 `phases.json`으로 적재한다. 각 phase는 `required_reads`, `starting_points`, `deliverables`, `completion_signal` bootstrap 정보를 가져야 하며, `spec.md`와 `task.json.intake`가 어긋나 있으면 plan을 시작하지 않는다.
Expand All @@ -49,7 +49,7 @@ NEVER: control plane 문서를 앱 source-of-truth보다 우선시하지 않는
11. verification이 다음 pending phase를 활성화하면 `task.json.kickoff_required_for_phase`를 기록하고 task를 다시 `approved`로 전이한다.
12. 모든 phase가 완료되면 `review`가 review readiness를 기록한다.
13. `review --close --user-validation-note ...`만 최종 완료를 닫을 수 있다.
14. 실패, block, 추가 요구사항이 생기면 `reopen`으로 target phase를 `pending`으로 되돌리고 repair loop를 재개한다. reopened phase가 2번째 이상 phase면 kickoff를 다시 요구한다.
14. 실패, block, 추가 요구사항이 생기면 `reopen`으로 target phase와 그 이후 downstream phase들을 `pending`으로 되돌리고 repair loop를 재개한다. reopened phase가 2번째 이상 phase면 kickoff를 다시 요구한다.
15. `pre_push`의 branch-aware 예외는 현재 브랜치가 `main`이고 로컬 `main` tip이 로컬 `develop` tip과 같을 때의 동기화 publish에만 허용한다.

## TDD Contract
Expand Down Expand Up @@ -89,7 +89,7 @@ python3 scripts/workflow.py hook pre_push --command-text "..."
- `init`는 `.githooks/*`와 `workflows/system/hooks.json`을 source 기준으로 다시 동기화하고, `doctor`는 drift를 실패로 취급한다.
- 실제 실행 엔진은 `scripts/workflow_runtime/cli.py`, `engine.py`, `models.py`, `guards.py`, `doctor.py`, `git_ops.py`가 분담한다.
- `workflow.py`를 유지하는 이유는 사람과 AI가 하나의 안정적인 명령 surface만 기억하면 되기 때문이다.
- `status`는 새 spec contract에서 `coverage_missing`과 active phase bootstrap summary를 노출해 다음 세션 시작점을 복원한다.
- `status`는 새 spec contract에서 `ready_for_approval`, clarification count, open/resolved count, `open_clarifications`, active phase bootstrap summary를 노출해 다음 세션 시작점을 복원한다.

## Source Of Truth Order

Expand Down
7 changes: 3 additions & 4 deletions docs/artifact-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ workflows/

## Artifact Roles

- `workflows/tasks/<task-id>/spec.md`: 사람용 requirement artifact. 요청, 문제, 목표, 비목표, 제약, acceptance, 소크라테스 질문 로그, 승인 기록을 담는다. 새 spec contract에서는 clarification question마다 coverage category를 잠근다.
- `workflows/tasks/<task-id>/spec.md`: 사람용 requirement artifact. 요청, 문제, 목표, 비목표, 제약, acceptance, 소크라테스 질문 로그, 승인 기록을 담는다. 새 spec contract에서는 clarification마다 `Status: open|resolved`를 명시하고, 열린 질문이 없어질 때까지 질의를 계속한다.
- `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`를 담는다.
- `workflows/tasks/<task-id>/phases.json`: 승인 이후 생성된 executable phase 집합이다. phase 목표, write scope, acceptance command, test policy, retry count와 다음 세션 kickoff용 bootstrap metadata를 담는다.
- `workflows/tasks/<task-id>/runs/*.json`: phase completion, phase kickoff, verification, review, reopen evidence다.
Expand All @@ -28,7 +28,7 @@ workflows/
## Spec And Phase Loading Flow

1. `new`가 task 디렉터리와 `spec.md`, `task.json`, `phases.json` skeleton을 만든다.
2. 소크라테스 질문으로 `spec.md`를 채운다. `Socratic Clarification Log`는 `Q:`, `A:`, `Decision:` triplet만 허용하고, 새 contract에서는 `[scope]`, `[goal]`, `[non_goal]`, `[constraint]`, `[acceptance]` coverage를 모두 채운다.
2. 소크라테스 질문으로 `spec.md`를 채운다. `Socratic Clarification Log`는 clarification마다 `Q:`로 시작하고 마지막 줄에 `Status:`를 둔다. `open`은 `Q:`와 선택적 `A:`를 허용하고, `resolved`는 `Q:`/`A:`/`Decision:`/`Status: resolved`를 순서대로 가진다.
3. 사용자가 현재 spec 초안에 명시적으로 동의하면 `approve`가 같은 `spec.md`에 Approval block을 추가하고, 내용을 `task.json.intake`로 잠근 뒤 `task.json`을 `approved`로 전이한다.
4. 추가 요구사항으로 spec을 다시 잠그면 `approve`를 다시 실행해 `task.json.intake`를 갱신한다.
5. `plan --from` 또는 `plan --stdin`이 외부 phase 초안을 읽어 같은 task 디렉터리의 `phases.json`으로 적재한다.
Expand Down Expand Up @@ -65,10 +65,9 @@ workflows/
`intake.clarifications`의 각 항목은 아래 필드를 가진다.

- `question`
- `category`
- `answer`
- `decision`
- `resolved`
- `status`

## Phase Fields

Expand Down
14 changes: 11 additions & 3 deletions docs/runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ python3 -m unittest discover -s tests -v
python3 scripts/workflow.py new task-001 --title "..." --primary-repo git-ranker-workflow
```

이후 `workflows/tasks/task-001/spec.md`를 소크라테스 질문으로 잠근다. 새 spec contract에서는 `Socratic Clarification Log`가 아래처럼 coverage category를 포함한 `Q/A/Decision` triplet을 모두 채워야 한다.
이후 `workflows/tasks/task-001/spec.md`를 소크라테스 질문으로 잠근다. 새 spec contract에서는 `Socratic Clarification Log`가 질문 단위의 `Status:`를 명시하고, `Status: open` 질문이 하나라도 남아 있으면 승인되지 않는다.

```md
- Q: [scope] phase canonical source는 무엇인가?
- Q: phase canonical source는 무엇인가?
- A: executable plan은 prose가 아니라 JSON이어야 한다.
- Decision: `phases.json`만 canonical plan으로 쓴다.
- Status: resolved
```

답을 아직 못 받았거나 추가 확인이 필요한 질문은 아래처럼 열린 상태로 남긴다.

```md
- Q: 아직 확인이 필요한 요구사항은 무엇인가?
- Status: open
```

사용자가 현재 spec 초안에 명시적으로 동의하면 approve 한다. 이때 `approve`가 `spec.md`를 `task.json.intake`로 잠근다.
Expand Down Expand Up @@ -57,7 +65,7 @@ python3 scripts/workflow.py review task-001 --close --user-validation-note "vali

## Repair / Reopen

실패, block, review follow-up, 추가 요구사항이 들어오면 `reopen`으로 다시 `approved` 상태로 되돌린다. `reopen`은 target phase를 `pending`으로 복구해서 바로 `run --start`로 재개할 수 있게 만든다. 추가 요구사항이면 `spec.md`를 다시 잠근 뒤 `approve`를 다시 실행하고, 그 다음 `plan`으로 phase를 갱신한다.
실패, block, review follow-up, 추가 요구사항이 들어오면 `reopen`으로 다시 `approved` 상태로 되돌린다. `reopen`은 target phase와 그 이후 downstream phase를 `pending`으로 복구해서 repair loop가 뒤 단계 실패 상태에 걸리지 않게 만든다. 추가 요구사항이면 `spec.md`를 다시 잠근 뒤 `approve`를 다시 실행하고, 그 다음 `plan`으로 phase를 갱신한다.

```bash
python3 scripts/workflow.py reopen task-001 --note "추가 요구사항 반영"
Expand Down
11 changes: 6 additions & 5 deletions docs/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
## Runtime Rules

- `approve` 전에는 `plan`, `run`, `verify`, `review`를 허용하지 않는다.
- `approve`는 `spec.md`의 필수 section, placeholder 제거 여부, `Socratic Clarification Log`의 `Q/A/Decision` triplet 형식을 검증한다.
- 새 task contract에서 `approve`는 clarification coverage도 검증한다. `scope`, `goal`, `non_goal`, `constraint`, `acceptance`가 모두 없으면 승인되지 않는다.
- 새 clarification contract에서 열린 질문은 `Status: open`으로 남기고, 모든 질문이 닫힌 뒤에만 승인을 요청한다.
- `approve`는 `spec.md`의 필수 section, placeholder 제거 여부, `Socratic Clarification Log`의 `Q:`/`A:`/`Decision:`/`Status:` 형식을 검증한다.
- `approve`는 clarification이 최소 1개 이상인지, 열린 질문이 없는지, `open` 항목에 `Decision:`이 없는지, `resolved` 항목이 `A:`와 `Decision:`으로 완결되는지 검증한다.
- `approve`는 승인된 spec을 `task.json.intake`로 잠그며, 이후 `spec.md`를 수정했으면 `approve`를 다시 실행해 intake를 재잠가야 한다.
- `plan`은 명시적 phase 입력 없이는 실행되지 않는다.
- `plan`은 `task.json.intake`와 현재 `spec.md`가 일치할 때만 허용하며, 각 phase를 새 세션이 시작할 수 있도록 bootstrap metadata를 함께 적재한다.
- `status`는 `spec.md`를 읽어 `ready_for_approval`, `clarification_count`, `coverage_present`, `coverage_missing`, `unresolved_clarifications`를 JSON으로 노출한다.
- `status`는 `spec.md`를 읽어 `ready_for_approval`, `clarification_count`, `open_clarification_count`, `resolved_clarification_count`, `open_clarifications`, `validation_errors`를 JSON으로 노출한다.
- `status`는 active phase의 `required_reads`, `starting_points`, `deliverables`, `completion_signal`도 함께 노출해 다음 세션 시작점을 복원한다.
- `run --complete`는 `allowed_write_paths`와 `workflows/tasks/<task-id>/` 밖 변경을 차단한다.
- `run --start`는 `task.json.kickoff_required_for_phase`가 active phase와 일치하면, matching `phase_kickoff` evidence 없이는 시작되지 않는다.
Expand Down Expand Up @@ -75,6 +76,6 @@
- verification 실패도 retry에 포함한다.
- 동일한 `error_fingerprint`가 짧은 시간 안에 반복되면 Circuit Breaker가 `blocked`로 전이한다.
- `blocked`는 외부 입력, spec 재정의, phase 재계획이 필요한 상태다.
- `reopen`은 `failed`, `blocked`, `review_ready`, `completed` task를 다시 `approved`로 되돌리고 target phase를 `pending`으로 복구한 뒤 repair loop를 재시작한다.
- `reopen`은 `failed`, `blocked`, `review_ready`, `completed` task를 다시 `approved`로 되돌리고 target phase와 그 이후 downstream phase를 `pending`으로 복구한 뒤 repair loop를 재시작한다.
- reopened target phase가 2번째 이상 phase면 kickoff proof를 다시 요구한다.
- 추가 요구사항이면 `reopen` 뒤 `spec.md`를 다시 잠그고 `approve`를 재실행한 뒤 `plan`으로 phase를 다시 적재한다.
- 추가 요구사항이면 `reopen` 뒤 `spec.md`에 새 clarification을 열고, 질문을 닫은 다음 `approve`를 재실행한 뒤 `plan`으로 phase를 다시 적재한다.
9 changes: 4 additions & 5 deletions scripts/workflow_runtime/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from pathlib import Path

CURRENT_TASK_CONTRACT_VERSION = 2
CLARIFICATION_REQUIRED_CATEGORIES = ["scope", "goal", "non_goal", "constraint", "acceptance"]
CURRENT_TASK_CONTRACT_VERSION = 3

TASK_STATES = {"draft", "approved", "in_progress", "failed", "blocked", "review_ready", "completed"}
PHASE_STATES = {"pending", "in_progress", "completed", "failed", "blocked"}
Expand Down Expand Up @@ -65,10 +64,10 @@

DOC_REQUIRED_MARKERS = {
"docs/README.md": ["AGENTS.md", "docs/runtime.md", "docs/artifact-model.md"],
"docs/artifact-model.md": ["task.json", "intake", "clarifications", "kickoff_required_for_phase", "required_reads"],
"docs/runtime.md": ["소크라테스 질문", "approve", "plan", "kickoff", "review --close"],
"docs/artifact-model.md": ["task.json", "intake", "clarifications", "status", "kickoff_required_for_phase", "required_reads"],
"docs/runtime.md": ["소크라테스 질문", "Status: open", "approve", "plan", "kickoff", "review --close"],
"docs/hooks.md": [".githooks/", "TDD Guard", "Dangerous Command Guard", "Circuit Breaker", "workflow.py hook"],
"docs/runbook.md": ["사용자가 현재 spec 초안에 명시적으로 동의하면 approve 한다.", "approve", "plan", "kickoff"],
"docs/runbook.md": ["Status: open", "사용자가 현재 spec 초안에 명시적으로 동의하면 approve 한다.", "approve", "plan", "kickoff"],
}

STALE_REFERENCE_PATTERNS = [
Expand Down
Loading
Loading