polydeukes 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/README.ko.md +43 -18
- package/dist/docs/README.md +39 -17
- package/dist/docs/catalog.json +50 -162
- package/dist/docs/concepts/judgment.ko.md +2 -0
- package/dist/docs/concepts/judgment.md +2 -0
- package/dist/docs/how-to/write-disciplines.ko.md +68 -31
- package/dist/docs/how-to/write-disciplines.md +69 -32
- package/dist/docs/index.json +519 -173
- package/dist/docs/reference/configuration/index.ko.md +14 -20
- package/dist/docs/reference/configuration/index.md +16 -24
- package/dist/docs/reference/declaration-language/index.ko.md +280 -0
- package/dist/docs/reference/declaration-language/index.md +277 -0
- package/dist/docs/reference/packages/adapter-claude-code.ko.md +1 -1
- package/dist/docs/reference/packages/adapter-claude-code.md +1 -1
- package/dist/docs/reference/packages/adapter-codex.ko.md +2 -2
- package/dist/docs/reference/packages/adapter-codex.md +2 -2
- package/dist/docs/reference/packages/core.ko.md +2 -2
- package/dist/docs/reference/packages/core.md +2 -2
- package/dist/docs/reference/packages/sdk-ts.ko.md +15 -18
- package/dist/docs/reference/packages/sdk-ts.md +14 -17
- package/dist/docs/troubleshooting.ko.md +10 -6
- package/dist/docs/troubleshooting.md +10 -6
- package/package.json +2 -2
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Declaration language reference
|
|
2
|
+
|
|
3
|
+
**English** · [한국어](./index.ko.md)
|
|
4
|
+
|
|
5
|
+
Use this reference to write the `declare` block of a discipline. The tables list every supported
|
|
6
|
+
source, extraction step, combinator, relation, and mechanism. For installation and worked examples,
|
|
7
|
+
see [Write disciplines](../../how-to/write-disciplines.md). Project settings and enforcement are in
|
|
8
|
+
the [configuration reference](../configuration/index.md).
|
|
9
|
+
|
|
10
|
+
<a id="declaration-shape"></a>
|
|
11
|
+
## Declaration structure
|
|
12
|
+
|
|
13
|
+
A judged entry has `id`, `declare`, and optional `why` and `enforce` fields. Put it in the
|
|
14
|
+
[list that can observe its sources](../configuration/index.md#three-lists).
|
|
15
|
+
|
|
16
|
+
| Field inside `declare` | Required | Meaning |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `mechanism` | Yes | A name from the mechanism table below; it restricts the allowed axes and relations. |
|
|
19
|
+
| `scope` | No | Select observations using regular expressions over one source. |
|
|
20
|
+
| `sources` | No | Bind names to files or session evidence. |
|
|
21
|
+
| `supply` | No | Choose what happens when a source is absent. Unspecified sources use `error`. |
|
|
22
|
+
| `extract` | Yes | A map from extraction names to non-empty lists of steps. |
|
|
23
|
+
| `relate` | Yes | A non-empty list of comparisons and their diagnostic messages. |
|
|
24
|
+
| `witness` | No | Additional comparisons that can allow a violation through. |
|
|
25
|
+
|
|
26
|
+
The outer `id` names the discipline; do not repeat it as `discipline` inside `declare`.
|
|
27
|
+
Names and keys are case-sensitive. Unknown declaration keys are rejected.
|
|
28
|
+
|
|
29
|
+
This complete entry reports `.db` paths outside `data/`:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
disciplines:
|
|
33
|
+
- id: 'database-location'
|
|
34
|
+
why: 'Keep database files under data/.'
|
|
35
|
+
enforce: advise
|
|
36
|
+
declare:
|
|
37
|
+
mechanism: 'naming'
|
|
38
|
+
scope: { source: 'target.path', include: ['\.db$'] }
|
|
39
|
+
extract:
|
|
40
|
+
outside:
|
|
41
|
+
- { op: 'source', of: 'target.path' }
|
|
42
|
+
- { op: 'matches', re: '^(?!data/)' }
|
|
43
|
+
relate:
|
|
44
|
+
- id: 'location'
|
|
45
|
+
relation: { op: 'empty', of: 'outside' }
|
|
46
|
+
message: '{value} must be under data/'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
<a id="scope"></a>
|
|
50
|
+
## Scope
|
|
51
|
+
|
|
52
|
+
| Key | Meaning |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `source` | Required. One of `target.path`, `pre`, `post`, `command`, or a named `file` source. |
|
|
55
|
+
| `include` | Regex strings. At least one must match. Omitted or empty accepts any string. |
|
|
56
|
+
| `exclude` | Regex strings. Any match excludes the observation. Omitted or empty excludes nothing. |
|
|
57
|
+
| `excludeIgnoreCase` | Optional boolean, default `false`. Applies only to `exclude`. |
|
|
58
|
+
|
|
59
|
+
Without `scope`, every observation is eligible. With `scope`, an absent source does not match.
|
|
60
|
+
These patterns are regular expressions, not path globs. `include` is always case-sensitive.
|
|
61
|
+
|
|
62
|
+
<a id="fixed-sources"></a>
|
|
63
|
+
## Fixed sources
|
|
64
|
+
|
|
65
|
+
Each observation supplies the sources it can prove. File changes are evaluated separately, so
|
|
66
|
+
`target.path`, `pre`, and `post` refer to the current change.
|
|
67
|
+
|
|
68
|
+
| Source | Value | Availability |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `target.path` | Repository-relative path string | An observation with a file target. |
|
|
71
|
+
| `pre` | File text before the change | Modifications; deletions when the prior text is available. Absent on creation. |
|
|
72
|
+
| `post` | Proposed file text after the change | Creations and modifications. Absent on deletion. |
|
|
73
|
+
| `state` | Before/after pair `{ pre, post }` | Modifications. Its pipeline runs separately on each side. |
|
|
74
|
+
| `changes` | Array of paths in the observed change set | Read in `changeSetDisciplines`; use `items` to extract individual paths. |
|
|
75
|
+
| `command` | Shell command text | Session shell calls, including calls with no file target. Literal stdin data is excluded from this source. |
|
|
76
|
+
| `actor` | Object with optional `agentType` | A session host that proves the actor: `{}` for its main session. Absent when the host supplies no actor. |
|
|
77
|
+
|
|
78
|
+
An absent source differs from a present empty string or empty array. Use `supply` to handle absence.
|
|
79
|
+
`state` does not store workflow progress between calls. Only `unchanged` accepts its paired result.
|
|
80
|
+
The [command-source example](../configuration/index.md#disciplines) explains shell stdin handling.
|
|
81
|
+
|
|
82
|
+
<a id="source-kinds"></a>
|
|
83
|
+
## Additional source kinds
|
|
84
|
+
|
|
85
|
+
`sources` maps a new name to exactly one binding. A new name cannot replace a fixed source name.
|
|
86
|
+
|
|
87
|
+
| Kind | Binding example | Supplied value |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `file` | `en: { file: 'locales/en.json' }` | File text. Paths are repository-relative, with no leading `/` or `..` segment. |
|
|
90
|
+
| `sidecar` | `spawns: { sidecar: true }` | JSON text containing the host's spawn records. Parse with `json` before `agentType` or `items`. |
|
|
91
|
+
| `transcript` | `session: { transcript: true }` | Session snapshot with `observedAtMs`, `toolCalls`, and `userMessages`. |
|
|
92
|
+
|
|
93
|
+
Read a binding with `{ op: 'source', of: 'en' }`. A changed file uses its proposed `post` text;
|
|
94
|
+
other named files use the surface's observation of the project. `sidecar` and `transcript` require
|
|
95
|
+
`sessionDisciplines` and a host that supplies those channels. Their marker is the literal `true`.
|
|
96
|
+
|
|
97
|
+
<a id="supply-policies"></a>
|
|
98
|
+
## Supply policies
|
|
99
|
+
|
|
100
|
+
| Policy | On an absent source |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `error` | Default. The observation cannot be judged and is blocked, including at `advise`. |
|
|
103
|
+
| `pass` | Record `skipped` with reason `supply-pass`; do not judge this declaration. |
|
|
104
|
+
| `empty` | Continue with an empty item list. Valid for single sources, never `state`. |
|
|
105
|
+
|
|
106
|
+
Every `supply` key must name a fixed or bound source. For before/after comparisons that should skip
|
|
107
|
+
creations and deletions, use `supply: { state: 'pass' }`. For added-only content checks, use
|
|
108
|
+
`supply: { pre: 'empty', post: 'empty' }`. Invalid JSON is a supply error even with `pass` or
|
|
109
|
+
`empty`; those policies apply to absent sources.
|
|
110
|
+
|
|
111
|
+
<a id="items-and-pipelines"></a>
|
|
112
|
+
## Items and pipelines
|
|
113
|
+
|
|
114
|
+
An extraction produces ordered items shaped as `{ key, value }`. The key identifies an item for
|
|
115
|
+
combinators and key comparisons. The value is the data compared by value relations. Re-keying an
|
|
116
|
+
item does not change its value.
|
|
117
|
+
|
|
118
|
+
Each pipeline begins with `source` or a combinator. Combinators reference other extraction names
|
|
119
|
+
and can appear only first. References must exist and cannot form cycles. A combinator cannot
|
|
120
|
+
combine a paired extraction from `state`. Further steps transform the result in sequence.
|
|
121
|
+
|
|
122
|
+
<a id="extract-steps"></a>
|
|
123
|
+
## Extraction steps
|
|
124
|
+
|
|
125
|
+
The table lists all 17 unary steps. Example arguments show their exact keys; an unknown argument
|
|
126
|
+
causes a compilation error. Unless stated otherwise, steps preserve item order.
|
|
127
|
+
|
|
128
|
+
| Step | Arguments | Result |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `source` | `of: 'post'` (required) | Start from the named source as one item with key `'0'`. `state` starts a paired extraction. |
|
|
131
|
+
| `json` | None | Parse each string value as JSON, keeping its key. Invalid JSON fails supply. |
|
|
132
|
+
| `select` | `path: 'args.command'` (required) | Follow a dot path through objects. Drop missing paths. An array result becomes items keyed by position; a scalar keeps its key. |
|
|
133
|
+
| `items` | None | Expand each array by one level into items keyed by zero-based position. Drop non-arrays. |
|
|
134
|
+
| `keyBy` | `field: 'id'` (required) | Set the key to the string form of an object's field. Drop non-objects and absent, null, or object-valued fields. Keep the original value. |
|
|
135
|
+
| `keyByPattern` | `re: '^(.+)\.ts$'` (required), `i: true` (optional, default `false`) | Set the key to capture group 1 of the first regex match. Drop non-matches and unbound captures. Keep the original value. |
|
|
136
|
+
| `field` | `name: 'version'` (required) | Keep the key and replace the value with that object property. An absent property yields `undefined`; a non-object is dropped. |
|
|
137
|
+
| `filter` | `when: [{ field: 'succeeded', eq: true }]` (required) | Keep items satisfying every predicate. `when: []` keeps all items. See the predicate table below. |
|
|
138
|
+
| `flattenKeys` | None | List nested leaf paths, such as `home.title`, as both keys and values. Translation text is discarded. |
|
|
139
|
+
| `sort` | None | Stable ascending sort by value: numeric if all values are numbers, otherwise by string comparison. |
|
|
140
|
+
| `lines` | None | Split stringified values on newline, trim each line, and drop empty lines. Keys are original one-based line numbers. |
|
|
141
|
+
| `matches` | `re: '^test:'` (required), `i: true` (optional, default `false`) | Keep items whose stringified value matches the regex; preserve keys and values. |
|
|
142
|
+
| `toolUses` | `names: ['Bash']`, `subagentType: 'reviewer'` (both optional) | Extract calls from a session snapshot, keyed by observation ordinal. Supplied filters must both match. Does not require success automatically. |
|
|
143
|
+
| `userTexts` | `re: '^approved$'` (required), `i: true` (optional, default `false`) | Extract matching user messages, keyed by ordinal. Each value also receives the snapshot's `observedAtMs`. |
|
|
144
|
+
| `agentType` | `is: 'reviewer'` (required) | Keep matching parsed sidecar records, keyed by position. Accepts a record array or a single object. |
|
|
145
|
+
| `first` | None | Keep the first item and its key. An empty input stays empty. Does not sort. |
|
|
146
|
+
| `ageMs` | None | Add `ageMs = observedAtMs - timestampMs` to object values. Drop missing/non-numeric timestamps and future observations. |
|
|
147
|
+
|
|
148
|
+
`items` and array-valued `select` number each array separately. If several arrays are expanded,
|
|
149
|
+
their keys can collide; use `keyBy` when a later comparison needs an object's identifier.
|
|
150
|
+
`flattenKeys` descends through plain objects. An array is a leaf at its property's path, so array
|
|
151
|
+
indices are not enumerated. Empty objects produce no paths, including when nested.
|
|
152
|
+
|
|
153
|
+
Regex steps use JavaScript regular expressions. `i` is the supported flag; there is no `g` or `m`
|
|
154
|
+
argument. A regex over whole file text anchors `^` at the start of that text. Put `lines` first to
|
|
155
|
+
match each trimmed line. `keyByPattern` requires a capturing group, and uses only its first match.
|
|
156
|
+
|
|
157
|
+
<a id="filter-predicates"></a>
|
|
158
|
+
## Filter predicates
|
|
159
|
+
|
|
160
|
+
Each predicate contains `field` and exactly one operator. `field` names a direct object property,
|
|
161
|
+
not a dot path. Non-object values fail a predicate. All predicates in `when` must pass.
|
|
162
|
+
|
|
163
|
+
| Operator | Example | Condition |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `eq` | `{ field: 'succeeded', eq: true }` | Structural equality with the constant. |
|
|
166
|
+
| `ne` | `{ field: 'status', ne: 'draft' }` | Structural inequality with the constant. |
|
|
167
|
+
| `size` | `{ field: 'errors', size: 0 }` | The field is an array with exactly this many elements. |
|
|
168
|
+
| `notIn` | `{ field: 'status', notIn: ['draft', 'failed'] }` | The field value is unequal to every constant in the array. |
|
|
169
|
+
| `lte` | `{ field: 'ageMs', lte: 600000 }` | The field is a number less than or equal to the numeric bound. |
|
|
170
|
+
| `gte` | `{ field: 'count', gte: 1 }` | The field is a number greater than or equal to the numeric bound. |
|
|
171
|
+
|
|
172
|
+
`size`, `lte`, and `gte` take numbers; `notIn` takes an array. An absent property is `undefined`,
|
|
173
|
+
so it can satisfy `ne` or `notIn`. Neither operator establishes that the property exists.
|
|
174
|
+
|
|
175
|
+
<a id="combinators"></a>
|
|
176
|
+
## Combinators
|
|
177
|
+
|
|
178
|
+
The operands are two distinct extraction names. `onlyIn` and `intersect` compare **keys**;
|
|
179
|
+
`union` concatenates the lists. All three preserve item values and do not sort or deduplicate.
|
|
180
|
+
|
|
181
|
+
| Combinator | Syntax | Result |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `union` | `{ op: 'union', of: ['a', 'b'] }` | All items from `a`, followed by all items from `b`, including duplicate keys. |
|
|
184
|
+
| `onlyIn` | `{ op: 'onlyIn', of: 'a', notIn: 'b' }` | Items from `a` whose keys do not occur in `b`. |
|
|
185
|
+
| `intersect` | `{ op: 'intersect', of: ['a', 'b'] }` | Items from `a` whose keys occur in `b`, with values from `a`. |
|
|
186
|
+
|
|
187
|
+
<a id="relations"></a>
|
|
188
|
+
## Relations
|
|
189
|
+
|
|
190
|
+
All seven relations return the items that violate the condition. No returned items means the
|
|
191
|
+
condition holds. `a` and `b` below name extractions, not source files.
|
|
192
|
+
|
|
193
|
+
| Relation | Syntax | Condition |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| `empty` | `{ op: 'empty', of: 'a' }` | `a` has no items. Every item is reported on failure. |
|
|
196
|
+
| `nonEmpty` | `{ op: 'nonEmpty', of: 'a' }` | `a` has at least one item. Failure reports the extraction name with value `null`. |
|
|
197
|
+
| `equal` | `{ op: 'equal', of: ['a', 'b'] }` | The sets of values are equal in both directions. Reports left-only items, then right-only items. |
|
|
198
|
+
| `subset` | `{ op: 'subset', of: 'a', in: 'b' }` | Every value in `a` occurs in `b`. Reports unmatched items from `a`. |
|
|
199
|
+
| `implies` | `{ op: 'implies', of: 'a', requires: 'b' }` | Every key in `a` occurs in `b`. Reports items from `a` with missing required keys. |
|
|
200
|
+
| `ordered` | `{ op: 'ordered', of: 'a', strict: false }` | Values are ascending. `strict` defaults to `false`; `true` also rejects equal neighbours. Reports the later item in each failing pair. |
|
|
201
|
+
| `unchanged` | `{ op: 'unchanged', of: 'a' }` | For a paired extraction from `state`, values at shared keys agree before and after. Added and removed keys do not violate this relation. |
|
|
202
|
+
|
|
203
|
+
`equal` and `subset` compare values structurally, ignoring item keys, collection order, and
|
|
204
|
+
duplicate counts. Arrays *inside* values remain ordered. `implies` compares keys and ignores
|
|
205
|
+
values. For example, `{ key: 'en', value: 'home' }` and `{ key: 'ko', value: 'home' }` satisfy
|
|
206
|
+
`equal`, but the first does not imply the second because their keys differ.
|
|
207
|
+
|
|
208
|
+
`ordered` compares numerically when every value is a number; otherwise it compares string forms.
|
|
209
|
+
It does not sort. Empty and single-item inputs satisfy it. Sorting immediately before `ordered`
|
|
210
|
+
cannot establish that the original input was ordered.
|
|
211
|
+
|
|
212
|
+
Only `unchanged` accepts a pair; all other relations take single extractions. `equal`, `subset`,
|
|
213
|
+
and `implies` require two distinct extraction names.
|
|
214
|
+
|
|
215
|
+
<a id="messages-and-witness"></a>
|
|
216
|
+
## Messages and declaration witnesses
|
|
217
|
+
|
|
218
|
+
Each `relate` entry requires a unique `id`, a `relation`, and exactly one message form:
|
|
219
|
+
|
|
220
|
+
| Field | Use |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `message` | One diagnostic template for any relation. |
|
|
223
|
+
| `messageBySide` | `{ left: '…', right: '…' }`, allowed only for `equal`. |
|
|
224
|
+
|
|
225
|
+
Templates substitute `{key}` and `{value}` from the first violating item. `{before}` is its
|
|
226
|
+
previous value for `unchanged`, or an empty string when absent. Multiple violations add a count
|
|
227
|
+
suffix. Object values use their JavaScript string form; extract the field you want to display.
|
|
228
|
+
|
|
229
|
+
The optional declaration `witness` has its own optional `extract` and required `relate`. It can
|
|
230
|
+
reference the body's extractions; the body cannot reference witness extractions, and witness
|
|
231
|
+
extraction names cannot shadow body names. If the body fails and every witness comparison holds,
|
|
232
|
+
the declaration is witnessed. A witness supply failure does not release the violation.
|
|
233
|
+
The top-level [human witness setting](../configuration/index.md#witness) is configured separately.
|
|
234
|
+
|
|
235
|
+
<a id="mechanisms"></a>
|
|
236
|
+
## Mechanisms
|
|
237
|
+
|
|
238
|
+
Every declaration names one mechanism. The compiler derives axes from `source` steps: fixed
|
|
239
|
+
sources except `actor` give `change`; `actor` gives `actor`; file and sidecar bindings give
|
|
240
|
+
`world`; transcript bindings give `history`. A scope alone does not add an axis. Body relation
|
|
241
|
+
names and derived axes must fit the selected mechanism. Witness extraction sources also contribute
|
|
242
|
+
axes. The mechanism does not supply a predicate; write the extraction and comparison yourself.
|
|
243
|
+
|
|
244
|
+
| Mechanism | Allowed axes | Allowed body relations | Purpose or required structure |
|
|
245
|
+
|---|---|---|---|
|
|
246
|
+
| `pairing` | `world` | `equal`, `subset` | Compare corresponding data from supplied files. |
|
|
247
|
+
| `companion` | `change`, `world` | `implies` | Require matching keys in another extraction. |
|
|
248
|
+
| `monotonic-order` | `change`, `world` | `ordered` | Check a sequence's order. |
|
|
249
|
+
| `fingerprint-sync` | `world` | `equal` | Compare extracted fingerprint values. |
|
|
250
|
+
| `producer-owned` | `actor` | `empty`, `nonEmpty` | Check the observed actor. |
|
|
251
|
+
| `self-absolution-ban` | `change` | `unchanged`, `empty` | Check changes to the file's own contents. |
|
|
252
|
+
| `actor-scope` | `actor` | `empty`, `nonEmpty` | Restrict work by the observed actor. |
|
|
253
|
+
| `precedent` | `history`, `world` | `nonEmpty` | Require prior evidence. |
|
|
254
|
+
| `phase-order` | `history` | `ordered` | Compare extracted observation ordinals. |
|
|
255
|
+
| `turn-locality` | `history` | `nonEmpty` | Require evidence within a declared time window. |
|
|
256
|
+
| `stated-ground` | `history` | `nonEmpty` | Require a matching user statement. |
|
|
257
|
+
| `controlled-vocabulary` | `change`, `world` | `subset` | Compare extracted values with an allowed set. |
|
|
258
|
+
| `naming` | `change` | `empty`, `nonEmpty` | `scope.source` must be `target.path`. |
|
|
259
|
+
| `added-only` | `change` | `empty` | Usually compares the `post`/`pre` difference. |
|
|
260
|
+
| `one-way-marker` | `change` | `subset` | Require selected values to remain present. |
|
|
261
|
+
| `delegated-scope` | — | — | Reserved; rejected at load time. |
|
|
262
|
+
| `scoped-valve` | `change`, `actor`, `world`, `history` | All seven | A declaration `witness` block is required. |
|
|
263
|
+
| `forbidden-command` | `change` | `empty` | `scope.source` must be `command`. |
|
|
264
|
+
|
|
265
|
+
The 18 names include one reserved name, so 17 can be used. Mechanism constraints and
|
|
266
|
+
[discipline-list placement](../configuration/index.md#placement-rule) are separate checks.
|
|
267
|
+
|
|
268
|
+
<a id="validation"></a>
|
|
269
|
+
## Validate a declaration
|
|
270
|
+
|
|
271
|
+
Run `pnpm exec pdks explain` and confirm the entry is a `declare` registration on the intended
|
|
272
|
+
surface. A `skip` registration with `config-fault` means compilation failed; read its location
|
|
273
|
+
and reason. Unknown keys or invalid source/list combinations can instead fail configuration loading.
|
|
274
|
+
|
|
275
|
+
Then exercise a violating input and a valid input through the matching surface. See
|
|
276
|
+
[the worked locale example](../../how-to/write-disciplines.md#locale-key-pairing).
|
|
277
|
+
An exit code of 0 alone is insufficient: `advised` and `skipped` can both exit 0.
|
|
@@ -69,7 +69,7 @@ Claude Code의 입력을 공통 형식으로 번역합니다. 에이전트와
|
|
|
69
69
|
<a id="consumer-contract"></a>
|
|
70
70
|
## 사용자와의 접점
|
|
71
71
|
|
|
72
|
-
프로젝트 루트에서
|
|
72
|
+
프로젝트 루트에서 다음 명령을 실행하면 Claude Code 세션 표면을 설치하고 연결합니다.
|
|
73
73
|
|
|
74
74
|
```sh
|
|
75
75
|
npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
|
|
@@ -72,7 +72,7 @@ there is no separate precedent evaluator in this package. The grammar is in
|
|
|
72
72
|
<a id="consumer-contract"></a>
|
|
73
73
|
## Where the consumer touches it
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Run these commands from the project root to install and connect the Claude Code session surface:
|
|
76
76
|
|
|
77
77
|
```sh
|
|
78
78
|
npm install --save-dev polydeukes @polydeukes/core @polydeukes/adapter-claude-code
|
|
@@ -30,8 +30,8 @@ Codex의 입력을 공통 형식으로 번역합니다. 에이전트와 도구
|
|
|
30
30
|
`pdks covenant check --enforce block`을 스폰하고 그 자식 프로세스의 종료 코드를 그대로
|
|
31
31
|
돌려줍니다. 판정은 그 자식 프로세스가 하며, 이 패키지에는 판정 코드가 없습니다.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
**텔레메트리는 `pdks`가 기록합니다.** 어댑터는 스폰 전에 발생한 실패도 `pdks`의 stdin으로
|
|
34
|
+
보내 같은 경로로 기록합니다.
|
|
35
35
|
|
|
36
36
|
<a id="apply-patch"></a>
|
|
37
37
|
## 형제 어댑터는 인자를 읽는데 이 어댑터가 텍스트를 해석하는 이유
|
|
@@ -29,8 +29,8 @@ removes only that session's file. `PreToolUse` builds the IR with the `tools` ro
|
|
|
29
29
|
`pdks covenant check --enforce block` in `repoRoot` and returns the child's exit code. The
|
|
30
30
|
judging happens in that child process; this package carries no judgment logic.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
stdin, so
|
|
32
|
+
**`pdks` writes the telemetry.** The adapter sends failures that occur before spawning to
|
|
33
|
+
`pdks` on stdin, so those failures are recorded through the same path.
|
|
34
34
|
|
|
35
35
|
<a id="apply-patch"></a>
|
|
36
36
|
## Why this adapter parses text where its siblings read arguments
|
|
@@ -141,8 +141,8 @@ function declarationChannels(body: Omit<AlgebraDeclaration, 'discipline'>): Decl
|
|
|
141
141
|
다섯 가운데 하나도 이름 짓지 않는 본체는 변경된 파일과 저장소 파일만 읽고 그 둘은 두 표면이
|
|
142
142
|
모두 공급하므로 `disciplines`에 속합니다. 그 밖은 항목과 통로와 가야 할 목록을 대는
|
|
143
143
|
`ConfigValidationError`이며, 메시지는
|
|
144
|
-
[설정 참조](../configuration/index.ko.md#placement-rule)에 있습니다. 우산 패키지는
|
|
145
|
-
|
|
144
|
+
[설정 참조](../configuration/index.ko.md#placement-rule)에 있습니다. 우산 패키지는 이 함수를
|
|
145
|
+
사용해 적용할 규율 목록을 정합니다.
|
|
146
146
|
|
|
147
147
|
<a id="consumer-contract"></a>
|
|
148
148
|
## 사용자와의 접점
|
|
@@ -147,8 +147,8 @@ compare the same list.
|
|
|
147
147
|
A body naming none of the five reads the changed file and repository files alone, which both
|
|
148
148
|
surfaces supply, so it belongs in `disciplines`. Anything else is a `ConfigValidationError`
|
|
149
149
|
naming the entry, its channels, and the list it belongs in; the messages are in [the
|
|
150
|
-
configuration reference](../configuration/index.md#placement-rule). The umbrella
|
|
151
|
-
function
|
|
150
|
+
configuration reference](../configuration/index.md#placement-rule). The umbrella uses this
|
|
151
|
+
function to select the applicable discipline list.
|
|
152
152
|
|
|
153
153
|
<a id="consumer-contract"></a>
|
|
154
154
|
## Where the consumer touches it
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[English](sdk-ts.md) · **한국어**
|
|
4
4
|
|
|
5
|
-
> **TypeScript에서
|
|
6
|
-
> `pdks covenant check
|
|
5
|
+
> **TypeScript에서 판정기를 호출합니다.** `checkCovenant`에 약속(covenant) 입력 IR을
|
|
6
|
+
> 전달하면 `pdks covenant check`의 판정 결과를 값으로 반환합니다.
|
|
7
7
|
>
|
|
8
8
|
> 베타입니다. `polydeukes` · `@polydeukes/core`와 함께 설치하며, 둘 다 이 패키지의
|
|
9
9
|
> `peerDependencies`입니다.
|
|
@@ -11,18 +11,16 @@
|
|
|
11
11
|
<a id="ownership"></a>
|
|
12
12
|
## 담당하는 기능
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
코드는 여기에 없습니다. 분기는 우산 패키지를 찾았는지와 자식이 어떤 상태로 끝났는지뿐입니다.
|
|
14
|
+
판정받는 프로젝트에서 `polydeukes`를 찾고, 실행 파일의 표준 입력으로 IR을 전달한 뒤
|
|
15
|
+
자식 프로세스의 종료 코드를 판정 결과로 변환합니다. 실제 판정은 자식 프로세스가 수행합니다.
|
|
17
16
|
|
|
18
17
|
| 단위 | 하는 일 |
|
|
19
18
|
|---|---|
|
|
20
19
|
| `checkCovenant` | 판정받는 프로젝트에서 `pdks covenant check`를 스폰하고 판정 결과를 돌려줍니다 |
|
|
21
|
-
| 우산
|
|
20
|
+
| 우산 패키지 찾기 | `repoRoot`의 설치 그래프에서 `polydeukes`를 찾아 `pdks` 실행 파일을 읽습니다 |
|
|
22
21
|
| 판정 결과 변환 | 종료 코드 `0`은 `upheld`, `2`는 `blocked`, 그 밖은 모두 `unjudged`입니다 |
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
프로세스가 쓰므로, 호출 하나에 행 하나는 그대로입니다.
|
|
23
|
+
텔레메트리는 자식 프로세스가 판정 중에 기록합니다. SDK는 중복 행을 추가하지 않습니다.
|
|
26
24
|
|
|
27
25
|
<a id="install"></a>
|
|
28
26
|
## 설치
|
|
@@ -31,11 +29,12 @@
|
|
|
31
29
|
pnpm add @polydeukes/sdk-ts polydeukes @polydeukes/core
|
|
32
30
|
```
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
별도의 초기화 명령은 필요하지 않습니다. 우산 패키지가 SDK가 스폰할 판정기를 공급하고, 코어가
|
|
35
33
|
호출자가 채우는 `CovenantInput` 타입을 공급합니다.
|
|
36
34
|
|
|
35
|
+
<a id="동사"></a>
|
|
37
36
|
<a id="verb"></a>
|
|
38
|
-
##
|
|
37
|
+
## `checkCovenant`
|
|
39
38
|
|
|
40
39
|
이 패키지는 ESM 전용입니다(`"type": "module"`, `import` 조건만 있고 `require`는 없음).
|
|
41
40
|
호출하는 파일이 `.mjs`이거나 그 `package.json`이 `"type": "module"`을 선언해야 합니다.
|
|
@@ -90,7 +89,7 @@ type CheckCovenantSpawnSpec = { command: string; args: string[]; cwd: string; st
|
|
|
90
89
|
| `repoRoot` | 판정받는 프로젝트입니다. 설정 발견, 세계 축, 자식의 cwd, 우산 패키지를 찾는 설치 그래프가 모두 여기 걸립니다 |
|
|
91
90
|
| `input` | 호출자 자신의 IR이며 자식의 표준 입력으로 원문 그대로 갑니다 |
|
|
92
91
|
| `enforce` | 실행 전체에 대한 관측자의 기본 자세입니다. **적지 않으면 `block`입니다** |
|
|
93
|
-
| `spawn` |
|
|
92
|
+
| `spawn` | 자식 프로세스 실행 함수를 지정합니다. 생략하면 현재 프로세스의 Node.js 실행 파일을 사용합니다 |
|
|
94
93
|
|
|
95
94
|
**`enforce`의 기본값은 `block`입니다.** 이것은 표면의 강제 수준이지 항목의 것이 아닙니다.
|
|
96
95
|
보호 경로와 `enforce: block`을 단 항목이 호출을 멈추고, 나머지 위반은 종료 코드 0에
|
|
@@ -118,17 +117,15 @@ type CheckCovenantVerdict =
|
|
|
118
117
|
| `blocked` | `2` | 호출이 판정을 받았고 무언가 막았습니다. `reason`은 자식의 stderr 원문입니다. 진행하지 않습니다 |
|
|
119
118
|
| `unjudged` | 그 밖의 상태이거나 우산 패키지가 없음 | 판정이 일어나지 않았습니다. `reason`이 어느 쪽인지 말합니다. 이것을 통과로 읽으면 판정기가 설치되지 않은 프로젝트에서 모든 호출이 지나갑니다 |
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
[규율 작성하기](../../how-to/write-disciplines.ko.md#posture)에 있습니다.
|
|
120
|
+
SDK는 `blocked.reason`과 `upheld.advisories`를 데이터로 반환합니다. 소비자는 이 내용을
|
|
121
|
+
모델에게 전달하거나 이슈 또는 로그에 기록할 수 있습니다. SDK는 별도의 증인 인자를 받지 않습니다.
|
|
122
|
+
무인 루프에서 결과를 처리하는 방법은
|
|
123
|
+
[규율 작성하기](../../how-to/write-disciplines.ko.md#posture)를 참고하세요.
|
|
126
124
|
|
|
127
125
|
<a id="failure"></a>
|
|
128
126
|
## 실패 예제
|
|
129
127
|
|
|
130
|
-
프로젝트에 `polydeukes`가 설치돼 있지 않으면
|
|
131
|
-
그 사실을 말합니다.
|
|
128
|
+
프로젝트에 `polydeukes`가 설치돼 있지 않으면 `checkCovenant`는 `unjudged`를 반환합니다.
|
|
132
129
|
|
|
133
130
|
```ts
|
|
134
131
|
const verdict = await checkCovenant({ repoRoot: '/tmp/project-without-polydeukes', input });
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**English** · [한국어](sdk-ts.ko.md)
|
|
4
4
|
|
|
5
|
-
> **
|
|
6
|
-
> `pdks covenant check`
|
|
5
|
+
> **Call the judge from TypeScript.** Pass a covenant input IR to `checkCovenant`
|
|
6
|
+
> and receive the verdict from `pdks covenant check` as a value.
|
|
7
7
|
>
|
|
8
8
|
> Beta. Install it next to `polydeukes` and `@polydeukes/core`, which it names as
|
|
9
9
|
> `peerDependencies`.
|
|
@@ -11,10 +11,9 @@
|
|
|
11
11
|
<a id="ownership"></a>
|
|
12
12
|
## What this package owns
|
|
13
13
|
|
|
14
|
-
The
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
umbrella resolved and what status the child left with.
|
|
14
|
+
The package finds `polydeukes` in the project being judged, runs its bin with the input on
|
|
15
|
+
stdin, and converts the child process's exit status into a verdict. The child process performs
|
|
16
|
+
the judgment.
|
|
18
17
|
|
|
19
18
|
| Unit | What it does |
|
|
20
19
|
|---|---|
|
|
@@ -22,8 +21,7 @@ umbrella resolved and what status the child left with.
|
|
|
22
21
|
| Umbrella resolution | Finds `polydeukes` in the install graph of `repoRoot` and reads its `pdks` bin |
|
|
23
22
|
| Verdict translation | Exit `0` is `upheld`, exit `2` is `blocked`, everything else is `unjudged` |
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
where the judgment happened, so one call still leaves one row.
|
|
24
|
+
The child process writes telemetry during judgment. The SDK does not add duplicate rows.
|
|
27
25
|
|
|
28
26
|
<a id="install"></a>
|
|
29
27
|
## Install
|
|
@@ -32,11 +30,12 @@ where the judgment happened, so one call still leaves one row.
|
|
|
32
30
|
pnpm add @polydeukes/sdk-ts polydeukes @polydeukes/core
|
|
33
31
|
```
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
No separate initialization command is needed. The umbrella supplies the judge the SDK spawns, and the
|
|
36
34
|
core supplies the `CovenantInput` type the caller fills in.
|
|
37
35
|
|
|
36
|
+
<a id="the-verb"></a>
|
|
38
37
|
<a id="verb"></a>
|
|
39
|
-
##
|
|
38
|
+
## `checkCovenant`
|
|
40
39
|
|
|
41
40
|
The package is ESM only (`"type": "module"`, an `import` condition and no `require`): the calling
|
|
42
41
|
file is a `.mjs`, or its `package.json` declares `"type": "module"`.
|
|
@@ -120,17 +119,15 @@ type CheckCovenantVerdict =
|
|
|
120
119
|
| `blocked` | `2` | The call was judged and something blocked it. `reason` is the child's stderr verbatim. Do not proceed |
|
|
121
120
|
| `unjudged` | anything else, or no umbrella | No judgment happened. `reason` says which. Reading it as an uphold would let an uninstalled judge pass every call |
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
author and for a consumer are in [write disciplines](../../how-to/write-disciplines.md#posture).
|
|
122
|
+
The SDK returns `blocked.reason` and `upheld.advisories` as data. The consumer decides where
|
|
123
|
+
to send them: to the model, an issue, or a log. The SDK accepts no separate witness argument.
|
|
124
|
+
See [write disciplines](../../how-to/write-disciplines.md#posture) for handling these results
|
|
125
|
+
in an unattended loop.
|
|
128
126
|
|
|
129
127
|
<a id="failure"></a>
|
|
130
128
|
## A failure example
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
rather than answering `upheld`:
|
|
130
|
+
If the project has no `polydeukes` installed, `checkCovenant` returns `unjudged`:
|
|
134
131
|
|
|
135
132
|
```ts
|
|
136
133
|
const verdict = await checkCovenant({ repoRoot: '/tmp/project-without-polydeukes', input });
|
|
@@ -153,13 +153,17 @@ covenant check failed closed: invalid config in polydeukes.config.yaml: … —
|
|
|
153
153
|
<a id="skipped-rows-on-the-change-set-surface"></a>
|
|
154
154
|
## 변경 집합 표면의 미판정 기록
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
있습니다. 모든 자료 부재를 같은 실패로 취급하지 말고 등록 내용과 사유를 확인하세요.
|
|
156
|
+
변경 집합 표면은 `disciplines`와 `changeSetDisciplines`를 컴파일합니다.
|
|
157
|
+
대화 기록이나 명령줄을 읽는 항목은 `sessionDisciplines`에 속하며 diff 판정에는 포함되지
|
|
158
|
+
않습니다. 이런 항목을 공용 목록이나 변경 집합 목록에 넣으면 설정 오류가 발생합니다.
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
변경 집합 항목이 읽는 소스가 없고 `supply` 정책이 `pass`이면 `supply-pass`를 기록합니다.
|
|
161
|
+
선언을 컴파일할 수 없으면 `config-fault`를 기록합니다. `pdks explain`과 로그의 사유를
|
|
162
|
+
확인하세요. 미판정은 규율을 지켰다는 증거가 아닙니다.
|
|
163
|
+
|
|
164
|
+
세션 표면에서는 호스트가 대화 기록을 공급하지 않을 때
|
|
165
|
+
`supply: { session: 'pass' }`로 건너뛸 수 있습니다.
|
|
166
|
+
[규율 목록 셋](./reference/configuration/index.ko.md#three-lists)을 참고하세요.
|
|
163
167
|
|
|
164
168
|
<a id="local-state"></a>
|
|
165
169
|
## 다른 컴퓨터로 프로젝트를 옮길 때
|
|
@@ -152,13 +152,17 @@ from the hook command rather than editing the config — the row is still writte
|
|
|
152
152
|
<a id="skipped-rows-on-the-change-set-surface"></a>
|
|
153
153
|
## `skipped` rows on the change-set surface
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
reason instead of treating every missing source as the same failure.
|
|
155
|
+
The change-set surface compiles `disciplines` and `changeSetDisciplines`.
|
|
156
|
+
Transcript- and command-reading entries belong in `sessionDisciplines` and are not compiled
|
|
157
|
+
for a diff. Putting either kind in a shared or change-set list causes a configuration error.
|
|
159
158
|
|
|
160
|
-
A
|
|
161
|
-
|
|
159
|
+
A change-set entry can record `supply-pass` when a source it reads is absent and its `supply`
|
|
160
|
+
policy is `pass`, or `config-fault` when the declaration cannot compile. Check `pdks explain`
|
|
161
|
+
and the log's reason field. A skip does not establish that the discipline was upheld.
|
|
162
|
+
|
|
163
|
+
On the session surface, a transcript-reading entry can use `supply: { session: 'pass' }`
|
|
164
|
+
when a host supplies no session history. See the [three discipline
|
|
165
|
+
lists](./reference/configuration/index.md#three-lists).
|
|
162
166
|
|
|
163
167
|
<a id="local-state"></a>
|
|
164
168
|
## Moving a project between machines
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydeukes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
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
5
|
"author": "huskyhoochu <dfg1499@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"yaml": "2.9.0",
|
|
47
|
-
"@polydeukes/core": "^0.
|
|
47
|
+
"@polydeukes/core": "^0.10.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^24.0.0",
|