polydeukes 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +2 -0
- package/README.md +2 -0
- package/dist/covenant/discipline.d.ts +6 -0
- package/dist/covenant/discipline.js +1 -1
- package/dist/covenant/dispatch.d.ts +10 -7
- package/dist/covenant/dispatch.js +21 -8
- package/dist/covenant/shell-mod.d.ts +15 -4
- package/dist/covenant/shell-mod.js +63 -8
- package/dist/covenant/transcript-mod.js +8 -5
- package/dist/covenant-check.d.ts +2 -2
- package/dist/covenant-check.js +113 -9
- package/dist/docs/README.ko.md +3 -2
- package/dist/docs/README.md +3 -2
- package/dist/docs/catalog.json +32 -0
- package/dist/docs/how-to/connect-surfaces.ko.md +45 -5
- package/dist/docs/how-to/connect-surfaces.md +49 -7
- package/dist/docs/how-to/write-disciplines.ko.md +3 -1
- package/dist/docs/how-to/write-disciplines.md +3 -1
- package/dist/docs/index.json +338 -190
- package/dist/docs/reference/cli/explain.ko.md +8 -8
- package/dist/docs/reference/cli/explain.md +10 -8
- package/dist/docs/reference/cli/init.ko.md +46 -4
- package/dist/docs/reference/cli/init.md +48 -5
- package/dist/docs/reference/configuration/index.ko.md +11 -5
- package/dist/docs/reference/configuration/index.md +10 -5
- package/dist/docs/reference/packages/adapter-claude-code.ko.md +5 -4
- package/dist/docs/reference/packages/adapter-claude-code.md +6 -4
- package/dist/docs/reference/packages/adapter-codex.ko.md +116 -0
- package/dist/docs/reference/packages/adapter-codex.md +118 -0
- package/dist/docs/reference/packages/adapter-grok.ko.md +6 -2
- package/dist/docs/reference/packages/adapter-grok.md +6 -2
- package/dist/docs/reference/packages/core.ko.md +1 -1
- package/dist/docs/reference/packages/core.md +1 -1
- package/dist/docs/reference/packages/polydeukes.ko.md +4 -3
- package/dist/docs/reference/packages/polydeukes.md +5 -4
- package/dist/docs/reference/packages/sdk-ts.ko.md +6 -3
- package/dist/docs/reference/packages/sdk-ts.md +6 -3
- package/dist/docs/troubleshooting.ko.md +39 -5
- package/dist/docs/troubleshooting.md +41 -5
- package/dist/docs/tutorials/first-judgment.ko.md +5 -3
- package/dist/docs/tutorials/first-judgment.md +5 -3
- package/dist/load-config.d.ts +24 -0
- package/dist/load-config.js +20 -2
- package/dist/scaffold-project.js +3 -1
- package/package.json +4 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# `@polydeukes/adapter-codex`
|
|
2
|
+
|
|
3
|
+
**English** · [한국어](adapter-codex.ko.md)
|
|
4
|
+
|
|
5
|
+
> **The Codex install unit** — lifecycle events become adapter-owned session evidence, and
|
|
6
|
+
> `PreToolUse` payloads become covenant input IR with one element per file the patch touches.
|
|
7
|
+
>
|
|
8
|
+
> Beta. Install it next to `polydeukes`, which it names as a `peerDependency`.
|
|
9
|
+
|
|
10
|
+
<a id="ownership"></a>
|
|
11
|
+
## What this package owns
|
|
12
|
+
|
|
13
|
+
The boundary where Codex's vocabulary is translated away. Agent and tool literals live *here*
|
|
14
|
+
by design, so that they never reach the core.
|
|
15
|
+
|
|
16
|
+
| Unit | What it does |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `pdks-codex` bin | One subcommand, `pdks-codex init`, which registers the session surface in a project |
|
|
19
|
+
| `runHook` | Records lifecycle evidence, or translates one `PreToolUse` payload into the input IR and spawns the judge |
|
|
20
|
+
| Session evidence | Stores timestamped human messages and completed tool calls under a SHA-256 session filename, then removes it at `SessionEnd` |
|
|
21
|
+
| Payload validation | Demands every key the host's generated schema marks required, in the one spelling that host sends |
|
|
22
|
+
| Patch parsing | Turns the raw patch text of an `apply_patch` call into one file change per file it touches |
|
|
23
|
+
| Path rebasing | Resolves a patch path against the call's working directory and carries it relative to the project root |
|
|
24
|
+
|
|
25
|
+
`runHook({ repoRoot })` is what the generated hook delegator imports. `UserPromptSubmit` and
|
|
26
|
+
`PostToolUse` append strict JSONL records under `.polydeukes/codex-sessions/`; `SessionEnd`
|
|
27
|
+
removes only that session's file. `PreToolUse` builds the IR with the `tools` roster and a
|
|
28
|
+
`session` sourced from those records, but no synthesized `actor` or `channels`, then spawns
|
|
29
|
+
`pdks covenant check --enforce block` in `repoRoot` and returns the child's exit code. The
|
|
30
|
+
judging happens in that child process; this package carries no judgment logic.
|
|
31
|
+
|
|
32
|
+
**This package writes no telemetry rows.** A failure before the spawn is sent to `pdks` on
|
|
33
|
+
stdin, so the row that call earns is written by the one writer.
|
|
34
|
+
|
|
35
|
+
<a id="apply-patch"></a>
|
|
36
|
+
## Why this adapter parses text where its siblings read arguments
|
|
37
|
+
|
|
38
|
+
Codex normalises every file edit that reaches the hook into a single tool name, `apply_patch`,
|
|
39
|
+
and puts the patch itself in `tool_input.command` — the same field a shell call uses for its
|
|
40
|
+
command line. There is no path argument to read. `Edit` and `Write` exist as matcher aliases
|
|
41
|
+
you may write in `.codex/hooks.json`, but the payload always names the tool `apply_patch`, so
|
|
42
|
+
a roster or a branch keyed on the aliases matches nothing that ever arrives.
|
|
43
|
+
|
|
44
|
+
One patch can create, update, delete and rename files in one call. The adapter carries each as
|
|
45
|
+
its own element of one IR, on one spawn: every file is judged, and any one of them blocking
|
|
46
|
+
blocks the whole call. A rename contributes two elements, because it changes the path it
|
|
47
|
+
leaves as well as the one it takes.
|
|
48
|
+
|
|
49
|
+
<a id="consumer"></a>
|
|
50
|
+
## Where the consumer touches it
|
|
51
|
+
|
|
52
|
+
Two lines install the Codex session surface, run from the project root:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-codex
|
|
56
|
+
npx pdks-codex init
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`pdks-codex init` resolves `polydeukes` from the project, spawns `pdks init` for the
|
|
60
|
+
agent-neutral scaffold, then writes the delegator and merges its entries for `PreToolUse`,
|
|
61
|
+
`UserPromptSubmit`, `PostToolUse`, and `SessionEnd` into
|
|
62
|
+
`.codex/hooks.json` non-destructively — other events, other matchers and keys it does not know
|
|
63
|
+
are left alone. A re-run reports each existing artifact as skipped and overwrites nothing. The
|
|
64
|
+
full artifact list is in [`pdks init`](../cli/init.md#init-codex).
|
|
65
|
+
|
|
66
|
+
**Writing the registration is not the end of the install.** Codex records trust against the
|
|
67
|
+
hash of a hook's definition, so the generated hook is listed for review and skipped until you
|
|
68
|
+
approve it with `/hooks`. This is why `init` writes a byte-identical command string on every
|
|
69
|
+
run: a changed one needs approving again, and until someone does, nothing is judged.
|
|
70
|
+
|
|
71
|
+
Installing this adapter beside `@polydeukes/adapter-claude-code` or
|
|
72
|
+
`@polydeukes/adapter-grok` in one project can run the judge twice per call.
|
|
73
|
+
|
|
74
|
+
- **The generated hook** imports `runHook` from this package. Upgrading the package upgrades
|
|
75
|
+
what runs; the hook file itself never changes.
|
|
76
|
+
|
|
77
|
+
No configuration namespace of its own. The scaffold `pdks init` writes protects `.codex/hooks`
|
|
78
|
+
by default, so the registration this installer creates is covered by the config it creates.
|
|
79
|
+
|
|
80
|
+
<a id="limits"></a>
|
|
81
|
+
## Declared limits
|
|
82
|
+
|
|
83
|
+
The first four are the host's own, and no adapter can narrow them. The first is measured
|
|
84
|
+
rather than documented; the next three are stated in the host's hook documentation.
|
|
85
|
+
|
|
86
|
+
- **A Code Mode `exec` dispatch is not observed.** In codex-cli 0.154 the host does not emit
|
|
87
|
+
`PreToolUse` for a Code Mode `exec` call, nor for the `tools.apply_patch` and
|
|
88
|
+
`tools.exec_command` calls nested in its JavaScript
|
|
89
|
+
([openai/codex#23411](https://github.com/openai/codex/issues/23411),
|
|
90
|
+
[#38850](https://github.com/openai/codex/issues/38850)). A hook that `/hooks` lists as
|
|
91
|
+
Active still sees nothing on that surface, and a protected path edited there leaves no
|
|
92
|
+
telemetry row. `pdks-codex init` prints this as a `note:` line.
|
|
93
|
+
- **The roster, not the matcher, decides what is judged.** The adapter translates
|
|
94
|
+
`apply_patch` and `Bash`; every other name — a Code Mode name, an MCP tool, `write_stdin` —
|
|
95
|
+
is refused with exit 2 and a `blocked` runner row before the judge runs. Widening the
|
|
96
|
+
matcher in `.codex/hooks.json` to such a name blocks every call under it rather than
|
|
97
|
+
judging it, and the edit changes the trust hash, so the hook is skipped until `/hooks`
|
|
98
|
+
approves it again.
|
|
99
|
+
- **`write_stdin` is not judged again.** It delivers input to a unified-exec session that
|
|
100
|
+
already passed `PreToolUse`. A shell left open for input is judged once, at the call that
|
|
101
|
+
opened it.
|
|
102
|
+
- **Hosted tools do not take this path.** Web search and its kind do not run through the local
|
|
103
|
+
function-tool hooks, so they reach no covenant.
|
|
104
|
+
- **The host calls its tool hooks a guardrail rather than a complete enforcement boundary.**
|
|
105
|
+
Some specialized tool paths can opt out of the default hook path.
|
|
106
|
+
- **The unstable transcript is not a channel.** The payload names a transcript path, but the
|
|
107
|
+
host documents that format as unstable, so no judgment reads it. The adapter instead builds
|
|
108
|
+
`session` from `UserPromptSubmit` and `PostToolUse`. A fresh configured token, alone on the
|
|
109
|
+
first line of a human message, can release the retried protected call. If no human evidence
|
|
110
|
+
was recorded, or evidence storage failed, the recovery message directs the repair to the user
|
|
111
|
+
terminal. `actor`, `channels`, and tool success are never synthesized.
|
|
112
|
+
- **A patch resolving outside the project is refused rather than judged.** Such a path has no
|
|
113
|
+
project-relative form, and an element carrying one would land in no scope — judged over
|
|
114
|
+
nothing, and passed.
|
|
115
|
+
- **An unresolvable `polydeukes` leaves no row.** When the umbrella cannot be resolved from the
|
|
116
|
+
project there is no process to spawn and no log path to write to, so the hook exits `2` with
|
|
117
|
+
one line on stderr and the telemetry log gains nothing. Every other pre-spawn failure does
|
|
118
|
+
reach `pdks` and does leave a row.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> 판정기가 읽는 파일 변경 증거가 함께 실립니다. 세션 표면을 프로젝트에 설치하는 것도 이
|
|
7
7
|
> 패키지가 합니다.
|
|
8
8
|
>
|
|
9
|
-
>
|
|
9
|
+
> 베타입니다. `polydeukes`와 함께 설치하며, `polydeukes`는 이 패키지의 `peerDependency`입니다.
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
12
12
|
## 담당하는 기능
|
|
@@ -41,7 +41,7 @@ Grok의 입력을 공통 형식으로 번역합니다. 에이전트와 도구의
|
|
|
41
41
|
프로젝트 루트에서 두 줄이면 Grok 세션 표면이 설치됩니다.
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
npm install --save-dev polydeukes @polydeukes/adapter-grok
|
|
44
|
+
npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-grok
|
|
45
45
|
npx pdks-grok init
|
|
46
46
|
```
|
|
47
47
|
|
|
@@ -75,3 +75,7 @@ npx pdks-grok init
|
|
|
75
75
|
스폰할 프로세스도, 기록할 로그 경로도 없습니다. 훅은 stderr에 한 줄을 남기고 종료 코드
|
|
76
76
|
`2`를 내며 텔레메트리 로그에는 아무것도 추가되지 않습니다. 스폰 전 실패 가운데 이 경우만
|
|
77
77
|
그렇고, 나머지는 모두 `pdks`에 도달해 행을 남깁니다.
|
|
78
|
+
- **다른 호스트는 각자의 어댑터로 설치합니다.** Claude Code는
|
|
79
|
+
`@polydeukes/adapter-claude-code`로, Codex는 `@polydeukes/adapter-codex`로 설치합니다.
|
|
80
|
+
각 패키지가 자기 위임자와 명부를 씁니다. 한 프로젝트에 세션 어댑터를 둘 이상 설치하면
|
|
81
|
+
호출마다 판정기가 여러 번 실행될 수 있습니다.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> file-change evidence the judge reads, and the package installs the session surface into a
|
|
7
7
|
> project.
|
|
8
8
|
>
|
|
9
|
-
>
|
|
9
|
+
> Beta. Install it next to `polydeukes`, which it names as a `peerDependency`.
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
12
12
|
## What this package owns
|
|
@@ -42,7 +42,7 @@ file; `run_terminal_command` carries a shell line.
|
|
|
42
42
|
Two lines install the Grok session surface, run from the project root:
|
|
43
43
|
|
|
44
44
|
```sh
|
|
45
|
-
npm install --save-dev polydeukes @polydeukes/adapter-grok
|
|
45
|
+
npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-grok
|
|
46
46
|
npx pdks-grok init
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -77,3 +77,7 @@ No configuration namespace of its own.
|
|
|
77
77
|
project there is no process to spawn and no log path to write to, so the hook exits `2` with
|
|
78
78
|
one line on stderr and the telemetry log gains nothing. Every other pre-spawn failure does
|
|
79
79
|
reach `pdks` and does leave a row.
|
|
80
|
+
- **Other hosts install through their own adapters.** Claude Code through
|
|
81
|
+
`@polydeukes/adapter-claude-code`, Codex through `@polydeukes/adapter-codex`. Each package
|
|
82
|
+
writes its own delegator and roster. Installing more than one session adapter in a project
|
|
83
|
+
can run the judge more than once per call.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **모든 약속(covenant)이 말하는 프로토콜**입니다. 입력 IR과 판정 결과 형태, 설정 스키마,
|
|
6
6
|
> 텔레메트리 수집기가 여기 있습니다.
|
|
7
7
|
>
|
|
8
|
-
>
|
|
8
|
+
> 베타입니다. 일반 사용자는 이 패키지를 따로 설치하거나 불러올 필요가 없습니다. 통합 패키지의 의존성으로 설치되며, 사용자 진입점은
|
|
9
9
|
> [`polydeukes`](polydeukes.ko.md)입니다.
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **The protocol every covenant speaks** — the input IR, the verdict shape, the config
|
|
6
6
|
> schema, and the telemetry collector.
|
|
7
7
|
>
|
|
8
|
-
>
|
|
8
|
+
> Beta. A transitive dependency of the umbrella: you do not install it and you do not import
|
|
9
9
|
> it. The consumer entry point is [`polydeukes`](polydeukes.md).
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
@@ -31,7 +31,8 @@ import하지 않고 peer 의존으로 선언합니다.
|
|
|
31
31
|
| `pdks docs search <query>` | 동봉된 문서를 검색 |
|
|
32
32
|
| `pdks docs show <document-id>` | 동봉된 문서 또는 절을 표시 |
|
|
33
33
|
|
|
34
|
-
세션 표면 설치기는 어댑터에 있습니다. `pdks-claude-code init
|
|
34
|
+
세션 표면 설치기는 어댑터에 있습니다. `pdks-claude-code init`, `pdks-grok init`,
|
|
35
|
+
`pdks-codex init`입니다.
|
|
35
36
|
|
|
36
37
|
<a id="surface-from-input-mode"></a>
|
|
37
38
|
### 입력 방식이 곧 표면이다
|
|
@@ -112,7 +113,7 @@ IR의 `session` 키는 다른 것을 말합니다. 호스트가 그 호출에
|
|
|
112
113
|
| 등록 | 축 | 판정 대상 |
|
|
113
114
|
|---|---|---|
|
|
114
115
|
| self-mod | 도구 | 편집 도구를 통한 보호 경로 변형입니다. 호출의 증명된 변형 대상만 대조하므로, 편집 **내용** 안의 보호 경로는 언급이고 통과합니다 |
|
|
115
|
-
| shell-mod | 셸 | 같은 것을 명령줄로 합니다. 보호 경로를 언급하는 명령은 첫
|
|
116
|
+
| shell-mod | 셸 | 같은 것을 명령줄로 합니다. 보호 경로를 언급하는 명령은 읽기 전용임이 증명될 때만 통과합니다. 허용 목록의 첫 낱말이나, `git ls-files`·변형·실행·실행 확인·파일 출력 동작이 없는 `find`·숫자 범위 `sed -n …p`처럼 지원하는 인자 판정형 읽기 명령이 이를 증명합니다 |
|
|
116
117
|
| transcript-mod | 대화 기록 | 라이브 세션 대화 기록에 대한 쓰기입니다. 전체 경로 **등가**로 판정하고 보호 조상으로는 결코 보지 않습니다 |
|
|
117
118
|
|
|
118
119
|
**낱말 여섯**이 텔레메트리 계약입니다. 판정 결과 다섯과 관측 하나입니다. `.polydeukes/roi.log`의
|
|
@@ -173,7 +174,7 @@ fail-open입니다.
|
|
|
173
174
|
- **완전 봉쇄는 목표가 아닙니다.** 여기에 차단 목록은 없습니다. 우회 철자를 열거하는 일은
|
|
174
175
|
언제나 한 걸음 뒤지므로 논리를 뒤집었습니다. 보호 경로를 언급하면 안전이 증명되지 않는
|
|
175
176
|
한 차단합니다. 간접 경로 계산 같은 잔여 벡터는 차단 대상이 아니라 텔레메트리 대상입니다.
|
|
176
|
-
마찰 밸브 둘, 곧 읽기 전용
|
|
177
|
+
마찰 밸브 둘, 곧 읽기 전용 증명과 TTL 증인은 둘 다 측정 가능한 흔적을 남깁니다.
|
|
177
178
|
- **밸브는 판정 뒤에 확인합니다.** 실제로 차단한 판정만 증언으로 열 수 있고, 문장 중간의 토큰
|
|
178
179
|
언급은 밸브를 무장시키지 않으며, AI는 자기 밸브를 결코 스스로 열 수 없습니다.
|
|
179
180
|
|
|
@@ -31,7 +31,8 @@ takes it as a peer dependency rather than importing it.
|
|
|
31
31
|
| `pdks docs search <query>` | Search the bundled docs |
|
|
32
32
|
| `pdks docs show <document-id>` | Show one bundled document or section |
|
|
33
33
|
|
|
34
|
-
Session-surface installers live on the adapters: `pdks-claude-code init
|
|
34
|
+
Session-surface installers live on the adapters: `pdks-claude-code init`, `pdks-grok init`, and
|
|
35
|
+
`pdks-codex init`.
|
|
35
36
|
|
|
36
37
|
<a id="surface-from-input-mode"></a>
|
|
37
38
|
### The input mode is the surface
|
|
@@ -113,7 +114,7 @@ vocabulary below applies to them unchanged.
|
|
|
113
114
|
| Registration | Axis | Judges |
|
|
114
115
|
|---|---|---|
|
|
115
116
|
| self-mod | Tool | Mutations to protected paths through editing tools. Only the call's proven mutation target is compared — a protected path inside an edit's *content* is a mention and passes |
|
|
116
|
-
| shell-mod | Shell | The same, through a command line. A command mentioning a protected path passes only
|
|
117
|
+
| shell-mod | Shell | The same, through a command line. A command mentioning a protected path passes only with read-only proof: an allowlisted leading word, or a supported argument-sensitive reader such as `git ls-files`, `find` without mutation, execution, prompting, or file-output actions, or numeric-range `sed -n …p` |
|
|
117
118
|
| transcript-mod | Transcript | Writes to the live session transcript, judged by whole-path **equality** — never as a protected ancestor |
|
|
118
119
|
|
|
119
120
|
**Six words** are the telemetry contract — five verdicts and one observation. A row in
|
|
@@ -178,8 +179,8 @@ No import. The umbrella assembles the module for both surfaces.
|
|
|
178
179
|
- **Complete containment is a non-goal.** There are no blocklists here — enumerating bypass
|
|
179
180
|
spellings is always one step behind, so the logic is inverted: a mention of a protected
|
|
180
181
|
path blocks unless proven safe. Residual vectors such as indirect path computation are
|
|
181
|
-
telemetry targets, not block targets. The two friction valves —
|
|
182
|
-
|
|
182
|
+
telemetry targets, not block targets. The two friction valves — read-only proof and the TTL
|
|
183
|
+
witness — both leave a measurable trace.
|
|
183
184
|
- **The valve stands after the verdict.** Only a judgment that actually blocked can be
|
|
184
185
|
witnessed open, a mid-sentence mention of the token does not arm it, and an AI can never
|
|
185
186
|
open the valve for itself.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **TypeScript에서 판정기로 가는 동사 하나**입니다. 약속(covenant) 입력 IR을
|
|
6
6
|
> `pdks covenant check`에 건네고 판정 결과를 값으로 돌려받습니다.
|
|
7
7
|
>
|
|
8
|
-
>
|
|
8
|
+
> 베타입니다. `polydeukes` · `@polydeukes/core`와 함께 설치하며, 둘 다 이 패키지의
|
|
9
9
|
> `peerDependencies`입니다.
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
@@ -37,6 +37,9 @@ pnpm add @polydeukes/sdk-ts polydeukes @polydeukes/core
|
|
|
37
37
|
<a id="verb"></a>
|
|
38
38
|
## 동사
|
|
39
39
|
|
|
40
|
+
이 패키지는 ESM 전용입니다(`"type": "module"`, `import` 조건만 있고 `require`는 없음).
|
|
41
|
+
호출하는 파일이 `.mjs`이거나 그 `package.json`이 `"type": "module"`을 선언해야 합니다.
|
|
42
|
+
|
|
40
43
|
```ts
|
|
41
44
|
import { checkCovenant } from '@polydeukes/sdk-ts';
|
|
42
45
|
|
|
@@ -92,8 +95,8 @@ type CheckCovenantSpawnSpec = { command: string; args: string[]; cwd: string; st
|
|
|
92
95
|
**`enforce`의 기본값은 `block`입니다.** 이것은 표면의 강제 수준이지 항목의 것이 아닙니다.
|
|
93
96
|
보호 경로와 `enforce: block`을 단 항목이 호출을 멈추고, 나머지 위반은 종료 코드 0에
|
|
94
97
|
`advised`로 기록됩니다. 항목 자신의 강제 수준은 다른 표면에서와 같이 느슨한 쪽이 이기도록
|
|
95
|
-
조합됩니다. `@polydeukes/adapter-claude-code
|
|
96
|
-
판정기를 스폰합니다.
|
|
98
|
+
조합됩니다. `@polydeukes/adapter-claude-code`, `@polydeukes/adapter-grok`,
|
|
99
|
+
`@polydeukes/adapter-codex`도 같은 수준으로 판정기를 스폰합니다.
|
|
97
100
|
|
|
98
101
|
기본 스폰은 파일 서술자를 하나도 상속하지 않습니다. 호출자가 자기 서술자를 갖지 않을 수 있고,
|
|
99
102
|
상속한 stdout이 닫혀 있으면 자식이 답하기 전에 EPIPE로 죽기 때문입니다. stderr는 모아서
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **One verb from TypeScript to the judge** — hand a covenant input IR to
|
|
6
6
|
> `pdks covenant check` and read the verdict back as a value.
|
|
7
7
|
>
|
|
8
|
-
>
|
|
8
|
+
> Beta. Install it next to `polydeukes` and `@polydeukes/core`, which it names as
|
|
9
9
|
> `peerDependencies`.
|
|
10
10
|
|
|
11
11
|
<a id="ownership"></a>
|
|
@@ -38,6 +38,9 @@ core supplies the `CovenantInput` type the caller fills in.
|
|
|
38
38
|
<a id="verb"></a>
|
|
39
39
|
## The verb
|
|
40
40
|
|
|
41
|
+
The package is ESM only (`"type": "module"`, an `import` condition and no `require`): the calling
|
|
42
|
+
file is a `.mjs`, or its `package.json` declares `"type": "module"`.
|
|
43
|
+
|
|
41
44
|
```ts
|
|
42
45
|
import { checkCovenant } from '@polydeukes/sdk-ts';
|
|
43
46
|
|
|
@@ -93,8 +96,8 @@ type CheckCovenantSpawnSpec = { command: string; args: string[]; cwd: string; st
|
|
|
93
96
|
**`enforce` defaults to `block`.** That is the surface's level, not an entry's: protected paths
|
|
94
97
|
and entries carrying `enforce: block` stop the call, and every other break is recorded
|
|
95
98
|
`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
|
|
97
|
-
the same level.
|
|
99
|
+
surface. `@polydeukes/adapter-claude-code`, `@polydeukes/adapter-grok`, and
|
|
100
|
+
`@polydeukes/adapter-codex` spawn the judge at the same level.
|
|
98
101
|
|
|
99
102
|
The default spawn inherits no file descriptor. A caller may hold none of its own, and an
|
|
100
103
|
inherited stdout that is closed would kill the child with EPIPE before it answered. stderr is
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
프로젝트 루트 바로 아래에 `polydeukes.config.yaml`, `polydeukes.config.yml`,
|
|
13
13
|
`polydeukes.config.json` 중 하나도 없으면 설정이 필요한 명령은 종료 코드 2를 반환합니다.
|
|
14
14
|
Git에서 원래 파일을 복원하세요. 새 프로젝트라면 `pdks init`, `pdks-claude-code init`,
|
|
15
|
-
`pdks-grok init`로 만들 수 있습니다. 이후 `pdks explain`을 실행합니다.
|
|
16
|
-
기본 정책으로 대신 실행하지는 않습니다.
|
|
15
|
+
`pdks-grok init`, `pdks-codex init`로 만들 수 있습니다. 이후 `pdks explain`을 실행합니다.
|
|
16
|
+
설정이 없다고 기본 정책으로 대신 실행하지는 않습니다.
|
|
17
17
|
|
|
18
18
|
<a id="multiple-config"></a>
|
|
19
19
|
## 설정 파일이 여러 개일 때
|
|
@@ -34,6 +34,16 @@ Git에서 원래 파일을 복원하세요. 새 프로젝트라면 `pdks init`,
|
|
|
34
34
|
남겨 두었습니다. 아무도 구현하지 않은 네임스페이스도 설정으로 읽히지만 읽는 쪽이 없습니다.
|
|
35
35
|
수정한 뒤 `pdks explain`에서 실제 등록 내용을 확인하세요.
|
|
36
36
|
|
|
37
|
+
세션 안에서는 수정 자체가 막히지 않습니다. 설정이 로드되지 않는 동안 모든 호출은 차단되지만
|
|
38
|
+
하나는 예외입니다. 대상이 설정 파일 하나뿐이고, 시작 텍스트가 디스크에 있는 파일 그대로이며,
|
|
39
|
+
그 결과가 로드되는 Edit 또는 Write는 종료 코드 0으로 통과하며, `covenant-check` 라벨의
|
|
40
|
+
`advised` 행 하나를 고쳐진 설정 자신의 `telemetry.logPath`에 남기고 stderr에 고친 오류를
|
|
41
|
+
알립니다. 이 통과는 `--enforce` 기본 자세를 읽지 않습니다. 세션 훅은 항상 `--enforce block`으로
|
|
42
|
+
실행되므로, 그 아래에서 차단되는 수정은 어디에서도 실행되지 못하기 때문입니다. 결과가 여전히
|
|
43
|
+
로드되지 않는 수정은 다른 호출처럼 차단되고, 설정 파일과 다른 파일을 함께 건드리는 호출이나
|
|
44
|
+
디스크의 바이트에서 시작하지 않는 증거를 실은 호출도 차단됩니다. 변경 집합 표면에는 이런 경로가
|
|
45
|
+
없습니다. 설정을 고치는 커밋은 오류를 볼 수 있는 터미널에서 사람이 만드는 커밋이기 때문입니다.
|
|
46
|
+
|
|
37
47
|
<a id="grok-witness"></a>
|
|
38
48
|
## Grok 증인
|
|
39
49
|
|
|
@@ -48,6 +58,25 @@ Git에서 원래 파일을 복원하세요. 새 프로젝트라면 `pdks init`,
|
|
|
48
58
|
|
|
49
59
|
커밋 증인은 해당 스테이징 검사만 허용합니다. 차단된 Grok 도구 호출까지 허용하지 않습니다.
|
|
50
60
|
|
|
61
|
+
<a id="codex-witness"></a>
|
|
62
|
+
## Codex 증인
|
|
63
|
+
|
|
64
|
+
여기서도 두 문제는 구별해야 하며, 첫 번째는 원인이 다릅니다.
|
|
65
|
+
|
|
66
|
+
- `pdks-codex init` 실행 뒤 훅 신뢰는 훅 정의의 해시에 묶입니다. `.codex/hooks.json`이
|
|
67
|
+
바뀌면 `/hooks`에서 승인하기 전까지 신뢰하지 않으므로, 설치기가 성공해도 실행되는 훅이
|
|
68
|
+
없을 수 있습니다. 실제 도구를 호출하고 텔레메트리를 확인하세요.
|
|
69
|
+
- Codex는 대화 기록 경로를 알려 주지만 그 형식을 안정된 것으로 문서화하지 않으므로 어떤
|
|
70
|
+
판정도 읽지 않습니다. 대신 어댑터가 `UserPromptSubmit`과 `PostToolUse`를 자기 세션 증거
|
|
71
|
+
파일에 기록하고 `SessionEnd`에서 지웁니다. IR은 이 `session`을 싣되 `actor`를 합성하지
|
|
72
|
+
않습니다.
|
|
73
|
+
- 의도한 차단 뒤에는 설정된 증인 토큰을 첫 줄에 단독으로 보내고 다시 시도합니다. stderr가
|
|
74
|
+
`UserPromptSubmit` 증거가 없다고 알리면 생명주기 항목 넷이 모두 승인됐는지 확인합니다.
|
|
75
|
+
그래도 증거가 없다면 토큰을 반복해도 관측되지 않은 호출을 풀 수 없으므로 본인의 터미널에서
|
|
76
|
+
작업합니다.
|
|
77
|
+
|
|
78
|
+
커밋 증인은 스테이징 검사만 허용하며 Codex 세션 증인을 대신하지 않습니다.
|
|
79
|
+
|
|
51
80
|
<a id="config-fault"></a>
|
|
52
81
|
## 선언을 판정으로 구성하지 못할 때
|
|
53
82
|
|
|
@@ -64,16 +93,21 @@ Git에서 원래 파일을 복원하세요. 새 프로젝트라면 `pdks init`,
|
|
|
64
93
|
판정기를 별도로 복사해 가지고 있지 않습니다. 복구 뒤 실제 호출로 다시 확인합니다.
|
|
65
94
|
텔레메트리를 불러오기 전에 실패했다면 기록이 전혀 남지 않을 수도 있습니다.
|
|
66
95
|
|
|
67
|
-
|
|
68
|
-
`covenant check failed closed:`를 붙입니다.
|
|
96
|
+
판정기 자신이 거부하는 실패(설정 없음 · 잘못된 설정 · 빌드되지 않은 판정기)는 두 표면 모두
|
|
97
|
+
`covenant check failed closed:`를 붙입니다. 훅이 `pdks covenant check`에 판정을 맡기고 그 메시지를
|
|
98
|
+
그대로 전달하기 때문입니다. 판정기를 스폰하기 *전에* 실패한 경우 — 어댑터가 `polydeukes`를
|
|
99
|
+
찾지 못하거나 자식이 판정 없이 종료한 경우 — 만 `covenant hook failed closed:`를 붙입니다.
|
|
100
|
+
실제로 보게 되는 두 형태는 다음과 같습니다.
|
|
69
101
|
|
|
70
102
|
```text
|
|
71
103
|
covenant hook failed closed: Cannot find package 'polydeukes' imported from …
|
|
72
104
|
covenant check failed closed: the covenant judges could not be loaded from … — run 'pnpm build' to rebuild them: Cannot find module './self-mod.js' …
|
|
105
|
+
covenant check failed closed: invalid config in polydeukes.config.yaml: … — fix polydeukes.config.yaml in one Edit or Write whose result loads; every other call stays blocked until it does
|
|
73
106
|
```
|
|
74
107
|
|
|
75
108
|
첫째는 설치된 패키지가 없는 경우이고, 둘째는 소스 체크아웃에서 판정기 빌드 산출물이 없거나
|
|
76
|
-
일부만 있는
|
|
109
|
+
일부만 있는 경우이며, 셋째는 세션 표면에서 설정이 로드되지 않는 경우로 그 줄이 설정을 고칠
|
|
110
|
+
호출 하나를 알려 줍니다.
|
|
77
111
|
|
|
78
112
|
<a id="reading-verdict"></a>
|
|
79
113
|
## 판정 결과 읽기
|
|
@@ -12,8 +12,8 @@ or the judging packages, provided its own installed documentation bundle is inta
|
|
|
12
12
|
Commands that need configuration exit 2 when none of `polydeukes.config.yaml`,
|
|
13
13
|
`polydeukes.config.yml`, or `polydeukes.config.json` exists directly at the project root.
|
|
14
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
|
|
16
|
-
default policy.
|
|
15
|
+
`pdks-grok init` / `pdks-codex init` for a new project. Then run `pdks explain`. No
|
|
16
|
+
configuration means no silent default policy.
|
|
17
17
|
|
|
18
18
|
<a id="multiple-config"></a>
|
|
19
19
|
## More than one config file
|
|
@@ -32,6 +32,18 @@ Typos such as `protectedPath:` or `adaptors:` are refused. Adapter namespace nam
|
|
|
32
32
|
open, however: a namespace nobody implements loads without being read by anything. After repair,
|
|
33
33
|
run `pdks explain` and check the assembled registrations.
|
|
34
34
|
|
|
35
|
+
Inside a session the repair itself is not locked out. While the config does not load, every
|
|
36
|
+
call fails closed except one: an Edit or Write whose only target is the config file, whose
|
|
37
|
+
starting text is the file as it is on disk, and whose result loads. That call passes with exit
|
|
38
|
+
0 and one `advised` row under the `covenant-check` label, written to the repaired config's own
|
|
39
|
+
`telemetry.logPath`, and the stderr line names the fault it repaired. The pass does not read
|
|
40
|
+
the `--enforce` posture: the session hook always runs with `--enforce block`, and a repair that
|
|
41
|
+
blocked under it would never run anywhere. A rewrite that still does not load is blocked like
|
|
42
|
+
any other call, and so is a call that touches the config together with another file, or one
|
|
43
|
+
whose evidence does not start from the bytes on disk. The change-set surface has no such path:
|
|
44
|
+
a commit that repairs the config is a human's commit, made from a terminal that can see the
|
|
45
|
+
error.
|
|
46
|
+
|
|
35
47
|
<a id="grok-witness"></a>
|
|
36
48
|
## Grok witness
|
|
37
49
|
|
|
@@ -45,6 +57,25 @@ A hook not yet loaded and an unavailable witness valve are different problems:
|
|
|
45
57
|
|
|
46
58
|
A commit witness authorizes its staged check only. It cannot release a blocked Grok tool call.
|
|
47
59
|
|
|
60
|
+
<a id="codex-witness"></a>
|
|
61
|
+
## Codex witness
|
|
62
|
+
|
|
63
|
+
The same two problems are distinct here, and the first has its own cause:
|
|
64
|
+
|
|
65
|
+
- After `pdks-codex init`, hook trust is bound to the hash of the hook definition. A changed
|
|
66
|
+
`.codex/hooks.json` is not trusted until you approve it through `/hooks`, so an installer that
|
|
67
|
+
succeeded can still leave no hook running. Verify an actual call and its telemetry.
|
|
68
|
+
- Codex names a transcript path but documents the format as unstable, so no judgment reads it.
|
|
69
|
+
The adapter records `UserPromptSubmit` and `PostToolUse` into its own session evidence file
|
|
70
|
+
and removes it at `SessionEnd`; the IR carries that `session` without synthesizing `actor`.
|
|
71
|
+
- After an intentional block, send the configured witness token alone on the first line and
|
|
72
|
+
retry. If stderr says no `UserPromptSubmit` evidence was recorded, confirm all four lifecycle
|
|
73
|
+
entries are approved. If evidence is still unavailable, perform the repair from your own
|
|
74
|
+
terminal; repeating the token cannot release an unobserved call.
|
|
75
|
+
|
|
76
|
+
A commit witness authorizes only its staged check; it does not substitute for the Codex session
|
|
77
|
+
witness.
|
|
78
|
+
|
|
48
79
|
<a id="config-fault"></a>
|
|
49
80
|
## Config-fault
|
|
50
81
|
|
|
@@ -61,16 +92,21 @@ workspace build from your own terminal. The generated hook delegates to the inst
|
|
|
61
92
|
it is not an independent copy of the judge. Verify another real call after repair. A failure
|
|
62
93
|
before telemetry can load may leave no row at all.
|
|
63
94
|
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
A failure the judge itself refuses — a missing or invalid config, an unbuilt judge — carries
|
|
96
|
+
`covenant check failed closed:` on both surfaces, because the hook delegates to
|
|
97
|
+
`pdks covenant check` and passes its message through. Only a failure *before* the judge could be
|
|
98
|
+
spawned — the adapter cannot find `polydeukes`, or the child exited without a verdict — carries
|
|
99
|
+
`covenant hook failed closed:`. The two shapes you will see:
|
|
66
100
|
|
|
67
101
|
```text
|
|
68
102
|
covenant hook failed closed: Cannot find package 'polydeukes' imported from …
|
|
69
103
|
covenant check failed closed: the covenant judges could not be loaded from … — run 'pnpm build' to rebuild them: Cannot find module './self-mod.js' …
|
|
104
|
+
covenant check failed closed: invalid config in polydeukes.config.yaml: … — fix polydeukes.config.yaml in one Edit or Write whose result loads; every other call stays blocked until it does
|
|
70
105
|
```
|
|
71
106
|
|
|
72
107
|
The first is the installed package missing; the second is a source checkout whose judge
|
|
73
|
-
build output is missing or partial
|
|
108
|
+
build output is missing or partial; the third is a config that does not load, on the session
|
|
109
|
+
surface, where the line names the one call that would repair it.
|
|
74
110
|
|
|
75
111
|
<a id="reading-verdict"></a>
|
|
76
112
|
## Reading a verdict
|
|
@@ -17,12 +17,13 @@ mkdir pdks-example
|
|
|
17
17
|
cd pdks-example
|
|
18
18
|
git init
|
|
19
19
|
printf '{"name":"pdks-example","private":true}\n' > package.json
|
|
20
|
-
pnpm add -D polydeukes @polydeukes/adapter-claude-code # 프로젝트 의존성. 일회성 npx 실행이 아님
|
|
20
|
+
pnpm add -D polydeukes @polydeukes/core @polydeukes/adapter-claude-code # 프로젝트 의존성. 일회성 npx 실행이 아님
|
|
21
21
|
pnpm exec pdks-claude-code init
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
설치기는 각 파일을 만들었으면 `created`, 이미 있어서 보존했으면 `skipped`로 보고합니다.
|
|
25
|
-
초기 설정, 훅 위임
|
|
25
|
+
초기 설정, 훅 위임 파일(`.claude/hooks/covenant-pretooluse.mjs`), Claude Code 등록 설정
|
|
26
|
+
(`.claude/settings.json`), 문서 조회 안내(`.claude/rules/polydeukes.md`), `discipline-draft` 스킬과
|
|
26
27
|
텔레메트리 제외 항목을 만듭니다. 기존 사용자 파일은 보존하고, 설정은 통째로 덮지 않고
|
|
27
28
|
병합합니다.
|
|
28
29
|
|
|
@@ -73,7 +74,8 @@ tail -n 5 .polydeukes/roi.log
|
|
|
73
74
|
|
|
74
75
|
- [프로젝트 설정](../how-to/configure-project.ko.md)에서 임시 언어 이름과 테스트 명령을
|
|
75
76
|
바꿉니다.
|
|
76
|
-
- Grok
|
|
77
|
+
- Grok, Codex, git pre-commit 훅은 [관측 표면 연결](../how-to/connect-surfaces.ko.md)을
|
|
78
|
+
참고합니다.
|
|
77
79
|
- [규율 작성](../how-to/write-disciplines.ko.md) 예제를 실행하고, 권고 결과를 확인한 뒤 차단
|
|
78
80
|
여부를 결정합니다.
|
|
79
81
|
|
|
@@ -17,12 +17,13 @@ mkdir pdks-example
|
|
|
17
17
|
cd pdks-example
|
|
18
18
|
git init
|
|
19
19
|
printf '{"name":"pdks-example","private":true}\n' > package.json
|
|
20
|
-
pnpm add -D polydeukes @polydeukes/adapter-claude-code # project dependencies, not a one-off npx run
|
|
20
|
+
pnpm add -D polydeukes @polydeukes/core @polydeukes/adapter-claude-code # project dependencies, not a one-off npx run
|
|
21
21
|
pnpm exec pdks-claude-code init
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
The installer reports `created` or `skipped` for each artifact. It creates a starter config,
|
|
25
|
-
the hook delegator, the Claude Code registration
|
|
25
|
+
the hook delegator (`.claude/hooks/covenant-pretooluse.mjs`), the Claude Code registration
|
|
26
|
+
(`.claude/settings.json`), a documentation discovery file (`.claude/rules/polydeukes.md`), the
|
|
26
27
|
`discipline-draft` skill, and a telemetry ignore entry. Existing user files are preserved;
|
|
27
28
|
settings are merged rather than replaced.
|
|
28
29
|
|
|
@@ -73,7 +74,8 @@ valve is assembled. See [configuration errors](../troubleshooting.md#invalid-con
|
|
|
73
74
|
|
|
74
75
|
- [Configure the project](../how-to/configure-project.md) to replace the placeholder language
|
|
75
76
|
and test command.
|
|
76
|
-
- [Connect the surfaces](../how-to/connect-surfaces.md) for Grok or a git pre-commit
|
|
77
|
+
- [Connect the surfaces](../how-to/connect-surfaces.md) for Grok, Codex, or a git pre-commit
|
|
78
|
+
hook.
|
|
77
79
|
- [Write a discipline](../how-to/write-disciplines.md) and observe an advisory before choosing
|
|
78
80
|
whether it should block.
|
|
79
81
|
|
package/dist/load-config.d.ts
CHANGED
|
@@ -20,6 +20,17 @@ export declare const CONFIG_FILENAMES: readonly ['polydeukes.config.yaml', 'poly
|
|
|
20
20
|
export type LoadConfigSpec = {
|
|
21
21
|
rootDir: string;
|
|
22
22
|
};
|
|
23
|
+
/** {@link discoverConfigPath} input — the directory the candidates are looked for in. */
|
|
24
|
+
export type DiscoverConfigPathSpec = {
|
|
25
|
+
rootDir: string;
|
|
26
|
+
};
|
|
27
|
+
/** {@link parseConfigSource} input — the config text and the path it was discovered at. */
|
|
28
|
+
export type ParseConfigSourceSpec = {
|
|
29
|
+
/** The config file's whole text. */
|
|
30
|
+
source: string;
|
|
31
|
+
/** rootDir-relative path the source came from — the self-protection entry and error context. */
|
|
32
|
+
configPath: string;
|
|
33
|
+
};
|
|
23
34
|
/** `LoadedConfig` — the loader's return value. */
|
|
24
35
|
export type LoadedConfig = {
|
|
25
36
|
/** defineConfig() resolution — protectedPaths already includes configPath */
|
|
@@ -43,3 +54,16 @@ export type LoadedConfig = {
|
|
|
43
54
|
* protection surface, guaranteed here so no assembler has to remember.
|
|
44
55
|
*/
|
|
45
56
|
export declare function loadConfig(spec: LoadConfigSpec): LoadedConfig;
|
|
57
|
+
/**
|
|
58
|
+
* The discovery half: the rootDir-relative filename of the one candidate present, or the
|
|
59
|
+
* throw that names the zero or the collision. Exported so a caller that has to know WHICH
|
|
60
|
+
* file failed to load — the runner's config-repair branch — asks the same question the
|
|
61
|
+
* loader does rather than a second spelling of it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function discoverConfigPath(spec: DiscoverConfigPathSpec): string;
|
|
64
|
+
/**
|
|
65
|
+
* The parse-and-validate half, over a text rather than a file: parse, `$schema` strip,
|
|
66
|
+
* `defineConfig`, self-protection attach. Exported so the runner can ask whether a text a
|
|
67
|
+
* call is about to write would load, without opening any file.
|
|
68
|
+
*/
|
|
69
|
+
export declare function parseConfigSource(spec: ParseConfigSourceSpec): LoadedConfig;
|
package/dist/load-config.js
CHANGED
|
@@ -39,6 +39,17 @@ export const CONFIG_FILENAMES = [
|
|
|
39
39
|
* protection surface, guaranteed here so no assembler has to remember.
|
|
40
40
|
*/
|
|
41
41
|
export function loadConfig(spec) {
|
|
42
|
+
const configPath = discoverConfigPath({ rootDir: spec.rootDir });
|
|
43
|
+
const source = readFileSync(join(spec.rootDir, configPath), 'utf-8');
|
|
44
|
+
return parseConfigSource({ source, configPath });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The discovery half: the rootDir-relative filename of the one candidate present, or the
|
|
48
|
+
* throw that names the zero or the collision. Exported so a caller that has to know WHICH
|
|
49
|
+
* file failed to load — the runner's config-repair branch — asks the same question the
|
|
50
|
+
* loader does rather than a second spelling of it.
|
|
51
|
+
*/
|
|
52
|
+
export function discoverConfigPath(spec) {
|
|
42
53
|
const { rootDir } = spec;
|
|
43
54
|
const found = CONFIG_FILENAMES.filter((name) => existsSync(join(rootDir, name)));
|
|
44
55
|
if (found.length === 0) {
|
|
@@ -47,8 +58,15 @@ export function loadConfig(spec) {
|
|
|
47
58
|
if (found.length > 1) {
|
|
48
59
|
throw new Error(`ambiguous Polydeukes config in ${rootDir} — found ${found.join(' and ')}; keep exactly one`);
|
|
49
60
|
}
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
return found[0];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The parse-and-validate half, over a text rather than a file: parse, `$schema` strip,
|
|
65
|
+
* `defineConfig`, self-protection attach. Exported so the runner can ask whether a text a
|
|
66
|
+
* call is about to write would load, without opening any file.
|
|
67
|
+
*/
|
|
68
|
+
export function parseConfigSource(spec) {
|
|
69
|
+
const { source, configPath } = spec;
|
|
52
70
|
// Default core schema — custom tags stay unresolved and surface as errors or
|
|
53
71
|
// warnings depending on version; both escalate to a throw (config-as-data:
|
|
54
72
|
// uncomputable, so it cannot lie).
|
package/dist/scaffold-project.js
CHANGED
|
@@ -50,7 +50,8 @@ languages:
|
|
|
50
50
|
# The protection list. A tool call whose proven target is one of these paths is blocked, and
|
|
51
51
|
# so is a shell command that mentions one without a read-only head.
|
|
52
52
|
#
|
|
53
|
-
# .claude/hooks, .claude/settings.json, .grok/hooks — the gate definitions
|
|
53
|
+
# .claude/hooks, .claude/settings.json, .grok/hooks, .codex/hooks — the gate definitions
|
|
54
|
+
# themselves.
|
|
54
55
|
# Editing them does not evade a judgment, it removes the judgment; the session surface
|
|
55
56
|
# is the only layer that can watch it happen.
|
|
56
57
|
#
|
|
@@ -62,6 +63,7 @@ protectedPaths:
|
|
|
62
63
|
- '.claude/hooks'
|
|
63
64
|
- '.claude/settings.json'
|
|
64
65
|
- '.grok/hooks'
|
|
66
|
+
- '.codex/hooks'
|
|
65
67
|
|
|
66
68
|
# The time-boxed witness — the human valve on a blocked verdict. A human types this token so
|
|
67
69
|
# it stands alone on a message's FIRST line, the window holds for ttlMinutes, then blocking
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydeukes",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A development discipline framework for building alongside an AI coding partner — deterministic covenants, a verifiable work ledger, local memory, and adversarial verification.
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "A development discipline framework for building alongside an AI coding partner — deterministic covenants, a verifiable work ledger, local memory, and adversarial verification. Beta.",
|
|
5
|
+
"author": "huskyhoochu <dfg1499@gmail.com>",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"harness",
|
|
7
8
|
"guard",
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
45
46
|
"yaml": "2.9.0",
|
|
46
|
-
"@polydeukes/core": "^0.
|
|
47
|
+
"@polydeukes/core": "^0.9.0"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@types/node": "^24.0.0",
|