polydeukes 0.8.0 → 0.10.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.
- package/dist/covenant/shell-mod.d.ts +15 -4
- package/dist/covenant/shell-mod.js +63 -8
- package/dist/covenant/transcript-mod.js +8 -5
- package/dist/docs/README.ko.md +43 -18
- package/dist/docs/README.md +39 -17
- package/dist/docs/catalog.json +50 -162
- package/dist/docs/concepts/judgment.ko.md +2 -0
- package/dist/docs/concepts/judgment.md +2 -0
- package/dist/docs/how-to/connect-surfaces.ko.md +19 -7
- package/dist/docs/how-to/connect-surfaces.md +24 -12
- package/dist/docs/how-to/write-disciplines.ko.md +68 -31
- package/dist/docs/how-to/write-disciplines.md +69 -32
- package/dist/docs/index.json +577 -231
- package/dist/docs/reference/cli/init.ko.md +10 -7
- package/dist/docs/reference/cli/init.md +16 -11
- package/dist/docs/reference/configuration/index.ko.md +14 -20
- package/dist/docs/reference/configuration/index.md +16 -24
- package/dist/docs/reference/declaration-language/index.ko.md +280 -0
- package/dist/docs/reference/declaration-language/index.md +277 -0
- package/dist/docs/reference/packages/adapter-claude-code.ko.md +1 -1
- package/dist/docs/reference/packages/adapter-claude-code.md +1 -1
- package/dist/docs/reference/packages/adapter-codex.ko.md +34 -17
- package/dist/docs/reference/packages/adapter-codex.md +39 -21
- package/dist/docs/reference/packages/core.ko.md +2 -2
- package/dist/docs/reference/packages/core.md +2 -2
- package/dist/docs/reference/packages/polydeukes.ko.md +2 -2
- package/dist/docs/reference/packages/polydeukes.md +3 -3
- package/dist/docs/reference/packages/sdk-ts.ko.md +15 -18
- package/dist/docs/reference/packages/sdk-ts.md +14 -17
- package/dist/docs/troubleshooting.ko.md +18 -10
- package/dist/docs/troubleshooting.md +19 -11
- package/package.json +2 -2
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Analyzes the command-line strings of *shell* tool calls (names and arg keys are injected
|
|
5
5
|
* values, never source literals) per simple command: the fixed detection rules catch writes
|
|
6
6
|
* to a protected path, undecidable structures (opaque mentions, opaque write targets) fail
|
|
7
|
-
* closed,
|
|
7
|
+
* closed, read-only proof absolves safe reads, and every other protected-path
|
|
8
8
|
* mention breaks — "mention + unproven = block". It judges only its own axis: a non-shell
|
|
9
9
|
* tool call is upheld, since the tool axis belongs to the self-mod meta-covenant and
|
|
10
10
|
* run-all co-existence depends on that boundary.
|
|
@@ -18,7 +18,7 @@ import type { CovenantRegistration, MetaCovenantRegistration } from './dispatch.
|
|
|
18
18
|
* `protectedPaths` are literal path strings; `shellToolNames` are the tool names whose
|
|
19
19
|
* calls carry shell lines; `commandArgNames` are the `args` keys those lines live under;
|
|
20
20
|
* `readOnlyCommands` are allowlist entries — space-separated word sequences (`'cat'`,
|
|
21
|
-
* `'git
|
|
21
|
+
* `'git status'`). Empty-string entries in every list are ignored (an unguarded `''` would
|
|
22
22
|
* match every path / tool / arg / command).
|
|
23
23
|
*/
|
|
24
24
|
export type ShellModificationSpec = {
|
|
@@ -38,6 +38,16 @@ export type ShellModificationSpec = {
|
|
|
38
38
|
* redirect-free truncating write. `git status`/`git grep` reject `--output`, so they stay.
|
|
39
39
|
*/
|
|
40
40
|
export declare const DEFAULT_READ_ONLY_COMMANDS: string[];
|
|
41
|
+
/**
|
|
42
|
+
* True when a configured allowlist has the same effective entries as the shipped default.
|
|
43
|
+
* Conditional readers belong to that default contract and stay disabled for replacements.
|
|
44
|
+
*/
|
|
45
|
+
export declare function usesDefaultReadOnlyCommands(commands: string[]): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Prove the finite argument-sensitive readers that cannot be represented by a leading-word
|
|
48
|
+
* allowlist. Every word must be transparent because these readers inspect their later words.
|
|
49
|
+
*/
|
|
50
|
+
export declare function matchesConditionalReadOnlyCommand(command: SimpleCommand): boolean;
|
|
41
51
|
/**
|
|
42
52
|
* True when the command's leading words match the allowlist entry's word sequence. Exported
|
|
43
53
|
* so the transcript judge's allowlist clause absolves reads by this exact comparison instead
|
|
@@ -59,8 +69,9 @@ export declare function judgeShellModification(input: CovenantInput, spec: Shell
|
|
|
59
69
|
/**
|
|
60
70
|
* `ShellModRegistrationSpec` — the assembly values baked into the registration. The call
|
|
61
71
|
* set is not among them: the dispatcher supplies it to the judge at call time.
|
|
62
|
-
* `readOnlyCommands` REPLACES {@link DEFAULT_READ_ONLY_COMMANDS} when given — no merge
|
|
63
|
-
*
|
|
72
|
+
* `readOnlyCommands` REPLACES {@link DEFAULT_READ_ONLY_COMMANDS} when given — no merge.
|
|
73
|
+
* Any replacement, including a superset made by spreading the default, disables the finite
|
|
74
|
+
* argument-sensitive readers because their proof belongs to the exact shipped default.
|
|
64
75
|
*/
|
|
65
76
|
export type ShellModRegistrationSpec = {
|
|
66
77
|
protectedPaths: string[];
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Analyzes the command-line strings of *shell* tool calls (names and arg keys are injected
|
|
5
5
|
* values, never source literals) per simple command: the fixed detection rules catch writes
|
|
6
6
|
* to a protected path, undecidable structures (opaque mentions, opaque write targets) fail
|
|
7
|
-
* closed,
|
|
7
|
+
* closed, read-only proof absolves safe reads, and every other protected-path
|
|
8
8
|
* mention breaks — "mention + unproven = block". It judges only its own axis: a non-shell
|
|
9
9
|
* tool call is upheld, since the tool axis belongs to the self-mod meta-covenant and
|
|
10
10
|
* run-all co-existence depends on that boundary.
|
|
@@ -39,6 +39,58 @@ export const DEFAULT_READ_ONLY_COMMANDS = [
|
|
|
39
39
|
'git status',
|
|
40
40
|
'git grep',
|
|
41
41
|
];
|
|
42
|
+
const FIND_WRITE_OR_EXECUTE_ACTIONS = new Set([
|
|
43
|
+
'-delete',
|
|
44
|
+
'-exec',
|
|
45
|
+
'-execdir',
|
|
46
|
+
'-ok',
|
|
47
|
+
'-okdir',
|
|
48
|
+
'-fprint',
|
|
49
|
+
'-fprint0',
|
|
50
|
+
'-fprintf',
|
|
51
|
+
'-fls',
|
|
52
|
+
]);
|
|
53
|
+
function normalizedReadOnlyCommands(commands) {
|
|
54
|
+
return [
|
|
55
|
+
...new Set(commands
|
|
56
|
+
.map((entry) => entry
|
|
57
|
+
.split(/\s+/)
|
|
58
|
+
.filter((word) => word !== '')
|
|
59
|
+
.join(' '))
|
|
60
|
+
.filter((entry) => entry !== '')),
|
|
61
|
+
].sort();
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* True when a configured allowlist has the same effective entries as the shipped default.
|
|
65
|
+
* Conditional readers belong to that default contract and stay disabled for replacements.
|
|
66
|
+
*/
|
|
67
|
+
export function usesDefaultReadOnlyCommands(commands) {
|
|
68
|
+
const configured = normalizedReadOnlyCommands(commands);
|
|
69
|
+
const shipped = normalizedReadOnlyCommands(DEFAULT_READ_ONLY_COMMANDS);
|
|
70
|
+
return (configured.length === shipped.length && configured.every((entry, i) => entry === shipped[i]));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Prove the finite argument-sensitive readers that cannot be represented by a leading-word
|
|
74
|
+
* allowlist. Every word must be transparent because these readers inspect their later words.
|
|
75
|
+
*/
|
|
76
|
+
export function matchesConditionalReadOnlyCommand(command) {
|
|
77
|
+
if (command.words.length === 0 || command.words.some((word) => word.opaque))
|
|
78
|
+
return false;
|
|
79
|
+
const name = commandBasename(command.words[0]);
|
|
80
|
+
if (name === 'git')
|
|
81
|
+
return command.words[1]?.text === 'ls-files';
|
|
82
|
+
if (name === 'find') {
|
|
83
|
+
return !command.words.some((word) => FIND_WRITE_OR_EXECUTE_ACTIONS.has(word.text));
|
|
84
|
+
}
|
|
85
|
+
if (name !== 'sed')
|
|
86
|
+
return false;
|
|
87
|
+
const script = command.words[2]?.text;
|
|
88
|
+
return (command.words[1]?.text === '-n' &&
|
|
89
|
+
script !== undefined &&
|
|
90
|
+
/^\d+(?:,\d+)?p$/.test(script) &&
|
|
91
|
+
command.words.length > 3 &&
|
|
92
|
+
command.words.slice(3).every((word) => !word.text.startsWith('-')));
|
|
93
|
+
}
|
|
42
94
|
// The rule set is fixed, not injectable: dropping a rule from an assembly would be a
|
|
43
95
|
// detection hole, and no consumer needs a subset.
|
|
44
96
|
const MUTATION_RULES = [redirectWriteRule, teeRule, sedInPlaceRule];
|
|
@@ -65,9 +117,9 @@ export function matchesReadOnlyEntry(command, entry) {
|
|
|
65
117
|
* Judge one simple command. Returns the break reason, or null when the command contributes
|
|
66
118
|
* to uphold. The clause order below is normative: each clause exists to be reached before
|
|
67
119
|
* the next one can absolve. `lineFullyRead` is false when the line carried a span the
|
|
68
|
-
* tokenizer could not read, which withholds
|
|
120
|
+
* tokenizer could not read, which withholds read-only proof.
|
|
69
121
|
*/
|
|
70
|
-
function judgeCommand(command, protectedPaths, readOnlyEntries, lineFullyRead) {
|
|
122
|
+
function judgeCommand(command, protectedPaths, readOnlyEntries, conditionalReadersEnabled, lineFullyRead) {
|
|
71
123
|
// (a) Precise rules: a detected mutation whose target carries a protected path breaks.
|
|
72
124
|
for (const rule of MUTATION_RULES) {
|
|
73
125
|
for (const target of rule.detect(command)) {
|
|
@@ -100,16 +152,18 @@ function judgeCommand(command, protectedPaths, readOnlyEntries, lineFullyRead) {
|
|
|
100
152
|
if (command.redirects.some((r) => r.operator.includes('>') && r.target.opaque)) {
|
|
101
153
|
return `opaque redirect target alongside protected path ${mentioned}`;
|
|
102
154
|
}
|
|
103
|
-
// (e) Read-only
|
|
104
|
-
// (`eval`/`sh -c …`) re-parses its string args, so it can never be
|
|
105
|
-
// if it was injected into the allowlist. Its mention falls through
|
|
155
|
+
// (e) Read-only proof: the allowlist or a finite argument-sensitive reader absolves the
|
|
156
|
+
// mention. A nested shell (`eval`/`sh -c …`) re-parses its string args, so it can never be
|
|
157
|
+
// proven read-only even if it was injected into the allowlist. Its mention falls through
|
|
158
|
+
// to the backstop. A line
|
|
106
159
|
// carrying an unread span is refused the same way: what the scanner never read could be
|
|
107
160
|
// anything, so no head vouches for it.
|
|
108
161
|
const first = command.words[0];
|
|
109
162
|
const firstBasename = first !== undefined ? commandBasename(first) : '';
|
|
110
163
|
if (lineFullyRead &&
|
|
111
164
|
!isNestedShellCommand(firstBasename) &&
|
|
112
|
-
readOnlyEntries.some((entry) => matchesReadOnlyEntry(command, entry))
|
|
165
|
+
(readOnlyEntries.some((entry) => matchesReadOnlyEntry(command, entry)) ||
|
|
166
|
+
(conditionalReadersEnabled && matchesConditionalReadOnlyCommand(command)))) {
|
|
113
167
|
return null;
|
|
114
168
|
}
|
|
115
169
|
// (f) Backstop — mention + unproven = block.
|
|
@@ -133,6 +187,7 @@ export function judgeShellModification(input, spec) {
|
|
|
133
187
|
const readOnlyEntries = spec.readOnlyCommands
|
|
134
188
|
.map((entry) => entry.split(/\s+/).filter((word) => word !== ''))
|
|
135
189
|
.filter((entry) => entry.length > 0);
|
|
190
|
+
const conditionalReadersEnabled = usesDefaultReadOnlyCommands(spec.readOnlyCommands);
|
|
136
191
|
for (const call of input.toolCalls) {
|
|
137
192
|
if (!shellToolNames.includes(call.name)) {
|
|
138
193
|
continue;
|
|
@@ -167,7 +222,7 @@ export function judgeShellModification(input, spec) {
|
|
|
167
222
|
}
|
|
168
223
|
}
|
|
169
224
|
for (const command of commands) {
|
|
170
|
-
const reason = judgeCommand(command, protectedPaths, readOnlyEntries, unread.length === 0);
|
|
225
|
+
const reason = judgeCommand(command, protectedPaths, readOnlyEntries, conditionalReadersEnabled, unread.length === 0);
|
|
171
226
|
if (reason !== null)
|
|
172
227
|
return { upheld: false, reason };
|
|
173
228
|
}
|
|
@@ -13,7 +13,7 @@ import { isNestedShellCommand, tokenizeCommandLine } from './bash-line.js';
|
|
|
13
13
|
import { pathCandidates, pathSegments, provenChangePath, resolveDotSegments, someStringValue, untokenizableLineCandidates, } from './mention.js';
|
|
14
14
|
import { commandBasename, redirectWriteRule, sedInPlaceRule, teeRule } from './mutation-rules.js';
|
|
15
15
|
import { outcomeFromVerdict, UNJUDGEABLE_OUTCOME } from './run-covenant.js';
|
|
16
|
-
import { DEFAULT_READ_ONLY_COMMANDS, matchesReadOnlyEntry } from './shell-mod.js';
|
|
16
|
+
import { DEFAULT_READ_ONLY_COMMANDS, matchesConditionalReadOnlyCommand, matchesReadOnlyEntry, usesDefaultReadOnlyCommands, } from './shell-mod.js';
|
|
17
17
|
// The rule set is fixed, assembled exactly as shell-mod assembles it: dropping one would be
|
|
18
18
|
// a detection hole, and the two judges must not diverge on what counts as a write.
|
|
19
19
|
const MUTATION_RULES = [redirectWriteRule, teeRule, sedInPlaceRule];
|
|
@@ -55,6 +55,7 @@ function resolveTranscript(spec) {
|
|
|
55
55
|
readOnlyEntries: spec.readOnlyCommands
|
|
56
56
|
.map((entry) => entry.split(/\s+/).filter((word) => word !== ''))
|
|
57
57
|
.filter((entry) => entry.length > 0),
|
|
58
|
+
conditionalReadersEnabled: usesDefaultReadOnlyCommands(spec.readOnlyCommands),
|
|
58
59
|
};
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
@@ -96,7 +97,7 @@ function argsNameTranscript(value, transcript) {
|
|
|
96
97
|
* it has to break before the allowlist gets a chance to absolve it. The letters skip `(c)`
|
|
97
98
|
* because this ladder has no opaque-mention clause, matching the shell ladder's numbering
|
|
98
99
|
* rather than closing the gap. `lineFullyRead` is false when the line carried a span the
|
|
99
|
-
* tokenizer could not read, which withholds
|
|
100
|
+
* tokenizer could not read, which withholds read-only proof.
|
|
100
101
|
*/
|
|
101
102
|
function judgeCommand(command, transcript, lineFullyRead) {
|
|
102
103
|
// (a) Precise rules: a detected mutation whose target is the transcript breaks.
|
|
@@ -118,15 +119,17 @@ function judgeCommand(command, transcript, lineFullyRead) {
|
|
|
118
119
|
if (command.redirects.some((r) => r.operator.includes('>') && r.target.opaque)) {
|
|
119
120
|
return `opaque redirect target alongside the session transcript ${transcript.path}`;
|
|
120
121
|
}
|
|
121
|
-
// (e) Read-only
|
|
122
|
-
// nested shell (`eval`/`sh -c …`) re-parses its string args,
|
|
122
|
+
// (e) Read-only proof: the allowlist or a finite argument-sensitive reader absolves the
|
|
123
|
+
// mention in every spelling. A nested shell (`eval`/`sh -c …`) re-parses its string args,
|
|
124
|
+
// so it is never provably a read.
|
|
123
125
|
// A line carrying an unread span is refused the same way: reading the session is free, but
|
|
124
126
|
// only on a line we finished reading.
|
|
125
127
|
const first = command.words[0];
|
|
126
128
|
const firstBasename = first !== undefined ? commandBasename(first) : '';
|
|
127
129
|
if (lineFullyRead &&
|
|
128
130
|
!isNestedShellCommand(firstBasename) &&
|
|
129
|
-
transcript.readOnlyEntries.some((entry) => matchesReadOnlyEntry(command, entry))
|
|
131
|
+
(transcript.readOnlyEntries.some((entry) => matchesReadOnlyEntry(command, entry)) ||
|
|
132
|
+
(transcript.conditionalReadersEnabled && matchesConditionalReadOnlyCommand(command)))) {
|
|
130
133
|
return null;
|
|
131
134
|
}
|
|
132
135
|
// (f) Backstop — mention + unproven = block.
|
package/dist/docs/README.ko.md
CHANGED
|
@@ -2,34 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
[English](./README.md) · **한국어**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
폴리데우케스는 AI 코딩 파트너와 함께 개발하기 위한 규율(discipline) 프레임워크입니다.
|
|
6
|
+
아래에서 하려는 작업에 맞는 안내를 선택하세요.
|
|
6
7
|
|
|
8
|
+
<a id="여기서-시작하십시오"></a>
|
|
7
9
|
<a id="start-here"></a>
|
|
8
|
-
##
|
|
10
|
+
## 시작하기
|
|
9
11
|
|
|
10
12
|
| 하려는 것 | 읽을 문서 |
|
|
11
13
|
|---|---|
|
|
12
|
-
| 첫
|
|
13
|
-
| Claude Code, Grok, Codex, git을 연결하고 싶다 | [표면 연결하기](./how-to/connect-surfaces.ko.md) — 세션과 커밋
|
|
14
|
-
| 프로젝트 설정을 다듬고 싶다 | [프로젝트 설정하기](./how-to/configure-project.ko.md) —
|
|
15
|
-
| 실제 규율을 쓰고 싶다 | [규율 작성하기](./how-to/write-disciplines.ko.md) —
|
|
14
|
+
| 첫 판정을 확인하고 싶다 | [첫 판정](./tutorials/first-judgment.ko.md) — 설치와 Claude Code 연동을 마치고 보호 파일 편집에 대한 판정을 확인합니다 |
|
|
15
|
+
| Claude Code, Grok, Codex, git을 연결하고 싶다 | [표면 연결하기](./how-to/connect-surfaces.ko.md) — 세션과 커밋 연동 설정, Grok와 Codex 포함 |
|
|
16
|
+
| 프로젝트 설정을 다듬고 싶다 | [프로젝트 설정하기](./how-to/configure-project.ko.md) — 설정 파일 찾기, IDE 지원, advise와 block 선택 |
|
|
17
|
+
| 실제 규율을 쓰고 싶다 | [규율 작성하기](./how-to/write-disciplines.ko.md) — 번역 키 짝 맞춤을 포함한 선언 예제 |
|
|
16
18
|
| 차단이나 건너뜀에서 회복하고 싶다 | [문제 해결](./troubleshooting.ko.md) — fail-closed 상태, 증인 밸브, 로그 |
|
|
17
19
|
| 이 프레임워크가 왜 있는지 알고 싶다 | [왜 폴리데우케스인가?](./why-polydeukes.ko.md) — 설계 백서 |
|
|
18
20
|
| 이 문서에 기여하고 싶다 | [문서에 기여하기](./contributing.ko.md) — 영한 쌍, 안정 ID, 카탈로그, 검사 |
|
|
19
21
|
|
|
20
22
|
<a id="reference"></a>
|
|
21
|
-
##
|
|
23
|
+
## 참조
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
<a id="reference-cli"></a>
|
|
26
|
+
### CLI 명령어
|
|
24
27
|
|
|
25
|
-
|
|
|
28
|
+
| 명령어 | 용도 |
|
|
29
|
+
|---|---|
|
|
30
|
+
| [`pdks covenant check`](./reference/cli/covenant-check.ko.md) | 입력 IR이나 unified diff를 판정하고 결과와 종료 코드 확인 |
|
|
31
|
+
| [`pdks init`](./reference/cli/init.ko.md) | 프로젝트 설정 생성 |
|
|
32
|
+
| [`pdks explain`](./reference/cli/explain.ko.md) | 등록된 규율과 강제 수준 확인 |
|
|
33
|
+
| [`pdks docs`](./reference/cli/docs.ko.md) | 설치된 문서 검색과 조회 |
|
|
34
|
+
|
|
35
|
+
<a id="reference-configuration"></a>
|
|
36
|
+
### 설정
|
|
37
|
+
|
|
38
|
+
[설정 참조](./reference/configuration/index.ko.md)에서 `polydeukes.config.yaml`의 키와
|
|
39
|
+
강제 수준, 규율 목록, 증인 설정을 확인합니다.
|
|
40
|
+
|
|
41
|
+
<a id="reference-declaration-language"></a>
|
|
42
|
+
### 선언 언어
|
|
43
|
+
|
|
44
|
+
[선언 언어 참조](./reference/declaration-language/index.ko.md)에서 소스, 추출 단계,
|
|
45
|
+
조합 연산, 관계, 기전의 전체 문법과 제약을 확인합니다.
|
|
46
|
+
|
|
47
|
+
<a id="reference-packages"></a>
|
|
48
|
+
### 패키지
|
|
49
|
+
|
|
50
|
+
| 패키지 | 담당 기능 |
|
|
26
51
|
|---|---|
|
|
27
|
-
| [설정 레퍼런스](./reference/configuration/index.ko.md) | `polydeukes.config.yaml`에 무엇을 넣을 수 있고 각 키가 무엇을 하는지 |
|
|
28
52
|
| [`polydeukes` (`pdks` CLI)](./reference/packages/polydeukes.ko.md) | 패키지 계약과 그 안에 있는 판정기. 서브커맨드는 [`reference/cli/`](./reference/cli/covenant-check.ko.md) |
|
|
29
53
|
| [`@polydeukes/core`](./reference/packages/core.ko.md) | 프로토콜, 입력 IR, 설정 스키마, 텔레메트리 |
|
|
30
54
|
| [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.ko.md) | Claude Code 세션 표면입니다. 훅 페이로드에서 입력 IR로 |
|
|
31
55
|
| [`@polydeukes/adapter-grok`](./reference/packages/adapter-grok.ko.md) | Grok 세션 표면입니다. 훅 페이로드에서 입력 IR로 |
|
|
32
56
|
| [`@polydeukes/adapter-codex`](./reference/packages/adapter-codex.ko.md) | Codex 세션 표면입니다. 훅 페이로드에서 입력 IR로, 패치가 건드리는 파일마다 원소 하나 |
|
|
57
|
+
| [`@polydeukes/sdk-ts`](./reference/packages/sdk-ts.ko.md) | TypeScript에서 판정기를 호출하고 결과를 처리하는 방법 |
|
|
33
58
|
|
|
34
59
|
<a id="shape-of-the-thing"></a>
|
|
35
60
|
## 한 페이지로 보는 구조
|
|
@@ -37,16 +62,16 @@
|
|
|
37
62
|
폴리데우케스는 개발자나 AI 에이전트가 하려는 일을 판정하고 결과를 기록합니다.
|
|
38
63
|
기본값으로는 작업을 차단하지 않습니다. 설계의 바탕은 다음 세 가지입니다.
|
|
39
64
|
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
**약속(covenant)은 합의한 개발 관행을 검사합니다.** 같은 규율을 사람과 AI의 작업에
|
|
66
|
+
적용하며, 이 프로젝트의 작성자도 일상적인 개발에서 사용합니다.
|
|
42
67
|
|
|
43
|
-
**판정과 차단은
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
프레임워크 자체를 보호하는 경우뿐입니다.
|
|
68
|
+
**판정과 차단은 별도로 정합니다.** 선언된 규율은 적용 범위에 해당하는 호출을 판정합니다.
|
|
69
|
+
기본값으로는 위반 사유를 기록하고 호출을 계속합니다. 위반을 차단하려면 항목에
|
|
70
|
+
`enforce: block`을 설정합니다. 프레임워크 자체의 보호 기능은 세션 호출을 기본으로 차단합니다.
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
**판정 결과를 기록합니다.** `.polydeukes/roi.log`에 판정 결과와 관련 정보가 쌓입니다.
|
|
73
|
+
이 로그로 위반, 건너뛴 검사, 예상과 다른 결과를 조사할 수 있습니다.
|
|
74
|
+
[설계 설명](./why-polydeukes.ko.md)에서는 기록을 바탕으로 프로젝트를 개선한 과정을 다룹니다.
|
|
50
75
|
|
|
51
76
|
<a id="two-surfaces"></a>
|
|
52
77
|
## 두 표면
|
package/dist/docs/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**English** · [한국어](./README.ko.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Polydeukes is a development discipline framework for building alongside an AI coding partner.
|
|
6
|
+
Choose a guide for your task below.
|
|
7
7
|
|
|
8
8
|
<a id="start-here"></a>
|
|
9
9
|
## Start here
|
|
@@ -21,36 +21,58 @@ question is.
|
|
|
21
21
|
<a id="reference"></a>
|
|
22
22
|
## Reference
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
<a id="reference-cli"></a>
|
|
25
|
+
### CLI commands
|
|
26
26
|
|
|
27
|
-
|
|
|
27
|
+
| Command | Purpose |
|
|
28
|
+
|---|---|
|
|
29
|
+
| [`pdks covenant check`](./reference/cli/covenant-check.md) | Judge an input IR or unified diff; read verdicts and exit codes |
|
|
30
|
+
| [`pdks init`](./reference/cli/init.md) | Create project configuration |
|
|
31
|
+
| [`pdks explain`](./reference/cli/explain.md) | Inspect registered disciplines and enforcement |
|
|
32
|
+
| [`pdks docs`](./reference/cli/docs.md) | Search and retrieve installed documentation |
|
|
33
|
+
|
|
34
|
+
<a id="reference-configuration"></a>
|
|
35
|
+
### Configuration
|
|
36
|
+
|
|
37
|
+
[Configuration reference](./reference/configuration/index.md) covers `polydeukes.config.yaml`
|
|
38
|
+
keys, enforcement levels, discipline lists, and witness settings.
|
|
39
|
+
|
|
40
|
+
<a id="reference-declaration-language"></a>
|
|
41
|
+
### Declaration language
|
|
42
|
+
|
|
43
|
+
[Declaration language reference](./reference/declaration-language/index.md) lists every source,
|
|
44
|
+
extraction step, combinator, relation, and mechanism with its syntax and constraints.
|
|
45
|
+
|
|
46
|
+
<a id="reference-packages"></a>
|
|
47
|
+
### Packages
|
|
48
|
+
|
|
49
|
+
| Package | Responsibility |
|
|
28
50
|
|---|---|
|
|
29
|
-
| [Configuration reference](./reference/configuration/index.md) | What may go in `polydeukes.config.yaml`, and what each key does |
|
|
30
51
|
| [`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
52
|
| [`@polydeukes/core`](./reference/packages/core.md) | The protocol, the input IR, the config schema, telemetry |
|
|
32
53
|
| [`@polydeukes/adapter-claude-code`](./reference/packages/adapter-claude-code.md) | Claude Code session surface — hook payloads become the input IR |
|
|
33
54
|
| [`@polydeukes/adapter-grok`](./reference/packages/adapter-grok.md) | Grok session surface — hook payloads become the input IR |
|
|
34
55
|
| [`@polydeukes/adapter-codex`](./reference/packages/adapter-codex.md) | Codex session surface — hook payloads become the input IR, one element per file the patch touches |
|
|
56
|
+
| [`@polydeukes/sdk-ts`](./reference/packages/sdk-ts.md) | Call the judge from TypeScript and handle its result |
|
|
35
57
|
|
|
58
|
+
<a id="the-shape-of-the-thing-in-one-page"></a>
|
|
36
59
|
<a id="shape-of-the-thing"></a>
|
|
37
|
-
##
|
|
60
|
+
## How it works
|
|
38
61
|
|
|
39
62
|
Polydeukes judges what a developer or an AI agent is about to do, records the verdict, and by
|
|
40
63
|
default lets the work proceed. Three ideas carry the rest.
|
|
41
64
|
|
|
42
|
-
**
|
|
43
|
-
|
|
44
|
-
own authors get judged by them daily.
|
|
65
|
+
**Covenants check agreed development practices.** The same disciplines apply to human and AI
|
|
66
|
+
work. This project's authors use them in daily development.
|
|
45
67
|
|
|
46
|
-
**Judging and stopping are separate decisions.** Every declared discipline is judged on
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
**Judging and stopping are separate decisions.** Every declared discipline is judged on matching
|
|
69
|
+
calls. By default, a violation is recorded with its reason and the call continues. Set
|
|
70
|
+
`enforce: block` on an entry to stop violations. The framework's own protections block session
|
|
71
|
+
calls by default.
|
|
50
72
|
|
|
51
|
-
**
|
|
52
|
-
|
|
53
|
-
|
|
73
|
+
**Judgments are recorded.** `.polydeukes/roi.log` stores verdicts and their context. Use the log
|
|
74
|
+
to investigate violations, skipped checks, and unexpected results. The
|
|
75
|
+
[design explanation](./why-polydeukes.md) describes how these records informed the project.
|
|
54
76
|
|
|
55
77
|
<a id="two-surfaces"></a>
|
|
56
78
|
## Two surfaces
|