polydeukes 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.ko.md +2 -0
  2. package/README.md +2 -0
  3. package/dist/covenant/discipline.d.ts +6 -0
  4. package/dist/covenant/discipline.js +1 -1
  5. package/dist/covenant/dispatch.d.ts +10 -7
  6. package/dist/covenant/dispatch.js +21 -8
  7. package/dist/covenant/shell-mod.d.ts +15 -4
  8. package/dist/covenant/shell-mod.js +63 -8
  9. package/dist/covenant/transcript-mod.js +8 -5
  10. package/dist/covenant-check.d.ts +2 -2
  11. package/dist/covenant-check.js +113 -9
  12. package/dist/docs/README.ko.md +3 -2
  13. package/dist/docs/README.md +3 -2
  14. package/dist/docs/catalog.json +32 -0
  15. package/dist/docs/how-to/connect-surfaces.ko.md +45 -5
  16. package/dist/docs/how-to/connect-surfaces.md +49 -7
  17. package/dist/docs/how-to/write-disciplines.ko.md +3 -1
  18. package/dist/docs/how-to/write-disciplines.md +3 -1
  19. package/dist/docs/index.json +338 -190
  20. package/dist/docs/reference/cli/explain.ko.md +8 -8
  21. package/dist/docs/reference/cli/explain.md +10 -8
  22. package/dist/docs/reference/cli/init.ko.md +46 -4
  23. package/dist/docs/reference/cli/init.md +48 -5
  24. package/dist/docs/reference/configuration/index.ko.md +11 -5
  25. package/dist/docs/reference/configuration/index.md +10 -5
  26. package/dist/docs/reference/packages/adapter-claude-code.ko.md +5 -4
  27. package/dist/docs/reference/packages/adapter-claude-code.md +6 -4
  28. package/dist/docs/reference/packages/adapter-codex.ko.md +116 -0
  29. package/dist/docs/reference/packages/adapter-codex.md +118 -0
  30. package/dist/docs/reference/packages/adapter-grok.ko.md +6 -2
  31. package/dist/docs/reference/packages/adapter-grok.md +6 -2
  32. package/dist/docs/reference/packages/core.ko.md +1 -1
  33. package/dist/docs/reference/packages/core.md +1 -1
  34. package/dist/docs/reference/packages/polydeukes.ko.md +4 -3
  35. package/dist/docs/reference/packages/polydeukes.md +5 -4
  36. package/dist/docs/reference/packages/sdk-ts.ko.md +6 -3
  37. package/dist/docs/reference/packages/sdk-ts.md +6 -3
  38. package/dist/docs/troubleshooting.ko.md +39 -5
  39. package/dist/docs/troubleshooting.md +41 -5
  40. package/dist/docs/tutorials/first-judgment.ko.md +5 -3
  41. package/dist/docs/tutorials/first-judgment.md +5 -3
  42. package/dist/load-config.d.ts +24 -0
  43. package/dist/load-config.js +20 -2
  44. package/dist/scaffold-project.js +3 -1
  45. package/package.json +4 -3
@@ -49,21 +49,21 @@ pdks explain
49
49
  ```
50
50
 
51
51
  출력은 설정 파일 경로로 시작하고, 그다음 세션 표면 블록 하나와 변경 집합 표면 블록 하나가 나옵니다.
52
- 추가 규율이 없는 시작 설정은 이런 모양입니다.
52
+ 추가 규율이 없는 시작 설정은 이런 모양입니다(`N`은 조립이 센 보호 경로 개수이고, `skip` 행 하나는 정상입니다. 쓰기 대상을 판정할 수 없는 셸 명령이 착지하는 자리입니다).
53
53
 
54
54
  ```text
55
55
  pdks explain — polydeukes.config.yaml
56
56
 
57
57
  input: call IR (one call, stdin) · disciplines 0 · sessionDisciplines 0 · disciplines: advise unless enforce: block · meta: block
58
- registrations 3 · declare 0 · skip 0 · meta 3 · draft 0
59
- meta self-mod paths N (common; includes the config file itself)
60
- meta shell-mod paths N (common)
61
- meta transcript-mod content predicate · conditional: session.evidencePath
58
+ registrations 3 · declare 0 · skip 1 · meta 2 · draft 0
59
+ meta self-mod paths N (common; includes the config file itself)
60
+ meta transcript-mod content predicate · conditional: session.evidencePath
61
+ skip shell-unjudgeable a shell command whose write target this layer cannot determine
62
62
 
63
63
  input: --diff (change set, stdin) · disciplines 0 · changeSetDisciplines 0 · disciplines: advise unless enforce: block
64
- registrations 2 · declare 0 · skip 0 · meta 2 · draft 0
65
- meta self-mod paths N (common; includes the config file itself)
66
- meta shell-mod paths N (common)
64
+ registrations 2 · declare 0 · skip 1 · meta 1 · draft 0
65
+ meta self-mod paths N (common; includes the config file itself)
66
+ skip shell-unjudgeable a shell command whose write target this layer cannot determine
67
67
  ```
68
68
 
69
69
  **표면 머리줄은 그 표면이 컴파일하는 목록의 이름과 각 목록의 항목 수를 적습니다.** 세션
@@ -53,21 +53,23 @@ pdks explain
53
53
  ```
54
54
 
55
55
  The output starts with the config file path, then one block for the session surface and one for the
56
- change-set surface. A starter config with no extra disciplines looks like this:
56
+ change-set surface. A starter config with no extra disciplines looks like this (`N` stands for
57
+ the number of protected paths the assembly counted; the one `skip` row is normal — it is where a
58
+ shell command whose write target cannot be determined lands):
57
59
 
58
60
  ```text
59
61
  pdks explain — polydeukes.config.yaml
60
62
 
61
63
  input: call IR (one call, stdin) · disciplines 0 · sessionDisciplines 0 · disciplines: advise unless enforce: block · meta: block
62
- registrations 3 · declare 0 · skip 0 · meta 3 · draft 0
63
- meta self-mod paths N (common; includes the config file itself)
64
- meta shell-mod paths N (common)
65
- meta transcript-mod content predicate · conditional: session.evidencePath
64
+ registrations 3 · declare 0 · skip 1 · meta 2 · draft 0
65
+ meta self-mod paths N (common; includes the config file itself)
66
+ meta transcript-mod content predicate · conditional: session.evidencePath
67
+ skip shell-unjudgeable a shell command whose write target this layer cannot determine
66
68
 
67
69
  input: --diff (change set, stdin) · disciplines 0 · changeSetDisciplines 0 · disciplines: advise unless enforce: block
68
- registrations 2 · declare 0 · skip 0 · meta 2 · draft 0
69
- meta self-mod paths N (common; includes the config file itself)
70
- meta shell-mod paths N (common)
70
+ registrations 2 · declare 0 · skip 1 · meta 1 · draft 0
71
+ meta self-mod paths N (common; includes the config file itself)
72
+ skip shell-unjudgeable a shell command whose write target this layer cannot determine
71
73
  ```
72
74
 
73
75
  **The surface header names the lists that surface compiles and how many entries each holds.**
@@ -4,7 +4,8 @@
4
4
 
5
5
  `pdks init`은 에이전트와 무관한 초기 파일을 만듭니다. 설정 파일과 텔레메트리 제외 항목
6
6
  둘입니다. 이 명령은 어느 에이전트도 알지 못합니다. 세션 표면 등록은 그 에이전트의 어댑터가
7
- 맡는 별도 명령입니다. Claude Code는 `pdks-claude-code init`, Grok는 `pdks-grok init`입니다.
7
+ 맡는 별도 명령입니다. Claude Code는 `pdks-claude-code init`, Grok는 `pdks-grok init`,
8
+ Codex는 `pdks-codex init`입니다.
8
9
 
9
10
  <a id="init-syntax"></a>
10
11
  ## 구문
@@ -40,7 +41,7 @@ Claude Code 세션 표면은
40
41
  어댑터에는 자체 실행 파일이 있습니다.
41
42
 
42
43
  ```sh
43
- npm install --save-dev polydeukes @polydeukes/adapter-claude-code
44
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
44
45
  npx pdks-claude-code init
45
46
  ```
46
47
 
@@ -61,7 +62,7 @@ Grok 세션 표면은
61
62
  어댑터에는 자체 실행 파일이 있습니다.
62
63
 
63
64
  ```sh
64
- npm install --save-dev polydeukes @polydeukes/adapter-grok
65
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-grok
65
66
  npx pdks-grok init
66
67
  ```
67
68
 
@@ -72,13 +73,51 @@ npx pdks-grok init
72
73
 
73
74
  `.claude/` 파일을 만들거나 고치지 않습니다. 새 등록의 제한 시간은 60초입니다. Grok 호스트
74
75
  기본값은 5초이며, 훅 실행이 시간 초과로 끝나면 해당 호출을 차단하지 않습니다(fail-open).
75
- 두 세션 어댑터를 한 프로젝트에 함께 설치하면 호출마다 판정기가 두 번 실행될 수 있습니다.
76
+ 세션 어댑터를 한 프로젝트에 둘 이상 설치하면 호출마다 판정기가 두 번 실행될 수 있습니다.
76
77
 
77
78
  Grok는 Claude 세션 증인(witness) 밸브가 요구하는 인간 메시지 증거를 제공하지 않습니다.
78
79
  대화 기록은 Claude JSONL이 아니라 ACP `updates.jsonl`입니다.
79
80
  [Grok 복구 안내](../../troubleshooting.ko.md#grok-witness)를 참고하세요. 산출물별 동작은
80
81
  [표면 연결하기](../../how-to/connect-surfaces.ko.md#grok)에 있습니다.
81
82
 
83
+ <a id="init-codex"></a>
84
+ ## Codex — `pdks-codex init`
85
+
86
+ Codex 세션 표면은
87
+ [`@polydeukes/adapter-codex`](../packages/adapter-codex.ko.md)가 설치합니다. 이
88
+ 어댑터에는 자체 실행 파일이 있습니다.
89
+
90
+ ```sh
91
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
92
+ npx pdks-codex init
93
+ ```
94
+
95
+ 이 명령은 먼저 `pdks init`으로 초기 파일을 만든 뒤 Codex 등록 산출물을 씁니다.
96
+
97
+ - `.codex/hooks/covenant-pretooluse.mjs`
98
+ - `.codex/hooks.json`
99
+
100
+ `hooks.json`에는 `PreToolUse`, `UserPromptSubmit`, `PostToolUse`, `SessionEnd` 항목이
101
+ 생깁니다. 파일은 덮어쓰지 않고 병합합니다. 사용자 항목, 같은 항목의 다른 handler, 다른
102
+ 이벤트, 설치기가 모르는 키는 그대로 둡니다. 초기 설정은 기본적으로 `.codex/hooks`를
103
+ 보호하므로, 이 설치기가 만드는 등록 파일은 같은 설치가 만든 설정이 지킵니다.
104
+
105
+ **훅 승인까지가 설치입니다.** Codex는 훅 정의의 해시로 신뢰를 기록하므로, 생성된 훅은 검토
106
+ 대상으로 표시되고 `/hooks`에서 승인하기 전까지 건너뛰어집니다. 누군가 승인하기 전까지는
107
+ 아무것도 판정되지 않습니다. `init`이 실행할 때마다 바이트가 같은 명령 문자열을 쓰는 이유가
108
+ 이것입니다. 문자열이 바뀌면 다시 승인해야 합니다.
109
+
110
+ Codex는 훅에 도달하는 모든 파일 편집을 `apply_patch` 하나로 정규화하고, 경로 인자가 아니라 패치 텍스트를
111
+ 보냅니다. `Edit`과 `Write`는 `.codex/hooks.json`에 적을 수 있는 matcher 별칭이며 도구 이름으로
112
+ 도착하지 않습니다. 패치 하나가 여러 파일을 건드리면 파일마다 IR 원소 하나가 실리고, 그중
113
+ 하나라도 차단되면 호출 전체가 차단됩니다.
114
+
115
+ 불안정한 Codex 대화 기록은 해석하지 않습니다. `UserPromptSubmit`은 시각을 붙인 사람
116
+ 메시지를, `PostToolUse`는 완료된 도구 호출을 공급하고, `SessionEnd`는 어댑터 소유 증거
117
+ 파일을 정리합니다. 따라서 설정된 증인 토큰으로 다시 시도한 보호 호출을 허용할 수 있습니다.
118
+ 프롬프트 증거가 기록되지 않았다면 복구 메시지가 안내하는 사용자 터미널을 사용합니다.
119
+ 산출물별 동작은 [표면 연결하기](../../how-to/connect-surfaces.ko.md#codex)에 있습니다.
120
+
82
121
  <a id="init-results"></a>
83
122
  ## 결과와 실패 조건
84
123
 
@@ -103,6 +142,7 @@ Grok는 Claude 세션 증인(witness) 밸브가 요구하는 인간 메시지
103
142
  pdks init
104
143
  npx pdks-claude-code init
105
144
  npx pdks-grok init
145
+ npx pdks-codex init
106
146
  ```
107
147
 
108
148
  설치기는 CLI 명령입니다. `polydeukes` 계약의 공개 심볼이 아닙니다.
@@ -113,6 +153,8 @@ npx pdks-grok init
113
153
  - [`@polydeukes/adapter-claude-code`](../packages/adapter-claude-code.ko.md) — Claude Code 설치
114
154
  단위와 그 실행 파일
115
155
  - [`@polydeukes/adapter-grok`](../packages/adapter-grok.ko.md) — Grok 설치 단위와 그 실행 파일
156
+ - [`@polydeukes/adapter-codex`](../packages/adapter-codex.ko.md) — Codex 설치 단위와 그 실행
157
+ 파일
116
158
  - [`pdks docs`](./docs.ko.md)
117
159
  - [`pdks explain`](./explain.ko.md)
118
160
  - [설정 참조](../configuration/index.ko.md)
@@ -4,7 +4,8 @@
4
4
 
5
5
  `pdks init` creates the agent-neutral project scaffold: the config file and the telemetry ignore
6
6
  line. It knows no agent. Registering a session surface is a separate command owned by that
7
- agent's adapter — `pdks-claude-code init` for Claude Code, and `pdks-grok init` for Grok.
7
+ agent's adapter — `pdks-claude-code init` for Claude Code, `pdks-grok init` for Grok, and
8
+ `pdks-codex init` for Codex.
8
9
 
9
10
  <a id="init-syntax"></a>
10
11
  ## Syntax
@@ -39,7 +40,7 @@ The Claude Code session surface is installed by
39
40
  [`@polydeukes/adapter-claude-code`](../packages/adapter-claude-code.md), which ships its own bin:
40
41
 
41
42
  ```sh
42
- npm install --save-dev polydeukes @polydeukes/adapter-claude-code
43
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
43
44
  npx pdks-claude-code init
44
45
  ```
45
46
 
@@ -61,7 +62,7 @@ The Grok session surface is installed by
61
62
  [`@polydeukes/adapter-grok`](../packages/adapter-grok.md), which ships its own bin:
62
63
 
63
64
  ```sh
64
- npm install --save-dev polydeukes @polydeukes/adapter-grok
65
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-grok
65
66
  npx pdks-grok init
66
67
  ```
67
68
 
@@ -71,14 +72,53 @@ That command runs `pdks init` for the scaffold, then writes the Grok registratio
71
72
  - `.grok/hooks/covenant-pretooluse.json`
72
73
 
73
74
  It does not create or rewrite `.claude/` files. Generated registrations use a timeout of 60
74
- seconds. The Grok host default is 5 seconds, and a timed-out hook fails open. Installing both
75
- session adapters in one project can run the judge twice per call.
75
+ seconds. The Grok host default is 5 seconds, and a timed-out hook fails open. Installing more
76
+ than one session adapter in one project can run the judge twice per call.
76
77
 
77
78
  Grok does not supply the human-message evidence required by the Claude session witness valve.
78
79
  The session log is ACP `updates.jsonl`, not Claude's JSONL.
79
80
  See [Grok recovery](../../troubleshooting.md#grok-witness). Details are in
80
81
  [Connect the surfaces](../../how-to/connect-surfaces.md#grok).
81
82
 
83
+ <a id="init-codex"></a>
84
+ ## Codex — `pdks-codex init`
85
+
86
+ The Codex session surface is installed by
87
+ [`@polydeukes/adapter-codex`](../packages/adapter-codex.md), which ships its own bin:
88
+
89
+ ```sh
90
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
91
+ npx pdks-codex init
92
+ ```
93
+
94
+ That command runs `pdks init` for the scaffold, then writes the Codex registration artifacts:
95
+
96
+ - `.codex/hooks/covenant-pretooluse.mjs`
97
+ - `.codex/hooks.json`
98
+
99
+ `hooks.json` receives entries for `PreToolUse`, `UserPromptSubmit`, `PostToolUse`, and
100
+ `SessionEnd`. It is merged rather than overwritten: user entries, sibling handlers, other
101
+ events, and keys the installer does not know are left in place. The scaffold config protects
102
+ `.codex/hooks` by default, so the registration this installer writes is covered by the config
103
+ it writes.
104
+
105
+ **Approving the hook is part of the install.** Codex records trust against the hash of a hook's
106
+ definition, so the generated hook is listed for review and skipped until you approve it with
107
+ `/hooks`. Until someone does, nothing is judged. This is why `init` writes a byte-identical
108
+ command string on every run — a changed string needs approving again.
109
+
110
+ Codex normalises every file edit that reaches the hook into one tool, `apply_patch`, and
111
+ delivers the patch text rather than a path argument. `Edit` and `Write` are matcher aliases
112
+ you may write in `.codex/hooks.json`; they never arrive as the tool name. One patch that
113
+ touches several files carries one IR element per file, and any one of them blocking blocks
114
+ the whole call.
115
+
116
+ The unstable Codex transcript is never parsed. `UserPromptSubmit` supplies timestamped human
117
+ messages, `PostToolUse` supplies completed tool calls, and `SessionEnd` cleans up the
118
+ adapter-owned evidence file. A configured witness token can therefore release a retried
119
+ protected call. If no prompt evidence was recorded, use the user terminal named by the recovery
120
+ message. Details are in [Connect the surfaces](../../how-to/connect-surfaces.md#codex).
121
+
82
122
  <a id="init-results"></a>
83
123
  ## Results and failure conditions
84
124
 
@@ -102,6 +142,7 @@ filesystem problem, and rerun rather than assuming every failed installation lef
102
142
  pdks init
103
143
  npx pdks-claude-code init
104
144
  npx pdks-grok init
145
+ npx pdks-codex init
105
146
  ```
106
147
 
107
148
  The installers are CLI commands. They are not symbols on the `polydeukes` contract.
@@ -112,6 +153,8 @@ The installers are CLI commands. They are not symbols on the `polydeukes` contra
112
153
  - [`@polydeukes/adapter-claude-code`](../packages/adapter-claude-code.md) — the Claude Code
113
154
  install unit and its bin.
114
155
  - [`@polydeukes/adapter-grok`](../packages/adapter-grok.md) — the Grok install unit and its bin.
156
+ - [`@polydeukes/adapter-codex`](../packages/adapter-codex.md) — the Codex install unit and its
157
+ bin.
115
158
  - [`pdks docs`](../packages/polydeukes.md#polydeukes-bin) — the installed documentation reader lives
116
159
  in the same package.
117
160
  - [`pdks explain`](./explain.md)
@@ -103,7 +103,7 @@ fail-open입니다. 기록 실패가 판정을 바꾸는 일은 없습니다.
103
103
 
104
104
  ```yaml
105
105
  witness:
106
- token: 'covenant witness' # 사람이 대화에 직접 입력하는 합의 문구
106
+ token: 'pdks witness' # 사람이 대화에 직접 입력하는 합의 문구
107
107
  ttlMinutes: 10 # 그 메시지 시점부터의 유효 시간(분)
108
108
  ```
109
109
 
@@ -128,7 +128,7 @@ witness:
128
128
  발동하는 메시지입니다. 첫 줄에 토큰만 두고 나머지 줄은 자유롭게 씁니다.
129
129
 
130
130
  ```text
131
- covenant witness
131
+ pdks witness
132
132
 
133
133
  이제 훅 파일을 고쳐줘
134
134
  ```
@@ -136,7 +136,7 @@ covenant witness
136
136
  언급일 뿐인 메시지입니다. 밸브는 닫힌 채입니다.
137
137
 
138
138
  ```text
139
- 그런데 `covenant witness` 는 언제 만료되나요?
139
+ 그런데 `pdks witness` 는 언제 만료되나요?
140
140
  ```
141
141
 
142
142
  토큰 값 자체는 자유입니다. 어떤 문구든 쓸 수 있고, 접두사나 명령 형태를 검사하지 않습니다.
@@ -338,7 +338,11 @@ stderr에 쓰입니다. `block`을 지정하면 항목의 강제 수준을 차
338
338
  그 차이가 비어 있는지 판정합니다. 기존 일치 항목은 위반으로 세지 않으므로 선언을 도입해도
339
339
  기존 코드 전체를 차단하지 않습니다. `supply: empty`를 지정하면 파일 생성(`pre` 없음)은
340
340
  전체 내용을 추가한 것으로, 삭제(`post` 없음)는 아무것도 추가하지 않은 것으로 처리합니다.
341
- `scope` 블록에서는 `in`/`except` 대신 경로에 적용할 정규식을 사용합니다.
341
+ `scope` 블록에서는 `in`/`except` 대신 경로에 적용할 정규식을 사용합니다. 목록은
342
+ `include`와 `exclude` 둘입니다. 경로가 `include` 패턴 중 하나 이상에 일치하고(`include`가
343
+ 없으면 모든 경로가 대상입니다) `exclude` 패턴 중 어느 것에도 일치하지 않을 때 범위 안에
344
+ 듭니다. `excludeIgnoreCase: true`는 `exclude` 패턴의 대소문자 구분을 없애며, `include`는
345
+ 항상 대소문자를 구분합니다.
342
346
 
343
347
  ```yaml
344
348
  disciplines:
@@ -517,7 +521,9 @@ stdin으로 무엇을 하는지는 판정하지 않습니다. 해석기에 넘
517
521
  `sources: { session: { transcript: true } }`는 세션 자신의 대화 기록(transcript)을 이름
518
522
  붙입니다 — 표면이 읽는 사용자 턴과 도구 호출을, 항목마다 관측
519
523
  순번을 실은 스냅샷 하나로 선언에 건넵니다. 이력 단계(`toolUses` · `userTexts` · `first` ·
520
- `ageMs`)가 그것을 읽고, `agentType`은 파싱된 사이드카를 읽습니다. 이 저장소의 라이브
524
+ `ageMs`)가 그것을 읽고, `agentType`은 파싱된 사이드카를 읽습니다. `agentType`은 남길
525
+ 에이전트 종류를 `is` 인자로 요구합니다(`{ op: 'agentType', is: 'tdd-test-writer' }`).
526
+ `is`가 없으면 그 단계는 컴파일되지 않고 해당 항목은 skip 등록으로 남습니다. 이 저장소의 라이브
521
527
  설정은 그런 선언 하나를 싣습니다. `tests-before-implementation`은 서브에이전트 스폰 둘의 순번
522
528
  위의 `ordered`이고 `sessionDisciplines`에 적혀 있습니다. 일곱째 고정 이름
523
529
  `actor`는 관측의 주체(actor)입니다. 서브에이전트 안에서는 `{ agentType }`, 주 세션에서는
@@ -108,7 +108,7 @@ Optional.
108
108
 
109
109
  ```yaml
110
110
  witness:
111
- token: 'covenant witness' # the phrase a human types in the conversation
111
+ token: 'pdks witness' # the phrase a human types in the conversation
112
112
  ttlMinutes: 10 # validity window, in minutes, from that message
113
113
  ```
114
114
 
@@ -135,7 +135,7 @@ carrying the token alone does, with any following lines free for the work itself
135
135
  A message that invokes — the token alone on the first line, the rest free:
136
136
 
137
137
  ```text
138
- covenant witness
138
+ pdks witness
139
139
 
140
140
  now fix the hook file
141
141
  ```
@@ -143,7 +143,7 @@ now fix the hook file
143
143
  A message that merely mentions — the valve stays shut:
144
144
 
145
145
  ```text
146
- so when does `covenant witness` expire?
146
+ so when does `pdks witness` expire?
147
147
  ```
148
148
 
149
149
  The token's value is free — any phrase works, and it is never checked for a prefix or a
@@ -352,7 +352,10 @@ banned word, a stray `.only`, a citation that resolves nowhere — is written as
352
352
  verdict. Existing occurrences are forgiven, so adopting the discipline never blocks a legacy
353
353
  codebase. `supply: empty` is what lets a file creation (no `pre`) count as all-added and a
354
354
  deletion (no `post`) as adding nothing; the `scope` block replaces `in`/`except` with
355
- regular expressions over the path.
355
+ regular expressions over the path. It takes two lists, `include` and `exclude`: a path is
356
+ in scope when it matches at least one `include` pattern (an absent `include` admits every
357
+ path) and matches no `exclude` pattern. `excludeIgnoreCase: true` makes the `exclude`
358
+ patterns case-insensitive; `include` is always case-sensitive.
356
359
 
357
360
  ```yaml
358
361
  disciplines:
@@ -542,7 +545,9 @@ third kind, `sources: { session: { transcript: true } }`, names the session's ow
542
545
  conversation history — the user turns and tool calls the surface reads, handed to the
543
546
  declaration as one snapshot whose entries carry their
544
547
  observation ordinal; the history steps (`toolUses`, `userTexts`, `first`, `ageMs`) read it, and
545
- `agentType` reads the parsed sidecar. This repository's live config carries one —
548
+ `agentType` reads the parsed sidecar and requires `is`, the agent type to keep
549
+ (`{ op: 'agentType', is: 'tdd-test-writer' }`); without it the step does not compile and
550
+ the entry lands as a skip registration. This repository's live config carries one —
546
551
  `tests-before-implementation`, an `ordered` over the ordinals of two subagent spawns, written
547
552
  in `sessionDisciplines`. The seventh fixed name, `actor`, is the
548
553
  observation's actor — `{ agentType }` inside a subagent, `{}` in the main session, absent
@@ -6,7 +6,7 @@
6
6
  > 판정기가 읽는 파일 변경 증거와 대화 기록(transcript) 통로가 함께 실립니다. 세션 표면을
7
7
  > 프로젝트에 설치하는 것도 이 패키지가 합니다.
8
8
  >
9
- > 알파입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
9
+ > 베타입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
10
10
 
11
11
  <a id="ownership"></a>
12
12
  ## 담당하는 기능
@@ -72,7 +72,7 @@ Claude Code의 입력을 공통 형식으로 번역합니다. 에이전트와
72
72
  프로젝트 루트에서 두 줄이면 Claude Code 세션 표면이 섭니다.
73
73
 
74
74
  ```sh
75
- npm install --save-dev polydeukes @polydeukes/adapter-claude-code
75
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
76
76
  npx pdks-claude-code init
77
77
  ```
78
78
 
@@ -105,6 +105,7 @@ npx pdks-claude-code init
105
105
  스폰할 프로세스도, 기록할 로그 경로도 없습니다. 훅은 stderr에 한 줄을 남기고 종료 코드
106
106
  `2`를 내며 텔레메트리 로그에는 아무것도 추가되지 않습니다. 스폰 전 실패 가운데 이 경우만
107
107
  그렇고, 나머지는 모두 `pdks`에 도달해 행을 남깁니다.
108
- - **Grok는 `@polydeukes/adapter-grok`로 설치합니다.** 그 패키지가 자기 위임자와 명부를
109
- 씁니다. 두 세션 어댑터를 한 프로젝트에 함께 설치하면 호출마다 판정기가 두 번 실행될 수
108
+ - **다른 호스트는 각자의 어댑터로 설치합니다.** Grok는 `@polydeukes/adapter-grok`로,
109
+ Codex는 `@polydeukes/adapter-codex`로 설치합니다. 각 패키지가 자기 위임자와 명부를
110
+ 씁니다. 한 프로젝트에 세션 어댑터를 둘 이상 설치하면 호출마다 판정기가 여러 번 실행될 수
110
111
  있습니다.
@@ -6,7 +6,7 @@
6
6
  > with the file-change evidence and the transcript channel the judge reads, and the
7
7
  > package installs the session surface into a project.
8
8
  >
9
- > Alpha. Install it next to `polydeukes`, which it names as a `peerDependency`.
9
+ > Beta. Install it next to `polydeukes`, which it names as a `peerDependency`.
10
10
 
11
11
  <a id="ownership"></a>
12
12
  ## What this package owns
@@ -75,7 +75,7 @@ there is no separate precedent evaluator in this package. The grammar is in
75
75
  Two lines install the Claude Code session surface, run from the project root:
76
76
 
77
77
  ```sh
78
- npm install --save-dev polydeukes @polydeukes/adapter-claude-code
78
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
79
79
  npx pdks-claude-code init
80
80
  ```
81
81
 
@@ -108,5 +108,7 @@ No configuration namespace of its own.
108
108
  project there is no process to spawn and no log path to write to, so the hook exits `2` with
109
109
  one line on stderr and the telemetry log gains nothing. Every other pre-spawn failure does
110
110
  reach `pdks` and does leave a row.
111
- - **Grok installs through `@polydeukes/adapter-grok`.** That package writes its own delegator
112
- and roster. Installing both session adapters in one project can run the judge twice per call.
111
+ - **Other hosts install through their own adapters.** Grok through
112
+ `@polydeukes/adapter-grok`, Codex through `@polydeukes/adapter-codex`. Each package writes
113
+ its own delegator and roster. Installing more than one session adapter in a project can run
114
+ the judge more than once per call.
@@ -0,0 +1,116 @@
1
+ # `@polydeukes/adapter-codex`
2
+
3
+ [English](adapter-codex.md) · **한국어**
4
+
5
+ > **Codex의 설치 단위**입니다. 생명주기 이벤트는 어댑터 소유 세션 증거가 되고,
6
+ > `PreToolUse` 페이로드는 패치가 건드리는 파일마다 원소 하나를 실은 약속(covenant) 입력 IR이
7
+ > 됩니다.
8
+ >
9
+ > 베타입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
10
+
11
+ <a id="ownership"></a>
12
+ ## 담당하는 기능
13
+
14
+ Codex의 입력을 공통 형식으로 번역합니다. 에이전트와 도구의 구체적인 이름은 이 패키지에서
15
+ 처리하고 코어에는 넣지 않습니다.
16
+
17
+ | 단위 | 하는 일 |
18
+ |---|---|
19
+ | `pdks-codex` 실행 파일 | 하위 명령 하나 `pdks-codex init`으로 프로젝트에 세션 표면을 등록합니다 |
20
+ | `runHook` | 생명주기 증거를 기록하거나, `PreToolUse` 페이로드 하나를 입력 IR로 바꾸고 판정기를 스폰합니다 |
21
+ | 세션 증거 | 시각을 붙인 사람 메시지와 완료된 도구 호출을 SHA-256 세션 파일에 저장하고 `SessionEnd`에서 지웁니다 |
22
+ | 페이로드 검증 | 호스트의 생성 스키마가 필수로 지정한 키를 모두 요구하며, 그 호스트가 보내는 한 가지 표기만 받습니다 |
23
+ | 패치 해석 | `apply_patch` 호출의 원본 패치 텍스트를 건드리는 파일마다 변경 하나로 풉니다 |
24
+ | 경로 기준 변환 | 패치 경로를 호출의 작업 디렉터리 기준으로 해석한 뒤 프로젝트 루트 기준으로 실습니다 |
25
+
26
+ 생성된 훅 위임자가 불러오는 것이 `runHook({ repoRoot })`입니다. `UserPromptSubmit`과
27
+ `PostToolUse`는 `.polydeukes/codex-sessions/` 아래에 엄격한 JSONL 레코드를 추가하고,
28
+ `SessionEnd`는 그 세션 파일만 지웁니다. `PreToolUse`는 `tools` 명부와 이 레코드에서 만든
29
+ `session`을 싣되 `actor`나 `channels`를 합성하지 않은 뒤, `repoRoot`에서
30
+ `pdks covenant check --enforce block`을 스폰하고 그 자식 프로세스의 종료 코드를 그대로
31
+ 돌려줍니다. 판정은 그 자식 프로세스가 하며, 이 패키지에는 판정 코드가 없습니다.
32
+
33
+ **이 패키지는 텔레메트리 행을 쓰지 않습니다.** 스폰 전에 실패하면 그 사실을 한 줄로 만들어
34
+ `pdks`의 stdin으로 보내므로, 그 호출이 남기는 행은 언제나 한 곳에서만 기록됩니다.
35
+
36
+ <a id="apply-patch"></a>
37
+ ## 형제 어댑터는 인자를 읽는데 이 어댑터가 텍스트를 해석하는 이유
38
+
39
+ Codex는 훅에 도달하는 모든 파일 편집을 `apply_patch`라는 이름 하나로 정규화하고, 패치 자체를
40
+ `tool_input.command`에 담습니다. 셸 호출이 명령줄을 싣는 것과 같은 자리입니다. 읽을 경로
41
+ 인자가 없습니다. `Edit`과 `Write`는 `.codex/hooks.json`에 적을 수 있는 matcher 별칭이지만,
42
+ 페이로드는 언제나 도구 이름을 `apply_patch`로 보냅니다. 그래서 별칭을 기준으로 삼은 명부나
43
+ 분기는 실제로 도착하는 어떤 호출과도 일치하지 않습니다.
44
+
45
+ 패치 하나가 한 호출에서 파일을 만들고 고치고 지우고 이름을 바꿀 수 있습니다. 이 어댑터는
46
+ 각각을 IR 하나의 원소로 실어 한 번만 스폰합니다. 모든 파일이 판정되고, 그중 하나라도
47
+ 차단되면 호출 전체가 차단됩니다. 이름 변경은 원소를 둘 만듭니다. 떠나는 경로와 도착하는
48
+ 경로를 모두 바꾸기 때문입니다.
49
+
50
+ <a id="consumer"></a>
51
+ ## 사용자가 다루는 부분
52
+
53
+ 프로젝트 루트에서 두 줄이면 Codex 세션 표면이 설치됩니다.
54
+
55
+ ```sh
56
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
57
+ npx pdks-codex init
58
+ ```
59
+
60
+ `pdks-codex init`은 프로젝트에서 `polydeukes`를 찾아 확인한 뒤, 에이전트 중립 초기 구성을
61
+ 위해 `pdks init`을 스폰하고, 위임자를 쓴 뒤 `PreToolUse`, `UserPromptSubmit`, `PostToolUse`,
62
+ `SessionEnd` 항목을 `.codex/hooks.json`에 병합합니다.
63
+ 병합은 기존 내용을 지우지 않습니다. 다른 이벤트, 다른 matcher, 이 패키지가 모르는 키는 그대로
64
+ 둡니다. 다시 실행하면 이미 있는 산출물을 건너뛴 것으로 보고하고 아무것도 덮어쓰지 않습니다.
65
+ 전체 산출물 목록은 [`pdks init`](../cli/init.ko.md#init-codex)에 있습니다.
66
+
67
+ **등록 파일을 쓰는 것으로 설치가 끝나지 않습니다.** Codex는 훅 정의의 해시로 신뢰를
68
+ 기록하므로, 생성된 훅은 검토 대상으로 표시되고 `/hooks`에서 승인하기 전까지 건너뛰어집니다.
69
+ `init`이 실행할 때마다 바이트가 같은 명령 문자열을 쓰는 이유가 이것입니다. 문자열이 바뀌면
70
+ 다시 승인해야 하고, 누군가 승인하기 전까지는 아무것도 판정되지 않습니다.
71
+
72
+ 이 어댑터를 `@polydeukes/adapter-claude-code`나 `@polydeukes/adapter-grok`과 한 프로젝트에
73
+ 함께 설치하면 호출마다 판정기가 두 번 실행될 수 있습니다.
74
+
75
+ - **생성된 훅**은 이 패키지에서 `runHook`을 불러옵니다. 패키지를 올리면 실행되는 내용이
76
+ 올라가며, 훅 파일 자체는 다시 만들 필요가 없습니다.
77
+
78
+ 자체 설정 이름 공간은 없습니다. `pdks init`이 쓰는 초기 설정은 기본적으로 `.codex/hooks`를
79
+ 보호하므로, 이 설치기가 만드는 등록 파일은 같은 설치가 만든 설정이 지킵니다.
80
+
81
+ <a id="limits"></a>
82
+ ## 선언된 한계
83
+
84
+ 앞의 넷은 호스트 자신의 한계이고 어떤 어댑터도 이 범위를 좁힐 수 없습니다. 첫째는 문서가
85
+ 아니라 실제 측정으로 확인한 사항이고, 다음 셋은 호스트 훅 문서가 밝힌 사항입니다.
86
+
87
+ - **Code Mode의 `exec` 호출은 관측되지 않습니다.** codex-cli 0.154는 Code Mode `exec` 호출에도,
88
+ 그 JavaScript 안에 중첩된 `tools.apply_patch` · `tools.exec_command` 호출에도 `PreToolUse`를
89
+ 발화하지 않습니다([openai/codex#23411](https://github.com/openai/codex/issues/23411),
90
+ [#38850](https://github.com/openai/codex/issues/38850)). `/hooks`에 Active로 표시된 훅도 그
91
+ 표면에서는 아무것도 보지 못하고, 거기서 편집된 보호 경로는 telemetry 행을 남기지 않습니다.
92
+ `pdks-codex init`이 이 사실을 `note:` 줄로 출력합니다.
93
+ - **무엇을 판정하는지는 matcher가 아니라 명부가 정합니다.** 어댑터는 `apply_patch`와 `Bash`만
94
+ 번역하고, 그 밖의 이름(Code Mode 이름, MCP 도구, `write_stdin`)은 판정기를 띄우기 전에
95
+ exit 2와 `blocked` 러너 행으로 거부합니다. `.codex/hooks.json`의 matcher를 그런 이름까지
96
+ 넓히면 그 아래의 모든 호출이 판정 대신 차단되고, 그 편집은 신뢰 해시를 바꾸므로 `/hooks`에서
97
+ 다시 승인하기 전까지 훅이 건너뛰어집니다.
98
+ - **`write_stdin`은 다시 판정되지 않습니다.** 이미 `PreToolUse`를 통과한 unified-exec 세션에
99
+ 입력을 전달합니다. 입력을 받으려고 열어 둔 셸은 그것을 연 호출에서 한 번 판정됩니다.
100
+ - **호스트가 제공하는 도구는 이 경로를 지나지 않습니다.** 웹 검색 같은 도구는 로컬 함수 도구
101
+ 훅을 거치지 않으므로 어떤 약속에도 닿지 않습니다.
102
+ - **호스트는 자기 도구 훅을 완전한 차단 경계가 아니라 보조 장치라고 밝힙니다.** 일부 특수한
103
+ 도구 경로는 기본 훅 경로를 지나지 않을 수 있습니다.
104
+ - **불안정한 대화 기록은 채널로 쓰지 않습니다.** 페이로드가 대화 기록 경로를 지목하지만
105
+ 호스트가 그 형식을 안정된 인터페이스가 아니라고 밝혔으므로 어떤 판정도 그것을 읽지
106
+ 않습니다. 대신 어댑터가 `UserPromptSubmit`과 `PostToolUse`로 `session`을 만듭니다. 설정된
107
+ 토큰을 사람 메시지의 첫 줄에 단독으로 보내면 다시 시도한 보호 호출을 허용할 수 있습니다.
108
+ 사람 증거가 기록되지 않았거나 저장에 실패했다면 복구 메시지가 사용자 터미널을 안내합니다.
109
+ `actor`, `channels`, 도구 성공 여부는 합성하지 않습니다.
110
+ - **프로젝트 밖으로 해석되는 패치는 판정하지 않고 거부합니다.** 그런 경로는 프로젝트 기준
111
+ 상대 경로가 없고, 그것을 실은 원소는 어떤 관측 범위에도 들어가지 않아 판정 없이 지나가게
112
+ 됩니다.
113
+ - **`polydeukes`를 찾지 못하면 행이 남지 않습니다.** 프로젝트에서 통합 패키지를 찾을 수 없으면
114
+ 스폰할 프로세스도 기록할 로그 경로도 없으므로, 훅은 stderr에 한 줄을 남기고 `2`로 끝나며
115
+ 텔레메트리 로그에는 아무것도 추가되지 않습니다. 그 밖의 모든 스폰 전 실패는 `pdks`에 도달해
116
+ 행을 남깁니다.