polydeukes 0.6.1 → 0.8.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 (108) hide show
  1. package/README.ko.md +16 -28
  2. package/README.md +16 -28
  3. package/dist/baseline.d.ts +37 -1
  4. package/dist/baseline.js +68 -1
  5. package/dist/bin.d.ts +3 -4
  6. package/dist/bin.js +73 -90
  7. package/dist/covenant/bash-line.d.ts +130 -0
  8. package/dist/covenant/bash-line.js +566 -0
  9. package/dist/covenant/declaration-engine.d.ts +108 -0
  10. package/dist/covenant/declaration-engine.js +415 -0
  11. package/dist/covenant/discipline.d.ts +109 -0
  12. package/dist/covenant/discipline.js +667 -0
  13. package/dist/covenant/dispatch.d.ts +156 -0
  14. package/dist/covenant/dispatch.js +250 -0
  15. package/dist/covenant/extract-steps.d.ts +122 -0
  16. package/dist/covenant/extract-steps.js +0 -0
  17. package/dist/covenant/mention.d.ts +117 -0
  18. package/dist/covenant/mention.js +209 -0
  19. package/dist/covenant/module.d.ts +25 -0
  20. package/dist/covenant/module.js +23 -0
  21. package/dist/covenant/mutation-rules.d.ts +40 -0
  22. package/dist/covenant/mutation-rules.js +146 -0
  23. package/dist/covenant/relations.d.ts +46 -0
  24. package/dist/covenant/relations.js +68 -0
  25. package/dist/covenant/run-covenant.d.ts +95 -0
  26. package/dist/covenant/run-covenant.js +164 -0
  27. package/dist/covenant/self-mod.d.ts +55 -0
  28. package/dist/covenant/self-mod.js +84 -0
  29. package/dist/covenant/shell-evidence.d.ts +38 -0
  30. package/dist/covenant/shell-evidence.js +247 -0
  31. package/dist/covenant/shell-mod.d.ts +84 -0
  32. package/dist/covenant/shell-mod.js +213 -0
  33. package/dist/covenant/supply.d.ts +54 -0
  34. package/dist/covenant/supply.js +50 -0
  35. package/dist/covenant/transcript-mod.d.ts +60 -0
  36. package/dist/covenant/transcript-mod.js +254 -0
  37. package/dist/covenant/ttl-witness.d.ts +47 -0
  38. package/dist/covenant/ttl-witness.js +80 -0
  39. package/dist/covenant-check.d.ts +74 -41
  40. package/dist/covenant-check.js +372 -129
  41. package/dist/diff-ir.d.ts +28 -0
  42. package/dist/diff-ir.js +310 -0
  43. package/dist/docs/README.ko.md +10 -9
  44. package/dist/docs/README.md +10 -9
  45. package/dist/docs/catalog.json +76 -28
  46. package/dist/docs/concepts/judgment.ko.md +2 -2
  47. package/dist/docs/concepts/judgment.md +2 -2
  48. package/dist/docs/how-to/configure-project.ko.md +16 -16
  49. package/dist/docs/how-to/configure-project.md +15 -12
  50. package/dist/docs/how-to/connect-surfaces.ko.md +67 -34
  51. package/dist/docs/how-to/connect-surfaces.md +67 -34
  52. package/dist/docs/how-to/write-disciplines.ko.md +64 -7
  53. package/dist/docs/how-to/write-disciplines.md +65 -7
  54. package/dist/docs/index.json +744 -362
  55. package/dist/docs/reference/cli/covenant-check.ko.md +112 -65
  56. package/dist/docs/reference/cli/covenant-check.md +114 -59
  57. package/dist/docs/reference/cli/docs.ko.md +2 -2
  58. package/dist/docs/reference/cli/docs.md +2 -2
  59. package/dist/docs/reference/cli/explain.ko.md +20 -15
  60. package/dist/docs/reference/cli/explain.md +22 -15
  61. package/dist/docs/reference/cli/init.ko.md +91 -52
  62. package/dist/docs/reference/cli/init.md +81 -55
  63. package/dist/docs/reference/configuration/index.ko.md +182 -71
  64. package/dist/docs/reference/configuration/index.md +188 -76
  65. package/dist/docs/reference/packages/adapter-claude-code.ko.md +39 -11
  66. package/dist/docs/reference/packages/adapter-claude-code.md +40 -14
  67. package/dist/docs/reference/packages/adapter-codex.ko.md +99 -0
  68. package/dist/docs/reference/packages/adapter-codex.md +100 -0
  69. package/dist/docs/reference/packages/adapter-grok.ko.md +81 -0
  70. package/dist/docs/reference/packages/adapter-grok.md +83 -0
  71. package/dist/docs/reference/packages/core.ko.md +50 -4
  72. package/dist/docs/reference/packages/core.md +55 -6
  73. package/dist/docs/reference/packages/polydeukes.ko.md +139 -77
  74. package/dist/docs/reference/packages/polydeukes.md +147 -81
  75. package/dist/docs/reference/packages/sdk-ts.ko.md +164 -0
  76. package/dist/docs/reference/packages/sdk-ts.md +167 -0
  77. package/dist/docs/troubleshooting.ko.md +51 -19
  78. package/dist/docs/troubleshooting.md +53 -17
  79. package/dist/docs/tutorials/first-judgment.ko.md +6 -4
  80. package/dist/docs/tutorials/first-judgment.md +6 -4
  81. package/dist/explain.d.ts +1 -1
  82. package/dist/explain.js +37 -22
  83. package/dist/load-config.d.ts +25 -1
  84. package/dist/load-config.js +21 -3
  85. package/dist/pre-state-reader.d.ts +1 -1
  86. package/dist/pre-state-reader.js +1 -1
  87. package/dist/scaffold-project.d.ts +2 -2
  88. package/dist/scaffold-project.js +12 -4
  89. package/dist/schema/polydeukes.schema.json +12 -0
  90. package/dist/worktree-reader.d.ts +19 -0
  91. package/dist/worktree-reader.js +30 -0
  92. package/package.json +5 -18
  93. package/dist/claude-code-hook.d.ts +0 -79
  94. package/dist/claude-code-hook.js +0 -372
  95. package/dist/claude-code.d.ts +0 -6
  96. package/dist/claude-code.js +0 -6
  97. package/dist/covenant-module.d.ts +0 -25
  98. package/dist/covenant-module.js +0 -42
  99. package/dist/docs/reference/packages/adapter-git.ko.md +0 -101
  100. package/dist/docs/reference/packages/adapter-git.md +0 -108
  101. package/dist/docs/reference/packages/covenant.ko.md +0 -115
  102. package/dist/docs/reference/packages/covenant.md +0 -123
  103. package/dist/index.d.ts +0 -22
  104. package/dist/index.js +0 -21
  105. package/dist/init-claude-code.d.ts +0 -52
  106. package/dist/init-claude-code.js +0 -586
  107. package/dist/init-grok.d.ts +0 -51
  108. package/dist/init-grok.js +0 -242
package/dist/init-grok.js DELETED
@@ -1,242 +0,0 @@
1
- /**
2
- * `initGrok` — the Grok session-surface installer.
3
- *
4
- * Preflight first, then the shared project-side scaffold, then the generated hook and the
5
- * `.grok/hooks` JSON registration. When a Claude delegator is already on disk, the JSON
6
- * command names that file instead of planting a second one — two command strings would
7
- * spawn two judges per call.
8
- *
9
- * Nothing existing is overwritten, with one command-field exception: a grok JSON whose
10
- * `command` is still the grok-mjs string is rewritten to the Claude-hook command when that
11
- * Claude file is on disk — otherwise grok-then-claude leaves two command strings. Any entry
12
- * naming the Claude-hook command also takes the matcher of the `.claude/settings.json` entry
13
- * carrying that command, because the host collapses the two registrations only when command
14
- * and matcher are byte-identical; with no such entry the matcher stays. Timeout stays either
15
- * way, and a command that is not the grok-mjs string is left byte-identical.
16
- *
17
- * Rules and skills are not copied; `.claude/settings.json` is not written.
18
- */
19
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
20
- import { findPackageJSON } from 'node:module';
21
- import { dirname, join } from 'node:path';
22
- import { isPlainObject } from '@polydeukes/core';
23
- import { scaffoldProject } from './scaffold-project.js';
24
- /** The published entry point the generated hook loads the judge through. */
25
- const HOOK_SPECIFIER = 'polydeukes/claude-code';
26
- /** The registration artifacts, as `projectRoot`-relative paths (the report vocabulary). */
27
- const GROK_HOOK_RELATIVE = '.grok/hooks/covenant-pretooluse.mjs';
28
- const GROK_JSON_RELATIVE = '.grok/hooks/covenant-pretooluse.json';
29
- /** The Claude delegator this installer reuses when it is already on disk. */
30
- const CLAUDE_HOOK_RELATIVE = '.claude/hooks/covenant-pretooluse.mjs';
31
- /** Where that delegator's own registration — and the matcher it was registered under — lives. */
32
- const CLAUDE_SETTINGS_RELATIVE = '.claude/settings.json';
33
- const GROK_HOOK_COMMAND = `node "$CLAUDE_PROJECT_DIR"/${GROK_HOOK_RELATIVE}`;
34
- const CLAUDE_HOOK_COMMAND = `node "$CLAUDE_PROJECT_DIR"/${CLAUDE_HOOK_RELATIVE}`;
35
- /**
36
- * Which calls reach the judge — Grok's mutating+shell roster plus the Claude aliases a
37
- * host without Grok's alias table still sends.
38
- */
39
- const HOOK_MATCHER = 'write|search_replace|run_terminal_command|Edit|Write|MultiEdit|NotebookEdit|Bash';
40
- /**
41
- * The generated hook. It carries no assembly at all, so upgrading the package upgrades the
42
- * judge without regenerating this file. Same text as the Claude installer besides the
43
- * header: the session subpath, `repoRoot` from this file's location, and `process.exitCode`
44
- * rather than `process.exit`.
45
- */
46
- const GENERATED_HOOK = `#!/usr/bin/env node
47
- /**
48
- * Polydeukes PreToolUse covenant hook — generated by \`pdks init grok\`.
49
- *
50
- * A delegator and nothing more: the judgment assembly lives in the \`polydeukes\` package as
51
- * \`runClaudeCodeHook\`, reached here through its session subpath. The package barrel would
52
- * work too and is the wrong door — its re-exports are eager, so every session call would
53
- * load the commit surface and its git adapter alongside the judge it actually needs.
54
- *
55
- * \`repoRoot\` comes from this file's own location, never from the working directory. A hook
56
- * is spawned with whatever directory the agent happened to hold, and what config discovery
57
- * and the protection list need is the project that CONTAINS this hook — always \`../..\`
58
- * from here.
59
- *
60
- * fail-closed: \`runClaudeCodeHook\` translates every failure it can reach into exit 2 with
61
- * one blocked record. This catch answers only for what it cannot reach — the package failing
62
- * to resolve or load at all (never installed, or installed without a build) — where no
63
- * telemetry writer exists yet. Recovery is installing the package again.
64
- */
65
-
66
- import { dirname, join } from 'node:path';
67
- import { fileURLToPath } from 'node:url';
68
-
69
- const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
70
-
71
- try {
72
- const { runClaudeCodeHook } = await import('${HOOK_SPECIFIER}');
73
- const { exitCode } = await runClaudeCodeHook({ repoRoot });
74
- // Assign and let the process end naturally instead of process.exit(): an explicit exit
75
- // can preempt a buffered stderr write on platforms with async pipes, dropping the break
76
- // reason the agent needs to read.
77
- process.exitCode = exitCode;
78
- } catch (error) {
79
- console.error(\`covenant hook failed closed: \${error?.message ?? error}\`);
80
- process.exitCode = 2;
81
- }
82
- `;
83
- /**
84
- * The default preflight: is `polydeukes` installed where `projectRoot` can reach it?
85
- *
86
- * ESM resolution specifically, because that is what the generated hook's `await import(...)`
87
- * runs. The generated hook loads `polydeukes/claude-code`, so that is the subpath this
88
- * checks — a Grok-named entry point is not added.
89
- */
90
- function resolveFromProjectRoot(projectRoot) {
91
- const manifestPath = findPackageJSON('polydeukes', join(projectRoot, 'package.json'));
92
- if (manifestPath === undefined) {
93
- throw new Error('polydeukes is not installed where this project can reach it');
94
- }
95
- const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
96
- const subpath = isPlainObject(manifest) && isPlainObject(manifest.exports)
97
- ? manifest.exports[`./${HOOK_SPECIFIER.split('/')[1]}`]
98
- : undefined;
99
- const target = isPlainObject(subpath) ? subpath.import : undefined;
100
- if (typeof target !== 'string' || !existsSync(join(dirname(manifestPath), target))) {
101
- throw new Error(`the installed polydeukes does not expose '${HOOK_SPECIFIER}' — update or rebuild it`);
102
- }
103
- }
104
- /** Write one generated artifact unless it is already there, recording which happened. */
105
- function writeIfAbsent(projectRoot, relative, contents, report) {
106
- const path = join(projectRoot, relative);
107
- if (existsSync(path)) {
108
- report.skipped.push(relative);
109
- return;
110
- }
111
- mkdirSync(dirname(path), { recursive: true });
112
- writeFileSync(path, contents);
113
- report.created.push(relative);
114
- }
115
- /**
116
- * The matcher `.claude/settings.json` registered `command` under, when it has one. Anything
117
- * unreadable, unparseable, or shaped otherwise answers `undefined` — the caller then keeps its
118
- * own roster rather than narrowing the registration to a shape it could not read.
119
- */
120
- function claudeSettingsMatcherFor(projectRoot, command) {
121
- const path = join(projectRoot, CLAUDE_SETTINGS_RELATIVE);
122
- if (!existsSync(path)) {
123
- return undefined;
124
- }
125
- let root;
126
- try {
127
- root = JSON.parse(readFileSync(path, 'utf-8'));
128
- }
129
- catch {
130
- return undefined;
131
- }
132
- if (!isPlainObject(root) || !isPlainObject(root.hooks) || !Array.isArray(root.hooks.PreToolUse)) {
133
- return undefined;
134
- }
135
- for (const entry of root.hooks.PreToolUse) {
136
- if (!isPlainObject(entry) || !Array.isArray(entry.hooks)) {
137
- continue;
138
- }
139
- if (entry.hooks.some((hook) => isPlainObject(hook) && hook.command === command)) {
140
- return typeof entry.matcher === 'string' ? entry.matcher : undefined;
141
- }
142
- }
143
- return undefined;
144
- }
145
- function grokHookJson(command, matcher) {
146
- return `${JSON.stringify({
147
- hooks: {
148
- PreToolUse: [
149
- {
150
- matcher,
151
- hooks: [{ type: 'command', command, timeout: 60 }],
152
- },
153
- ],
154
- },
155
- }, null, 2)}\n`;
156
- }
157
- /**
158
- * Rewrite the grok JSON `command` from the grok-mjs string to the Claude-hook string.
159
- *
160
- * The Claude installer calls this after writing its delegator; this installer calls it on
161
- * re-run when that file is already on disk. Only the installer-generated grok-mjs command
162
- * is rewritten; any other string is the consumer's spawn target and the file is not touched.
163
- * Every entry naming the Claude-hook command — rewritten now or by an earlier install — takes
164
- * the matcher the Claude settings file registered that command under, so the host sees one
165
- * pair rather than two and a re-run converges. Parse failure leaves the file as it was —
166
- * existence is presence, not parse success.
167
- */
168
- export function retargetGrokHookCommandToClaude(projectRoot) {
169
- const path = join(projectRoot, GROK_JSON_RELATIVE);
170
- if (!existsSync(path)) {
171
- return;
172
- }
173
- let root;
174
- try {
175
- root = JSON.parse(readFileSync(path, 'utf-8'));
176
- }
177
- catch {
178
- return;
179
- }
180
- if (!isPlainObject(root) || !isPlainObject(root.hooks) || !Array.isArray(root.hooks.PreToolUse)) {
181
- return;
182
- }
183
- const settingsMatcher = claudeSettingsMatcherFor(projectRoot, CLAUDE_HOOK_COMMAND);
184
- let changed = false;
185
- for (const entry of root.hooks.PreToolUse) {
186
- if (!isPlainObject(entry) || !Array.isArray(entry.hooks)) {
187
- continue;
188
- }
189
- let namesClaudeHook = false;
190
- for (const hook of entry.hooks) {
191
- if (!isPlainObject(hook)) {
192
- continue;
193
- }
194
- if (hook.command === GROK_HOOK_COMMAND) {
195
- hook.command = CLAUDE_HOOK_COMMAND;
196
- changed = true;
197
- }
198
- namesClaudeHook ||= hook.command === CLAUDE_HOOK_COMMAND;
199
- }
200
- // Whether this pass rewrote the command or an earlier install already did, an entry
201
- // naming the Claude hook pairs with the settings entry only on the same matcher.
202
- if (namesClaudeHook && settingsMatcher !== undefined && entry.matcher !== settingsMatcher) {
203
- entry.matcher = settingsMatcher;
204
- changed = true;
205
- }
206
- }
207
- if (changed) {
208
- writeFileSync(path, `${JSON.stringify(root, null, 2)}\n`);
209
- }
210
- }
211
- /**
212
- * Install the Grok session surface into `spec.projectRoot`, skipping whatever is already
213
- * there and reporting both halves per artifact.
214
- *
215
- * Throws before any write when the package cannot be resolved from that root — that leaves
216
- * zero files. Translating a throw into exit 2 with the install command is the bin's job.
217
- */
218
- export function initGrok(spec) {
219
- const resolvePolydeukes = spec.resolvePolydeukes ?? resolveFromProjectRoot;
220
- try {
221
- resolvePolydeukes(spec.projectRoot);
222
- }
223
- catch (error) {
224
- throw new Error(`cannot use 'polydeukes' from ${spec.projectRoot} — install or update it there first ` +
225
- "(e.g. 'npm install --save-dev polydeukes'), then run this command again: " +
226
- `${error instanceof Error ? error.message : String(error)}`);
227
- }
228
- const report = scaffoldProject(spec.projectRoot);
229
- const claudeHookExists = existsSync(join(spec.projectRoot, CLAUDE_HOOK_RELATIVE));
230
- if (!claudeHookExists) {
231
- writeIfAbsent(spec.projectRoot, GROK_HOOK_RELATIVE, GENERATED_HOOK, report);
232
- }
233
- const command = claudeHookExists ? CLAUDE_HOOK_COMMAND : GROK_HOOK_COMMAND;
234
- const matcher = claudeHookExists
235
- ? (claudeSettingsMatcherFor(spec.projectRoot, CLAUDE_HOOK_COMMAND) ?? HOOK_MATCHER)
236
- : HOOK_MATCHER;
237
- writeIfAbsent(spec.projectRoot, GROK_JSON_RELATIVE, grokHookJson(command, matcher), report);
238
- if (claudeHookExists) {
239
- retargetGrokHookCommandToClaude(spec.projectRoot);
240
- }
241
- return report;
242
- }