polydeukes 0.7.1 → 0.8.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 (42) 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-check.d.ts +2 -2
  8. package/dist/covenant-check.js +113 -9
  9. package/dist/docs/README.ko.md +3 -2
  10. package/dist/docs/README.md +3 -2
  11. package/dist/docs/catalog.json +32 -0
  12. package/dist/docs/how-to/connect-surfaces.ko.md +33 -5
  13. package/dist/docs/how-to/connect-surfaces.md +37 -7
  14. package/dist/docs/how-to/write-disciplines.ko.md +3 -1
  15. package/dist/docs/how-to/write-disciplines.md +3 -1
  16. package/dist/docs/index.json +338 -190
  17. package/dist/docs/reference/cli/explain.ko.md +8 -8
  18. package/dist/docs/reference/cli/explain.md +10 -8
  19. package/dist/docs/reference/cli/init.ko.md +43 -4
  20. package/dist/docs/reference/cli/init.md +43 -5
  21. package/dist/docs/reference/configuration/index.ko.md +11 -5
  22. package/dist/docs/reference/configuration/index.md +10 -5
  23. package/dist/docs/reference/packages/adapter-claude-code.ko.md +5 -4
  24. package/dist/docs/reference/packages/adapter-claude-code.md +6 -4
  25. package/dist/docs/reference/packages/adapter-codex.ko.md +99 -0
  26. package/dist/docs/reference/packages/adapter-codex.md +100 -0
  27. package/dist/docs/reference/packages/adapter-grok.ko.md +6 -2
  28. package/dist/docs/reference/packages/adapter-grok.md +6 -2
  29. package/dist/docs/reference/packages/core.ko.md +1 -1
  30. package/dist/docs/reference/packages/core.md +1 -1
  31. package/dist/docs/reference/packages/polydeukes.ko.md +2 -1
  32. package/dist/docs/reference/packages/polydeukes.md +2 -1
  33. package/dist/docs/reference/packages/sdk-ts.ko.md +6 -3
  34. package/dist/docs/reference/packages/sdk-ts.md +6 -3
  35. package/dist/docs/troubleshooting.ko.md +35 -5
  36. package/dist/docs/troubleshooting.md +37 -5
  37. package/dist/docs/tutorials/first-judgment.ko.md +5 -3
  38. package/dist/docs/tutorials/first-judgment.md +5 -3
  39. package/dist/load-config.d.ts +24 -0
  40. package/dist/load-config.js +20 -2
  41. package/dist/scaffold-project.js +3 -1
  42. 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,48 @@ 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`은 덮어쓰지 않고 병합합니다. 다른 이벤트, 다른 matcher, 설치기가 모르는 키는
101
+ 그대로 둡니다. 초기 설정은 기본적으로 `.codex/hooks`를 보호하므로, 이 설치기가 만드는 등록
102
+ 파일은 같은 설치가 만든 설정이 지킵니다.
103
+
104
+ **훅 승인까지가 설치입니다.** Codex는 훅 정의의 해시로 신뢰를 기록하므로, 생성된 훅은 검토
105
+ 대상으로 표시되고 `/hooks`에서 승인하기 전까지 건너뛰어집니다. 누군가 승인하기 전까지는
106
+ 아무것도 판정되지 않습니다. `init`이 실행할 때마다 바이트가 같은 명령 문자열을 쓰는 이유가
107
+ 이것입니다. 문자열이 바뀌면 다시 승인해야 합니다.
108
+
109
+ Codex는 모든 파일 편집을 `apply_patch` 하나로 정규화하고, 경로 인자가 아니라 패치 텍스트를
110
+ 보냅니다. `Edit`과 `Write`는 `.codex/hooks.json`에 적을 수 있는 matcher 별칭이며 도구 이름으로
111
+ 도착하지 않습니다. 패치 하나가 여러 파일을 건드리면 파일마다 IR 원소 하나가 실리고, 그중
112
+ 하나라도 차단되면 호출 전체가 차단됩니다.
113
+
114
+ Codex에는 대화 기록 채널이 없어서 세션 증인(witness) 밸브가 읽을 사람 메시지 증거가
115
+ 없습니다. 의도한 편집이 차단되면 자신의 터미널에서 수행하세요. 산출물별 동작은
116
+ [표면 연결하기](../../how-to/connect-surfaces.ko.md#codex)에 있습니다.
117
+
82
118
  <a id="init-results"></a>
83
119
  ## 결과와 실패 조건
84
120
 
@@ -103,6 +139,7 @@ Grok는 Claude 세션 증인(witness) 밸브가 요구하는 인간 메시지
103
139
  pdks init
104
140
  npx pdks-claude-code init
105
141
  npx pdks-grok init
142
+ npx pdks-codex init
106
143
  ```
107
144
 
108
145
  설치기는 CLI 명령입니다. `polydeukes` 계약의 공개 심볼이 아닙니다.
@@ -113,6 +150,8 @@ npx pdks-grok init
113
150
  - [`@polydeukes/adapter-claude-code`](../packages/adapter-claude-code.ko.md) — Claude Code 설치
114
151
  단위와 그 실행 파일
115
152
  - [`@polydeukes/adapter-grok`](../packages/adapter-grok.ko.md) — Grok 설치 단위와 그 실행 파일
153
+ - [`@polydeukes/adapter-codex`](../packages/adapter-codex.ko.md) — Codex 설치 단위와 그 실행
154
+ 파일
116
155
  - [`pdks docs`](./docs.ko.md)
117
156
  - [`pdks explain`](./explain.ko.md)
118
157
  - [설정 참조](../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,48 @@ 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` is merged rather than overwritten: other events, other matchers, and keys the
100
+ installer does not know are left in place. The scaffold config protects `.codex/hooks` by
101
+ default, so the registration this installer writes is covered by the config it writes.
102
+
103
+ **Approving the hook is part of the install.** Codex records trust against the hash of a hook's
104
+ definition, so the generated hook is listed for review and skipped until you approve it with
105
+ `/hooks`. Until someone does, nothing is judged. This is why `init` writes a byte-identical
106
+ command string on every run — a changed string needs approving again.
107
+
108
+ Codex normalises every file edit into one tool, `apply_patch`, and delivers the patch text
109
+ rather than a path argument. `Edit` and `Write` are matcher aliases you may write in
110
+ `.codex/hooks.json`; they never arrive as the tool name. One patch that touches several files
111
+ carries one IR element per file, and any one of them blocking blocks the whole call.
112
+
113
+ Codex supplies no transcript channel, so the session witness valve has no human-message
114
+ evidence to read. For an intentional blocked edit, use your own terminal. Details are in
115
+ [Connect the surfaces](../../how-to/connect-surfaces.md#codex).
116
+
82
117
  <a id="init-results"></a>
83
118
  ## Results and failure conditions
84
119
 
@@ -102,6 +137,7 @@ filesystem problem, and rerun rather than assuming every failed installation lef
102
137
  pdks init
103
138
  npx pdks-claude-code init
104
139
  npx pdks-grok init
140
+ npx pdks-codex init
105
141
  ```
106
142
 
107
143
  The installers are CLI commands. They are not symbols on the `polydeukes` contract.
@@ -112,6 +148,8 @@ The installers are CLI commands. They are not symbols on the `polydeukes` contra
112
148
  - [`@polydeukes/adapter-claude-code`](../packages/adapter-claude-code.md) — the Claude Code
113
149
  install unit and its bin.
114
150
  - [`@polydeukes/adapter-grok`](../packages/adapter-grok.md) — the Grok install unit and its bin.
151
+ - [`@polydeukes/adapter-codex`](../packages/adapter-codex.md) — the Codex install unit and its
152
+ bin.
115
153
  - [`pdks docs`](../packages/polydeukes.md#polydeukes-bin) — the installed documentation reader lives
116
154
  in the same package.
117
155
  - [`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,99 @@
1
+ # `@polydeukes/adapter-codex`
2
+
3
+ [English](adapter-codex.md) · **한국어**
4
+
5
+ > **Codex의 설치 단위**입니다. `PreToolUse` 페이로드가 약속(covenant) 입력 IR이 되고, 패치가
6
+ > 건드리는 파일마다 원소 하나가 실립니다. 세션 표면을 프로젝트에 설치하는 것도 이 패키지가
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
+ | 페이로드 검증 | 호스트의 생성 스키마가 필수로 지정한 키를 모두 요구하며, 그 호스트가 보내는 한 가지 표기만 받습니다 |
22
+ | 패치 해석 | `apply_patch` 호출의 원본 패치 텍스트를 건드리는 파일마다 변경 하나로 풉니다 |
23
+ | 경로 기준 변환 | 패치 경로를 호출의 작업 디렉터리 기준으로 해석한 뒤 프로젝트 루트 기준으로 실습니다 |
24
+
25
+ 생성된 훅 위임자가 불러오는 것이 `runHook({ repoRoot })`입니다. `tools` 명부를 실은 입력 IR을
26
+ 만든 뒤 — `session`과 `actor` 키는 없습니다 — `repoRoot`에서
27
+ `pdks covenant check --enforce block`을 스폰하고 그 자식 프로세스의 종료 코드를 그대로
28
+ 돌려줍니다. 판정은 그 자식 프로세스가 하며, 이 패키지에는 판정 코드가 없습니다.
29
+
30
+ **이 패키지는 텔레메트리 행을 쓰지 않습니다.** 스폰 전에 실패하면 그 사실을 한 줄로 만들어
31
+ `pdks`의 stdin으로 보내므로, 그 호출이 남기는 행은 언제나 한 곳에서만 기록됩니다.
32
+
33
+ <a id="apply-patch"></a>
34
+ ## 형제 어댑터는 인자를 읽는데 이 어댑터가 텍스트를 해석하는 이유
35
+
36
+ Codex는 모든 파일 편집을 `apply_patch`라는 이름 하나로 정규화하고, 패치 자체를
37
+ `tool_input.command`에 담습니다. 셸 호출이 명령줄을 싣는 것과 같은 자리입니다. 읽을 경로
38
+ 인자가 없습니다. `Edit`과 `Write`는 `.codex/hooks.json`에 적을 수 있는 matcher 별칭이지만,
39
+ 페이로드는 언제나 도구 이름을 `apply_patch`로 보냅니다. 그래서 별칭을 기준으로 삼은 명부나
40
+ 분기는 실제로 도착하는 어떤 호출과도 일치하지 않습니다.
41
+
42
+ 패치 하나가 한 호출에서 파일을 만들고 고치고 지우고 이름을 바꿀 수 있습니다. 이 어댑터는
43
+ 각각을 IR 하나의 원소로 실어 한 번만 스폰합니다. 모든 파일이 판정되고, 그중 하나라도
44
+ 차단되면 호출 전체가 차단됩니다. 이름 변경은 원소를 둘 만듭니다. 떠나는 경로와 도착하는
45
+ 경로를 모두 바꾸기 때문입니다.
46
+
47
+ <a id="consumer"></a>
48
+ ## 사용자가 다루는 부분
49
+
50
+ 프로젝트 루트에서 두 줄이면 Codex 세션 표면이 설치됩니다.
51
+
52
+ ```sh
53
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
54
+ npx pdks-codex init
55
+ ```
56
+
57
+ `pdks-codex init`은 프로젝트에서 `polydeukes`를 찾아 확인한 뒤, 에이전트 중립 초기 구성을
58
+ 위해 `pdks init`을 스폰하고, 위임자를 쓰고 자기 항목을 `.codex/hooks.json`에 병합합니다.
59
+ 병합은 기존 내용을 지우지 않습니다. 다른 이벤트, 다른 matcher, 이 패키지가 모르는 키는 그대로
60
+ 둡니다. 다시 실행하면 이미 있는 산출물을 건너뛴 것으로 보고하고 아무것도 덮어쓰지 않습니다.
61
+ 전체 산출물 목록은 [`pdks init`](../cli/init.ko.md#init-codex)에 있습니다.
62
+
63
+ **등록 파일을 쓰는 것으로 설치가 끝나지 않습니다.** Codex는 훅 정의의 해시로 신뢰를
64
+ 기록하므로, 생성된 훅은 검토 대상으로 표시되고 `/hooks`에서 승인하기 전까지 건너뛰어집니다.
65
+ `init`이 실행할 때마다 바이트가 같은 명령 문자열을 쓰는 이유가 이것입니다. 문자열이 바뀌면
66
+ 다시 승인해야 하고, 누군가 승인하기 전까지는 아무것도 판정되지 않습니다.
67
+
68
+ 이 어댑터를 `@polydeukes/adapter-claude-code`나 `@polydeukes/adapter-grok`과 한 프로젝트에
69
+ 함께 설치하면 호출마다 판정기가 두 번 실행될 수 있습니다.
70
+
71
+ - **생성된 훅**은 이 패키지에서 `runHook`을 불러옵니다. 패키지를 올리면 실행되는 내용이
72
+ 올라가며, 훅 파일 자체는 다시 만들 필요가 없습니다.
73
+
74
+ 자체 설정 이름 공간은 없습니다. `pdks init`이 쓰는 초기 설정은 기본적으로 `.codex/hooks`를
75
+ 보호하므로, 이 설치기가 만드는 등록 파일은 같은 설치가 만든 설정이 지킵니다.
76
+
77
+ <a id="limits"></a>
78
+ ## 선언된 한계
79
+
80
+ 앞의 셋은 호스트 자신의 한계이고 호스트 훅 문서가 밝힌 사항입니다. 어떤 어댑터도 이 범위를
81
+ 좁힐 수 없습니다.
82
+
83
+ - **`write_stdin`은 다시 판정되지 않습니다.** 이미 `PreToolUse`를 통과한 unified-exec 세션에
84
+ 입력을 전달합니다. 입력을 받으려고 열어 둔 셸은 그것을 연 호출에서 한 번 판정됩니다.
85
+ - **호스트가 제공하는 도구는 이 경로를 지나지 않습니다.** 웹 검색 같은 도구는 로컬 함수 도구
86
+ 훅을 거치지 않으므로 어떤 약속에도 닿지 않습니다.
87
+ - **호스트는 자기 도구 훅을 완전한 차단 경계가 아니라 보조 장치라고 밝힙니다.** 일부 특수한
88
+ 도구 경로는 기본 훅 경로를 지나지 않을 수 있습니다.
89
+ - **대화 기록 채널이 없습니다.** IR에 `session`과 `actor` 키가 없습니다. 페이로드가 대화 기록
90
+ 경로를 지목하지만 호스트가 그 형식을 안정된 인터페이스가 아니라고 밝혔으므로 어떤 판정도
91
+ 그것을 읽지 않습니다. 그래서 세션 증인 밸브가 필요로 하는 사람 메시지 증거를 얻을 수
92
+ 없습니다. 의도적으로 차단된 편집을 하려면 사용자의 터미널을 쓰십시오.
93
+ - **프로젝트 밖으로 해석되는 패치는 판정하지 않고 거부합니다.** 그런 경로는 프로젝트 기준
94
+ 상대 경로가 없고, 그것을 실은 원소는 어떤 관측 범위에도 들어가지 않아 판정 없이 지나가게
95
+ 됩니다.
96
+ - **`polydeukes`를 찾지 못하면 행이 남지 않습니다.** 프로젝트에서 통합 패키지를 찾을 수 없으면
97
+ 스폰할 프로세스도 기록할 로그 경로도 없으므로, 훅은 stderr에 한 줄을 남기고 `2`로 끝나며
98
+ 텔레메트리 로그에는 아무것도 추가되지 않습니다. 그 밖의 모든 스폰 전 실패는 `pdks`에 도달해
99
+ 행을 남깁니다.
@@ -0,0 +1,100 @@
1
+ # `@polydeukes/adapter-codex`
2
+
3
+ **English** · [한국어](adapter-codex.ko.md)
4
+
5
+ > **The Codex install unit** — `PreToolUse` payloads become the covenant input IR, with one
6
+ > element per file the patch touches, and the package installs the session surface into a
7
+ > project.
8
+ >
9
+ > Beta. Install it next to `polydeukes`, which it names as a `peerDependency`.
10
+
11
+ <a id="ownership"></a>
12
+ ## What this package owns
13
+
14
+ The boundary where Codex's vocabulary is translated away. Agent and tool literals live *here*
15
+ by design, so that they never reach the core.
16
+
17
+ | Unit | What it does |
18
+ |---|---|
19
+ | `pdks-codex` bin | One subcommand, `pdks-codex init`, which registers the session surface in a project |
20
+ | `runHook` | Translates one `PreToolUse` payload into the input IR and spawns the judge |
21
+ | Payload validation | Demands every key the host's generated schema marks required, in the one spelling that host sends |
22
+ | Patch parsing | Turns the raw patch text of an `apply_patch` call into one file change per file it touches |
23
+ | Path rebasing | Resolves a patch path against the call's working directory and carries it relative to the project root |
24
+
25
+ `runHook({ repoRoot })` is what the generated hook delegator imports. It builds the IR — the
26
+ `tools` roster included, with no `session` or `actor` key — then spawns
27
+ `pdks covenant check --enforce block` in `repoRoot` and returns the child's exit code. The
28
+ judging happens in that child process; this package carries no judgment logic.
29
+
30
+ **This package writes no telemetry rows.** A failure before the spawn is sent to `pdks` on
31
+ stdin, so the row that call earns is written by the one writer.
32
+
33
+ <a id="apply-patch"></a>
34
+ ## Why this adapter parses text where its siblings read arguments
35
+
36
+ Codex normalises every file edit into a single tool name, `apply_patch`, and puts the patch
37
+ itself in `tool_input.command` — the same field a shell call uses for its command line. There
38
+ is no path argument to read. `Edit` and `Write` exist as matcher aliases you may write in
39
+ `.codex/hooks.json`, but the payload always names the tool `apply_patch`, so a roster or a
40
+ branch keyed on the aliases matches nothing that ever arrives.
41
+
42
+ One patch can create, update, delete and rename files in one call. The adapter carries each as
43
+ its own element of one IR, on one spawn: every file is judged, and any one of them blocking
44
+ blocks the whole call. A rename contributes two elements, because it changes the path it
45
+ leaves as well as the one it takes.
46
+
47
+ <a id="consumer"></a>
48
+ ## Where the consumer touches it
49
+
50
+ Two lines install the Codex session surface, run from the project root:
51
+
52
+ ```sh
53
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
54
+ npx pdks-codex init
55
+ ```
56
+
57
+ `pdks-codex init` resolves `polydeukes` from the project, spawns `pdks init` for the
58
+ agent-neutral scaffold, then writes the delegator and merges its entry into
59
+ `.codex/hooks.json` non-destructively — other events, other matchers and keys it does not know
60
+ are left alone. A re-run reports each existing artifact as skipped and overwrites nothing. The
61
+ full artifact list is in [`pdks init`](../cli/init.md#init-codex).
62
+
63
+ **Writing the registration is not the end of the install.** Codex records trust against the
64
+ hash of a hook's definition, so the generated hook is listed for review and skipped until you
65
+ approve it with `/hooks`. This is why `init` writes a byte-identical command string on every
66
+ run: a changed one needs approving again, and until someone does, nothing is judged.
67
+
68
+ Installing this adapter beside `@polydeukes/adapter-claude-code` or
69
+ `@polydeukes/adapter-grok` in one project can run the judge twice per call.
70
+
71
+ - **The generated hook** imports `runHook` from this package. Upgrading the package upgrades
72
+ what runs; the hook file itself never changes.
73
+
74
+ No configuration namespace of its own. The scaffold `pdks init` writes protects `.codex/hooks`
75
+ by default, so the registration this installer creates is covered by the config it creates.
76
+
77
+ <a id="limits"></a>
78
+ ## Declared limits
79
+
80
+ The first three are the host's own, stated in its hook documentation, and no adapter can
81
+ narrow them.
82
+
83
+ - **`write_stdin` is not judged again.** It delivers input to a unified-exec session that
84
+ already passed `PreToolUse`. A shell left open for input is judged once, at the call that
85
+ opened it.
86
+ - **Hosted tools do not take this path.** Web search and its kind do not run through the local
87
+ function-tool hooks, so they reach no covenant.
88
+ - **The host calls its tool hooks a guardrail rather than a complete enforcement boundary.**
89
+ Some specialized tool paths can opt out of the default hook path.
90
+ - **There is no transcript channel.** The IR omits `session` and `actor`. The payload names a
91
+ transcript path, but the host documents that format as unstable, so no judgment reads it —
92
+ which leaves the session witness valve without the human-message evidence it needs. For an
93
+ intentional blocked edit, use your own terminal.
94
+ - **A patch resolving outside the project is refused rather than judged.** Such a path has no
95
+ project-relative form, and an element carrying one would land in no scope — judged over
96
+ nothing, and passed.
97
+ - **An unresolvable `polydeukes` leaves no row.** When the umbrella cannot be resolved from the
98
+ project there is no process to spawn and no log path to write to, so the hook exits `2` with
99
+ one line on stderr and the telemetry log gains nothing. Every other pre-spawn failure does
100
+ reach `pdks` and does leave a row.
@@ -6,7 +6,7 @@
6
6
  > 판정기가 읽는 파일 변경 증거가 함께 실립니다. 세션 표면을 프로젝트에 설치하는 것도 이
7
7
  > 패키지가 합니다.
8
8
  >
9
- > 알파입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
9
+ > 베타입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
10
10
 
11
11
  <a id="ownership"></a>
12
12
  ## 담당하는 기능
@@ -41,7 +41,7 @@ Grok의 입력을 공통 형식으로 번역합니다. 에이전트와 도구의
41
41
  프로젝트 루트에서 두 줄이면 Grok 세션 표면이 설치됩니다.
42
42
 
43
43
  ```sh
44
- npm install --save-dev polydeukes @polydeukes/adapter-grok
44
+ npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-grok
45
45
  npx pdks-grok init
46
46
  ```
47
47
 
@@ -75,3 +75,7 @@ npx pdks-grok init
75
75
  스폰할 프로세스도, 기록할 로그 경로도 없습니다. 훅은 stderr에 한 줄을 남기고 종료 코드
76
76
  `2`를 내며 텔레메트리 로그에는 아무것도 추가되지 않습니다. 스폰 전 실패 가운데 이 경우만
77
77
  그렇고, 나머지는 모두 `pdks`에 도달해 행을 남깁니다.
78
+ - **다른 호스트는 각자의 어댑터로 설치합니다.** Claude Code는
79
+ `@polydeukes/adapter-claude-code`로, Codex는 `@polydeukes/adapter-codex`로 설치합니다.
80
+ 각 패키지가 자기 위임자와 명부를 씁니다. 한 프로젝트에 세션 어댑터를 둘 이상 설치하면
81
+ 호출마다 판정기가 여러 번 실행될 수 있습니다.