polydeukes 0.6.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 (108) hide show
  1. package/README.ko.md +16 -28
  2. package/README.md +16 -28
  3. package/dist/baseline.d.ts +37 -1
  4. package/dist/baseline.js +68 -1
  5. package/dist/bin.d.ts +3 -4
  6. package/dist/bin.js +73 -90
  7. package/dist/covenant/bash-line.d.ts +130 -0
  8. package/dist/covenant/bash-line.js +566 -0
  9. package/dist/covenant/declaration-engine.d.ts +108 -0
  10. package/dist/covenant/declaration-engine.js +415 -0
  11. package/dist/covenant/discipline.d.ts +109 -0
  12. package/dist/covenant/discipline.js +667 -0
  13. package/dist/covenant/dispatch.d.ts +156 -0
  14. package/dist/covenant/dispatch.js +250 -0
  15. package/dist/covenant/extract-steps.d.ts +122 -0
  16. package/dist/covenant/extract-steps.js +0 -0
  17. package/dist/covenant/mention.d.ts +117 -0
  18. package/dist/covenant/mention.js +209 -0
  19. package/dist/covenant/module.d.ts +25 -0
  20. package/dist/covenant/module.js +23 -0
  21. package/dist/covenant/mutation-rules.d.ts +40 -0
  22. package/dist/covenant/mutation-rules.js +146 -0
  23. package/dist/covenant/relations.d.ts +46 -0
  24. package/dist/covenant/relations.js +68 -0
  25. package/dist/covenant/run-covenant.d.ts +95 -0
  26. package/dist/covenant/run-covenant.js +164 -0
  27. package/dist/covenant/self-mod.d.ts +55 -0
  28. package/dist/covenant/self-mod.js +84 -0
  29. package/dist/covenant/shell-evidence.d.ts +38 -0
  30. package/dist/covenant/shell-evidence.js +247 -0
  31. package/dist/covenant/shell-mod.d.ts +84 -0
  32. package/dist/covenant/shell-mod.js +213 -0
  33. package/dist/covenant/supply.d.ts +54 -0
  34. package/dist/covenant/supply.js +50 -0
  35. package/dist/covenant/transcript-mod.d.ts +60 -0
  36. package/dist/covenant/transcript-mod.js +254 -0
  37. package/dist/covenant/ttl-witness.d.ts +47 -0
  38. package/dist/covenant/ttl-witness.js +80 -0
  39. package/dist/covenant-check.d.ts +74 -41
  40. package/dist/covenant-check.js +372 -129
  41. package/dist/diff-ir.d.ts +28 -0
  42. package/dist/diff-ir.js +310 -0
  43. package/dist/docs/README.ko.md +10 -9
  44. package/dist/docs/README.md +10 -9
  45. package/dist/docs/catalog.json +76 -28
  46. package/dist/docs/concepts/judgment.ko.md +2 -2
  47. package/dist/docs/concepts/judgment.md +2 -2
  48. package/dist/docs/how-to/configure-project.ko.md +16 -16
  49. package/dist/docs/how-to/configure-project.md +15 -12
  50. package/dist/docs/how-to/connect-surfaces.ko.md +67 -34
  51. package/dist/docs/how-to/connect-surfaces.md +67 -34
  52. package/dist/docs/how-to/write-disciplines.ko.md +64 -7
  53. package/dist/docs/how-to/write-disciplines.md +65 -7
  54. package/dist/docs/index.json +744 -362
  55. package/dist/docs/reference/cli/covenant-check.ko.md +112 -65
  56. package/dist/docs/reference/cli/covenant-check.md +114 -59
  57. package/dist/docs/reference/cli/docs.ko.md +2 -2
  58. package/dist/docs/reference/cli/docs.md +2 -2
  59. package/dist/docs/reference/cli/explain.ko.md +20 -15
  60. package/dist/docs/reference/cli/explain.md +22 -15
  61. package/dist/docs/reference/cli/init.ko.md +91 -52
  62. package/dist/docs/reference/cli/init.md +81 -55
  63. package/dist/docs/reference/configuration/index.ko.md +182 -71
  64. package/dist/docs/reference/configuration/index.md +188 -76
  65. package/dist/docs/reference/packages/adapter-claude-code.ko.md +39 -11
  66. package/dist/docs/reference/packages/adapter-claude-code.md +40 -14
  67. package/dist/docs/reference/packages/adapter-codex.ko.md +99 -0
  68. package/dist/docs/reference/packages/adapter-codex.md +100 -0
  69. package/dist/docs/reference/packages/adapter-grok.ko.md +81 -0
  70. package/dist/docs/reference/packages/adapter-grok.md +83 -0
  71. package/dist/docs/reference/packages/core.ko.md +50 -4
  72. package/dist/docs/reference/packages/core.md +55 -6
  73. package/dist/docs/reference/packages/polydeukes.ko.md +139 -77
  74. package/dist/docs/reference/packages/polydeukes.md +147 -81
  75. package/dist/docs/reference/packages/sdk-ts.ko.md +164 -0
  76. package/dist/docs/reference/packages/sdk-ts.md +167 -0
  77. package/dist/docs/troubleshooting.ko.md +51 -19
  78. package/dist/docs/troubleshooting.md +53 -17
  79. package/dist/docs/tutorials/first-judgment.ko.md +6 -4
  80. package/dist/docs/tutorials/first-judgment.md +6 -4
  81. package/dist/explain.d.ts +1 -1
  82. package/dist/explain.js +37 -22
  83. package/dist/load-config.d.ts +25 -1
  84. package/dist/load-config.js +21 -3
  85. package/dist/pre-state-reader.d.ts +1 -1
  86. package/dist/pre-state-reader.js +1 -1
  87. package/dist/scaffold-project.d.ts +2 -2
  88. package/dist/scaffold-project.js +12 -4
  89. package/dist/schema/polydeukes.schema.json +12 -0
  90. package/dist/worktree-reader.d.ts +19 -0
  91. package/dist/worktree-reader.js +30 -0
  92. package/package.json +5 -18
  93. package/dist/claude-code-hook.d.ts +0 -79
  94. package/dist/claude-code-hook.js +0 -372
  95. package/dist/claude-code.d.ts +0 -6
  96. package/dist/claude-code.js +0 -6
  97. package/dist/covenant-module.d.ts +0 -25
  98. package/dist/covenant-module.js +0 -42
  99. package/dist/docs/reference/packages/adapter-git.ko.md +0 -101
  100. package/dist/docs/reference/packages/adapter-git.md +0 -108
  101. package/dist/docs/reference/packages/covenant.ko.md +0 -115
  102. package/dist/docs/reference/packages/covenant.md +0 -123
  103. package/dist/index.d.ts +0 -22
  104. package/dist/index.js +0 -21
  105. package/dist/init-claude-code.d.ts +0 -52
  106. package/dist/init-claude-code.js +0 -586
  107. package/dist/init-grok.d.ts +0 -51
  108. package/dist/init-grok.js +0 -242
@@ -0,0 +1,310 @@
1
+ /**
2
+ * unified diff → `CovenantInput`. One pure translation, no judgment and no disk.
3
+ *
4
+ * The accepted grammar is finite: `diff --git` blocks and header-less `---`/`+++` blocks,
5
+ * covering creation, deletion, modification, mode-only changes, renames, and binary blobs.
6
+ * Anything else throws, so an unrecognised shape fails the run closed instead of translating
7
+ * to a partial observation.
8
+ *
9
+ * A modification's `pre`/`post` are the hunk's `-` and `+` lines, never the whole file: a
10
+ * unified diff carries the changed lines and the context around them, and reconstructing the
11
+ * file from them is not a translation. A creation and a deletion carry the whole text because
12
+ * every line of the file is in the hunk.
13
+ */
14
+ /** The tool name a staged write is dispatched under — telemetry and configs read it. */
15
+ export const STAGED_WRITE = 'staged-write';
16
+ /** The tool name a staged deletion is dispatched under. */
17
+ export const STAGED_DELETE = 'staged-delete';
18
+ function emptyBlock() {
19
+ return { binary: false, deletedFile: false, newFile: false, removed: [], added: [] };
20
+ }
21
+ /** A path as git prints it after `rename from` / `rename to`: quoted only when it has to be. */
22
+ function readBarePath(raw) {
23
+ return raw.startsWith('"') ? unquotePath(raw) : raw;
24
+ }
25
+ /**
26
+ * Decode git's C-quoted path form: the octal escapes are BYTES of the path, so they are
27
+ * collected and decoded as UTF-8 together — decoding each one on its own would turn every
28
+ * non-ASCII character into replacement characters.
29
+ */
30
+ function unquotePath(quoted) {
31
+ const body = quoted.slice(1, -1);
32
+ const bytes = [];
33
+ for (let at = 0; at < body.length; at += 1) {
34
+ const char = body[at];
35
+ if (char !== '\\') {
36
+ bytes.push(...Buffer.from(char, 'utf-8'));
37
+ continue;
38
+ }
39
+ const next = body[at + 1];
40
+ const octal = body.slice(at + 1, at + 4);
41
+ if (/^[0-7]{3}$/.test(octal)) {
42
+ bytes.push(Number.parseInt(octal, 8));
43
+ at += 3;
44
+ continue;
45
+ }
46
+ const simple = {
47
+ t: 0x09,
48
+ n: 0x0a,
49
+ r: 0x0d,
50
+ '"': 0x22,
51
+ '\\': 0x5c,
52
+ };
53
+ bytes.push(simple[next] ?? Buffer.from(next, 'utf-8')[0] ?? 0);
54
+ at += 1;
55
+ }
56
+ return Buffer.from(bytes).toString('utf-8');
57
+ }
58
+ /**
59
+ * The path a `---`/`+++` line names, or null for `/dev/null`. A quoted path is unquoted
60
+ * before anything is cut, because a quoted path may itself contain a tab; an unquoted one is
61
+ * cut at the tab `diff -u` puts its timestamp behind. Exactly one `a/` or `b/` level is
62
+ * stripped, so a repository directory literally named `a/` survives.
63
+ */
64
+ function readPath(rest, prefix) {
65
+ let path;
66
+ if (rest.startsWith('"')) {
67
+ const end = rest.lastIndexOf('"');
68
+ path = unquotePath(rest.slice(0, end + 1));
69
+ }
70
+ else {
71
+ const tab = rest.indexOf('\t');
72
+ path = tab === -1 ? rest : rest.slice(0, tab);
73
+ }
74
+ if (path === '/dev/null')
75
+ return null;
76
+ return path.startsWith(prefix) ? path.slice(prefix.length) : path;
77
+ }
78
+ /** The two paths of a `diff --git a/X b/Y` header, or undefined when they cannot be read. */
79
+ function readHeaderPaths(rest) {
80
+ if (rest.startsWith('"')) {
81
+ const end = rest.indexOf('" "');
82
+ if (end === -1)
83
+ return undefined;
84
+ const old = unquotePath(rest.slice(0, end + 1));
85
+ const next = unquotePath(rest.slice(end + 2));
86
+ return { old: stripOnce(old, 'a/'), new: stripOnce(next, 'b/') };
87
+ }
88
+ // Unquoted paths may contain spaces, and git writes no separator between the two. The
89
+ // halves are equal in length whenever the prefixes are, which is git's own output; the
90
+ // midpoint split is what recovers them.
91
+ const middle = rest.length % 2 === 1 ? (rest.length - 1) / 2 : -1;
92
+ if (middle > 0 && rest[middle] === ' ') {
93
+ return {
94
+ old: stripOnce(rest.slice(0, middle), 'a/'),
95
+ new: stripOnce(rest.slice(middle + 1), 'b/'),
96
+ };
97
+ }
98
+ const at = rest.indexOf(' ');
99
+ if (at === -1)
100
+ return undefined;
101
+ return { old: stripOnce(rest.slice(0, at), 'a/'), new: stripOnce(rest.slice(at + 1), 'b/') };
102
+ }
103
+ function stripOnce(path, prefix) {
104
+ return path.startsWith(prefix) ? path.slice(prefix.length) : path;
105
+ }
106
+ /** The old and new line counts a hunk header declares, or undefined when it is not one. */
107
+ function readHunkCounts(line) {
108
+ const match = /^@@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? @@/.exec(line);
109
+ if (match === null)
110
+ return undefined;
111
+ return {
112
+ old: match[1] === undefined ? 1 : Number.parseInt(match[1], 10),
113
+ new: match[2] === undefined ? 1 : Number.parseInt(match[2], 10),
114
+ };
115
+ }
116
+ /**
117
+ * Split the text into file blocks, reading hunk bodies by the line counts their headers
118
+ * declare. The counts are what keeps a removed `-- note` line (which reads as `--- note`)
119
+ * from being taken for a new file header: header lines are only recognised outside a hunk.
120
+ */
121
+ function parseBlocks(text) {
122
+ const lines = text.split('\n');
123
+ const blocks = [];
124
+ let block;
125
+ const open = () => {
126
+ if (block === undefined) {
127
+ block = emptyBlock();
128
+ blocks.push(block);
129
+ }
130
+ return block;
131
+ };
132
+ for (let at = 0; at < lines.length; at += 1) {
133
+ const line = lines[at];
134
+ if (line === '' && at === lines.length - 1)
135
+ continue;
136
+ if (line.startsWith('diff --cc ') || line.startsWith('diff --combined ')) {
137
+ throw new Error(`unified diff: combined diffs are not translatable: ${line}`);
138
+ }
139
+ if (line.startsWith('diff --git ')) {
140
+ block = emptyBlock();
141
+ blocks.push(block);
142
+ block.headerPaths = readHeaderPaths(line.slice('diff --git '.length));
143
+ continue;
144
+ }
145
+ if (line.startsWith('--- ')) {
146
+ // A second `---` outside a hunk starts a new header-less block.
147
+ if (block !== undefined && block.oldPath !== undefined)
148
+ block = undefined;
149
+ open().oldPath = readPath(line.slice(4), 'a/');
150
+ continue;
151
+ }
152
+ if (line.startsWith('+++ ')) {
153
+ const current = open();
154
+ if (current.oldPath === undefined) {
155
+ throw new Error(`unified diff: '+++' line with no '---' partner: ${line}`);
156
+ }
157
+ current.newPath = readPath(line.slice(4), 'b/');
158
+ continue;
159
+ }
160
+ const counts = readHunkCounts(line);
161
+ if (counts !== undefined) {
162
+ const current = open();
163
+ if (current.oldPath === undefined || current.newPath === undefined) {
164
+ if (current.headerPaths === undefined) {
165
+ throw new Error(`unified diff: hunk with no file header: ${line}`);
166
+ }
167
+ }
168
+ let oldLeft = counts.old;
169
+ let newLeft = counts.new;
170
+ while ((oldLeft > 0 || newLeft > 0) && at + 1 < lines.length) {
171
+ const body = lines[at + 1];
172
+ at += 1;
173
+ if (body.startsWith('\\'))
174
+ continue;
175
+ // A line the declared counts have no room for is a malformed hunk: judging the
176
+ // lines that fit and dropping the rest would be an observation smaller than the
177
+ // input, so the whole run fails closed instead.
178
+ if (body.startsWith('+') && newLeft > 0) {
179
+ current.added.push(body.slice(1));
180
+ newLeft -= 1;
181
+ continue;
182
+ }
183
+ if (body.startsWith('-') && oldLeft > 0) {
184
+ current.removed.push(body.slice(1));
185
+ oldLeft -= 1;
186
+ continue;
187
+ }
188
+ if ((body.startsWith(' ') || body === '') && oldLeft > 0 && newLeft > 0) {
189
+ oldLeft -= 1;
190
+ newLeft -= 1;
191
+ continue;
192
+ }
193
+ throw new Error(`unified diff: unknown hunk line: ${body}`);
194
+ }
195
+ continue;
196
+ }
197
+ if (line.startsWith('rename from ')) {
198
+ open().renameFrom = readBarePath(line.slice('rename from '.length));
199
+ continue;
200
+ }
201
+ if (line.startsWith('rename to ')) {
202
+ open().renameTo = readBarePath(line.slice('rename to '.length));
203
+ continue;
204
+ }
205
+ if (line.startsWith('deleted file mode ')) {
206
+ open().deletedFile = true;
207
+ continue;
208
+ }
209
+ if (line.startsWith('new file mode ')) {
210
+ open().newFile = true;
211
+ continue;
212
+ }
213
+ if (line.startsWith('Binary files ') || line === 'GIT binary patch') {
214
+ const current = open();
215
+ current.binary = true;
216
+ if (line.endsWith('and /dev/null differ'))
217
+ current.deletedFile = true;
218
+ }
219
+ // Everything else outside a hunk is an extended header line (`index`, `old mode`,
220
+ // `similarity index`, a binary patch's base85 payload) that names nothing this
221
+ // translation reads.
222
+ }
223
+ return blocks;
224
+ }
225
+ /** The toolCalls one block translates to, in the order the judgment sees them. */
226
+ function blockToolCalls(block) {
227
+ const { renameFrom, renameTo } = block;
228
+ if (renameFrom !== undefined && renameTo !== undefined) {
229
+ return [
230
+ {
231
+ name: STAGED_DELETE,
232
+ args: { file_path: renameFrom },
233
+ fileChange: { kind: 'delete', path: renameFrom },
234
+ },
235
+ {
236
+ name: STAGED_WRITE,
237
+ args: { file_path: renameTo },
238
+ fileChange: {
239
+ kind: 'modify',
240
+ path: renameTo,
241
+ pre: block.removed.join('\n'),
242
+ post: block.added.join('\n'),
243
+ },
244
+ },
245
+ ];
246
+ }
247
+ // An empty file's deletion or creation carries no `---`/`+++` pair and no hunk, so the
248
+ // mode line is the only evidence of which one it is.
249
+ const deletion = block.newPath === null || block.deletedFile;
250
+ const path = deletion
251
+ ? (block.oldPath ?? block.headerPaths?.old)
252
+ : (block.newPath ?? block.headerPaths?.new);
253
+ if (path === undefined || path === null) {
254
+ throw new Error('unified diff: a file block names no path');
255
+ }
256
+ if (block.binary) {
257
+ return [{ name: deletion ? STAGED_DELETE : STAGED_WRITE, args: { file_path: path } }];
258
+ }
259
+ if (deletion) {
260
+ return [
261
+ {
262
+ name: STAGED_DELETE,
263
+ args: { file_path: path },
264
+ fileChange: { kind: 'delete', path, pre: block.removed.join('\n') },
265
+ },
266
+ ];
267
+ }
268
+ if (block.oldPath === null || block.newFile) {
269
+ return [
270
+ {
271
+ name: STAGED_WRITE,
272
+ args: { file_path: path },
273
+ fileChange: { kind: 'create', path, post: block.added.join('\n') },
274
+ },
275
+ ];
276
+ }
277
+ return [
278
+ {
279
+ name: STAGED_WRITE,
280
+ args: { file_path: path },
281
+ fileChange: {
282
+ kind: 'modify',
283
+ path,
284
+ pre: block.removed.join('\n'),
285
+ post: block.added.join('\n'),
286
+ },
287
+ },
288
+ ];
289
+ }
290
+ /**
291
+ * Translate a unified diff into the covenant input IR: one toolCall per file block in input
292
+ * order (a rename is two, the deletion first), and no `actor` key — a diff proves no author.
293
+ */
294
+ export function covenantInputFromUnifiedDiff(spec) {
295
+ const blocks = parseBlocks(spec.text);
296
+ // Text that is not blank yet contains no block the grammar recognizes — a colored diff,
297
+ // a pager banner, anything else — must not translate to "nothing staged": an empty
298
+ // observation is a pass, and this input may describe a whole commit.
299
+ if (blocks.length === 0 && spec.text.trim() !== '') {
300
+ throw new Error('unified diff: no file block recognized in the input');
301
+ }
302
+ const toolCalls = [];
303
+ for (const block of blocks) {
304
+ if (block.oldPath !== undefined && block.newPath === undefined) {
305
+ throw new Error(`unified diff: '---' line with no '+++' partner: ${block.oldPath}`);
306
+ }
307
+ toolCalls.push(...blockToolCalls(block));
308
+ }
309
+ return { toolCalls, subagentSpawns: [], userMessages: [] };
310
+ }
@@ -10,7 +10,7 @@
10
10
  | 하려는 것 | 읽을 문서 |
11
11
  |---|---|
12
12
  | 첫 눈에 보이는 판정을 보고 싶다 | [첫 판정](./tutorials/first-judgment.ko.md) — 설치하고 Claude Code를 배선한 뒤 보호된 편집이 판정되는 모습을 봅니다 |
13
- | Claude Code, Grok, git을 연결하고 싶다 | [표면 연결하기](./how-to/connect-surfaces.ko.md) — 세션과 커밋 배선, Grok 포함 |
13
+ | Claude Code, Grok, Codex, git을 연결하고 싶다 | [표면 연결하기](./how-to/connect-surfaces.ko.md) — 세션과 커밋 배선, Grok와 Codex 포함 |
14
14
  | 프로젝트 설정을 다듬고 싶다 | [프로젝트 설정하기](./how-to/configure-project.ko.md) — 발견, IDE 지원, advise와 block의 선택 |
15
15
  | 실제 규율을 쓰고 싶다 | [규율 작성하기](./how-to/write-disciplines.ko.md) — 실전 선언 예제, 특히 locale key pairing |
16
16
  | 차단이나 건너뜀에서 회복하고 싶다 | [문제 해결](./troubleshooting.ko.md) — fail-closed 상태, 증인 밸브, 로그 |
@@ -25,11 +25,11 @@
25
25
  | 문서 | 답하는 것 |
26
26
  |---|---|
27
27
  | [설정 레퍼런스](./reference/configuration/index.ko.md) | `polydeukes.config.yaml`에 무엇을 넣을 수 있고 각 키가 무엇을 하는지 |
28
- | [`polydeukes` (`pdks` CLI)](./reference/packages/polydeukes.ko.md) | 패키지 계약. 서브커맨드는 [`reference/cli/`](./reference/cli/covenant-check.ko.md) |
28
+ | [`polydeukes` (`pdks` CLI)](./reference/packages/polydeukes.ko.md) | 패키지 계약과 그 안에 있는 판정기. 서브커맨드는 [`reference/cli/`](./reference/cli/covenant-check.ko.md) |
29
29
  | [`@polydeukes/core`](./reference/packages/core.ko.md) | 프로토콜, 입력 IR, 설정 스키마, 텔레메트리 |
30
- | [`@polydeukes/covenant`](./reference/packages/covenant.ko.md) | 판정기입니다. 디스패처와 규율 라이브러리, 메타 약속, 밸브 |
31
- | [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.ko.md) | 세션 표면입니다. 훅 페이로드에서 입력 IR로 |
32
- | [`@polydeukes/adapter-git`](./reference/packages/adapter-git.ko.md) | 커밋 표면입니다. 스테이징·작업 트리·범위 diff에서 입력 IR로 |
30
+ | [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.ko.md) | Claude Code 세션 표면입니다. 훅 페이로드에서 입력 IR로 |
31
+ | [`@polydeukes/adapter-grok`](./reference/packages/adapter-grok.ko.md) | Grok 세션 표면입니다. 훅 페이로드에서 입력 IR로 |
32
+ | [`@polydeukes/adapter-codex`](./reference/packages/adapter-codex.ko.md) | Codex 세션 표면입니다. 훅 페이로드에서 입력 IR로, 패치가 건드리는 파일마다 원소 하나 |
33
33
 
34
34
  <a id="shape-of-the-thing"></a>
35
35
  ## 한 페이지로 보는 구조
@@ -53,8 +53,9 @@
53
53
 
54
54
  | 표면 | 판정 대상 | 배선 방법 | 대상 |
55
55
  |---|---|---|---|
56
- | **세션** | 도구 호출, 실행되기 전에 | `pdks init claude-code` 또는 `pdks init grok` | AI 파트너와 함께 개발하는 프로젝트 |
57
- | **커밋** | diff — 스테이징 영역, 작업 트리, ref 범위 | pre-commit 훅, 또는 필요할 때 직접 실행 | 혼자 개발하는 사람, 그리고 CI |
56
+ | **세션** | 도구 호출, 실행되기 전에 | `pdks-claude-code init`, `pdks-grok init`, 또는 `pdks-codex init` | AI 파트너와 함께 개발하는 프로젝트 |
57
+ | **커밋** | stdin의 unified diff — 스테이징 영역, 작업 트리, ref 범위 | `git diff --cached`를 파이프로 넘기는 pre-commit 훅, 또는 필요할 때 직접 실행 | 혼자 개발하는 사람, 그리고 CI |
58
58
 
59
- 커밋 판정기는 필요할 때 직접 실행할 수도 있습니다. 작업 후에는 `pdks covenant check --worktree`,
60
- PR 전에는 `--range`를 사용합니다. 같은 판정 기준으로 결과를 보고하며 증인 입력은 요청하지 않습니다.
59
+ 커밋 판정기는 필요할 때 직접 실행할 수도 있습니다. 작업 후에는 `git diff HEAD | pdks covenant check --diff`,
60
+ PR 전에는 `git diff main...HEAD | …`를 사용합니다. 같은 판정 기준을 종료 코드로 답하며 묻지
61
+ 않습니다. 관문은 그 코드를 소비하는 쪽입니다.
@@ -11,7 +11,7 @@ question is.
11
11
  | If you want to | Read |
12
12
  |---|---|
13
13
  | Get to a first visible judgment | [First judgment](./tutorials/first-judgment.md) — install, wire Claude Code, and watch one protected edit get judged |
14
- | Connect Claude Code, Grok, or git | [Connect the surfaces](./how-to/connect-surfaces.md) — session and commit setup, including Grok |
14
+ | Connect Claude Code, Grok, Codex, or git | [Connect the surfaces](./how-to/connect-surfaces.md) — session and commit setup, including Grok and Codex |
15
15
  | Shape the project config | [Configure the project](./how-to/configure-project.md) — discovery, IDE support, and advise versus block |
16
16
  | Write a real discipline | [Write disciplines](./how-to/write-disciplines.md) — worked declarations, especially locale key pairing |
17
17
  | Recover from a block or skip | [Troubleshooting](./troubleshooting.md) — the fail-closed states, the witness valve, and the log |
@@ -27,11 +27,11 @@ is aspirational.
27
27
  | Document | Answers |
28
28
  |---|---|
29
29
  | [Configuration reference](./reference/configuration/index.md) | What may go in `polydeukes.config.yaml`, and what each key does |
30
- | [`polydeukes` (the `pdks` CLI)](./reference/packages/polydeukes.md) | Package contract; subcommands live under [`reference/cli/`](./reference/cli/covenant-check.md) |
30
+ | [`polydeukes` (the `pdks` CLI)](./reference/packages/polydeukes.md) | Package contract, and the judge that lives inside it; subcommands live under [`reference/cli/`](./reference/cli/covenant-check.md) |
31
31
  | [`@polydeukes/core`](./reference/packages/core.md) | The protocol, the input IR, the config schema, telemetry |
32
- | [`@polydeukes/covenant`](./reference/packages/covenant.md) | The judge — dispatcher, discipline library, meta-covenants, the valve |
33
- | [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.md) | Session surface — hook payloads become the input IR |
34
- | [`@polydeukes/adapter-git`](./reference/packages/adapter-git.md) | Commit surface — staged, worktree, and range diffs become the input IR |
32
+ | [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.md) | Claude Code session surface — hook payloads become the input IR |
33
+ | [`@polydeukes/adapter-grok`](./reference/packages/adapter-grok.md) | Grok session surface — hook payloads become the input IR |
34
+ | [`@polydeukes/adapter-codex`](./reference/packages/adapter-codex.md) | Codex session surface — hook payloads become the input IR, one element per file the patch touches |
35
35
 
36
36
  <a id="shape-of-the-thing"></a>
37
37
  ## The shape of the thing, in one page
@@ -57,8 +57,9 @@ in the whitepaper, which were all found by counting rows rather than by reading
57
57
 
58
58
  | Surface | Judges | Wired by | For |
59
59
  |---|---|---|---|
60
- | **Session** | A tool call, before it runs | `pdks init claude-code` or `pdks init grok` | A project developed with an AI partner |
61
- | **Commit** | A diff — staged, the working tree, or a ref range | A pre-commit hook, or run on demand | A human developing alone, and CI |
60
+ | **Session** | A tool call, before it runs | `pdks-claude-code init`, `pdks-grok init`, or `pdks-codex init` | A project developed with an AI partner |
61
+ | **Commit** | A unified diff on stdin — staged, the working tree, or a ref range | A pre-commit hook piping `git diff --cached`, or run on demand | A human developing alone, and CI |
62
62
 
63
- The commit judge also answers on demand: `pdks covenant check --worktree` after a task, `--range`
64
- before a PR. Same verdict a commit would receive, delivered as a report with no prompt and no gate.
63
+ The commit judge also answers on demand: `git diff HEAD | pdks covenant check --diff` after a task,
64
+ `git diff main...HEAD | …` before a PR. Same verdict a commit would receive, delivered as an exit
65
+ code with no prompt — the gate is whatever consumes that code.
@@ -130,12 +130,12 @@
130
130
  "en": {
131
131
  "path": "reference/cli/covenant-check.md",
132
132
  "title": "`pdks covenant check`",
133
- "summary": "Inspect staged changes, --worktree, or a revision range."
133
+ "summary": "Judge a unified diff or an input IR from stdin, and read the exit codes."
134
134
  },
135
135
  "ko": {
136
136
  "path": "reference/cli/covenant-check.ko.md",
137
137
  "title": "`pdks covenant check`",
138
- "summary": "스테이징한 변경, 작업 트리 검사, 리비전 범위 검사를 설명합니다."
138
+ "summary": "stdin의 unified diff나 입력 IR을 판정하고 종료 코드를 읽는 방법을 설명합니다."
139
139
  }
140
140
  },
141
141
  {
@@ -146,12 +146,12 @@
146
146
  "en": {
147
147
  "path": "reference/cli/init.md",
148
148
  "title": "`pdks init`",
149
- "summary": "Install the Claude Code or Grok integration."
149
+ "summary": "Create the project scaffold, and find the Claude Code and Grok installers."
150
150
  },
151
151
  "ko": {
152
152
  "path": "reference/cli/init.ko.md",
153
153
  "title": "`pdks init`",
154
- "summary": "Claude Code 또는 Grok 연동을 설치합니다."
154
+ "summary": "프로젝트 초기 파일을 만들고, Claude Code와 Grok 설치기를 찾습니다."
155
155
  }
156
156
  },
157
157
  {
@@ -235,51 +235,67 @@
235
235
  }
236
236
  },
237
237
  {
238
- "id": "package-covenant",
238
+ "id": "package-adapter-claude-code",
239
239
  "category": "reference",
240
- "order": 14,
240
+ "order": 15,
241
241
  "bundled": true,
242
242
  "en": {
243
- "path": "reference/packages/covenant.md",
244
- "title": "`@polydeukes/covenant`",
245
- "summary": "Consult the covenant package contract and its limits."
243
+ "path": "reference/packages/adapter-claude-code.md",
244
+ "title": "`@polydeukes/adapter-claude-code`",
245
+ "summary": "Install the Claude Code session surface, and consult the adapter package contract and its limits."
246
246
  },
247
247
  "ko": {
248
- "path": "reference/packages/covenant.ko.md",
249
- "title": "`@polydeukes/covenant`",
250
- "summary": "covenant 패키지의 계약과 한계를 확인합니다."
248
+ "path": "reference/packages/adapter-claude-code.ko.md",
249
+ "title": "`@polydeukes/adapter-claude-code`",
250
+ "summary": "Claude Code 세션 표면을 설치하고, 어댑터 패키지의 계약과 한계를 확인합니다."
251
251
  }
252
252
  },
253
253
  {
254
- "id": "package-adapter-claude-code",
254
+ "id": "package-adapter-grok",
255
255
  "category": "reference",
256
- "order": 15,
256
+ "order": 16,
257
257
  "bundled": true,
258
258
  "en": {
259
- "path": "reference/packages/adapter-claude-code.md",
260
- "title": "`@polydeukes/adapter-claude-code`",
261
- "summary": "Consult the adapter-claude-code package contract and its limits."
259
+ "path": "reference/packages/adapter-grok.md",
260
+ "title": "`@polydeukes/adapter-grok`",
261
+ "summary": "Install the Grok session surface, and consult the adapter package contract and its limits."
262
262
  },
263
263
  "ko": {
264
- "path": "reference/packages/adapter-claude-code.ko.md",
265
- "title": "`@polydeukes/adapter-claude-code`",
266
- "summary": "adapter-claude-code 패키지의 계약과 한계를 확인합니다."
264
+ "path": "reference/packages/adapter-grok.ko.md",
265
+ "title": "`@polydeukes/adapter-grok`",
266
+ "summary": "Grok 세션 표면을 설치하고, 어댑터 패키지의 계약과 한계를 확인합니다."
267
267
  }
268
268
  },
269
269
  {
270
- "id": "package-adapter-git",
270
+ "id": "package-adapter-codex",
271
271
  "category": "reference",
272
- "order": 16,
272
+ "order": 17,
273
+ "bundled": true,
274
+ "en": {
275
+ "path": "reference/packages/adapter-codex.md",
276
+ "title": "`@polydeukes/adapter-codex`",
277
+ "summary": "Install the Codex session surface, and consult how patch text becomes file-change evidence."
278
+ },
279
+ "ko": {
280
+ "path": "reference/packages/adapter-codex.ko.md",
281
+ "title": "`@polydeukes/adapter-codex`",
282
+ "summary": "Codex 세션 표면을 설치하고, 패치 텍스트가 파일 변경 증거가 되는 방식을 확인합니다."
283
+ }
284
+ },
285
+ {
286
+ "id": "package-sdk-ts",
287
+ "category": "reference",
288
+ "order": 25,
273
289
  "bundled": true,
274
290
  "en": {
275
- "path": "reference/packages/adapter-git.md",
276
- "title": "`@polydeukes/adapter-git`",
277
- "summary": "Consult the adapter-git package contract and its limits."
291
+ "path": "reference/packages/sdk-ts.md",
292
+ "title": "`@polydeukes/sdk-ts`",
293
+ "summary": "Call the judge from TypeScript with one verb, and read the three verdicts it returns."
278
294
  },
279
295
  "ko": {
280
- "path": "reference/packages/adapter-git.ko.md",
281
- "title": "`@polydeukes/adapter-git`",
282
- "summary": "adapter-git 패키지의 계약과 한계를 확인합니다."
296
+ "path": "reference/packages/sdk-ts.ko.md",
297
+ "title": "`@polydeukes/sdk-ts`",
298
+ "summary": "TypeScript에서 동사 하나로 판정기를 부르고, 돌아오는 판정 결과 셋을 읽습니다."
283
299
  }
284
300
  },
285
301
  {
@@ -409,6 +425,38 @@
409
425
  "title": "<!--",
410
426
  "summary": "당시의 개발 기록이며 현재 사용법을 설명하는 참조 문서는 아닙니다."
411
427
  }
428
+ },
429
+ {
430
+ "id": "post-7",
431
+ "category": "history",
432
+ "order": 24,
433
+ "bundled": false,
434
+ "en": {
435
+ "path": "build-in-public/2026-09-v0.6.1-docs-and-search.md",
436
+ "title": "<!--",
437
+ "summary": "Historical development account; not a current usage reference."
438
+ },
439
+ "ko": {
440
+ "path": "build-in-public/2026-09-v0.6.1-docs-and-search.ko.md",
441
+ "title": "<!--",
442
+ "summary": "당시의 개발 기록이며 현재 사용법을 설명하는 참조 문서는 아닙니다."
443
+ }
444
+ },
445
+ {
446
+ "id": "post-8",
447
+ "category": "history",
448
+ "order": 25,
449
+ "bundled": false,
450
+ "en": {
451
+ "path": "build-in-public/2026-09-v0.7-entrypoint-reshape.md",
452
+ "title": "<!--",
453
+ "summary": "Historical development account; not a current usage reference."
454
+ },
455
+ "ko": {
456
+ "path": "build-in-public/2026-09-v0.7-entrypoint-reshape.ko.md",
457
+ "title": "<!--",
458
+ "summary": "당시의 개발 기록이며 현재 사용법을 설명하는 참조 문서는 아닙니다."
459
+ }
412
460
  }
413
461
  ],
414
462
  "topics": {
@@ -16,7 +16,7 @@ Polydeukes는 연결된 표면이 공급하는 증거를 바탕으로 선언된
16
16
  **표면(surface)**은 언제 증거를 수집하는지 결정합니다.
17
17
 
18
18
  - 세션 표면은 지원하는 호스트의 도구 호출을 실행 전에 관측합니다.
19
- - 커밋 표면은 스테이징한 변경, 작업 트리의 변경 또는 두 리비전 사이의 변경을 관측합니다.
19
+ - 변경 집합 표면은 스테이징한 변경, 작업 트리의 변경 또는 두 리비전 사이의 변경을 관측합니다.
20
20
 
21
21
  패키지를 설치하는 것과 표면을 연결하는 것은 다릅니다. 에이전트가 지침을 읽었다고 해서
22
22
  도구 호출에 자동으로 판정이 적용되지는 않습니다. 지원하는 연동을 설정하고 실제 호출로
@@ -103,7 +103,7 @@ Polydeukes는 연결된 표면이 공급하는 증거를 바탕으로 선언된
103
103
  ## 강제 수준과 증인
104
104
 
105
105
  규율 항목의 기본 강제 수준은 `advise`입니다. 위반과 정상 사례를 모두 확인한 뒤
106
- `enforce: block`으로 승격하세요. 커밋 표면의 수준과 항목의 수준을 함께 적용할 때는
106
+ `enforce: block`으로 승격하세요. 변경 집합 표면의 수준과 항목의 수준을 함께 적용할 때는
107
107
  **더 관대한 쪽을 따릅니다**. 표면만 `block`으로 설정해도 모든 항목이 차단 수준으로
108
108
  바뀌지는 않습니다. 판정 체계 자체의 보호는 일반 규율 항목과 별개입니다.
109
109
 
@@ -15,7 +15,7 @@ in the project's configuration. The **judge** evaluates evidence; a **verdict**
15
15
  A **surface** determines when evidence is gathered:
16
16
 
17
17
  - The session surface observes a supported host's tool call before it runs.
18
- - The commit surface observes staged changes, working-tree changes, or a revision range.
18
+ - The change-set surface observes staged changes, working-tree changes, or a revision range.
19
19
 
20
20
  Installing the package is not the same as connecting a surface. Instructions an agent reads are
21
21
  not automatic interception of its tools. Use a supported integration and verify an actual call.
@@ -102,7 +102,7 @@ that the practice was followed. An empty observation set establishes nothing abo
102
102
  ## Enforcement and witness
103
103
 
104
104
  Discipline entries default to `advise`. Promote an entry with `enforce: block` only after checking
105
- both its violating and valid cases. The commit surface's level and an entry's level compose:
105
+ both its violating and valid cases. The change-set surface's level and an entry's level compose:
106
106
  **the lenient side wins**. Setting only the surface to `block` does not promote every entry.
107
107
  Protection of the judging chain is separate from ordinary discipline entries.
108
108
 
@@ -36,8 +36,8 @@ YAML 파일에는 다음 줄을 넣어 설치된 스키마를 편집기에서
36
36
  # yaml-language-server: $schema=../../node_modules/polydeukes/dist/schema/polydeukes.schema.json
37
37
  ```
38
38
 
39
- `pdks init claude-code`는 생성한 설정 파일을 기준으로 기본 경로의 스키마를 찾을 수 있을 때만
40
- 스키마 줄을 넣습니다. 이 줄이 없다면 스키마 위치에 맞춰 상대 경로를 직접 추가하세요.
39
+ `pdks init`은 생성한 설정 파일을 기준으로 기본 경로의 스키마를 찾을 수 있을 때만 스키마 줄을
40
+ 넣습니다. `pdks-claude-code init`이 이 명령을 대신 실행합니다. 이 줄이 없다면 스키마 위치에 맞춰 상대 경로를 직접 추가하세요.
41
41
  `$schema` 경로를 찾지 못하면 편집기에 오류가 표시되지 않은 채 스키마 검증이 중단될 수 있습니다.
42
42
 
43
43
  우산이 아니라 `@polydeukes/core`를 직접 설치했다면 그 사본을 가리킵니다.
@@ -72,27 +72,27 @@ languages:
72
72
 
73
73
  | 설정 | 위반 시 동작 |
74
74
  |---|---|
75
- | `adapters.git.enforce: advise` | 권고를 기록하고 커밋을 계속합니다. 증인 입력은 요청하지 않습니다. |
76
- | `adapters.git.enforce: block` | 차단 판정을 받은 작업을 거부합니다. 스테이징 검사에서는 TTY로 증인 입력을 받을 수 있습니다. |
75
+ | 항목의 `enforce: advise`(또는 적지 않음) | 권고를 기록하고 호출을 진행합니다. 종료 코드 0입니다. |
76
+ | 항목의 `enforce: block` | 판정한 호출을 거부합니다. 종료 코드 2입니다. |
77
77
 
78
- 일반 규율(discipline) 항목에도 자체 강제 수준이 있으며 기본값은 `advise`입니다.
79
- **두 수준 중 더 관대한 쪽을 따릅니다.** 어댑터만 `block`으로 설정해도 일반 항목이 자동으로
80
- 차단 수준으로 바뀌지는 않습니다. 설정된 경로의 보호는 이 항목별 기본값과 별개입니다.
81
- 조립 단계에서 오류가 나면 어느 수준에서든 종료 코드 2를 반환합니다.
78
+ **적지 않으면 `advise`입니다.** 설정에는 표면 단위의 강제 수준 키가 없습니다. 강제 수준은
79
+ 각 항목이 가지며 적지 않은 항목을 승격하는 설정도 없습니다. 설정된 경로의 보호는 이 항목별
80
+ 기본값과 별개입니다. 세션 표면에서는 차단하고, 변경 집합 표면에서는 명령을 `--enforce block`으로
81
+ 실행하지 않는 한 `advised`로 기록합니다. 조립 단계에서 오류가 나면 종료 코드 2를
82
+ 반환합니다.
82
83
 
83
- 최상위 `protectedPaths`는 두 표면에 모두 적용합니다. `adapters.git.protectedPaths`에는
84
- 커밋할 때만 보호할 경로를 추가합니다. 세션 중에는 편집을 허용하되 커밋할 때 보호하려는
85
- 파일에 사용하세요. [표면 연결과 증인](./connect-surfaces.ko.md#witness-and-recovery)에서
86
- 자세히 설명합니다.
84
+ `protectedPaths`는 두 표면에 모두 적용하는 최상위 목록 하나입니다. 변경 집합 표면에서 판정기는
85
+ 종료 코드만 내므로, 커밋을 멈출지는 훅 배선이 정합니다.
86
+ [표면 연결과 증인](./connect-surfaces.ko.md#witness-and-recovery)에서 자세히 설명합니다.
87
87
 
88
88
  <a id="confirm-the-project"></a>
89
89
  ## 설정 확인하기
90
90
 
91
91
  - `pdks explain`은 설정을 읽고 등록된 항목을 보여 줍니다. 변경을 판정하지는 않습니다.
92
- - `pdks covenant check --worktree`는 HEAD와 디스크를 비교합니다. 아직 Git에 등록하지 않은
93
- 파일도 무시 대상이 아니면 포함합니다.
94
- - `pdks covenant check`는 스테이징한 변경을 관측합니다. 차단 결과가 나고 TTY를 사용할 수
95
- 있을 때 증인 입력을 요청할 수 있습니다. 어댑터가 `block`이라는 이유만으로 묻지는 않습니다.
92
+ - `git diff HEAD | pdks covenant check --diff`는 아직 커밋하지 않은 변경 전부를 판정합니다.
93
+ - `git diff --cached | pdks covenant check --diff`는 스테이징한 변경을 관측합니다. pre-commit
94
+ 훅이 쓰는 형태입니다. 이 명령은 사람에게 묻지 않고 종료 코드 0 또는 2만 내며, 커밋을
95
+ 멈출지는 훅 배선이 정합니다.
96
96
 
97
97
  종료 코드와 함께 stderr와 텔레메트리도 확인하세요. 권고나 일부 미판정도 종료 코드 0을
98
98
  반환합니다. 조립에 실패했다면 규율을 시험하기 전에 오류가 지목한 설정이나 빠진 패키지부터