polydeukes 0.8.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.
Files changed (32) hide show
  1. package/dist/covenant/shell-mod.d.ts +15 -4
  2. package/dist/covenant/shell-mod.js +63 -8
  3. package/dist/covenant/transcript-mod.js +8 -5
  4. package/dist/docs/README.ko.md +43 -18
  5. package/dist/docs/README.md +39 -17
  6. package/dist/docs/catalog.json +50 -162
  7. package/dist/docs/concepts/judgment.ko.md +2 -0
  8. package/dist/docs/concepts/judgment.md +2 -0
  9. package/dist/docs/how-to/connect-surfaces.ko.md +19 -7
  10. package/dist/docs/how-to/connect-surfaces.md +24 -12
  11. package/dist/docs/how-to/write-disciplines.ko.md +68 -31
  12. package/dist/docs/how-to/write-disciplines.md +69 -32
  13. package/dist/docs/index.json +577 -231
  14. package/dist/docs/reference/cli/init.ko.md +10 -7
  15. package/dist/docs/reference/cli/init.md +16 -11
  16. package/dist/docs/reference/configuration/index.ko.md +14 -20
  17. package/dist/docs/reference/configuration/index.md +16 -24
  18. package/dist/docs/reference/declaration-language/index.ko.md +280 -0
  19. package/dist/docs/reference/declaration-language/index.md +277 -0
  20. package/dist/docs/reference/packages/adapter-claude-code.ko.md +1 -1
  21. package/dist/docs/reference/packages/adapter-claude-code.md +1 -1
  22. package/dist/docs/reference/packages/adapter-codex.ko.md +34 -17
  23. package/dist/docs/reference/packages/adapter-codex.md +39 -21
  24. package/dist/docs/reference/packages/core.ko.md +2 -2
  25. package/dist/docs/reference/packages/core.md +2 -2
  26. package/dist/docs/reference/packages/polydeukes.ko.md +2 -2
  27. package/dist/docs/reference/packages/polydeukes.md +3 -3
  28. package/dist/docs/reference/packages/sdk-ts.ko.md +15 -18
  29. package/dist/docs/reference/packages/sdk-ts.md +14 -17
  30. package/dist/docs/troubleshooting.ko.md +18 -10
  31. package/dist/docs/troubleshooting.md +19 -11
  32. package/package.json +2 -2
@@ -6,6 +6,8 @@ A discipline describes a practice you want checked. Choose the observed files or
6
6
  write an extraction and relation, then exercise both a violation and a valid case. Leave enforcement
7
7
  at `advise` until you decide that the observed results justify blocking.
8
8
 
9
+ For the complete syntax of relations and extraction steps, see the [Declaration language reference](../reference/declaration-language/index.md).
10
+
9
11
  <a id="locale-key-pairing"></a>
10
12
  ## Locale key pairing
11
13
 
@@ -88,14 +90,56 @@ before it appears in the diff. This example commits a baseline to exercise modif
88
90
  cleanup predictable. A declaration does not run
89
91
  merely because its source exists: at least one observed change must match its scope.
90
92
 
93
+ <a id="locale-key-pairing-many"></a>
94
+ ### Three or more locale files
95
+
96
+ `equal` compares two extractions. For three or more files, build the union of every file's keys
97
+ and require each file to contain it: one `subset` per file. `onlyIn` adds only the keys the union
98
+ does not hold yet, so a key present in several files is still one witness per file that lacks it.
99
+ The recipe relies on `flattenKeys` giving each item its dot path as both key and value: `onlyIn`
100
+ compares keys and `subset` compares values. An extraction whose keys differ from its values, such
101
+ as `lines` (keyed by line number), cannot use it.
102
+
103
+ For `ko`, `en`, and `fr`, replace the `locale-key-parity` entry above with this one, and create
104
+ `locales/fr.json` with the same keys (`printf '{"home":"Accueil"}\n' > locales/fr.json`) before
105
+ running the walkthrough, since `supply: 'error'` refuses a missing file:
106
+
107
+ ```yaml
108
+ - id: 'locale-key-parity'
109
+ why: 'every locale file must carry the same keys'
110
+ declare:
111
+ mechanism: 'pairing'
112
+ sources:
113
+ ko: { file: 'locales/ko.json' }
114
+ en: { file: 'locales/en.json' }
115
+ fr: { file: 'locales/fr.json' }
116
+ supply: { ko: 'error', en: 'error', fr: 'error' }
117
+ scope: { source: 'target.path', include: ['^locales/(ko|en|fr)\.json$'] }
118
+ extract:
119
+ ko: [{ op: 'source', of: 'ko' }, { op: 'json' }, { op: 'flattenKeys' }]
120
+ en: [{ op: 'source', of: 'en' }, { op: 'json' }, { op: 'flattenKeys' }]
121
+ fr: [{ op: 'source', of: 'fr' }, { op: 'json' }, { op: 'flattenKeys' }]
122
+ enNew: [{ op: 'onlyIn', of: 'en', notIn: 'ko' }]
123
+ koEn: [{ op: 'union', of: ['ko', 'enNew'] }]
124
+ frNew: [{ op: 'onlyIn', of: 'fr', notIn: 'koEn' }]
125
+ all: [{ op: 'union', of: ['koEn', 'frNew'] }]
126
+ relate:
127
+ - { id: 'ko-full', relation: { op: 'subset', of: 'all', in: 'ko' }, message: '{value} is missing from ko' }
128
+ - { id: 'en-full', relation: { op: 'subset', of: 'all', in: 'en' }, message: '{value} is missing from en' }
129
+ - { id: 'fr-full', relation: { op: 'subset', of: 'all', in: 'fr' }, message: '{value} is missing from fr' }
130
+ ```
131
+
132
+ No file is the reference: a key only in `ko` breaks `en-full` and `fr-full`, and a key in `en`
133
+ and `fr` but not `ko` breaks `ko-full` alone. Each further file adds three extractions (its
134
+ keys, its `onlyIn`, the next `union`) and one relate entry, and every relate entry's `of` moves
135
+ to that last `union`.
136
+
91
137
  <a id="which-list"></a>
92
138
  ## Which list does it go in
93
139
 
94
- There are three discipline lists, and the source axis decides which one an entry belongs to.
95
- The mechanism does not decide it and the relation does not decide it: the same `companion`
96
- mechanism sits in `disciplines` when it stands over `file` sources, and in
97
- `changeSetDisciplines` when it stands over `changes`. Read the declaration's sources and the
98
- list follows.
140
+ Choose a discipline list by the sources the declaration reads. For example, a `companion`
141
+ declaration reading only `file` sources belongs in `disciplines`; one reading `changes`
142
+ belongs in `changeSetDisciplines`.
99
143
 
100
144
  | The declaration reads | List | Examples |
101
145
  |---|---|---|
@@ -111,37 +155,30 @@ names the entry, the channels it reads, and the list it belongs in, so the fix i
111
155
  body unchanged. The rule itself and the error shapes are in [the configuration
112
156
  reference](../reference/configuration/index.md#placement-rule).
113
157
 
114
- An entry can also read nothing a surface has to supply and still be surface-bound in practice:
115
- a valve (`witness`) that reads the transcript makes its entry a session entry, because the
116
- valve's own `extract` binds the transcript.
158
+ Include the `witness` block's sources when choosing a list. If its `extract` reads the
159
+ transcript, the whole entry belongs in `sessionDisciplines`.
117
160
 
118
161
  <a id="posture"></a>
119
162
  ## Posture on an unattended real-time surface
120
163
 
121
- An unattended real-time surface is an adapter hook or an SDK caller with no human at the
122
- terminal. Two rules apply there that do not apply where a person is watching.
123
-
124
- **Promote an entry to `enforce: block` when the loop cannot fix it inside the turn.** The
125
- criterion is not "is this irreversible". A real-time block costs seconds: the model reads the
126
- reason on stderr and retries, so the violation is corrected within the turn. Left at `advise`,
127
- the same violation travels to a later check — a test run, CI, a reviewer — and costs a whole
128
- turn, up to 45 minutes. This is not "block everything because nobody is watching": blocking
129
- produces avoidance, and avoidance leaves no telemetry row, so an entry the loop cannot act on
130
- belongs at `advise` where its break is at least recorded. The criterion is the config author's.
131
-
132
- **The reason comes back as a value, because there is no valve.** A real-time unattended
133
- surface has no witness valve: there is no TTY and no human turn, and the SDK takes no witness
134
- argument and invents no session. What stands in its place is the reason travelling as data.
135
- `checkCovenant` returns `{ verdict: 'blocked', reason }` where `reason` is the judge's own
136
- stderr, and `{ verdict: 'upheld', advisories }` carries the advisory lines of an exit-0 run.
137
- The consumer writes that text where a person reads it later — an issue, a log — and stops.
138
- Whether the model sees the advisory text is the consumer's decision too: an unattended loop has
139
- no reader for a stderr line, so advise is only consumed if the caller passes it on. The
140
- [`@polydeukes/sdk-ts` reference](../reference/packages/sdk-ts.md) has the verdict shapes.
141
-
142
- The SDK's own default is `enforce: 'block'` for the run, which is the surface's level, not an
143
- entry's: protected paths and `enforce: block` entries stop the call, and every other break is
144
- recorded as `advised`. Both adapters spawn the judge the same way.
164
+ An unattended adapter hook or SDK caller needs an explicit response to blocked and advised
165
+ judgments.
166
+
167
+ **Use `enforce: block` when an advisory alone will not lead the loop to correct a violation.**
168
+ The caller must give the model the reason and a way to retry. Keep an entry at `advise` if the
169
+ loop cannot act on its diagnostic, and arrange for someone to review the recorded violations.
170
+ Choose the level based on observations from that loop.
171
+
172
+ **Return diagnostics to the caller.** `checkCovenant` returns
173
+ `{ verdict: 'blocked', reason }` with the judge's stderr, or `{ verdict: 'upheld', advisories }`
174
+ with the advisory output of an exit-0 run. The SDK accepts no separate witness argument.
175
+ The caller decides whether to send diagnostics to the model, record them in an issue or log,
176
+ and retry or stop. An advisory reaches the model only if the caller forwards it.
177
+ See the [SDK reference](../reference/packages/sdk-ts.md#verdicts) for the return types.
178
+
179
+ The SDK defaults to `enforce: 'block'` for the whole run. At that level, protected paths and
180
+ entries with `enforce: block` can stop the call; other discipline violations remain `advised`.
181
+ The three agent adapters use the same setting.
145
182
 
146
183
  <a id="when-to-draft"></a>
147
184
  ## When to draft instead of declaring