docks-kit 0.20.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -78,7 +78,7 @@ omp SoT notes:
78
78
  - `modelRoles.task` is `openai-codex/gpt-6-sol:high`. `advisor` is `anthropic/claude-opus-5-5:medium` with an empty fallback chain, because a GPT-6 Sol advisor looped on repeated reads under an Opus 5.5 session; never put GPT-6 Sol in the advisor role or chain. `smol`, `commit`, and `tiny` use `openai-codex/gpt-6-luna`. The four reviewer entries in `task.agentModelOverrides` inherit `task` through `@task`. Only bundled `reviewer` and `security-reviewer` are discoverable OMP agents; `code-reviewer` and `plan-reviewer` stay dormant. omp 18.2.9 did not list `gpt-6-sol` or `gpt-6-luna` in its `openai-codex` catalog and fuzzy-matched both selectors to the GPT-5.6 models. omp 18.3.1 lists both ids and serves them as named. The `SoT/toolchain.json` omp floor is 18.3.1 because it is the oldest release the kit tested; releases 18.2.10 to 18.3.0 were not tested. `cli/docs/omp-models.md` records the checks.
79
79
  - The five Anthropic roles (`default`, `slow`, `plan`, `designer`, `vision`) and the five Anthropic retry chains use `anthropic/claude-opus-5-5` at the levels the role map records. `cli/docs/omp-models.md` carries the Artificial Analysis capture behind the role map, read 2026-09-22 at Intelligence Index v4.3.2 and Coding Agent Index v1.5 from the AA comparison-page metric tables. Opus 5.5 max has the highest index in that topic. AA has not measured speed or latency for Opus 5.5 max, GPT-6 Sol, or GPT-6 Luna.
80
80
  - `modelRoles.web` is `web/firecrawl` and `retry.fallbackChains.web` carries the explicit 20-entry provider order. The kit declares both keys because the legacy `providers.webSearchOrder` key is retired: omp expands it in memory into these two keys and then drops it, and never writes that expansion back to disk. An explicit chain replaces omp's built-in web order wholesale, so every entry left out is a provider omp never tries. The owner removed the seven entries that named older models (Gemini 2.5 Flash, Claude Haiku 4.5, GPT-5.6, GPT-5.5, and Grok 4.5); keep every other provider.
81
- - `SoT/.omp/models.yml` declares Astra's full `low, medium, high, xhigh, max` ladder with `defaultLevel: xhigh` as the worked provider ladder-override example. It also carries a temporary `anthropic.modelOverrides.claude-opus-5-5` block with that model's limits, ladder, and prices, because the shared catalog still serves the id as a stub with null limits and zero cost; remove the block once the catalog publishes the row. `ompYaml.ts mergeOmpModels` preserves deployed-only keys in `~/.omp/agent/models.yml`, because a user file may carry provider credentials. Whole-file replacement is wrong.
81
+ - `SoT/.omp/models.yml` declares Astra's full `low, medium, high, xhigh, max` ladder with `defaultLevel: xhigh` as the worked provider ladder-override example. The temporary `anthropic.modelOverrides.claude-opus-5-5` block is gone, because the shared catalog now publishes the same limits, ladder, and prices. `ompRemovals.ts syncOmpModelRemovals, retired-block inventory` prunes it from `~/.omp/agent/models.yml` after the models merge, but only while the deployed block still equals the shipped one. `ompYaml.ts mergeOmpModels` preserves deployed-only keys in `~/.omp/agent/models.yml`, because a user file may carry provider credentials. Whole-file replacement is wrong.
82
82
  - `SoT/.omp/AGENTS.md` carries the rule `Please remove all mannered prose.` Anthropic's Fable 5.1 prompting guide documents mannered prose as a Fable 5.1 behavior and gives that sentence as its short-version fix: https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1
83
83
  - `cli/docs/omp-models.md` (topic `omp-models`) records the role map rationale and the Artificial Analysis snapshot behind it. Model choices change with published benchmarks, so update that topic in the same commit as a role change.
84
84
  - `SoT/.omp/config.yml` sets `compaction.thresholdTokens` to `-1`, omp's schema default sentinel selecting reserve-based behavior: the trigger becomes `contextWindow` minus `max(floor(contextWindow * 0.15), 16384)`, which is 231,200 on the 272,000-token Codex window and 850,000 on the 1,000,000-token Anthropic window. The key ships as `-1` rather than being deleted because `ompYaml.ts mergeOmpConfig` is additive, so removing a key from SoT never removes it from a deployed file. `cli/docs/omp-context.md` (topic `omp-context`) carries the derivation and the measured evidence, so update that topic in the same commit as any compaction-setting change.
@@ -182,10 +182,12 @@ write, which the AA comparison table does not show. Context 1M, maximum output
182
182
  Index in this topic at this capture. AA has not measured speed or latency for
183
183
  max. It measures a longer TTFT for medium than for high.
184
184
 
185
- `SoT/.omp/models.yml` carries the Anthropic limits and prices as an `anthropic`
186
- `modelOverrides` block, because the shared catalog still serves this id as a
187
- stub with null limits and zero cost. Remove that block once the catalog
188
- publishes the row.
185
+ Until 0.20.1, `SoT/.omp/models.yml` carried the Anthropic limits and prices as
186
+ an `anthropic` `modelOverrides` block, because the shared catalog served this
187
+ id as a stub with null limits and zero cost. On 2026-09-25 the catalog at
188
+ `catalog.stencil.so` published the same context window, output cap, ladder,
189
+ and prices, so the block was removed. Sync prunes the deployed copy only while
190
+ it still equals the shipped block.
189
191
 
190
192
  ### Claude Fable 5.1 (Anthropic) - `anthropic/claude-fable-5-1`
191
193
 
@@ -78,7 +78,11 @@ these alone and warns:
78
78
  - `typescript-language-server` when Node is older than the `node` floor.
79
79
 
80
80
  When the PATH copy of an npm-owned server is outside `npm prefix -g`, it warns
81
- that the upgrade changes only the npm copy. A package that is not installed
81
+ that the upgrade changes only the npm copy. The check follows links and
82
+ accepts only a file inside the package directory
83
+ (`<prefix>/lib/node_modules/<pkg>` on POSIX), so a link from another PATH
84
+ directory into it counts as the npm copy, while a distro binary under a
85
+ `/usr` prefix does not. On Windows, a shim in `<prefix>` counts. A package that is not installed
82
86
  stays missing, because `sync claude` owns first installs. A failed npm call
83
87
  exits 1. After the install, it reads `npm ls -g` again and exits 1 when a
84
88
  package is not at its pin.
@@ -6,7 +6,8 @@
6
6
  * and spawned argv are part of the contract.
7
7
  */
8
8
  import { defaultProbeExecutor, npmGlobalVersions, type ToolId } from "./deps";
9
- import { capture, p, spawnProcess } from "./exec";
9
+ import { realpathSync } from "node:fs";
10
+ import { capture, spawnProcess } from "./exec";
10
11
  import type { Ctx } from "./index";
11
12
  import { isObject, parseJson } from "./jq";
12
13
  import { belowFloor, field, installedVersion, isNewer } from "./toolchain";
@@ -177,12 +178,30 @@ export async function upgradeLspServers(ctx: Ctx): Promise<number> {
177
178
  const owned = await npmGlobalVersions(defaultProbeExecutor);
178
179
  const prefix = await capture("npm", ["prefix", "-g"]);
179
180
  const windows = ctx.services.platform.name() === "windows";
180
- // npm links global executables into <prefix>/bin on POSIX and into <prefix> on Windows.
181
- const npmBin = prefix === "" ? "" : windows ? prefix : p(prefix, "bin");
182
181
  const comparable = (path: string): string => {
183
182
  const slashed = path.replaceAll("\\", "/");
184
183
  return windows ? slashed.toLowerCase() : slashed;
185
184
  };
185
+ const resolved = (path: string): string => {
186
+ try {
187
+ return realpathSync(path);
188
+ } catch {
189
+ return path;
190
+ }
191
+ };
192
+ // A PATH entry is the npm copy of `pkg` when the file it resolves to lies in
193
+ // that package's own directory: <prefix>/lib/node_modules/<pkg> on POSIX,
194
+ // where npm's bin entries are links into it. Any other file under the prefix
195
+ // does not count, because a system Node uses /usr or /usr/local as its prefix
196
+ // and distro binaries live there too. npm writes Windows shims straight into
197
+ // <prefix> instead of linking, so there a shim in <prefix> itself counts.
198
+ const npmRoot = prefix === "" ? "" : `${comparable(resolved(prefix))}/`;
199
+ const isNpmCopy = (path: string, pkg: string): boolean => {
200
+ const packageDir = `${npmRoot}${windows ? "" : "lib/"}node_modules/${comparable(pkg)}/`;
201
+ if (comparable(resolved(path)).startsWith(packageDir)) return true;
202
+ const entry = comparable(path);
203
+ return windows && entry.slice(0, entry.lastIndexOf("/") + 1) === `${comparable(prefix)}/`;
204
+ };
186
205
 
187
206
  const targets: Array<readonly [string, string]> = [];
188
207
  const moves: Array<string> = [];
@@ -202,13 +221,9 @@ export async function upgradeLspServers(ctx: Ctx): Promise<number> {
202
221
  }
203
222
  continue;
204
223
  }
205
- if (
206
- onPath !== "" &&
207
- npmBin !== "" &&
208
- !comparable(onPath).startsWith(`${comparable(npmBin)}/`)
209
- ) {
224
+ if (onPath !== "" && npmRoot !== "" && !isNpmCopy(onPath, pkg)) {
210
225
  warn(
211
- `${tool} on PATH is ${onPath}, not the npm global copy in ${npmBin}; an upgrade changes only the npm copy`,
226
+ `${tool} on PATH is ${onPath}, not the npm global copy under ${prefix}; an upgrade changes only the npm copy`,
212
227
  );
213
228
  }
214
229
  if (!isNewer(verified, installed)) {
@@ -1,13 +1,14 @@
1
1
  /**
2
- * EngineNative `sync omp` retired-key pruning. `ompYaml.ts mergeOmpConfig` is
3
- * additive: its `mergeMappings, deployed-key retention loop` returns every
4
- * deployed key absent from the SoT to the merged result. Removing a key from
5
- * `SoT/.omp/config.yml` therefore never removes it from an existing
6
- * `~/.omp/agent/config.yml`. This pass force-prunes an inventory of retired
7
- * kit-owned keys on every sync, without `--reconcile`. Message strings and
8
- * prune semantics are part of the contract.
2
+ * EngineNative `sync omp` retired-key pruning. `ompYaml.ts mergeOmpConfig` and
3
+ * `mergeOmpModels` are additive: their `mergeMappings, deployed-key retention
4
+ * loop` returns every deployed key absent from the SoT to the merged result.
5
+ * Removing a key from `SoT/.omp/config.yml` or `SoT/.omp/models.yml` therefore
6
+ * never removes it from the deployed file. This pass force-prunes an inventory
7
+ * of retired kit-owned keys on every sync, without `--reconcile`. Message
8
+ * strings and prune semantics are part of the contract.
9
9
  */
10
10
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { isDeepStrictEqual } from "node:util";
11
12
  import { isMap, isScalar, parseDocument, type YAMLMap } from "yaml";
12
13
  import type { Ctx } from "./index";
13
14
 
@@ -49,6 +50,37 @@ const OMP_RETIRED_VALUES: ReadonlyArray<readonly [string, RetiredScalar]> = [
49
50
  */
50
51
  const OMP_RETIRED_KEYS: ReadonlyArray<string> = ["providers.webSearchOrder"];
51
52
 
53
+ /**
54
+ * models.yml blocks the kit used to deploy, each with the exact value it
55
+ * deployed. A block is pruned only while the deployed block still equals that
56
+ * value, so a user edit survives.
57
+ *
58
+ * `claude-opus-5-5` carried limits, ladder, and prices while the shared catalog
59
+ * served the id as an empty stub. The catalog now publishes the same limits,
60
+ * prices, and ladder. The block's `defaultLevel: high` applied only to a bare
61
+ * selector, and every kit selector names its level.
62
+ */
63
+ const OMP_RETIRED_MODEL_BLOCKS: ReadonlyArray<readonly [string, unknown]> = [
64
+ [
65
+ "providers.anthropic.modelOverrides.claude-opus-5-5",
66
+ {
67
+ name: "Claude Opus 5.5",
68
+ reasoning: true,
69
+ input: ["text", "image"],
70
+ contextWindow: 1000000,
71
+ maxTokens: 128000,
72
+ cost: { input: 4, output: 20, cacheRead: 0.2, cacheWrite: 5 },
73
+ thinking: {
74
+ mode: "effort",
75
+ efforts: ["low", "medium", "high", "xhigh", "max"],
76
+ defaultLevel: "high",
77
+ },
78
+ },
79
+ ],
80
+ ];
81
+
82
+ type RetiredEntry = readonly [string, (node: unknown) => boolean];
83
+
52
84
  function indexOfKey(mapping: YAMLMap, key: string): number {
53
85
  return mapping.items.findIndex((pair) => {
54
86
  const name: unknown = pair.key;
@@ -122,38 +154,63 @@ function deletePath(
122
154
  return true;
123
155
  }
124
156
 
125
- /** Prunes retired kit-owned keys from a deployed omp config.yml. */
126
- export function syncOmpRemovals(ctx: Ctx, configFile: string): number {
157
+ /** Prunes each matching retired entry from one deployed omp YAML file. */
158
+ function pruneRetired(
159
+ ctx: Ctx,
160
+ file: string,
161
+ label: string,
162
+ entries: ReadonlyArray<RetiredEntry>,
163
+ ): number {
127
164
  const { change, echo, verbose, warn } = ctx.services.logger;
128
- if (!existsSync(configFile)) return 0;
165
+ if (!existsSync(file)) return 0;
129
166
 
130
- const doc = parseDocument(readFileSync(configFile, "utf8"));
167
+ const doc = parseDocument(readFileSync(file, "utf8"));
131
168
  const parseError = doc.errors[0];
132
169
  if (parseError !== undefined) {
133
- warn(`omp config.yml unreadable, retired keys not pruned: ${parseError.message}`);
170
+ warn(`omp ${label} unreadable, retired keys not pruned: ${parseError.message}`);
134
171
  return 0;
135
172
  }
136
173
  const contents = doc.contents;
137
174
  if (!isMap(contents)) return 0;
138
175
 
139
176
  const pruned: Array<string> = [];
140
- for (const [path, value] of OMP_RETIRED_VALUES) {
141
- const matches = (node: unknown): boolean => isScalar(node) && node.value === value;
177
+ for (const [path, matches] of entries) {
142
178
  if (deletePath(contents, path.split("."), matches)) pruned.push(path);
143
179
  }
144
- for (const path of OMP_RETIRED_KEYS) {
145
- if (deletePath(contents, path.split("."), () => true)) pruned.push(path);
146
- }
147
180
 
148
181
  if (pruned.length === 0) {
149
- verbose("omp config.yml carries no retired keys");
182
+ verbose(`omp ${label} carries no retired keys`);
150
183
  return 0;
151
184
  }
152
185
  if (ctx.dryRun) {
153
- echo(`[dry-run] prune ${configFile}: ${pruned.join(", ")}`);
186
+ echo(`[dry-run] prune ${file}: ${pruned.join(", ")}`);
154
187
  return pruned.length;
155
188
  }
156
- writeFileSync(configFile, String(doc));
157
- change(`omp config.yml pruned ${pruned.length} retired key(s): ${pruned.join(", ")}`);
189
+ writeFileSync(file, String(doc));
190
+ change(`omp ${label} pruned ${pruned.length} retired key(s): ${pruned.join(", ")}`);
158
191
  return pruned.length;
159
192
  }
193
+
194
+ /** Prunes retired kit-owned keys from a deployed omp config.yml. */
195
+ export function syncOmpRemovals(ctx: Ctx, configFile: string): number {
196
+ return pruneRetired(ctx, configFile, "config.yml", [
197
+ ...OMP_RETIRED_VALUES.map(([path, value]): RetiredEntry => [
198
+ path,
199
+ (node) => isScalar(node) && node.value === value,
200
+ ]),
201
+ ...OMP_RETIRED_KEYS.map((path): RetiredEntry => [path, () => true]),
202
+ ]);
203
+ }
204
+
205
+ /** Prunes retired kit-owned blocks from a deployed omp models.yml. */
206
+ export function syncOmpModelRemovals(ctx: Ctx, modelsFile: string): number {
207
+ return pruneRetired(
208
+ ctx,
209
+ modelsFile,
210
+ "models.yml",
211
+ OMP_RETIRED_MODEL_BLOCKS.map(([path, block]): RetiredEntry => [
212
+ path,
213
+ (node) => isMap(node) && isDeepStrictEqual(node.toJSON(), block),
214
+ ]),
215
+ );
216
+ }
@@ -21,7 +21,7 @@ import { mergeOmpConfig, mergeOmpModels } from "./ompYaml";
21
21
  import { ensureDirectory, syncMergedYaml, syncWholeFile } from "./ompFileDeploy";
22
22
  import { syncMarketplace } from "./ompMarketplace";
23
23
  import { syncPlugins } from "./ompPlugins";
24
- import { syncOmpRemovals } from "./ompRemovals";
24
+ import { syncOmpModelRemovals, syncOmpRemovals } from "./ompRemovals";
25
25
 
26
26
  export interface OmpState {
27
27
  readonly pluginsInstalled: number;
@@ -56,6 +56,7 @@ export async function ompSync(ctx: Ctx): Promise<OmpState> {
56
56
  // mergeOmpConfig is additive, so the prune must run on the merged result.
57
57
  syncOmpRemovals(ctx, p(agentDir, "config.yml"));
58
58
  syncMergedYaml(ctx, "SoT/.omp/models.yml", p(agentDir, "models.yml"), mergeOmpModels);
59
+ syncOmpModelRemovals(ctx, p(agentDir, "models.yml"));
59
60
 
60
61
  const intercomRootSetting = process.env["PI_CODING_AGENT_DIR"];
61
62
  const intercomRoot =
@@ -1,7 +1,7 @@
1
1
  // Generated by cli/scripts/generate-sot-payload.ts. DO NOT EDIT.
2
2
  // Edit SoT/, notification.mp3, or package.json, then run: bun cli/scripts/generate-sot-payload.ts
3
3
 
4
- export const GENERATED_PACKAGE_VERSION = "0.20.0"
4
+ export const GENERATED_PACKAGE_VERSION = "0.20.1"
5
5
 
6
6
  export const GENERATED_PAYLOAD_TEXT = {
7
7
  "SoT/.agents/skills.txt": "# Universal AI-agent skill manifest intentionally empty.\n# Global skill discovery is opt-in: add one <owner>/<repo> slug per line.\n# EngineNative ignores comments and blank lines.\n",
@@ -21,7 +21,7 @@ export const GENERATED_PAYLOAD_TEXT = {
21
21
  "SoT/.omp/config.yml": "statusLine:\n compactThinkingLevel: false\n\ndefaultThinkingLevel: high\n\ncycleOrder:\n - smol\n - default\n - slow\n - fable\n - astra\n\ntier:\n openai: none\n anthropic: none\n\nadvisor:\n enabled: true\n syncBacklog: \"1\"\n\ngithub:\n enabled: true\n\nfind:\n enabled: true\n\ntask:\n eager: always\n showResolvedModelBadge: true\n softRequestBudget: 200\n softRequestBudgetNotice: true\n batch: true\n enableLsp: true\n enableEffort: true\n maxEffort: max\n maxConcurrency: 16\n maxRecursionDepth: 2\n maxRuntimeMs: 3600000\n agentModelOverrides:\n reviewer: \"@task\"\n security-reviewer: \"@task\"\n code-reviewer: \"@task\"\n plan-reviewer: \"@task\"\n\nmodelRoles:\n smol: openai-codex/gpt-6-luna:medium\n advisor: anthropic/claude-opus-5-5:medium\n designer: anthropic/claude-opus-5-5:high\n plan: anthropic/claude-opus-5-5:xhigh\n commit: openai-codex/gpt-6-luna:medium\n task: openai-codex/gpt-6-sol:high\n vision: anthropic/claude-opus-5-5:medium\n tiny: openai-codex/gpt-6-luna:low\n default: anthropic/claude-opus-5-5:high\n slow: anthropic/claude-opus-5-5:xhigh\n fable: anthropic/claude-fable-5-1:medium\n switch_fable: anthropic/claude-fable-5-1:medium\n astra: openai-codex/gpt-6-astra:xhigh\n web: web/firecrawl\n\nmodelTags:\n fable:\n name: Fable 5.1\n switch_fable:\n name: Fable switch default\n hidden: true\n astra:\n name: GPT-6 Astra\n\ndisplay:\n showTokenUsage: true\n\nproviders:\n anthropic:\n serverSideFallback: false\n fetch: auto\n webSearchTimeoutSeconds: 30\n\nretry:\n usageAwareFallback: true\n fallbackChains:\n default:\n - openai-codex/gpt-6-sol:high\n advisor: []\n task:\n - anthropic/claude-opus-5-5:high\n vision:\n - openai-codex/gpt-6-sol:medium\n smol:\n - anthropic/claude-opus-5-5:low\n tiny:\n - anthropic/claude-opus-5-5:low\n commit:\n - anthropic/claude-opus-5-5:medium\n switch_fable: []\n fable:\n - openai-codex/gpt-6-astra:xhigh\n astra:\n - anthropic/claude-fable-5-1:medium\n web:\n - web/exa\n - web/perplexity\n - openai-codex/gpt-6-luna\n - web/parallel\n - web/zai\n - web/tinyfish\n - web/jina\n - web/kagi\n - web/tavily\n - web/brave\n - web/kimi\n - web/synthetic\n - web/ollama\n - web/searxng\n - web/startpage\n - web/duckduckgo\n - web/ecosia\n - web/google\n - web/mojeek\n - web/public\n\nincludeWorkspaceTree: false\n\nbranchSummary:\n enabled: true\n\ncommands:\n enableOpencodeProject: false\n enableOpencodeUser: false\n\nskills:\n enableClaudeUser: false\n enableCodexUser: false\n enableAgentsUser: true\n\nsteeringMode: all\n\ndev:\n autoqa: false\n autoqaConsent: denied\n\ncompaction:\n thresholdTokens: -1\n idleEnabled: true\n handoffSaveToDisk: true\n\ndoubleEscapeAction: tree\ntextVerbosity: low\n\nfeatures:\n unexpectedStopDetection: smart\n\ncodexResets:\n autoRedeem: \"no\"\n\nstartup:\n quiet: true\n\ntools:\n approvalMode: yolo\n",
22
22
  "SoT/.omp/intercom.json": "{\n \"brokerCommand\": \"bun\",\n \"brokerArgs\": []\n}\n",
23
23
  "SoT/.omp/mcp.json": "{\n \"$schema\": \"https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json\",\n \"disabledServers\": [\n \"chrome-devtools\",\n \"context7:context7\",\n \"openaiDeveloperDocs\"\n ]\n}\n",
24
- "SoT/.omp/models.yml": "providers:\n # Temporary metadata for an id the shared models.dev catalog still publishes\n # as an empty stub. Remove this block once that catalog row carries the real\n # context window, output cap, ladder, and prices. `defaultLevel` is the kit's\n # choice for a bare selector, not the Claude API default, which is `medium`.\n anthropic:\n modelOverrides:\n claude-opus-5-5:\n name: Claude Opus 5.5\n reasoning: true\n input:\n - text\n - image\n contextWindow: 1000000\n maxTokens: 128000\n cost:\n input: 4\n output: 20\n cacheRead: 0.2\n cacheWrite: 5\n thinking:\n mode: effort\n efforts:\n - low\n - medium\n - high\n - xhigh\n - max\n defaultLevel: high\n openai-codex:\n modelOverrides:\n gpt-6-astra:\n thinking:\n mode: effort\n efforts:\n - low\n - medium\n - high\n - xhigh\n - max\n defaultLevel: xhigh\n"
24
+ "SoT/.omp/models.yml": "providers:\n openai-codex:\n modelOverrides:\n gpt-6-astra:\n thinking:\n mode: effort\n efforts:\n - low\n - medium\n - high\n - xhigh\n - max\n defaultLevel: xhigh\n"
25
25
  } as const
26
26
 
27
27
  export const GENERATED_PAYLOAD_BASE64 = {
@@ -50,4 +50,4 @@ export const GENERATED_PAYLOAD_PATHS = [
50
50
  "notification.mp3"
51
51
  ] as const
52
52
 
53
- export const GENERATED_PAYLOAD_HASH = "f57eb42f09dac1f0336ff710bf9e6f3cf3ac68d8f72c9ff5212348ab943d1931"
53
+ export const GENERATED_PAYLOAD_HASH = "e2be3fa8d70047257cc542bd25040bbb1d5fe167d1ab4486f7c947c2955b0c5b"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docks-kit",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "description": "Portable AI coding agent config kit — SoT sync engine + typed CLI for Claude Code, Codex, and universal agent skills",
5
5
  "type": "module",
6
6
  "license": "MIT",