polydeukes 0.6.0 → 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 +30 -70
- package/README.md +31 -84
- package/dist/baseline.d.ts +37 -1
- package/dist/baseline.js +68 -1
- package/dist/bin.d.ts +3 -4
- package/dist/bin.js +79 -93
- 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 +60 -0
- package/dist/docs/README.md +64 -0
- package/dist/docs/catalog.json +480 -0
- package/dist/docs/concepts/judgment.ko.md +113 -0
- package/dist/docs/concepts/judgment.md +113 -0
- package/dist/docs/how-to/configure-project.ko.md +99 -0
- package/dist/docs/how-to/configure-project.md +98 -0
- package/dist/docs/how-to/connect-surfaces.ko.md +120 -0
- package/dist/docs/how-to/connect-surfaces.md +121 -0
- package/dist/docs/how-to/write-disciplines.ko.md +179 -0
- package/dist/docs/how-to/write-disciplines.md +181 -0
- package/dist/docs/index.json +2280 -0
- package/dist/docs/reference/cli/covenant-check.ko.md +148 -0
- package/dist/docs/reference/cli/covenant-check.md +153 -0
- package/dist/docs/reference/cli/docs.ko.md +97 -0
- package/dist/docs/reference/cli/docs.md +95 -0
- package/dist/docs/reference/cli/explain.ko.md +84 -0
- package/dist/docs/reference/cli/explain.md +89 -0
- package/dist/docs/reference/cli/init.ko.md +119 -0
- package/dist/docs/reference/cli/init.md +119 -0
- package/dist/docs/reference/configuration/index.ko.md +553 -0
- package/dist/docs/reference/{configuration.md → configuration/index.md} +215 -90
- package/dist/docs/reference/packages/adapter-claude-code.ko.md +110 -0
- package/dist/docs/reference/{adapter-claude-code.md → packages/adapter-claude-code.md} +47 -19
- 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 +174 -0
- package/dist/docs/reference/{core.md → packages/core.md} +74 -12
- package/dist/docs/reference/packages/polydeukes.ko.md +195 -0
- package/dist/docs/reference/packages/polydeukes.md +204 -0
- 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 +144 -0
- package/dist/docs/troubleshooting.md +103 -151
- package/dist/docs/tutorials/first-judgment.ko.md +82 -0
- package/dist/docs/tutorials/first-judgment.md +81 -0
- package/dist/docs-catalog.d.ts +25 -0
- package/dist/docs-catalog.js +450 -0
- package/dist/docs-library.d.ts +23 -0
- package/dist/docs-library.js +347 -0
- package/dist/docs-markdown.d.ts +32 -0
- package/dist/docs-markdown.js +150 -0
- package/dist/docs-query.d.ts +11 -40
- package/dist/docs-query.js +28 -122
- package/dist/docs-types.d.ts +105 -0
- package/dist/docs-types.js +2 -0
- 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/configuration.md +0 -103
- package/dist/docs/installation.md +0 -241
- package/dist/docs/reference/adapter-git.md +0 -100
- package/dist/docs/reference/covenant.md +0 -116
- package/dist/docs/reference/polydeukes.md +0 -315
- 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 -469
- package/dist/init-grok.d.ts +0 -51
- package/dist/init-grok.js +0 -242
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# `@polydeukes/sdk-ts`
|
|
2
|
+
|
|
3
|
+
**English** · [한국어](sdk-ts.ko.md)
|
|
4
|
+
|
|
5
|
+
> **One verb from TypeScript to the judge** — hand a covenant input IR to
|
|
6
|
+
> `pdks covenant check` and read the verdict back as a value.
|
|
7
|
+
>
|
|
8
|
+
> Alpha. Install it next to `polydeukes` and `@polydeukes/core`, which it names as
|
|
9
|
+
> `peerDependencies`.
|
|
10
|
+
|
|
11
|
+
<a id="ownership"></a>
|
|
12
|
+
## What this package owns
|
|
13
|
+
|
|
14
|
+
The spawn and the translation of an exit status into a value, and nothing else. It locates the
|
|
15
|
+
`polydeukes` install of the project being judged, runs its bin with the input on stdin, and
|
|
16
|
+
returns what the child answered. No judgment logic lives here: the branches are whether the
|
|
17
|
+
umbrella resolved and what status the child left with.
|
|
18
|
+
|
|
19
|
+
| Unit | What it does |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `checkCovenant` | Spawns `pdks covenant check` in the judged project and returns the verdict |
|
|
22
|
+
| Umbrella resolution | Finds `polydeukes` in the install graph of `repoRoot` and reads its `pdks` bin |
|
|
23
|
+
| Verdict translation | Exit `0` is `upheld`, exit `2` is `blocked`, everything else is `unjudged` |
|
|
24
|
+
|
|
25
|
+
This package writes no telemetry row. Every row a run leaves is written by the child process,
|
|
26
|
+
where the judgment happened, so one call still leaves one row.
|
|
27
|
+
|
|
28
|
+
<a id="install"></a>
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
pnpm add @polydeukes/sdk-ts polydeukes @polydeukes/core
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
There is no bin and no install step. The umbrella supplies the judge the SDK spawns, and the
|
|
36
|
+
core supplies the `CovenantInput` type the caller fills in.
|
|
37
|
+
|
|
38
|
+
<a id="verb"></a>
|
|
39
|
+
## The verb
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { checkCovenant } from '@polydeukes/sdk-ts';
|
|
43
|
+
|
|
44
|
+
const verdict = await checkCovenant({
|
|
45
|
+
repoRoot: '/path/to/the/project',
|
|
46
|
+
input: {
|
|
47
|
+
toolCalls: [
|
|
48
|
+
{
|
|
49
|
+
name: 'writeFile',
|
|
50
|
+
args: { path: 'src/index.ts', content: 'export const answer = 42;\n' },
|
|
51
|
+
fileChange: {
|
|
52
|
+
kind: 'modify',
|
|
53
|
+
path: 'src/index.ts',
|
|
54
|
+
pre: 'export const answer = 41;\n',
|
|
55
|
+
post: 'export const answer = 42;\n',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
subagentSpawns: [],
|
|
60
|
+
userMessages: [],
|
|
61
|
+
tools: { mutating: ['writeFile', 'rm'], shell: ['exec'], commandArgs: ['command'] },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The IR is the caller's. This package neither reads it nor completes it: it adds no `session`,
|
|
67
|
+
no `actor`, and no roster of its own, and the `tools` values above are the caller's own tool
|
|
68
|
+
names. `subagentSpawns` and `userMessages` are required collections, so a caller with neither
|
|
69
|
+
sends the empty arrays. A `world` key is refused by the judge — the runner reads the world from
|
|
70
|
+
the project on disk, and a client choosing the world would be choosing what is judged.
|
|
71
|
+
|
|
72
|
+
<a id="spec"></a>
|
|
73
|
+
## The spec
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type CheckCovenantSpec = {
|
|
77
|
+
repoRoot: string;
|
|
78
|
+
input: CovenantInput;
|
|
79
|
+
enforce?: 'advise' | 'block';
|
|
80
|
+
spawn?: (spec: CheckCovenantSpawnSpec) => Promise<{ status: number | null; stderr: string }>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type CheckCovenantSpawnSpec = { command: string; args: string[]; cwd: string; stdin: string };
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Field | What it is |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `repoRoot` | The project being judged: config discovery, the world axis, the child's cwd, and the install graph the umbrella is found in |
|
|
89
|
+
| `input` | The caller's own IR, sent verbatim as the child's stdin |
|
|
90
|
+
| `enforce` | The observer's posture for the whole run. **Absent is `block`** |
|
|
91
|
+
| `spawn` | An injected spawn seam. Absent, the child runs under this process's node executable |
|
|
92
|
+
|
|
93
|
+
**`enforce` defaults to `block`.** That is the surface's level, not an entry's: protected paths
|
|
94
|
+
and entries carrying `enforce: block` stop the call, and every other break is recorded
|
|
95
|
+
`advised` at exit 0. An entry's own level composes with it lenient-side-wins, as on every other
|
|
96
|
+
surface. `@polydeukes/adapter-claude-code` and `@polydeukes/adapter-grok` spawn the judge at
|
|
97
|
+
the same level.
|
|
98
|
+
|
|
99
|
+
The default spawn inherits no file descriptor. A caller may hold none of its own, and an
|
|
100
|
+
inherited stdout that is closed would kill the child with EPIPE before it answered. stderr is
|
|
101
|
+
collected and returned; stdout is drained and dropped, because the judge writes no verdict
|
|
102
|
+
there.
|
|
103
|
+
|
|
104
|
+
<a id="verdicts"></a>
|
|
105
|
+
## The three verdicts
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
type CheckCovenantVerdict =
|
|
109
|
+
| { verdict: 'upheld'; advisories: string }
|
|
110
|
+
| { verdict: 'blocked'; reason: string }
|
|
111
|
+
| { verdict: 'unjudged'; reason: string };
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Verdict | Child status | What it means for the caller |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `upheld` | `0` | The call was judged and nothing blocked it. `advisories` is the child's stderr verbatim, carrying any advisory lines the run produced. Proceed |
|
|
117
|
+
| `blocked` | `2` | The call was judged and something blocked it. `reason` is the child's stderr verbatim. Do not proceed |
|
|
118
|
+
| `unjudged` | anything else, or no umbrella | No judgment happened. `reason` says which. Reading it as an uphold would let an uninstalled judge pass every call |
|
|
119
|
+
|
|
120
|
+
**There is no valve, and the reason is the substitute.** An unattended real-time caller has no
|
|
121
|
+
TTY and no human turn, so this package takes no witness argument and invents no session.
|
|
122
|
+
`blocked.reason` and `upheld.advisories` come back as data instead, and the consumer decides
|
|
123
|
+
where the text goes — an issue, a log, or back to the model. The posture rules for a config
|
|
124
|
+
author and for a consumer are in [write disciplines](../../how-to/write-disciplines.md#posture).
|
|
125
|
+
|
|
126
|
+
<a id="failure"></a>
|
|
127
|
+
## A failure example
|
|
128
|
+
|
|
129
|
+
When the project has no `polydeukes` installed there is nothing to spawn, and the verb says so
|
|
130
|
+
rather than answering `upheld`:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const verdict = await checkCovenant({ repoRoot: '/tmp/project-without-polydeukes', input });
|
|
134
|
+
|
|
135
|
+
// {
|
|
136
|
+
// verdict: 'unjudged',
|
|
137
|
+
// reason: 'no polydeukes in the install graph of /tmp/project-without-polydeukes:
|
|
138
|
+
// install it to have this input judged',
|
|
139
|
+
// }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
No child process runs, and the telemetry log gains nothing: the row is written where the
|
|
143
|
+
judgment happens, and no judgment happened.
|
|
144
|
+
|
|
145
|
+
<a id="limits"></a>
|
|
146
|
+
## Declared limits
|
|
147
|
+
|
|
148
|
+
- **The caller builds the IR.** The tool roster, the pre-state, and the envelope are the
|
|
149
|
+
host's facts, so a consumer that knows them fills them in. This package supplies none of
|
|
150
|
+
them.
|
|
151
|
+
- **The SDK exposes the session surface only.** The input travels as an IR on stdin, which is
|
|
152
|
+
what makes the run a session-surface judgment. A caller that has a finished change set pipes
|
|
153
|
+
a unified diff to `pdks covenant check --diff` from its shell instead.
|
|
154
|
+
- **No telemetry row is written here.** Every row comes from the child.
|
|
155
|
+
- **An `unjudged` verdict is not a pass.** It records that the judge did not answer, and the
|
|
156
|
+
consumer decides what a project without a judge is allowed to do.
|
|
157
|
+
|
|
158
|
+
<a id="see-also"></a>
|
|
159
|
+
## See also
|
|
160
|
+
|
|
161
|
+
- [`pdks covenant check`](../cli/covenant-check.md)
|
|
162
|
+
- [`polydeukes`](polydeukes.md)
|
|
163
|
+
- [`@polydeukes/core`](core.md)
|
|
164
|
+
- [Configuration reference](../configuration/index.md)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Polydeukes 문제 해결
|
|
2
|
+
|
|
3
|
+
[English](./troubleshooting.md) · **한국어**
|
|
4
|
+
|
|
5
|
+
정책을 바꾸기 전에 어느 단계에서 실패했는지 확인하세요. 세션이 복구 명령까지 차단한다면
|
|
6
|
+
본인의 터미널에서 실행합니다. `pdks docs`는 동봉 문서가 온전하면 프로젝트 설정이나
|
|
7
|
+
판정 관련 패키지가 없어도 사용할 수 있습니다.
|
|
8
|
+
|
|
9
|
+
<a id="no-config"></a>
|
|
10
|
+
## 설정 파일이 없을 때
|
|
11
|
+
|
|
12
|
+
프로젝트 루트 바로 아래에 `polydeukes.config.yaml`, `polydeukes.config.yml`,
|
|
13
|
+
`polydeukes.config.json` 중 하나도 없으면 설정이 필요한 명령은 종료 코드 2를 반환합니다.
|
|
14
|
+
Git에서 원래 파일을 복원하세요. 새 프로젝트라면 `pdks init`, `pdks-claude-code init`,
|
|
15
|
+
`pdks-grok init`로 만들 수 있습니다. 이후 `pdks explain`을 실행합니다. 설정이 없다고
|
|
16
|
+
기본 정책으로 대신 실행하지는 않습니다.
|
|
17
|
+
|
|
18
|
+
<a id="multiple-config"></a>
|
|
19
|
+
## 설정 파일이 여러 개일 때
|
|
20
|
+
|
|
21
|
+
오류 메시지에 중복된 파일명이 나옵니다. 필요한 내용을 합친 뒤 허용되는 파일명 하나만
|
|
22
|
+
남기세요. 로더는 어느 파일을 사용할지 임의로 선택하지 않습니다. 정리한 뒤
|
|
23
|
+
`pdks explain`을 다시 실행합니다.
|
|
24
|
+
|
|
25
|
+
<a id="invalid-config"></a>
|
|
26
|
+
## 설정 오류
|
|
27
|
+
|
|
28
|
+
구문이나 스키마 오류가 있으면 종료 코드 2와 함께 파일명을 알립니다. 스키마 오류는 문제가
|
|
29
|
+
있는 필드도 알려 줍니다. 잘못된 YAML, 사용자 정의 태그, 알 수 없는 필드, 비어 있는
|
|
30
|
+
`languages` 객체를 고치세요. YAML 태그는 파서가 실행할 수 없더라도 거부합니다.
|
|
31
|
+
설정은 실행할 코드가 아니라 데이터이기 때문입니다.
|
|
32
|
+
|
|
33
|
+
`protectedPath:`나 `adaptors:` 같은 오타는 거부합니다. 다만 어댑터 이름에는 확장 가능성을
|
|
34
|
+
남겨 두었습니다. 아무도 구현하지 않은 네임스페이스도 설정으로 읽히지만 읽는 쪽이 없습니다.
|
|
35
|
+
수정한 뒤 `pdks explain`에서 실제 등록 내용을 확인하세요.
|
|
36
|
+
|
|
37
|
+
<a id="grok-witness"></a>
|
|
38
|
+
## Grok 증인
|
|
39
|
+
|
|
40
|
+
훅을 아직 읽지 않은 문제와 증인(witness) 밸브를 사용할 수 없는 문제는 구별해야 합니다.
|
|
41
|
+
|
|
42
|
+
- `pdks-grok init` 실행 뒤 Hooks 탭을 다시 불러오거나 새 세션을 시작하세요. 실제 도구를
|
|
43
|
+
호출하고 텔레메트리를 확인합니다. 설치기가 성공했다고 해서 열린 세션에 훅이 적용됐다는
|
|
44
|
+
뜻은 아닙니다.
|
|
45
|
+
- Grok의 ACP 대화 기록에는 현재 세션 증인 밸브가 요구하는 Claude 형식의 인간 메시지가
|
|
46
|
+
없습니다. 다시 불러와도 이 기능이 생기지는 않습니다. 복구가 필요하면 Grok에 Claude용
|
|
47
|
+
증인 토큰을 보내려 하지 말고 본인의 터미널에서 작업하세요.
|
|
48
|
+
|
|
49
|
+
커밋 증인은 해당 스테이징 검사만 허용합니다. 차단된 Grok 도구 호출까지 허용하지 않습니다.
|
|
50
|
+
|
|
51
|
+
<a id="config-fault"></a>
|
|
52
|
+
## 선언을 판정으로 구성하지 못할 때
|
|
53
|
+
|
|
54
|
+
설정은 읽었지만 어떤 항목을 판정할 수 있는 형태로 컴파일하지 못한 경우입니다. 적용 범위가
|
|
55
|
+
일치하면 `skipped`와 사유 `config-fault`를 기록합니다. `pdks explain`에서도 원인을 볼 수
|
|
56
|
+
있습니다. 추출 단계 이름, 인수, 정규식 문법, 쌍과 단일 추출 결과의 사용을 확인하세요.
|
|
57
|
+
지목된 선언을 고친 뒤 같은 관측으로 다시 검사합니다. 미판정은 정상 판정이 아닙니다.
|
|
58
|
+
|
|
59
|
+
<a id="judge-cannot-be-loaded"></a>
|
|
60
|
+
## 판정기를 불러올 수 없을 때
|
|
61
|
+
|
|
62
|
+
패키지나 판정 모듈이 빠져 있으면 작업을 차단합니다. 본인의 터미널에서 패키지를 다시
|
|
63
|
+
설치하거나 워크스페이스 전체를 빌드하세요. 생성된 훅은 설치된 패키지에 판정을 맡기며,
|
|
64
|
+
판정기를 별도로 복사해 가지고 있지 않습니다. 복구 뒤 실제 호출로 다시 확인합니다.
|
|
65
|
+
텔레메트리를 불러오기 전에 실패했다면 기록이 전혀 남지 않을 수도 있습니다.
|
|
66
|
+
|
|
67
|
+
세션 훅은 메시지 앞에 `covenant hook failed closed:`를, 커밋 검사는
|
|
68
|
+
`covenant check failed closed:`를 붙입니다. 실제로 보게 되는 두 형태는 다음과 같습니다.
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
covenant hook failed closed: Cannot find package 'polydeukes' imported from …
|
|
72
|
+
covenant check failed closed: the covenant judges could not be loaded from … — run 'pnpm build' to rebuild them: Cannot find module './self-mod.js' …
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
첫째는 설치된 패키지가 없는 경우이고, 둘째는 소스 체크아웃에서 판정기 빌드 산출물이 없거나
|
|
76
|
+
일부만 있는 경우입니다.
|
|
77
|
+
|
|
78
|
+
<a id="reading-verdict"></a>
|
|
79
|
+
## 판정 결과 읽기
|
|
80
|
+
|
|
81
|
+
| 기록 | 의미 |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `passed` | 관측한 입력을 판정했으며 약속(covenant)을 지켰습니다. |
|
|
84
|
+
| `blocked` | 위반 때문에 작업을 멈췄습니다. |
|
|
85
|
+
| `witnessed` | 차단 결과가 나왔지만 증인 밸브를 통해 작업을 허용했습니다. |
|
|
86
|
+
| `advised` | 위반을 기록하되 작업을 멈추지 않았습니다. 두 표면 모두에서 나올 수 있습니다. |
|
|
87
|
+
| `skipped` | 적용 범위가 일치한 등록을 판정할 수 없었습니다. 정상 판정이 아닙니다. |
|
|
88
|
+
| `unattributed` | 기준 상태와 비교해 판정으로 설명되지 않는 보호 대상의 변경을 발견했거나, 유효한 기준 상태를 읽지 못했습니다. 판정 결과가 아니라 관측 기록입니다. |
|
|
89
|
+
|
|
90
|
+
판정은 기본적으로 `.polydeukes/roi.log`에 추가됩니다. `telemetry.logPath`로 위치를 바꿀 수
|
|
91
|
+
있습니다. 로그 쓰기에 실패하더라도 판정 결과는 바뀌지 않습니다. 종료 코드 0은 작업을
|
|
92
|
+
계속해도 된다는 뜻이지 모든 규율을 지켰다는 뜻은 아닙니다.
|
|
93
|
+
|
|
94
|
+
<a id="opening-a-blocked-call"></a>
|
|
95
|
+
## 차단된 호출을 증언으로 허용하기
|
|
96
|
+
|
|
97
|
+
지원되는 Claude Code 세션에서 설정된 증인 토큰을 인간 메시지의 첫 줄에 단독으로 입력한 뒤,
|
|
98
|
+
유효 시간 안에 다시 시도합니다. 보호 대상을 의도적으로 편집하기 전에 입력해도 됩니다.
|
|
99
|
+
먼저 한 번 차단돼야 하는 것은 아닙니다. 토큰은 비밀이 아니며, 밸브는 사람이 직접 입력했는지
|
|
100
|
+
확인하고 차단 판정에만 적용됩니다. 증언으로 허용한 호출은 `witnessed` 행을 새로 남깁니다.
|
|
101
|
+
앞서 기록한 `blocked` 행을 고치는 것이 아닙니다.
|
|
102
|
+
|
|
103
|
+
모듈 누락처럼 판정기를 조립하지 못하게 하는 오류는 증인으로 해결할 수 없습니다.
|
|
104
|
+
|
|
105
|
+
<a id="blocked-commit"></a>
|
|
106
|
+
## 커밋이 차단됐을 때
|
|
107
|
+
|
|
108
|
+
변경 집합 표면은 사람에게 묻지 않습니다. 기본값에서는 모든 판정에 종료 코드 0을 내고 위반을
|
|
109
|
+
`advised`로 기록합니다. 종료 코드 2는 검사를 `--enforce block`으로 실행했을 때(보호 경로나
|
|
110
|
+
`enforce: block` 항목의 위반) 또는 판정 자체가 불가능할 때만 냅니다. 커밋을 멈출지는 훅
|
|
111
|
+
배선이 정합니다. 종료 코드를 따르는 훅은 커밋을 멈추고, 무시하는 훅은 멈추지 않습니다. Git은
|
|
112
|
+
커밋 실패를 다른 0이 아닌 코드로 알릴 수도 있습니다.
|
|
113
|
+
|
|
114
|
+
일반 규율 항목은 자신이 `enforce: block`을 적고 검사가 `--enforce block`으로 실행될 때만
|
|
115
|
+
작업을 멈춥니다. 설정에는 기본값 `advise`인 항목을 승격하는 것이 없습니다. 수준 변경은
|
|
116
|
+
정책을 바꾸는 결정이지 필수 복구 절차가 아닙니다. 판정된 위반을 통과시키려면 설정이 아니라
|
|
117
|
+
훅 명령에서 `--enforce block`을 빼세요. 행은 그대로 남습니다.
|
|
118
|
+
|
|
119
|
+
<a id="skipped-rows-on-the-change-set-surface"></a>
|
|
120
|
+
## 변경 집합 표면의 미판정 기록
|
|
121
|
+
|
|
122
|
+
대화 기록을 읽는 선언에 `supply: { session: 'pass' }`가 있으면 세션이 없는 변경 집합 표면에서는
|
|
123
|
+
`supply-pass`를 기록합니다. 이 약속은 세션 표면에서 확인하세요. 미판정은 과거 작업을
|
|
124
|
+
검증했다는 뜻이 아닙니다. 다른 채널을 공급할 수 없으면 `no-observation`이 나올 수도
|
|
125
|
+
있습니다. 모든 자료 부재를 같은 실패로 취급하지 말고 등록 내용과 사유를 확인하세요.
|
|
126
|
+
|
|
127
|
+
스테이징한 변경에는 명령줄이 없으므로 명령 범위 선언은 적용되지 않으며 판정도 기록하지
|
|
128
|
+
않습니다. 설정, 범위 일치, 자료 공급, 최종 비교는 각각 다른 단계입니다.
|
|
129
|
+
|
|
130
|
+
<a id="local-state"></a>
|
|
131
|
+
## 다른 컴퓨터로 프로젝트를 옮길 때
|
|
132
|
+
|
|
133
|
+
텔레메트리와 `.polydeukes/baseline.json`은 로컬 상태이며 Git이 옮겨 주는 판정 이력이
|
|
134
|
+
아닙니다. 이 파일 없이 저장소를 복제해도 과거 판정이 복원되지는 않습니다. 세션 훅은 기준
|
|
135
|
+
상태가 없거나 유효하지 않으면 이를 기록하고 다음 비교에 쓸 기준을 만듭니다. 과거 변경을
|
|
136
|
+
판정했다는 증거가 생기는 것은 아닙니다. 필요한 로그는 따로 보관해 옮기세요.
|
|
137
|
+
`telemetry.logPath`를 바꿨다면 모든 기록이 `.polydeukes/`에 있다고 가정해서는 안 됩니다.
|
|
138
|
+
|
|
139
|
+
<a id="next-steps"></a>
|
|
140
|
+
## 다음 단계
|
|
141
|
+
|
|
142
|
+
- [표면 연결하기](./how-to/connect-surfaces.ko.md)
|
|
143
|
+
- [프로젝트 설정하기](./how-to/configure-project.ko.md)
|
|
144
|
+
- [규율 작성하기](./how-to/write-disciplines.ko.md)
|
|
@@ -2,188 +2,140 @@
|
|
|
2
2
|
|
|
3
3
|
**English** · [한국어](./troubleshooting.ko.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
This is the guide layer for recovery: the fail-closed states, reading verdicts, and the
|
|
10
|
-
witness valve.
|
|
11
|
-
|
|
12
|
-
The one principle behind half of this page: **a gate that cannot judge blocks rather than
|
|
13
|
-
guesses.** A missing config, an ambiguous config, an invalid config, an installer that
|
|
14
|
-
cannot prove resolution, and a judge that cannot be loaded all fail closed, because a dead
|
|
15
|
-
gate that waves things through is the cheapest bypass of all. The recovery is never to
|
|
16
|
-
disable the gate — it is to give it back what it needs to judge. And run that recovery
|
|
17
|
-
**from your own terminal**: inside a session the repair commands are judged by the very
|
|
18
|
-
gate they repair, and while no config is loaded there is no witness valve to open.
|
|
19
|
-
|
|
20
|
-
## Every call is blocked and there is no config
|
|
21
|
-
|
|
22
|
-
**Symptom.** On the session surface, every editing tool call and shell command exits 2;
|
|
23
|
-
on the commit surface, every `pdks covenant check` run does. The error says no Polydeukes
|
|
24
|
-
config was found and names the three candidate filenames.
|
|
25
|
-
|
|
26
|
-
**Cause.** The surface is wired but config discovery found nothing at the project root.
|
|
27
|
-
Discovery looks for exactly these, in this order: `polydeukes.config.yaml`,
|
|
28
|
-
`polydeukes.config.yml`, `polydeukes.config.json`. A missing config never silently loads
|
|
29
|
-
defaults — silent defaults would mean silently unprotected.
|
|
30
|
-
|
|
31
|
-
**Recovery.** Restore the file from git. On the session path,
|
|
32
|
-
`pnpm exec pdks init claude-code` or `pdks init grok` recreates files that
|
|
33
|
-
are absent. An existing grok JSON is not rewritten except when its `command`
|
|
34
|
-
still names the grok delegator and a Claude delegator is on disk — then that
|
|
35
|
-
command is retargeted and the matcher follows the settings entry. On the commit path the
|
|
36
|
-
config is hand-written — the [install guide](./installation.md)'s commit-surface section
|
|
37
|
-
has a starting point.
|
|
5
|
+
Diagnose the failed stage before changing policy. If a session blocks the repair command itself,
|
|
6
|
+
run the repair from your own terminal. `pdks docs` remains usable without project configuration
|
|
7
|
+
or the judging packages, provided its own installed documentation bundle is intact.
|
|
38
8
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
**Symptom.** Every call exits 2 with an error naming two (or three) config files at once.
|
|
42
|
-
|
|
43
|
-
**Cause.** Two spellings coexist — say a `polydeukes.config.yaml` created next to a
|
|
44
|
-
project's existing `.yml`. Ambiguity never picks a winner.
|
|
9
|
+
<a id="no-config"></a>
|
|
10
|
+
## No config found
|
|
45
11
|
|
|
46
|
-
|
|
47
|
-
|
|
12
|
+
Commands that need configuration exit 2 when none of `polydeukes.config.yaml`,
|
|
13
|
+
`polydeukes.config.yml`, or `polydeukes.config.json` exists directly at the project root.
|
|
14
|
+
Restore the intended file from Git, or use `pdks init` / `pdks-claude-code init` /
|
|
15
|
+
`pdks-grok init` for a new project. Then run `pdks explain`. No configuration means no silent
|
|
16
|
+
default policy.
|
|
48
17
|
|
|
49
|
-
|
|
18
|
+
<a id="multiple-config"></a>
|
|
19
|
+
## More than one config file
|
|
50
20
|
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
An ambiguity error names the competing files. Merge their intended contents and retain exactly
|
|
22
|
+
one accepted filename. The loader will not choose one on your behalf. Retry `pdks explain`.
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
like `protectedPath:` is rejected with the full field path — with one open ground: an
|
|
57
|
-
adapter namespace's *name* is not validated, so `adapters.gti:` for `adapters.git:` loads
|
|
58
|
-
clean and its entries are simply never read; that one spelling you check yourself); or an
|
|
59
|
-
empty `languages` block, the schema's one required entry.
|
|
24
|
+
<a id="invalid-config"></a>
|
|
25
|
+
## Invalid config
|
|
60
26
|
|
|
61
|
-
|
|
62
|
-
|
|
27
|
+
Parsing or schema failures exit 2 and name the file; schema errors also identify the offending
|
|
28
|
+
field. Repair invalid YAML, custom tags, unknown fields, or an empty `languages` object.
|
|
29
|
+
Custom YAML tags are rejected even if the parser cannot execute them: configuration is data.
|
|
63
30
|
|
|
64
|
-
|
|
31
|
+
Typos such as `protectedPath:` or `adaptors:` are refused. Adapter namespace names are deliberately
|
|
32
|
+
open, however: a namespace nobody implements loads without being read by anything. After repair,
|
|
33
|
+
run `pdks explain` and check the assembled registrations.
|
|
65
34
|
|
|
66
|
-
|
|
67
|
-
|
|
35
|
+
<a id="grok-witness"></a>
|
|
36
|
+
## Grok witness
|
|
68
37
|
|
|
69
|
-
|
|
38
|
+
A hook not yet loaded and an unavailable witness valve are different problems:
|
|
70
39
|
|
|
71
|
-
|
|
72
|
-
|
|
40
|
+
- After `pdks-grok init`, reload the Hooks tab or start a new session. Verify an actual call and
|
|
41
|
+
its telemetry; a successful installer run does not prove the open host loaded the hook.
|
|
42
|
+
- Grok's ACP history does not supply the Claude-format human message required by the current
|
|
43
|
+
session witness valve. Reloading does not add that capability. Perform a necessary repair
|
|
44
|
+
from your own terminal rather than trying to send a Claude witness token through Grok.
|
|
73
45
|
|
|
74
|
-
|
|
46
|
+
A commit witness authorizes its staged check only. It cannot release a blocked Grok tool call.
|
|
75
47
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
milliseconds apart.
|
|
48
|
+
<a id="config-fault"></a>
|
|
49
|
+
## Config-fault
|
|
79
50
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
51
|
+
The configuration loaded, but an entry could not compile into a judgment. A matching registration
|
|
52
|
+
records `skipped` with `config-fault`; `pdks explain` shows the fault. Check extraction step names,
|
|
53
|
+
arguments, regex syntax, and paired versus single extraction use. Fix the named declaration and
|
|
54
|
+
repeat the same observation. A skipped entry is not a passing one.
|
|
83
55
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
names the Claude hook takes the settings entry's matcher.
|
|
56
|
+
<a id="judge-cannot-be-loaded"></a>
|
|
57
|
+
## The judge cannot be loaded
|
|
87
58
|
|
|
88
|
-
|
|
59
|
+
A missing package or judging module fails closed. Reinstall the package or run the complete
|
|
60
|
+
workspace build from your own terminal. The generated hook delegates to the installed package;
|
|
61
|
+
it is not an independent copy of the judge. Verify another real call after repair. A failure
|
|
62
|
+
before telemetry can load may leave no row at all.
|
|
89
63
|
|
|
90
|
-
|
|
64
|
+
The session hook prefixes the message with `covenant hook failed closed:` and the commit check
|
|
65
|
+
with `covenant check failed closed:`. The two shapes you will see:
|
|
91
66
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
installs where it is invoked).
|
|
67
|
+
```text
|
|
68
|
+
covenant hook failed closed: Cannot find package 'polydeukes' imported from …
|
|
69
|
+
covenant check failed closed: the covenant judges could not be loaded from … — run 'pnpm build' to rebuild them: Cannot find module './self-mod.js' …
|
|
70
|
+
```
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
72
|
+
The first is the installed package missing; the second is a source checkout whose judge
|
|
73
|
+
build output is missing or partial.
|
|
100
74
|
|
|
101
|
-
|
|
75
|
+
<a id="reading-verdict"></a>
|
|
76
|
+
## Reading a verdict
|
|
102
77
|
|
|
103
|
-
|
|
104
|
-
|
|
78
|
+
| Record | Meaning |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `passed` | The observed input was judged and upheld the covenant. |
|
|
81
|
+
| `blocked` | A violation stopped the operation. |
|
|
82
|
+
| `witnessed` | A blocking result was allowed through its witness valve. |
|
|
83
|
+
| `advised` | A violation was recorded without stopping the operation, on either surface. |
|
|
84
|
+
| `skipped` | No judgment was possible for the matching registration. This is not a pass. |
|
|
85
|
+
| `unattributed` | Baseline comparison found protected changes without an explaining judgment, or could not read a valid baseline. This is an observation, not a verdict. |
|
|
105
86
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
preflight prevents *wiring* a project into this state, but nothing prevents a wired
|
|
110
|
-
project from entering it later.
|
|
87
|
+
Judgments append telemetry at `.polydeukes/roi.log` unless `telemetry.logPath` changes the location.
|
|
88
|
+
Logging is fail-open: a write failure does not alter the verdict. Exit 0 means the operation may
|
|
89
|
+
continue, not that every discipline passed.
|
|
111
90
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
file itself needs no repair — it is a delegator, and it recovers the moment the package
|
|
115
|
-
resolves again.
|
|
91
|
+
<a id="opening-a-blocked-call"></a>
|
|
92
|
+
## Opening a blocked call
|
|
116
93
|
|
|
117
|
-
|
|
94
|
+
In a supported Claude Code session, type the configured witness token alone on the first line
|
|
95
|
+
of a human message, then retry within its configured TTL. The message may also precede an
|
|
96
|
+
intentional protected edit; no previous failed attempt is required. The token is not a secret.
|
|
97
|
+
The valve checks human provenance and applies only to a blocking judgment. A successful retry
|
|
98
|
+
appends a `witnessed` row; it does not rewrite the earlier blocked row.
|
|
118
99
|
|
|
119
|
-
|
|
100
|
+
A witness cannot repair missing modules or other failures that prevent judgment assembly.
|
|
120
101
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
move it).
|
|
102
|
+
<a id="blocked-commit"></a>
|
|
103
|
+
## A blocked commit
|
|
124
104
|
|
|
125
|
-
|
|
105
|
+
The change-set surface does not prompt. By default it exits 0 on every verdict and records the
|
|
106
|
+
break as `advised`; it exits 2 only when the check runs with `--enforce block` (a protected
|
|
107
|
+
path or an entry set to `enforce: block` broke) or when it could not judge at all. Whether the
|
|
108
|
+
commit stops is your hook wiring — a hook that honours the exit code stops it, one that ignores
|
|
109
|
+
it does not. Git may report a different nonzero exit code for the failed commit.
|
|
126
110
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
| `witnessed` | A blocked verdict a human opened in person. Never silent. |
|
|
132
|
-
| `advised` | Commit surface at `advise` level: a break recorded without stopping the commit. |
|
|
133
|
-
| `skipped` | A registration matched but could not judge — **the recorded absence of a judgment, not a pass.** |
|
|
134
|
-
| `unattributed` | A protected entry changed on disk and no judgment explains it — **an observation, not a verdict.** Nothing was blocked; the write already happened. |
|
|
111
|
+
A normal entry blocks only when it declares `enforce: block` and the check runs with
|
|
112
|
+
`--enforce block`; nothing in the config promotes a default-`advise` entry. Changing a level is
|
|
113
|
+
a policy decision, not a required repair. To let a judged break through, drop `--enforce block`
|
|
114
|
+
from the hook command rather than editing the config — the row is still written.
|
|
135
115
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
the session's view, which is exactly what the row is for.
|
|
116
|
+
<a id="skipped-rows-on-the-change-set-surface"></a>
|
|
117
|
+
## `skipped` rows on the change-set surface
|
|
139
118
|
|
|
140
|
-
|
|
119
|
+
A transcript-reading declaration with `supply: { session: 'pass' }` records `supply-pass` when the
|
|
120
|
+
change-set surface has no session. Use the session surface for that promise; a skip does not verify
|
|
121
|
+
history. Other unavailable channels can produce `no-observation`. Inspect the registration and
|
|
122
|
+
reason instead of treating every missing source as the same failure.
|
|
141
123
|
|
|
142
|
-
|
|
143
|
-
|
|
124
|
+
A command-scoped declaration does not match a staged diff's absent command line and records no
|
|
125
|
+
judgment there. Configuration, scope matching, supply, and the final comparison are separate steps.
|
|
144
126
|
|
|
145
|
-
|
|
146
|
-
|
|
127
|
+
<a id="local-state"></a>
|
|
128
|
+
## Moving a project between machines
|
|
147
129
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
typing the token for itself (only human-authored messages count — the defence is
|
|
154
|
-
provenance, not secrecy). Every allowance lands as one `witnessed` row.
|
|
130
|
+
Telemetry and `.polydeukes/baseline.json` are local state, not a portable history supplied by Git.
|
|
131
|
+
A clone without them does not reconstruct prior judgments. The session hook records an absent
|
|
132
|
+
or invalid baseline and establishes one for subsequent comparisons; this is not proof that old
|
|
133
|
+
changes were judged. Preserve needed logs separately when migrating, and check any custom
|
|
134
|
+
`telemetry.logPath` rather than assuming `.polydeukes/` holds all records.
|
|
155
135
|
|
|
156
|
-
|
|
136
|
+
<a id="next-steps"></a>
|
|
137
|
+
## Next steps
|
|
157
138
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
**Cause.** The commit surface at the default `block` level judges the staged diff, and its
|
|
162
|
-
valve is a TTY prompt. An agent-spawned commit has no TTY, so for it the valve is not even
|
|
163
|
-
assembled — a terminal-holding human is the pass condition, not a workaround.
|
|
164
|
-
|
|
165
|
-
**Recovery.** Run the commit from your own terminal and answer the prompt with the full
|
|
166
|
-
token — one answer covers that whole commit. If you want the commit surface to measure
|
|
167
|
-
without stopping, set `adapters.git.enforce: advise`: verdicts are then recorded as
|
|
168
|
-
`advised` and the commit proceeds with one advisory line on stderr. At either level a run
|
|
169
|
-
that *cannot judge* (missing or invalid config, an unresolvable judge) still exits 2 —
|
|
170
|
-
`advise` relaxes the verdict, never the gate's integrity.
|
|
171
|
-
|
|
172
|
-
## `skipped` rows on the commit surface
|
|
173
|
-
|
|
174
|
-
**Symptom.** A `precedent` declaration that judges normally in sessions always lands as
|
|
175
|
-
`skipped` on commits.
|
|
176
|
-
|
|
177
|
-
**Cause.** A declaration that reads the session judges *session history* — was the required
|
|
178
|
-
step actually executed before this change. A commit has no session to read, so the
|
|
179
|
-
declaration's own `supply: { session: 'pass' }` takes over: when its scope matches a staged
|
|
180
|
-
change it records `skipped` with the reason `supply-pass` and the entry's id, and proceeds.
|
|
181
|
-
|
|
182
|
-
**Recovery.** None needed — this is a declared condition of the surface, not a defect. The
|
|
183
|
-
row is the point: a gate that did nothing says so in the data. `pdks explain` shows the
|
|
184
|
-
same fact before any commit: the entry appears under the commit surface with its
|
|
185
|
-
`transcript` source, which that surface never supplies. Such a declaration is
|
|
186
|
-
really a session-surface tool — on a project that wires only the commit surface, such an
|
|
187
|
-
entry only ever buys telemetry, so declare it where an AI partner's session exists to be
|
|
188
|
-
judged. The row appears only when the entry's scope actually matched, so an unrelated
|
|
189
|
-
commit records nothing.
|
|
139
|
+
- [Connect the surfaces](./how-to/connect-surfaces.md)
|
|
140
|
+
- [Configure the project](./how-to/configure-project.md)
|
|
141
|
+
- [Write disciplines](./how-to/write-disciplines.md)
|