polydeukes 0.5.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 (79) hide show
  1. package/README.ko.md +54 -74
  2. package/README.md +55 -86
  3. package/dist/baseline.d.ts +82 -0
  4. package/dist/baseline.js +166 -0
  5. package/dist/bin.d.ts +1 -1
  6. package/dist/bin.js +26 -6
  7. package/dist/claude-code-hook.d.ts +7 -5
  8. package/dist/claude-code-hook.js +69 -17
  9. package/dist/claude-code.d.ts +6 -0
  10. package/dist/claude-code.js +6 -0
  11. package/dist/covenant-check.d.ts +10 -17
  12. package/dist/covenant-check.js +44 -12
  13. package/dist/covenant-module.d.ts +2 -2
  14. package/dist/covenant-module.js +9 -1
  15. package/dist/docs/README.ko.md +60 -0
  16. package/dist/docs/README.md +64 -0
  17. package/dist/docs/catalog.json +464 -0
  18. package/dist/docs/concepts/judgment.ko.md +113 -0
  19. package/dist/docs/concepts/judgment.md +113 -0
  20. package/dist/docs/how-to/configure-project.ko.md +99 -0
  21. package/dist/docs/how-to/configure-project.md +95 -0
  22. package/dist/docs/how-to/connect-surfaces.ko.md +115 -0
  23. package/dist/docs/how-to/connect-surfaces.md +118 -0
  24. package/dist/docs/how-to/write-disciplines.ko.md +124 -0
  25. package/dist/docs/how-to/write-disciplines.md +125 -0
  26. package/dist/docs/index.json +2046 -0
  27. package/dist/docs/reference/cli/covenant-check.ko.md +101 -0
  28. package/dist/docs/reference/cli/covenant-check.md +98 -0
  29. package/dist/docs/reference/cli/docs.ko.md +97 -0
  30. package/dist/docs/reference/cli/docs.md +95 -0
  31. package/dist/docs/reference/cli/explain.ko.md +79 -0
  32. package/dist/docs/reference/cli/explain.md +84 -0
  33. package/dist/docs/reference/cli/init.ko.md +119 -0
  34. package/dist/docs/reference/cli/init.md +131 -0
  35. package/dist/docs/reference/configuration/index.ko.md +448 -0
  36. package/dist/docs/reference/configuration/index.md +474 -0
  37. package/dist/docs/reference/packages/adapter-claude-code.ko.md +83 -0
  38. package/dist/docs/reference/{adapter-claude-code.md → packages/adapter-claude-code.md} +16 -10
  39. package/dist/docs/reference/packages/adapter-git.ko.md +101 -0
  40. package/dist/docs/reference/{adapter-git.md → packages/adapter-git.md} +25 -15
  41. package/dist/docs/reference/packages/core.ko.md +128 -0
  42. package/dist/docs/reference/{core.md → packages/core.md} +32 -13
  43. package/dist/docs/reference/packages/covenant.ko.md +115 -0
  44. package/dist/docs/reference/{covenant.md → packages/covenant.md} +41 -26
  45. package/dist/docs/reference/packages/polydeukes.ko.md +134 -0
  46. package/dist/docs/reference/packages/polydeukes.md +139 -0
  47. package/dist/docs/troubleshooting.ko.md +142 -0
  48. package/dist/docs/troubleshooting.md +97 -122
  49. package/dist/docs/tutorials/first-judgment.ko.md +82 -0
  50. package/dist/docs/tutorials/first-judgment.md +81 -0
  51. package/dist/docs-catalog.d.ts +25 -0
  52. package/dist/docs-catalog.js +450 -0
  53. package/dist/docs-library.d.ts +23 -0
  54. package/dist/docs-library.js +347 -0
  55. package/dist/docs-markdown.d.ts +32 -0
  56. package/dist/docs-markdown.js +150 -0
  57. package/dist/docs-query.d.ts +11 -40
  58. package/dist/docs-query.js +28 -122
  59. package/dist/docs-types.d.ts +105 -0
  60. package/dist/docs-types.js +2 -0
  61. package/dist/explain.d.ts +3 -5
  62. package/dist/explain.js +48 -47
  63. package/dist/index.d.ts +2 -3
  64. package/dist/index.js +1 -2
  65. package/dist/init-claude-code.d.ts +5 -3
  66. package/dist/init-claude-code.js +226 -63
  67. package/dist/init-grok.d.ts +51 -0
  68. package/dist/init-grok.js +242 -0
  69. package/dist/load-config.d.ts +5 -1
  70. package/dist/load-config.js +2 -1
  71. package/dist/pre-state-reader.d.ts +22 -0
  72. package/dist/pre-state-reader.js +32 -0
  73. package/dist/scaffold-project.js +48 -8
  74. package/dist/schema/polydeukes.schema.json +38 -91
  75. package/package.json +7 -7
  76. package/dist/docs/configuration.md +0 -103
  77. package/dist/docs/installation.md +0 -212
  78. package/dist/docs/reference/configuration.md +0 -338
  79. package/dist/docs/reference/polydeukes.md +0 -287
@@ -2,161 +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.
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.
8
8
 
9
- This is the guide layer for recovery: the fail-closed states, reading verdicts, and the
10
- witness valve.
9
+ <a id="no-config"></a>
10
+ ## No config found
11
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` recreates the missing artifacts; on the commit path the
33
- config is hand-written — the [install guide](./installation.md)'s commit-surface section
34
- has a starting point.
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.
35
16
 
17
+ <a id="multiple-config"></a>
36
18
  ## More than one config file
37
19
 
38
- **Symptom.** Every call exits 2 with an error naming two (or three) config files at once.
39
-
40
- **Cause.** Two spellings coexist — say a `polydeukes.config.yaml` created next to a
41
- project's existing `.yml`. Ambiguity never picks a winner.
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`.
42
22
 
43
- **Recovery.** Keep exactly one file and delete the others. If both have content, merge by
44
- hand first — the loader will not choose for you.
23
+ <a id="invalid-config"></a>
24
+ ## Invalid config
45
25
 
46
- ## The config is invalid
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.
47
29
 
48
- **Symptom.** Every call exits 2 with an error naming the offending file — and, for schema
49
- violations, the exact key.
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.
50
33
 
51
- **Cause.** One of: a YAML parse error; a custom YAML tag (rejected even though the parser
52
- cannot execute it — config data stays uncomputable by contract); an unknown key (a typo
53
- like `protectedPath:` is rejected with the full field path — with one open ground: an
54
- adapter namespace's *name* is not validated, so `adapters.gti:` for `adapters.git:` loads
55
- clean and its entries are simply never read; that one spelling you check yourself); or an
56
- empty `languages` block, the schema's one required entry.
34
+ <a id="grok-witness"></a>
35
+ ## Grok witness
57
36
 
58
- **Recovery.** Fix the named key in the named file. The error is specific on purpose — no
59
- rewrite-and-hope needed.
37
+ A hook not yet loaded and an unavailable witness valve are different problems:
60
38
 
61
- ## `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.
62
44
 
63
- **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.
64
46
 
65
- **Cause.** Preflight: before writing any file, the installer proves the `polydeukes`
66
- package resolves from the target project root. A hook generated without that would block
67
- every call through its own fail-closed catch — an uneditable tree. The usual trigger is
68
- running via a one-off `npx` without installing, or running in the wrong directory (it
69
- installs where it is invoked).
47
+ <a id="config-fault"></a>
48
+ ## Config-fault
70
49
 
71
- **Recovery.** `pnpm add -D polydeukes` in the project you meant, then re-run from that
72
- 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.
73
54
 
55
+ <a id="judge-cannot-be-loaded"></a>
74
56
  ## The judge cannot be loaded
75
57
 
76
- **Symptom.** Every call exits 2 with `covenant hook failed closed: Cannot find package
77
- '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:
78
65
 
79
- **Cause.** The hook is wired but the package it delegates to is gone or incomplete: the
80
- dependency was removed, the tree is a fresh clone that was never installed, or (in a
81
- source clone of this repository) the judge's build output is missing. The installer's
82
- preflight prevents *wiring* a project into this state, but nothing prevents a wired
83
- 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
+ ```
84
70
 
85
- **Recovery.** From your own terminal, reinstall the dependency (`pnpm install`, or
86
- `pnpm add -D polydeukes` if it was removed). In a source clone, run the build. The hook
87
- file itself needs no repair — it is a delegator, and it recovers the moment the package
88
- 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.
89
73
 
74
+ <a id="reading-verdict"></a>
90
75
  ## Reading a verdict
91
76
 
92
- **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. |
93
85
 
94
- **Cause.** Not a failure this is the measurement working. Every judgment appends exactly
95
- one record to the telemetry log (`.polydeukes/roi.log` by default, `telemetry.logPath` to
96
- 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.
97
89
 
98
- **Recovery.** Read the last lines and the six-word vocabulary:
90
+ <a id="opening-a-blocked-call"></a>
91
+ ## Opening a blocked call
99
92
 
100
- | Word | Means |
101
- |---|---|
102
- | `passed` | Judged, upheld the covenant. |
103
- | `blocked` | Judged, broke it. The call did not run. |
104
- | `witnessed` | A blocked verdict a human opened in person. Never silent. |
105
- | `advised` | Commit surface at `advise` level: a break recorded without stopping the commit. |
106
- | `skipped` | A registration matched but could not judge — **the recorded absence of a judgment, not a pass.** |
107
- | `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.
108
98
 
109
- An `unattributed` row names the entry, not the file inside it. Rebuilding a protected `dist`
110
- without a judged call producing one is expected — it says a write reached that entry outside
111
- 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.
112
100
 
113
- ## Opening a blocked call — the witness
101
+ <a id="blocked-commit"></a>
102
+ ## A blocked commit
114
103
 
115
- **Symptom.** A call you and your agent agree should proceed was blocked, and you want it
116
- 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.
117
107
 
118
- **Cause.** The valve exists for exactly this, and it sits *after* the verdict only a
119
- 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.
120
111
 
121
- **Recovery.** Type the token from your config's `witness:` block so it stands **alone on
122
- the first line** of a conversation message. The window holds for `ttlMinutes`, then
123
- blocking resumes on its own. Three things that do not work, by design: quoting or
124
- mentioning the token mid-sentence (invocation is first-line-standalone only); witnessing a
125
- call that was never blocked (the valve is consulted only after a block); and the agent
126
- typing the token for itself (only human-authored messages count — the defence is
127
- 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
128
114
 
129
- ## 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.
130
119
 
131
- **Symptom.** `git commit` stops at a prompt asking a human to witness a staged protected
132
- 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.
133
122
 
134
- **Cause.** The commit surface at the default `block` level judges the staged diff, and its
135
- valve is a TTY prompt. An agent-spawned commit has no TTY, so for it the valve is not even
136
- assembled — a terminal-holding human is the pass condition, not a workaround.
123
+ <a id="local-state"></a>
124
+ ## Moving a project between machines
137
125
 
138
- **Recovery.** Run the commit from your own terminal and answer the prompt with the full
139
- token one answer covers that whole commit. If you want the commit surface to measure
140
- without stopping, set `adapters.git.enforce: advise`: verdicts are then recorded as
141
- `advised` and the commit proceeds with one advisory line on stderr. At either level a run
142
- that *cannot judge* (missing or invalid config, an unresolvable judge) still exits 2 —
143
- `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.
144
131
 
145
- ## `skipped` rows on the commit surface
132
+ <a id="next-steps"></a>
133
+ ## Next steps
146
134
 
147
- **Symptom.** A `requirePrecedent` discipline that judges normally in sessions always lands
148
- as `skipped` on commits.
149
-
150
- **Cause.** Context-family disciplines judge *session history* — was the required step
151
- actually executed before this change. A commit has no session to read, so the entry
152
- assembles as a skip registration: routing intact, no judge body. When its scope matches a
153
- staged change it records `skipped` with the entry's id and proceeds.
154
-
155
- **Recovery.** None needed — this is a declared condition of the surface, not a defect. The
156
- row is the point: a gate that did nothing says so in the data. `pdks explain` shows the
157
- same fact before any commit: every context entry appears under the commit surface as a
158
- `skip` line carrying the reason. A context-family entry is
159
- really a session-surface tool — on a project that wires only the commit surface, such an
160
- entry only ever buys telemetry, so declare it where an AI partner's session exists to be
161
- judged. The row appears only when the entry's scope actually matched, so an unrelated
162
- 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)
@@ -0,0 +1,82 @@
1
+ # 설치하고 첫 판정 확인하기
2
+
3
+ [English](./first-judgment.md) · **한국어**
4
+
5
+ 빈 예제 프로젝트에 Polydeukes를 설치하고 보호된 파일을 바꾸지 않은 채 쓰기 요청의 판정
6
+ 결과를 확인합니다. Node.js 24 이상, pnpm, git이 필요합니다. 실제 세션 호출을 확인하려면
7
+ Claude Code도 필요하지만, 아래 훅 검사 명령은 Claude Code 없이 실행할 수 있습니다.
8
+
9
+ <a id="claude-code"></a>
10
+
11
+ ## 클로드 코드 연동 설치와 첫 쓰기 요청 검사
12
+
13
+ 기존에 보호 중인 프로젝트 밖에서, 자신의 터미널로 다음 명령을 실행합니다.
14
+
15
+ ```sh
16
+ mkdir pdks-example
17
+ cd pdks-example
18
+ git init
19
+ printf '{"name":"pdks-example","private":true}\n' > package.json
20
+ pnpm add -D polydeukes # 프로젝트 의존성. 일회성 npx 실행이 아님
21
+ pnpm exec pdks init claude-code
22
+ ```
23
+
24
+ 설치기는 각 파일을 만들었으면 `created`, 이미 있어서 보존했으면 `skipped`로 보고합니다.
25
+ 초기 설정, 훅 위임 파일, Claude Code 등록 설정, 문서 조회 안내, `discipline-draft` 스킬과
26
+ 텔레메트리 제외 항목을 만듭니다. 기존 사용자 파일은 보존하고, 설정은 통째로 덮지 않고
27
+ 병합합니다.
28
+
29
+ 생성된 훅에 설정 파일을 쓰려는 요청을 전달합니다.
30
+
31
+ ```sh
32
+ printf '%s\n' '{"tool_name":"Write","tool_input":{"file_path":".claude/settings.json","content":"{}"}}' \
33
+ | node .claude/hooks/covenant-pretooluse.mjs
34
+ printf 'exit=%s\n' "$?"
35
+ tail -n 5 .polydeukes/roi.log
36
+ ```
37
+
38
+ 예상 결과는 `exit=2`입니다. stderr에는 보호 경로를 지목한 메시지가 나오고, 로그에는
39
+ `blocked` 행이 남습니다. 이 명령은 판정만 요청하며 **실제로 파일을 쓰지 않습니다**.
40
+ 설정 파일은 그대로이므로 되돌릴 변경도 없습니다.
41
+
42
+ 이번에는 보호 목록 밖의 경로로 같은 검사를 합니다.
43
+
44
+ ```sh
45
+ printf '%s\n' '{"tool_name":"Write","tool_input":{"file_path":"example.txt","content":"hello"}}' \
46
+ | node .claude/hooks/covenant-pretooluse.mjs
47
+ printf 'exit=%s\n' "$?"
48
+ tail -n 5 .polydeukes/roi.log
49
+ ```
50
+
51
+ 초기 설정에서는 `exit=0`과 `passed` 행이 나와야 합니다. 이 명령도 파일을 쓰지는 않습니다.
52
+ 설치된 판정기로 차단할 요청과 허용할 요청을 각각 확인한 것입니다.
53
+
54
+ 실제 도구 호출에 훅을 적용하려면 이 프로젝트에서 Claude Code를 엽니다. 일반 텍스트 파일을
55
+ 만들도록 요청한 뒤 `.polydeukes/roi.log`에 새 행이 생기는지 확인합니다. 앞의 직접 호출
56
+ 검사만으로는 특정 호스트 세션이 훅 등록을 읽었다고 판단할 수 없습니다.
57
+
58
+ **처음 설정을 바꾸기 전에 확인하세요.** 로더는 발견한 설정 파일을 자동으로 보호합니다.
59
+ `protectedPaths`에 파일명이 없어도 같습니다. 세션에서 의도적으로 편집하려면
60
+ `witness.token`을 읽고, 사람이 직접 메시지 첫 줄에 그 토큰만 입력합니다. 초기 토큰은
61
+ `pdks witness`이며 유효 시간은 10분입니다. 증인(witness) 밸브는 판정기가 차단한 결과에만
62
+ 적용됩니다. 에이전트가 사람을 대신해 메시지를 공급할 수는 없습니다. 자신의 터미널에서
63
+ 의도한 설정 변경을 직접 수행해도 됩니다.
64
+
65
+ 패키지나 설정을 읽지 못해 검사가 실패하면 자신의 터미널에서 지목된 파일을 고치거나
66
+ 패키지를 다시 설치합니다. 밸브를 조립하는 단계에 이르기 전에 발생한 오류는 증인으로 해결할 수 없습니다.
67
+ [설정 오류](../troubleshooting.ko.md#invalid-config)와
68
+ [판정기 로드 실패](../troubleshooting.ko.md#judge-cannot-be-loaded)를 참고하세요.
69
+
70
+ <a id="next-step"></a>
71
+
72
+ ## 실제 프로젝트에 적용하기
73
+
74
+ - [프로젝트 설정](../how-to/configure-project.ko.md)에서 임시 언어 이름과 테스트 명령을
75
+ 바꿉니다.
76
+ - Grok이나 git pre-commit 훅은 [관측 표면 연결](../how-to/connect-surfaces.ko.md)을 참고합니다.
77
+ - [규율 작성](../how-to/write-disciplines.ko.md) 예제를 실행하고, 권고 결과를 확인한 뒤 차단
78
+ 여부를 결정합니다.
79
+
80
+ 종료 코드만으로 모든 관측 결과를 알 수는 없습니다. `advised`나 `skipped`가 있어도 exit 0일
81
+ 수 있습니다. 진단 메시지와 [판정 결과 어휘](../troubleshooting.ko.md#reading-verdict)를 함께
82
+ 확인하세요.
@@ -0,0 +1,81 @@
1
+ # Install and get your first judgment
2
+
3
+ **English** · [한국어](./first-judgment.ko.md)
4
+
5
+ Use an empty example project to install Polydeukes and check a protected write without changing
6
+ the protected file. You need Node.js 24 or later, pnpm, and git. Claude Code is needed to observe
7
+ live session calls, but not to run the hook probe below.
8
+
9
+ <a id="claude-code"></a>
10
+
11
+ ## Install Claude Code integration and check a write
12
+
13
+ Run these commands in your own terminal, outside an existing protected project:
14
+
15
+ ```sh
16
+ mkdir pdks-example
17
+ cd pdks-example
18
+ git init
19
+ printf '{"name":"pdks-example","private":true}\n' > package.json
20
+ pnpm add -D polydeukes # a project dependency, not a one-off npx run
21
+ pnpm exec pdks init claude-code
22
+ ```
23
+
24
+ The installer reports `created` or `skipped` for each artifact. It creates a starter config,
25
+ the hook delegator, the Claude Code registration, a documentation discovery file, the
26
+ `discipline-draft` skill, and a telemetry ignore entry. Existing user files are preserved;
27
+ settings are merged rather than replaced.
28
+
29
+ Now send the generated hook an observation of a proposed write to its settings file:
30
+
31
+ ```sh
32
+ printf '%s\n' '{"tool_name":"Write","tool_input":{"file_path":".claude/settings.json","content":"{}"}}' \
33
+ | node .claude/hooks/covenant-pretooluse.mjs
34
+ printf 'exit=%s\n' "$?"
35
+ tail -n 5 .polydeukes/roi.log
36
+ ```
37
+
38
+ Expect `exit=2`, a diagnostic naming the protected path on stderr, and a `blocked` row in the
39
+ log. This command only asks for a judgment. It does **not** perform the proposed write, so the
40
+ settings file stays unchanged and there is no destructive edit to undo.
41
+
42
+ Repeat with a path outside the protection list:
43
+
44
+ ```sh
45
+ printf '%s\n' '{"tool_name":"Write","tool_input":{"file_path":"example.txt","content":"hello"}}' \
46
+ | node .claude/hooks/covenant-pretooluse.mjs
47
+ printf 'exit=%s\n' "$?"
48
+ tail -n 5 .polydeukes/roi.log
49
+ ```
50
+
51
+ Expect `exit=0` and a `passed` row for this starter configuration. Again, no file is written.
52
+ You have checked both a blocked and an allowed observation using the installed judge.
53
+
54
+ Open Claude Code in this project to use the same hook on actual tool calls. Ask it to create
55
+ an ordinary text file, then confirm that a new row appears in `.polydeukes/roi.log`. The direct
56
+ probe above does not prove that a particular host session loaded its hook registration.
57
+
58
+ **Before the first config edit:** the loader automatically protects the discovered config
59
+ file, even though it is not written in `protectedPaths`. For an intentional session edit, read
60
+ `witness.token` and type that token yourself on the first line of a message, with nothing else
61
+ on that line. The starter token is `pdks witness` and its window is ten minutes. The valve
62
+ supplies permission only after a blocking verdict; an agent cannot supply the human message
63
+ for you. Alternatively, make the deliberate configuration edit from your own terminal.
64
+
65
+ If the probe fails because the package or configuration cannot load, repair the named file or
66
+ reinstall from your own terminal. A witness cannot repair a failure that occurs before the
67
+ valve is assembled. See [configuration errors](../troubleshooting.md#invalid-config) and
68
+ [missing judge](../troubleshooting.md#judge-cannot-be-loaded).
69
+
70
+ <a id="next-step"></a>
71
+
72
+ ## Continue with a real project
73
+
74
+ - [Configure the project](../how-to/configure-project.md) to replace the placeholder language
75
+ and test command.
76
+ - [Connect the surfaces](../how-to/connect-surfaces.md) for Grok or a git pre-commit hook.
77
+ - [Write a discipline](../how-to/write-disciplines.md) and observe an advisory before choosing
78
+ whether it should block.
79
+
80
+ An exit code alone does not describe all observations. `advised` and `skipped` can accompany
81
+ exit 0. Read the diagnostic and the [verdict vocabulary](../troubleshooting.md#reading-verdict).
@@ -0,0 +1,25 @@
1
+ import type { DocsBundleDocument, DocsBundleSection, DocsIndex, LoadedDocsBundle } from './docs-types.ts';
2
+ /**
3
+ * Validate the source collection before replacing the output with bundled Markdown and metadata.
4
+ *
5
+ * @param spec - Source and non-overlapping output roots, with an optional catalog file path.
6
+ * @returns Metadata for bundled documents and sections; excluded documents are not copied.
7
+ * @throws If the roots overlap or the catalog, source files, or topic references fail validation.
8
+ */
9
+ export declare function buildDocs(spec: {
10
+ sourceRoot: string;
11
+ outputRoot: string;
12
+ catalogPath?: string;
13
+ }): {
14
+ documents: DocsBundleDocument[];
15
+ sections: DocsBundleSection[];
16
+ };
17
+ /**
18
+ * Load a bundle only after its stored index matches the catalog and bundled Markdown.
19
+ *
20
+ * @param outputRoot - Built documentation directory containing catalog.json and index.json.
21
+ * @returns Validated metadata and bundled documents with their original Markdown and sections.
22
+ * @throws If metadata or documents are missing, invalid, or inconsistent with the stored index.
23
+ */
24
+ export declare function loadDocsBundle(outputRoot: string): LoadedDocsBundle;
25
+ export type { DocsIndex };