polydeukes 0.6.0 → 0.6.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.
Files changed (55) hide show
  1. package/README.ko.md +54 -80
  2. package/README.md +55 -94
  3. package/dist/bin.js +8 -5
  4. package/dist/docs/README.ko.md +60 -0
  5. package/dist/docs/README.md +64 -0
  6. package/dist/docs/catalog.json +464 -0
  7. package/dist/docs/concepts/judgment.ko.md +113 -0
  8. package/dist/docs/concepts/judgment.md +113 -0
  9. package/dist/docs/how-to/configure-project.ko.md +99 -0
  10. package/dist/docs/how-to/configure-project.md +95 -0
  11. package/dist/docs/how-to/connect-surfaces.ko.md +115 -0
  12. package/dist/docs/how-to/connect-surfaces.md +118 -0
  13. package/dist/docs/how-to/write-disciplines.ko.md +124 -0
  14. package/dist/docs/how-to/write-disciplines.md +125 -0
  15. package/dist/docs/index.json +2046 -0
  16. package/dist/docs/reference/cli/covenant-check.ko.md +101 -0
  17. package/dist/docs/reference/cli/covenant-check.md +98 -0
  18. package/dist/docs/reference/cli/docs.ko.md +97 -0
  19. package/dist/docs/reference/cli/docs.md +95 -0
  20. package/dist/docs/reference/cli/explain.ko.md +79 -0
  21. package/dist/docs/reference/cli/explain.md +84 -0
  22. package/dist/docs/reference/cli/init.ko.md +119 -0
  23. package/dist/docs/reference/cli/init.md +131 -0
  24. package/dist/docs/reference/configuration/index.ko.md +448 -0
  25. package/dist/docs/reference/{configuration.md → configuration/index.md} +48 -30
  26. package/dist/docs/reference/packages/adapter-claude-code.ko.md +83 -0
  27. package/dist/docs/reference/{adapter-claude-code.md → packages/adapter-claude-code.md} +10 -6
  28. package/dist/docs/reference/packages/adapter-git.ko.md +101 -0
  29. package/dist/docs/reference/{adapter-git.md → packages/adapter-git.md} +20 -12
  30. package/dist/docs/reference/packages/core.ko.md +128 -0
  31. package/dist/docs/reference/{core.md → packages/core.md} +21 -8
  32. package/dist/docs/reference/packages/covenant.ko.md +115 -0
  33. package/dist/docs/reference/{covenant.md → packages/covenant.md} +18 -11
  34. package/dist/docs/reference/packages/polydeukes.ko.md +134 -0
  35. package/dist/docs/reference/packages/polydeukes.md +139 -0
  36. package/dist/docs/troubleshooting.ko.md +142 -0
  37. package/dist/docs/troubleshooting.md +98 -150
  38. package/dist/docs/tutorials/first-judgment.ko.md +82 -0
  39. package/dist/docs/tutorials/first-judgment.md +81 -0
  40. package/dist/docs-catalog.d.ts +25 -0
  41. package/dist/docs-catalog.js +450 -0
  42. package/dist/docs-library.d.ts +23 -0
  43. package/dist/docs-library.js +347 -0
  44. package/dist/docs-markdown.d.ts +32 -0
  45. package/dist/docs-markdown.js +150 -0
  46. package/dist/docs-query.d.ts +11 -40
  47. package/dist/docs-query.js +28 -122
  48. package/dist/docs-types.d.ts +105 -0
  49. package/dist/docs-types.js +2 -0
  50. package/dist/init-claude-code.d.ts +1 -1
  51. package/dist/init-claude-code.js +159 -42
  52. package/package.json +5 -5
  53. package/dist/docs/configuration.md +0 -103
  54. package/dist/docs/installation.md +0 -241
  55. package/dist/docs/reference/polydeukes.md +0 -315
@@ -0,0 +1,139 @@
1
+ # `polydeukes`
2
+
3
+ **English** · [한국어](./polydeukes.ko.md)
4
+
5
+ The umbrella package is the only package a consumer installs. It owns the CLI bin, the config
6
+ loader, the commit-surface runner, the session-surface runner subpath, and the bundled schema
7
+ artifact.
8
+
9
+ <a id="polydeukes-entry-points"></a>
10
+ ## Entry points
11
+
12
+ | Specifier | What it exports |
13
+ |---|---|
14
+ | `polydeukes` | `loadConfig`, `runCovenantCheck`, and `ResolvedConfig` |
15
+ | `polydeukes/claude-code` | `runClaudeCodeHook` and its spec/outcome types |
16
+ | `polydeukes/schema.json` | The bundled config JSON Schema |
17
+
18
+ The package has one executable name in `bin`: `pdks`, with `polydeukes` as an alias.
19
+
20
+ <a id="polydeukes-bin"></a>
21
+ ## CLI surface
22
+
23
+ | Command | Purpose |
24
+ |---|---|
25
+ | `pdks covenant check` | Judge the staged diff, the working tree, or a ref range |
26
+ | `pdks init claude-code` | Install the Claude Code session surface |
27
+ | `pdks init grok` | Install the Grok session surface |
28
+ | `pdks explain` | Render the assembled registration table without judging |
29
+ | `pdks docs [topic]` | Read a bundled topic |
30
+ | `pdks docs search <query>` | Search the bundled docs |
31
+ | `pdks docs show <document-id>` | Show one bundled document or section |
32
+
33
+ `pdks docs` is offline. It reads the installed package, not the network. Flags, JSON, and
34
+ exit codes are in [`pdks docs`](../cli/docs.md).
35
+
36
+ <a id="polydeukes-export-map"></a>
37
+ ## Export map
38
+
39
+ <a id="root-export"></a>
40
+ ### `.` root export
41
+
42
+ | Symbol | Kind | Notes |
43
+ |---|---|---|
44
+ | `loadConfig` | function | Discovers exactly one `polydeukes.config.*` file under `rootDir`; throws on missing, ambiguous, parse, or validation failure. |
45
+ | `runCovenantCheck` | function | Runs the commit-surface runner and resolves to `{ exitCode: 0 \| 2 }`. |
46
+ | `ResolvedConfig` | type | Re-export from `@polydeukes/core`. |
47
+ | `LoadConfigSpec`, `LoadedConfig` | types | Configuration loader input and result. |
48
+ | `CovenantCheckSpec`, `CovenantCheckOutcome`, `CheckDomain` | types | Commit runner input, result, and observation selection. |
49
+
50
+ <a id="session-export"></a>
51
+ ### `./claude-code`
52
+
53
+ | Symbol | Kind | Notes |
54
+ |---|---|---|
55
+ | `runClaudeCodeHook` | function | Runs the session-surface runner and resolves to `{ exitCode: 0 \| 2 }`. |
56
+ | `ClaudeCodeHookSpec` | type | Input for the session runner. |
57
+ | `ClaudeCodeHookOutcome` | type | Session runner result. |
58
+
59
+ The generated hook imports this subpath, not the barrel. ESM imports are eager, so importing the
60
+ barrel would load the commit-surface runner — and the git adapter behind it — on every session tool
61
+ call that will never use them.
62
+
63
+ <a id="schema-export"></a>
64
+ ### `./schema.json`
65
+
66
+ | Artifact | Notes |
67
+ |---|---|
68
+ | `polydeukes.schema.json` | The config schema copy that ships with the umbrella package. |
69
+
70
+ <a id="polydeukes-signatures"></a>
71
+ ## Signatures and examples
72
+
73
+ ```ts
74
+ function loadConfig(spec: LoadConfigSpec): LoadedConfig;
75
+
76
+ type LoadConfigSpec = { rootDir: string };
77
+
78
+ type LoadedConfig = {
79
+ config: ResolvedConfig;
80
+ configPath: string;
81
+ };
82
+
83
+ function runCovenantCheck(spec: CovenantCheckSpec): Promise<CovenantCheckOutcome>;
84
+
85
+ type CovenantCheckSpec = {
86
+ repoRoot: string;
87
+ telemetryPath?: string;
88
+ covenantDist?: string;
89
+ ttyPrompt?: (prompt: string) => string | null;
90
+ domain?: CheckDomain;
91
+ };
92
+
93
+ type CheckDomain =
94
+ | { kind: 'staged' }
95
+ | { kind: 'worktree' }
96
+ | { kind: 'range'; base: string; head: string; ancestry?: 'merge-base' };
97
+
98
+ function runClaudeCodeHook(spec: ClaudeCodeHookSpec): Promise<ClaudeCodeHookOutcome>;
99
+
100
+ type ClaudeCodeHookSpec = {
101
+ repoRoot: string;
102
+ rawPayload?: string;
103
+ telemetryPath?: string;
104
+ covenantDist?: string;
105
+ };
106
+ ```
107
+
108
+ `ancestry: 'merge-base'` is the `<base>...<head>` reading. `rawPayload` absent means the hook reads
109
+ fd 0. The hook types live on `polydeukes/claude-code`, not on the root barrel.
110
+
111
+ ```ts
112
+ import { loadConfig, runCovenantCheck } from 'polydeukes';
113
+ import { runClaudeCodeHook } from 'polydeukes/claude-code';
114
+
115
+ const { configPath } = loadConfig({ rootDir: process.cwd() });
116
+ const check = await runCovenantCheck({ repoRoot: process.cwd() });
117
+ const hook = await runClaudeCodeHook({ repoRoot: process.cwd(), rawPayload: '{}' });
118
+ ```
119
+
120
+ <a id="polydeukes-failure-boundaries"></a>
121
+ ## Failure boundaries
122
+
123
+ - `loadConfig()` throws on missing, ambiguous, parse, or validation failure.
124
+ - `runCovenantCheck()` and `runClaudeCodeHook()` never throw; they resolve to `{ exitCode: 0 \| 2
125
+ }`.
126
+ - The numeric codes are `EXIT_UPHOLD` (`0`), `EXIT_BREAK_NON_BLOCKING` (`1`), and
127
+ `EXIT_BREAK_BLOCKING` (`2`) from `@polydeukes/core`. The umbrella runners expose only `0` or
128
+ `2`; they never return `1`.
129
+ - `pdks covenant check` prompts for a witness token only for the staged domain, never for
130
+ `--worktree` or `--range`.
131
+ - `pdks docs` and `pdks explain` print nothing partial on failure.
132
+
133
+ <a id="polydeukes-see-also"></a>
134
+ ## See also
135
+
136
+ - [`pdks covenant check`](../cli/covenant-check.md)
137
+ - [`pdks init`](../cli/init.md)
138
+ - [`pdks explain`](../cli/explain.md)
139
+ - [`Configuration reference`](../configuration/index.md)
@@ -0,0 +1,142 @@
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 claude-code` 또는
15
+ `pdks init grok`로 만들 수 있습니다. 이후 `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
+ 남겨 두었습니다. `adapters.gti:`도 설정으로 읽히지만 Git 어댑터는 사용하지 않습니다.
35
+ 올바른 키는 `adapters.git`입니다. 수정한 뒤 `pdks explain`에서 실제 등록 내용을 확인하세요.
36
+
37
+ <a id="grok-witness"></a>
38
+ ## Grok 증인
39
+
40
+ 훅을 아직 읽지 않은 문제와 증인(witness) 밸브를 사용할 수 없는 문제는 구별해야 합니다.
41
+
42
+ - `pdks init grok` 실행 뒤 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
+ 본인의 터미널에서 커밋을 실행하고 TTY 프롬프트에 설정된 토큰 전체를 입력하세요.
109
+ 비대화형 스테이징 검사는 이 응답을 받을 수 없습니다. 검사가 작업을 거부하면 종료 코드 2를
110
+ 반환합니다. Git은 커밋 실패를 다른 0이 아닌 코드로 알릴 수도 있습니다.
111
+
112
+ 일반 규율 항목은 자체 수준과 어댑터 수준이 모두 차단을 허용해야 작업을 멈춥니다.
113
+ `adapters.git.enforce: block`만 설정해도 기본값 `advise`인 항목이 자동 승격되지는 않습니다.
114
+ 수준 변경은 정책을 바꾸는 결정이지 필수 복구 절차가 아닙니다. 커밋 프롬프트와 세션 메시지는
115
+ 서로 별개의 증인 입력 경로입니다.
116
+
117
+ <a id="skipped-rows-on-the-commit-surface"></a>
118
+ ## 커밋 표면의 미판정 기록
119
+
120
+ 대화 기록을 읽는 선언에 `supply: { session: 'pass' }`가 있으면 세션이 없는 커밋 표면에서는
121
+ `supply-pass`를 기록합니다. 이 약속은 세션 표면에서 확인하세요. 미판정은 과거 작업을
122
+ 검증했다는 뜻이 아닙니다. 다른 채널을 공급할 수 없으면 `no-observation`이 나올 수도
123
+ 있습니다. 모든 자료 부재를 같은 실패로 취급하지 말고 등록 내용과 사유를 확인하세요.
124
+
125
+ 스테이징한 변경에는 명령줄이 없으므로 명령 범위 선언은 적용되지 않으며 판정도 기록하지
126
+ 않습니다. 설정, 범위 일치, 자료 공급, 최종 비교는 각각 다른 단계입니다.
127
+
128
+ <a id="local-state"></a>
129
+ ## 다른 컴퓨터로 프로젝트를 옮길 때
130
+
131
+ 텔레메트리와 `.polydeukes/baseline.json`은 로컬 상태이며 Git이 옮겨 주는 판정 이력이
132
+ 아닙니다. 이 파일 없이 저장소를 복제해도 과거 판정이 복원되지는 않습니다. 세션 훅은 기준
133
+ 상태가 없거나 유효하지 않으면 이를 기록하고 다음 비교에 쓸 기준을 만듭니다. 과거 변경을
134
+ 판정했다는 증거가 생기는 것은 아닙니다. 필요한 로그는 따로 보관해 옮기세요.
135
+ `telemetry.logPath`를 바꿨다면 모든 기록이 `.polydeukes/`에 있다고 가정해서는 안 됩니다.
136
+
137
+ <a id="next-steps"></a>
138
+ ## 다음 단계
139
+
140
+ - [표면 연결하기](./how-to/connect-surfaces.ko.md)
141
+ - [프로젝트 설정하기](./how-to/configure-project.ko.md)
142
+ - [규율 작성하기](./how-to/write-disciplines.ko.md)
@@ -2,188 +2,136 @@
2
2
 
3
3
  **English** · [한국어](./troubleshooting.ko.md)
4
4
 
5
- > Alpha. Nine states cover what ships today — five ways a fail-closed system refuses to
6
- > proceed, and four things worth knowing when a judgment surprises you. Each entry is
7
- > symptom → cause → recovery.
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
- ## More than one config file
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.
45
-
46
- **Recovery.** Keep exactly one file and delete the others. If both have content, merge by
47
- hand first — the loader will not choose for you.
48
-
49
- ## The config is invalid
50
-
51
- **Symptom.** Every call exits 2 with an error naming the offending file — and, for schema
52
- violations, the exact key.
53
-
54
- **Cause.** One of: a YAML parse error; a custom YAML tag (rejected even though the parser
55
- cannot execute it — config data stays uncomputable by contract); an unknown key (a typo
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.
60
-
61
- **Recovery.** Fix the named key in the named file. The error is specific on purpose — no
62
- rewrite-and-hope needed.
9
+ <a id="no-config"></a>
10
+ ## No config found
63
11
 
64
- ## A Grok session does not pick up a newly installed hook
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 claude-code` / `pdks init grok` for a new
15
+ project. Then run `pdks explain`. No configuration means no silent default policy.
65
16
 
66
- **Symptom.** `pdks init grok` reported created files, but this session's tool calls still
67
- leave no telemetry row.
17
+ <a id="multiple-config"></a>
18
+ ## More than one config file
68
19
 
69
- **Cause.** Grok loads hooks at session start. An already-open session keeps that snapshot.
20
+ An ambiguity error names the competing files. Merge their intended contents and retain exactly
21
+ one accepted filename. The loader will not choose one on your behalf. Retry `pdks explain`.
70
22
 
71
- **Recovery.** Press `r` in the Hooks tab, or start a new session. The witness valve also
72
- does not open on Grok — a block is recovered from another terminal or the commit-surface TTY.
23
+ <a id="invalid-config"></a>
24
+ ## Invalid config
73
25
 
74
- ## One Grok tool call leaves two telemetry rows
26
+ Parsing or schema failures exit 2 and name the file; schema errors also identify the offending
27
+ field. Repair invalid YAML, custom tags, unknown fields, or an empty `languages` object.
28
+ Custom YAML tags are rejected even if the parser cannot execute them: configuration is data.
75
29
 
76
- **Symptom.** In a tree wired for both Claude Code and Grok, every `write` or
77
- `run_terminal_command` in a Grok session appends two rows to `.polydeukes/roi.log`,
78
- milliseconds apart.
30
+ Typos such as `protectedPath:` or `adaptors:` are refused. Adapter namespace names are deliberately
31
+ open, however: `adapters.gti:` can load but is not read by the Git adapter. Its actual key is
32
+ `adapters.git`. After repair, run `pdks explain` and check the assembled registrations.
79
33
 
80
- **Cause.** Grok reads `.claude/settings.json` as well as `.grok/hooks/*.json` and collapses
81
- the two registrations only when `command` and `matcher` are both identical. A grok JSON
82
- whose matcher differs from the settings entry spawns the judge a second time.
34
+ <a id="grok-witness"></a>
35
+ ## Grok witness
83
36
 
84
- **Recovery.** Make the grok JSON's `matcher` the same string as the settings entry that
85
- registers the same command. Re-running either installer does it: every grok entry that
86
- names the Claude hook takes the settings entry's matcher.
37
+ A hook not yet loaded and an unavailable witness valve are different problems:
87
38
 
88
- ## `pdks init claude-code` refuses to run
39
+ - After `pdks init grok`, reload the Hooks tab or start a new session. Verify an actual call and
40
+ its telemetry; a successful installer run does not prove the open host loaded the hook.
41
+ - Grok's ACP history does not supply the Claude-format human message required by the current
42
+ session witness valve. Reloading does not add that capability. Perform a necessary repair
43
+ from your own terminal rather than trying to send a Claude witness token through Grok.
89
44
 
90
- **Symptom.** The installer prints an install command and exits 2 without creating anything.
45
+ A commit witness authorizes its staged check only. It cannot release a blocked Grok tool call.
91
46
 
92
- **Cause.** Preflight: before writing any file, the installer proves the `polydeukes`
93
- package resolves from the target project root. A hook generated without that would block
94
- every call through its own fail-closed catch — an uneditable tree. The usual trigger is
95
- running via a one-off `npx` without installing, or running in the wrong directory (it
96
- installs where it is invoked).
47
+ <a id="config-fault"></a>
48
+ ## Config-fault
97
49
 
98
- **Recovery.** `pnpm add -D polydeukes` in the project you meant, then re-run from that
99
- root. Zero files were written, so there is no partial state to clean up.
50
+ The configuration loaded, but an entry could not compile into a judgment. A matching registration
51
+ records `skipped` with `config-fault`; `pdks explain` shows the fault. Check extraction step names,
52
+ arguments, regex syntax, and paired versus single extraction use. Fix the named declaration and
53
+ repeat the same observation. A skipped entry is not a passing one.
100
54
 
55
+ <a id="judge-cannot-be-loaded"></a>
101
56
  ## The judge cannot be loaded
102
57
 
103
- **Symptom.** Every call exits 2 with `covenant hook failed closed: Cannot find package
104
- 'polydeukes'` — or an error naming a judge-body file that does not exist.
58
+ A missing package or judging module fails closed. Reinstall the package or run the complete
59
+ workspace build from your own terminal. The generated hook delegates to the installed package;
60
+ it is not an independent copy of the judge. Verify another real call after repair. A failure
61
+ before telemetry can load may leave no row at all.
62
+
63
+ The session hook prefixes the message with `covenant hook failed closed:` and the commit check
64
+ with `covenant check failed closed:`. The two shapes you will see:
105
65
 
106
- **Cause.** The hook is wired but the package it delegates to is gone or incomplete: the
107
- dependency was removed, the tree is a fresh clone that was never installed, or (in a
108
- source clone of this repository) the judge's build output is missing. The installer's
109
- preflight prevents *wiring* a project into this state, but nothing prevents a wired
110
- project from entering it later.
66
+ ```text
67
+ covenant hook failed closed: Cannot find package 'polydeukes' imported from …
68
+ covenant check failed closed: the covenant judges could not be loaded from … — run 'pnpm build' to rebuild them: Cannot find module './self-mod.js' …
69
+ ```
111
70
 
112
- **Recovery.** From your own terminal, reinstall the dependency (`pnpm install`, or
113
- `pnpm add -D polydeukes` if it was removed). In a source clone, run the build. The hook
114
- file itself needs no repair — it is a delegator, and it recovers the moment the package
115
- resolves again.
71
+ The first is the installed package missing; the second is a source checkout whose judge
72
+ build output is missing or partial.
116
73
 
74
+ <a id="reading-verdict"></a>
117
75
  ## Reading a verdict
118
76
 
119
- **Symptom.** Something was blocked (or passed) and you want to know what the record says.
77
+ | Record | Meaning |
78
+ |---|---|
79
+ | `passed` | The observed input was judged and upheld the covenant. |
80
+ | `blocked` | A violation stopped the operation. |
81
+ | `witnessed` | A blocking result was allowed through its witness valve. |
82
+ | `advised` | A violation was recorded without stopping the operation, on either surface. |
83
+ | `skipped` | No judgment was possible for the matching registration. This is not a pass. |
84
+ | `unattributed` | Baseline comparison found protected changes without an explaining judgment, or could not read a valid baseline. This is an observation, not a verdict. |
120
85
 
121
- **Cause.** Not a failure — this is the measurement working. Every judgment appends exactly
122
- one record to the telemetry log (`.polydeukes/roi.log` by default, `telemetry.logPath` to
123
- move it).
86
+ Judgments append telemetry at `.polydeukes/roi.log` unless `telemetry.logPath` changes the location.
87
+ Logging is fail-open: a write failure does not alter the verdict. Exit 0 means the operation may
88
+ continue, not that every discipline passed.
124
89
 
125
- **Recovery.** Read the last lines and the six-word vocabulary:
90
+ <a id="opening-a-blocked-call"></a>
91
+ ## Opening a blocked call
126
92
 
127
- | Word | Means |
128
- |---|---|
129
- | `passed` | Judged, upheld the covenant. |
130
- | `blocked` | Judged, broke it. The call did not run. |
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. |
93
+ In a supported Claude Code session, type the configured witness token alone on the first line
94
+ of a human message, then retry within its configured TTL. The message may also precede an
95
+ intentional protected edit; no previous failed attempt is required. The token is not a secret.
96
+ The valve checks human provenance and applies only to a blocking judgment. A successful retry
97
+ appends a `witnessed` row; it does not rewrite the earlier blocked row.
135
98
 
136
- An `unattributed` row names the entry, not the file inside it. Rebuilding a protected `dist`
137
- without a judged call producing one is expected — it says a write reached that entry outside
138
- the session's view, which is exactly what the row is for.
99
+ A witness cannot repair missing modules or other failures that prevent judgment assembly.
139
100
 
140
- ## Opening a blocked call — the witness
101
+ <a id="blocked-commit"></a>
102
+ ## A blocked commit
141
103
 
142
- **Symptom.** A call you and your agent agree should proceed was blocked, and you want it
143
- through without editing the policy.
104
+ Run the commit from your own terminal and answer its TTY prompt with the complete configured
105
+ token. A non-interactive staged check cannot obtain that answer. The check exits 2 when it refuses;
106
+ Git may report a different nonzero exit code for the failed commit.
144
107
 
145
- **Cause.** The valve exists for exactly this, and it sits *after* the verdict — only a
146
- judgment that actually blocked can be witnessed open.
108
+ A normal entry blocks only when its own level and the adapter's level both permit blocking.
109
+ Setting only `adapters.git.enforce: block` does not promote default-`advise` entries. Changing a
110
+ level is a policy decision, not a required repair. The prompt is separate from a session message.
147
111
 
148
- **Recovery.** Type the token from your config's `witness:` block so it stands **alone on
149
- the first line** of a conversation message. The window holds for `ttlMinutes`, then
150
- blocking resumes on its own. Three things that do not work, by design: quoting or
151
- mentioning the token mid-sentence (invocation is first-line-standalone only); witnessing a
152
- call that was never blocked (the valve is consulted only after a block); and the agent
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.
112
+ <a id="skipped-rows-on-the-commit-surface"></a>
113
+ ## `skipped` rows on the commit surface
155
114
 
156
- ## A blocked commit
115
+ A transcript-reading declaration with `supply: { session: 'pass' }` records `supply-pass` when the
116
+ commit surface has no session. Use the session surface for that promise; a skip does not verify
117
+ history. Other unavailable channels can produce `no-observation`. Inspect the registration and
118
+ reason instead of treating every missing source as the same failure.
157
119
 
158
- **Symptom.** `git commit` stops at a prompt asking a human to witness a staged protected
159
- change — or, from an agent, the commit simply fails with exit 2.
120
+ A command-scoped declaration does not match a staged diff's absent command line and records no
121
+ judgment there. Configuration, scope matching, supply, and the final comparison are separate steps.
160
122
 
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.
123
+ <a id="local-state"></a>
124
+ ## Moving a project between machines
164
125
 
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.
126
+ Telemetry and `.polydeukes/baseline.json` are local state, not a portable history supplied by Git.
127
+ A clone without them does not reconstruct prior judgments. The session hook records an absent
128
+ or invalid baseline and establishes one for subsequent comparisons; this is not proof that old
129
+ changes were judged. Preserve needed logs separately when migrating, and check any custom
130
+ `telemetry.logPath` rather than assuming `.polydeukes/` holds all records.
171
131
 
172
- ## `skipped` rows on the commit surface
132
+ <a id="next-steps"></a>
133
+ ## Next steps
173
134
 
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.
135
+ - [Connect the surfaces](./how-to/connect-surfaces.md)
136
+ - [Configure the project](./how-to/configure-project.md)
137
+ - [Write disciplines](./how-to/write-disciplines.md)