polydeukes 0.6.1 → 0.7.1
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.
- package/README.ko.md +14 -28
- package/README.md +14 -28
- package/dist/baseline.d.ts +37 -1
- package/dist/baseline.js +68 -1
- package/dist/bin.d.ts +3 -4
- package/dist/bin.js +73 -90
- package/dist/covenant/bash-line.d.ts +130 -0
- package/dist/covenant/bash-line.js +566 -0
- package/dist/covenant/declaration-engine.d.ts +108 -0
- package/dist/covenant/declaration-engine.js +415 -0
- package/dist/covenant/discipline.d.ts +103 -0
- package/dist/covenant/discipline.js +667 -0
- package/dist/covenant/dispatch.d.ts +153 -0
- package/dist/covenant/dispatch.js +237 -0
- package/dist/covenant/extract-steps.d.ts +122 -0
- package/dist/covenant/extract-steps.js +0 -0
- package/dist/covenant/mention.d.ts +117 -0
- package/dist/covenant/mention.js +209 -0
- package/dist/covenant/module.d.ts +25 -0
- package/dist/covenant/module.js +23 -0
- package/dist/covenant/mutation-rules.d.ts +40 -0
- package/dist/covenant/mutation-rules.js +146 -0
- package/dist/covenant/relations.d.ts +46 -0
- package/dist/covenant/relations.js +68 -0
- package/dist/covenant/run-covenant.d.ts +95 -0
- package/dist/covenant/run-covenant.js +164 -0
- package/dist/covenant/self-mod.d.ts +55 -0
- package/dist/covenant/self-mod.js +84 -0
- package/dist/covenant/shell-evidence.d.ts +38 -0
- package/dist/covenant/shell-evidence.js +247 -0
- package/dist/covenant/shell-mod.d.ts +84 -0
- package/dist/covenant/shell-mod.js +213 -0
- package/dist/covenant/supply.d.ts +54 -0
- package/dist/covenant/supply.js +50 -0
- package/dist/covenant/transcript-mod.d.ts +60 -0
- package/dist/covenant/transcript-mod.js +254 -0
- package/dist/covenant/ttl-witness.d.ts +47 -0
- package/dist/covenant/ttl-witness.js +80 -0
- package/dist/covenant-check.d.ts +72 -39
- package/dist/covenant-check.js +260 -121
- package/dist/diff-ir.d.ts +28 -0
- package/dist/diff-ir.js +310 -0
- package/dist/docs/README.ko.md +8 -8
- package/dist/docs/README.md +8 -8
- package/dist/docs/catalog.json +44 -28
- package/dist/docs/concepts/judgment.ko.md +2 -2
- package/dist/docs/concepts/judgment.md +2 -2
- package/dist/docs/how-to/configure-project.ko.md +16 -16
- package/dist/docs/how-to/configure-project.md +15 -12
- package/dist/docs/how-to/connect-surfaces.ko.md +39 -34
- package/dist/docs/how-to/connect-surfaces.md +36 -33
- package/dist/docs/how-to/write-disciplines.ko.md +61 -6
- package/dist/docs/how-to/write-disciplines.md +62 -6
- package/dist/docs/index.json +607 -373
- package/dist/docs/reference/cli/covenant-check.ko.md +112 -65
- package/dist/docs/reference/cli/covenant-check.md +114 -59
- package/dist/docs/reference/cli/docs.ko.md +2 -2
- package/dist/docs/reference/cli/docs.md +2 -2
- package/dist/docs/reference/cli/explain.ko.md +14 -9
- package/dist/docs/reference/cli/explain.md +15 -10
- package/dist/docs/reference/cli/init.ko.md +52 -52
- package/dist/docs/reference/cli/init.md +43 -55
- package/dist/docs/reference/configuration/index.ko.md +171 -66
- package/dist/docs/reference/configuration/index.md +178 -71
- package/dist/docs/reference/packages/adapter-claude-code.ko.md +38 -11
- package/dist/docs/reference/packages/adapter-claude-code.md +38 -14
- package/dist/docs/reference/packages/adapter-grok.ko.md +77 -0
- package/dist/docs/reference/packages/adapter-grok.md +79 -0
- package/dist/docs/reference/packages/core.ko.md +49 -3
- package/dist/docs/reference/packages/core.md +54 -5
- package/dist/docs/reference/packages/polydeukes.ko.md +138 -77
- package/dist/docs/reference/packages/polydeukes.md +146 -81
- package/dist/docs/reference/packages/sdk-ts.ko.md +161 -0
- package/dist/docs/reference/packages/sdk-ts.md +164 -0
- package/dist/docs/troubleshooting.ko.md +17 -15
- package/dist/docs/troubleshooting.md +18 -14
- package/dist/docs/tutorials/first-judgment.ko.md +2 -2
- package/dist/docs/tutorials/first-judgment.md +2 -2
- package/dist/explain.d.ts +1 -1
- package/dist/explain.js +37 -22
- package/dist/load-config.d.ts +1 -1
- package/dist/load-config.js +1 -1
- package/dist/pre-state-reader.d.ts +1 -1
- package/dist/pre-state-reader.js +1 -1
- package/dist/scaffold-project.d.ts +2 -2
- package/dist/scaffold-project.js +9 -3
- package/dist/schema/polydeukes.schema.json +12 -0
- package/dist/worktree-reader.d.ts +19 -0
- package/dist/worktree-reader.js +30 -0
- package/package.json +3 -17
- package/dist/claude-code-hook.d.ts +0 -79
- package/dist/claude-code-hook.js +0 -372
- package/dist/claude-code.d.ts +0 -6
- package/dist/claude-code.js +0 -6
- package/dist/covenant-module.d.ts +0 -25
- package/dist/covenant-module.js +0 -42
- package/dist/docs/reference/packages/adapter-git.ko.md +0 -101
- package/dist/docs/reference/packages/adapter-git.md +0 -108
- package/dist/docs/reference/packages/covenant.ko.md +0 -115
- package/dist/docs/reference/packages/covenant.md +0 -123
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -21
- package/dist/init-claude-code.d.ts +0 -52
- package/dist/init-claude-code.js +0 -586
- package/dist/init-grok.d.ts +0 -51
- package/dist/init-grok.js +0 -242
package/dist/diff-ir.js
ADDED
|
@@ -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
|
+
}
|
package/dist/docs/README.ko.md
CHANGED
|
@@ -25,11 +25,10 @@
|
|
|
25
25
|
| 문서 | 답하는 것 |
|
|
26
26
|
|---|---|
|
|
27
27
|
| [설정 레퍼런스](./reference/configuration/index.ko.md) | `polydeukes.config.yaml`에 무엇을 넣을 수 있고 각 키가 무엇을 하는지 |
|
|
28
|
-
| [`polydeukes` (`pdks` CLI)](./reference/packages/polydeukes.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/
|
|
31
|
-
| [`@polydeukes/adapter-
|
|
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로 |
|
|
33
32
|
|
|
34
33
|
<a id="shape-of-the-thing"></a>
|
|
35
34
|
## 한 페이지로 보는 구조
|
|
@@ -53,8 +52,9 @@
|
|
|
53
52
|
|
|
54
53
|
| 표면 | 판정 대상 | 배선 방법 | 대상 |
|
|
55
54
|
|---|---|---|---|
|
|
56
|
-
| **세션** | 도구 호출, 실행되기 전에 | `pdks
|
|
57
|
-
| **커밋** | diff — 스테이징 영역, 작업 트리, ref 범위 | pre-commit 훅, 또는 필요할 때 직접 실행 | 혼자 개발하는 사람, 그리고 CI |
|
|
55
|
+
| **세션** | 도구 호출, 실행되기 전에 | `pdks-claude-code init` 또는 `pdks-grok init` | AI 파트너와 함께 개발하는 프로젝트 |
|
|
56
|
+
| **커밋** | stdin의 unified diff — 스테이징 영역, 작업 트리, ref 범위 | `git diff --cached`를 파이프로 넘기는 pre-commit 훅, 또는 필요할 때 직접 실행 | 혼자 개발하는 사람, 그리고 CI |
|
|
58
57
|
|
|
59
|
-
커밋 판정기는 필요할 때 직접 실행할 수도 있습니다. 작업 후에는 `pdks covenant check --
|
|
60
|
-
PR 전에는
|
|
58
|
+
커밋 판정기는 필요할 때 직접 실행할 수도 있습니다. 작업 후에는 `git diff HEAD | pdks covenant check --diff`,
|
|
59
|
+
PR 전에는 `git diff main...HEAD | …`를 사용합니다. 같은 판정 기준을 종료 코드로 답하며 묻지
|
|
60
|
+
않습니다. 관문은 그 코드를 소비하는 쪽입니다.
|
package/dist/docs/README.md
CHANGED
|
@@ -27,11 +27,10 @@ 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/
|
|
33
|
-
| [`@polydeukes/adapter-
|
|
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 |
|
|
35
34
|
|
|
36
35
|
<a id="shape-of-the-thing"></a>
|
|
37
36
|
## The shape of the thing, in one page
|
|
@@ -57,8 +56,9 @@ in the whitepaper, which were all found by counting rows rather than by reading
|
|
|
57
56
|
|
|
58
57
|
| Surface | Judges | Wired by | For |
|
|
59
58
|
|---|---|---|---|
|
|
60
|
-
| **Session** | A tool call, before it runs | `pdks
|
|
61
|
-
| **Commit** | A diff — staged, the working tree, or a ref range | A pre-commit hook
|
|
59
|
+
| **Session** | A tool call, before it runs | `pdks-claude-code init` or `pdks-grok init` | A project developed with an AI partner |
|
|
60
|
+
| **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
61
|
|
|
63
|
-
The commit judge also answers on demand: `pdks covenant check --
|
|
64
|
-
before a PR. Same verdict a commit would receive, delivered as
|
|
62
|
+
The commit judge also answers on demand: `git diff HEAD | pdks covenant check --diff` after a task,
|
|
63
|
+
`git diff main...HEAD | …` before a PR. Same verdict a commit would receive, delivered as an exit
|
|
64
|
+
code with no prompt — the gate is whatever consumes that code.
|
package/dist/docs/catalog.json
CHANGED
|
@@ -130,12 +130,12 @@
|
|
|
130
130
|
"en": {
|
|
131
131
|
"path": "reference/cli/covenant-check.md",
|
|
132
132
|
"title": "`pdks covenant check`",
|
|
133
|
-
"summary": "
|
|
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": "
|
|
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
|
|
154
|
+
"summary": "프로젝트 초기 파일을 만들고, Claude Code와 Grok 설치기를 찾습니다."
|
|
155
155
|
}
|
|
156
156
|
},
|
|
157
157
|
{
|
|
@@ -235,51 +235,51 @@
|
|
|
235
235
|
}
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
|
-
"id": "package-
|
|
238
|
+
"id": "package-adapter-claude-code",
|
|
239
239
|
"category": "reference",
|
|
240
|
-
"order":
|
|
240
|
+
"order": 15,
|
|
241
241
|
"bundled": true,
|
|
242
242
|
"en": {
|
|
243
|
-
"path": "reference/packages/
|
|
244
|
-
"title": "`@polydeukes/
|
|
245
|
-
"summary": "
|
|
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/
|
|
249
|
-
"title": "`@polydeukes/
|
|
250
|
-
"summary": "
|
|
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-
|
|
254
|
+
"id": "package-adapter-grok",
|
|
255
255
|
"category": "reference",
|
|
256
|
-
"order":
|
|
256
|
+
"order": 16,
|
|
257
257
|
"bundled": true,
|
|
258
258
|
"en": {
|
|
259
|
-
"path": "reference/packages/adapter-
|
|
260
|
-
"title": "`@polydeukes/adapter-
|
|
261
|
-
"summary": "
|
|
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-
|
|
265
|
-
"title": "`@polydeukes/adapter-
|
|
266
|
-
"summary": "
|
|
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-
|
|
270
|
+
"id": "package-sdk-ts",
|
|
271
271
|
"category": "reference",
|
|
272
|
-
"order":
|
|
272
|
+
"order": 25,
|
|
273
273
|
"bundled": true,
|
|
274
274
|
"en": {
|
|
275
|
-
"path": "reference/packages/
|
|
276
|
-
"title": "`@polydeukes/
|
|
277
|
-
"summary": "
|
|
275
|
+
"path": "reference/packages/sdk-ts.md",
|
|
276
|
+
"title": "`@polydeukes/sdk-ts`",
|
|
277
|
+
"summary": "Call the judge from TypeScript with one verb, and read the three verdicts it returns."
|
|
278
278
|
},
|
|
279
279
|
"ko": {
|
|
280
|
-
"path": "reference/packages/
|
|
281
|
-
"title": "`@polydeukes/
|
|
282
|
-
"summary": "
|
|
280
|
+
"path": "reference/packages/sdk-ts.ko.md",
|
|
281
|
+
"title": "`@polydeukes/sdk-ts`",
|
|
282
|
+
"summary": "TypeScript에서 동사 하나로 판정기를 부르고, 돌아오는 판정 결과 셋을 읽습니다."
|
|
283
283
|
}
|
|
284
284
|
},
|
|
285
285
|
{
|
|
@@ -409,6 +409,22 @@
|
|
|
409
409
|
"title": "<!--",
|
|
410
410
|
"summary": "당시의 개발 기록이며 현재 사용법을 설명하는 참조 문서는 아닙니다."
|
|
411
411
|
}
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"id": "post-7",
|
|
415
|
+
"category": "history",
|
|
416
|
+
"order": 24,
|
|
417
|
+
"bundled": false,
|
|
418
|
+
"en": {
|
|
419
|
+
"path": "build-in-public/2026-09-v0.6.1-docs-and-search.md",
|
|
420
|
+
"title": "<!--",
|
|
421
|
+
"summary": "Historical development account; not a current usage reference."
|
|
422
|
+
},
|
|
423
|
+
"ko": {
|
|
424
|
+
"path": "build-in-public/2026-09-v0.6.1-docs-and-search.ko.md",
|
|
425
|
+
"title": "<!--",
|
|
426
|
+
"summary": "당시의 개발 기록이며 현재 사용법을 설명하는 참조 문서는 아닙니다."
|
|
427
|
+
}
|
|
412
428
|
}
|
|
413
429
|
],
|
|
414
430
|
"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
|
|
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
|
|
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
|
|
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
|
-
| `
|
|
76
|
-
| `
|
|
75
|
+
| 항목의 `enforce: advise`(또는 적지 않음) | 권고를 기록하고 호출을 진행합니다. 종료 코드 0입니다. |
|
|
76
|
+
| 항목의 `enforce: block` | 판정한 호출을 거부합니다. 종료 코드 2입니다. |
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
조립 단계에서 오류가 나면
|
|
78
|
+
**적지 않으면 `advise`입니다.** 설정에는 표면 단위의 강제 수준 키가 없습니다. 강제 수준은
|
|
79
|
+
각 항목이 가지며 적지 않은 항목을 승격하는 설정도 없습니다. 설정된 경로의 보호는 이 항목별
|
|
80
|
+
기본값과 별개입니다. 세션 표면에서는 차단하고, 변경 집합 표면에서는 명령을 `--enforce block`으로
|
|
81
|
+
실행하지 않는 한 `advised`로 기록합니다. 조립 단계에서 오류가 나면 종료 코드 2를
|
|
82
|
+
반환합니다.
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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 --
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
반환합니다. 조립에 실패했다면 규율을 시험하기 전에 오류가 지목한 설정이나 빠진 패키지부터
|
|
@@ -36,8 +36,9 @@ monorepo sub-package whose dependencies installed at the workspace root, count t
|
|
|
36
36
|
# yaml-language-server: $schema=../../node_modules/polydeukes/dist/schema/polydeukes.schema.json
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
`pdks init claude-code` adds the schema line only when the
|
|
40
|
-
generated config. If the line is absent, add a relative path
|
|
39
|
+
`pdks init` — which `pdks-claude-code init` runs for you — adds the schema line only when the
|
|
40
|
+
default path resolves relative to the generated config. If the line is absent, add a relative path
|
|
41
|
+
to the installed schema yourself.
|
|
41
42
|
An unresolvable `$schema` can disable editor validation without displaying an error.
|
|
42
43
|
|
|
43
44
|
If you installed `@polydeukes/core` directly rather than the umbrella, name its copy:
|
|
@@ -72,24 +73,26 @@ Loading this setting does not itself run the command.
|
|
|
72
73
|
|
|
73
74
|
| Setting | Effect on a violation |
|
|
74
75
|
|---|---|
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
76
|
+
| `enforce: advise` on an entry (or absent) | Record advice and let the call proceed, exit 0. |
|
|
77
|
+
| `enforce: block` on an entry | Refuse the judged call, exit 2. |
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
**Absent means `advise`.** There is no surface-level enforcement key in the config: each entry
|
|
80
|
+
carries its own level and nothing promotes an absent one. Protection of configured paths is
|
|
81
|
+
separate from that per-entry default — it blocks on the session surface, and on the change-set
|
|
82
|
+
surface it lands `advised` unless the command is run with `--enforce block`. Assembly errors
|
|
83
|
+
still exit 2.
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
`protectedPaths` is a single top-level list that applies to both surfaces. On the change-set
|
|
86
|
+
surface the judge only emits the exit code; whether the commit stops is your hook wiring.
|
|
84
87
|
See [surface connection and witnesses](./connect-surfaces.md#witness-and-recovery).
|
|
85
88
|
|
|
86
89
|
<a id="confirm-the-project"></a>
|
|
87
90
|
## Confirm the project
|
|
88
91
|
|
|
89
92
|
- `pdks explain` loads the configuration and shows registrations without judging a change.
|
|
90
|
-
- `pdks covenant check --
|
|
91
|
-
- `pdks covenant check` observes staged changes
|
|
92
|
-
|
|
93
|
+
- `git diff HEAD | pdks covenant check --diff` judges everything not yet committed.
|
|
94
|
+
- `git diff --cached | pdks covenant check --diff` observes staged changes — the pre-commit shape.
|
|
95
|
+
The command never prompts; it exits 0 or 2 and your hook wiring decides the commit's fate.
|
|
93
96
|
|
|
94
97
|
Check stderr and telemetry as well as the exit code. Advice and some skipped observations exit 0.
|
|
95
98
|
If assembly fails, diagnose the named configuration or missing package before testing a discipline.
|