docks-kit 0.20.0 → 0.20.2
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 +4 -4
- package/cli/docs/omp-models.md +183 -144
- package/cli/docs/toolchain.md +5 -1
- package/cli/src/engine-native/claudeLsp.ts +24 -9
- package/cli/src/engine-native/ompRemovals.ts +78 -21
- package/cli/src/engine-native/ompSync.ts +2 -1
- package/cli/src/generated/sotPayload.ts +7 -7
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -57,7 +57,7 @@ launcher can fall back to Bun source.
|
|
|
57
57
|
|
|
58
58
|
Codex SoT notes:
|
|
59
59
|
- `SoT/.codex/AGENTS.md` deploys to `~/.codex/AGENTS.md` as global Codex instructions.
|
|
60
|
-
- `SoT/.codex/config.toml` pins Codex to `model = "gpt-6-sol"`, sets normal and plan reasoning to `high` with concise summaries, and sets `model_verbosity = "low"`, `personality`, live top-level `web_search`, workspace-write sandboxing with sandboxed command network access, cross-session `memories` (+ dedicated note tools), `[agents]` subagent limits (`max_threads = 12`, `max_depth = 2` — intentionally above Codex defaults for broad parallel kit work; deeper recursion increases cost and predictability risk), a 128 KiB `project_doc_max_bytes` budget for the repo-side AGENTS.md chain (the global `~/.codex/AGENTS.md` is uncapped and not counted), and enables the two Docks plugins `docks@docks` and `plan-lifecycle@docks` (the shared plan lifecycle).
|
|
60
|
+
- `SoT/.codex/config.toml` pins Codex to `model = "gpt-6.1-sol"`, sets normal and plan reasoning to `high` with concise summaries, and sets `model_verbosity = "low"`, `personality`, live top-level `web_search`, workspace-write sandboxing with sandboxed command network access, cross-session `memories` (+ dedicated note tools), `[agents]` subagent limits (`max_threads = 12`, `max_depth = 2` — intentionally above Codex defaults for broad parallel kit work; deeper recursion increases cost and predictability risk), a 128 KiB `project_doc_max_bytes` budget for the repo-side AGENTS.md chain (the global `~/.codex/AGENTS.md` is uncapped and not counted), and enables the two Docks plugins `docks@docks` and `plan-lifecycle@docks` (the shared plan lifecycle).
|
|
61
61
|
- `SoT/.codex/rules/*.rules` deploys to `~/.codex/rules/` as kit-managed Codex command policy. This is Codex's equivalent of permission allow/prompt/block rules; user-learned approvals in `~/.codex/rules/default.rules` are preserved.
|
|
62
62
|
- `SoT/.codex/plugins/marketplace.json` deploys to Codex's personal marketplace path at `~/.agents/plugins/marketplace.json`; when the `codex` CLI is available, sync reruns `codex plugin add <plugin@marketplace>` for enabled SoT plugins so stale cached installs are refreshed.
|
|
63
63
|
- Codex `/import` can copy Claude hooks into `~/.codex/hooks.json`. `codexSync.ts removeRetiredImportedHooks, legacy SessionStart cleanup` removes only recognized hooks from retired docks-kit Claude settings, backs up a changed file, and preserves user-authored hooks. The current Claude SessionStart program emits the structured JSON shape shared by both tools.
|
|
@@ -75,10 +75,10 @@ omp SoT notes:
|
|
|
75
75
|
- `ompSync.ts syncMergedYaml` deep-merges `config.yml` through `ompYaml.ts mergeOmpConfig` and `models.yml` through `mergeOmpModels`. Both wrap one generic mapping merge; only the config wrapper prunes stale `retry.fallbackChains` wildcards.
|
|
76
76
|
- `ompSync.ts` runs `ompRemovals.ts syncOmpRemovals, retired-key inventory` right after the config merge, and that pass force-prunes retired kit-owned keys from `~/.omp/agent/config.yml` on every sync, without `--reconcile`. The pass is required because `mergeOmpConfig` is additive, so removing a key from the SoT alone never removes it from a deployed file. A key retired with a recorded value is pruned only while the deployed value still matches that value, so a user edit survives; a key retired outright, such as `providers.webSearchOrder`, is pruned at any value.
|
|
77
77
|
- `cycleOrder` ends with `astra` as its fifth stop. `modelRoles.astra` is `openai-codex/gpt-6-astra:xhigh`, and `modelTags.astra` is visible. Astra and Fable fall back to each other through concrete selectors. `modelRoles.fable` remains `anthropic/claude-fable-5-1:medium`, with visible `modelTags.fable`. The hidden `switch_fable` role uses the same Fable selector and keeps an empty fallback chain.
|
|
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
|
|
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-
|
|
78
|
+
- `modelRoles.task` is `openai-codex/gpt-6.1-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 any GPT model (`openai-codex/gpt-*`, including GPT-6.1 Sol and GPT-6 Astra) in the advisor role or chain; Astra also costs too much for this role. `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. The `SoT/toolchain.json` omp floor is 18.4.4, the oldest release the kit tested with `gpt-6.1-sol`. That release lists and serves the model through the `openai-codex` provider. `cli/docs/omp-models.md` records the checks.
|
|
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-29 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, at 58. AA has measured speed and latency for Opus 5.5 max and every GPT-6.1 Sol level; GPT-6 Luna medium is the only unmeasured speed and latency row.
|
|
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.
|
|
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. The removal switches omp from the block's `thinking.mode: effort` (a `budget_tokens` value per level from `ANTHROPIC_THINKING`, no effort value) to the catalog's `anthropic-adaptive` (adaptive thinking with the role's effort level); every kit Opus selector names its level, so the block's bare-selector `defaultLevel: high` is not needed. `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.
|
package/cli/docs/omp-models.md
CHANGED
|
@@ -8,30 +8,29 @@ against.
|
|
|
8
8
|
|
|
9
9
|
| Role | Model | Level | Index | Cost/task | TTFT |
|
|
10
10
|
|---|---|---|---:|---:|---:|
|
|
11
|
-
| `default` | `anthropic/claude-opus-5-5` | high | 54 | $1.82 |
|
|
12
|
-
| `slow` | `anthropic/claude-opus-5-5` | xhigh | 56 | $3.46 |
|
|
13
|
-
| `plan` | `anthropic/claude-opus-5-5` | xhigh | 56 | $3.46 |
|
|
14
|
-
| `task` | `openai-codex/gpt-6-sol` | high |
|
|
15
|
-
| `advisor` | `anthropic/claude-opus-5-5` | medium | 51 | $1.34 |
|
|
16
|
-
| `designer` | `anthropic/claude-opus-5-5` | high | 54 | $1.82 |
|
|
17
|
-
| `vision` | `anthropic/claude-opus-5-5` | medium | 51 | $1.34 |
|
|
11
|
+
| `default` | `anthropic/claude-opus-5-5` | high | 54 | $1.82 | 52.85 s |
|
|
12
|
+
| `slow` | `anthropic/claude-opus-5-5` | xhigh | 56 | $3.46 | 136.30 s |
|
|
13
|
+
| `plan` | `anthropic/claude-opus-5-5` | xhigh | 56 | $3.46 | 136.30 s |
|
|
14
|
+
| `task` | `openai-codex/gpt-6.1-sol` | high | 50 | $0.32 | 57.26 s |
|
|
15
|
+
| `advisor` | `anthropic/claude-opus-5-5` | medium | 51 | $1.34 | 21.87 s |
|
|
16
|
+
| `designer` | `anthropic/claude-opus-5-5` | high | 54 | $1.82 | 52.85 s |
|
|
17
|
+
| `vision` | `anthropic/claude-opus-5-5` | medium | 51 | $1.34 | 21.87 s |
|
|
18
18
|
| `smol` / `commit` | `openai-codex/gpt-6-luna` | medium | 29 | $0.02 | n/a |
|
|
19
|
-
| `tiny` | `openai-codex/gpt-6-luna` | low | 21 | $0.0045 |
|
|
20
|
-
| `fable` | `anthropic/claude-fable-5-1` | medium | 49 | $2.98 | 8.
|
|
21
|
-
| `switch_fable` | `anthropic/claude-fable-5-1` | medium | 49 | $2.98 | 8.
|
|
22
|
-
| `astra` | `openai-codex/gpt-6-astra` | xhigh | 52 | $2.31 |
|
|
19
|
+
| `tiny` | `openai-codex/gpt-6-luna` | low | 21 | $0.0045 | 2.18 s |
|
|
20
|
+
| `fable` | `anthropic/claude-fable-5-1` | medium | 49 | $2.98 | 8.00 s |
|
|
21
|
+
| `switch_fable` | `anthropic/claude-fable-5-1` | medium | 49 | $2.98 | 8.00 s |
|
|
22
|
+
| `astra` | `openai-codex/gpt-6-astra` | xhigh | 52 | $2.31 | 126.90 s |
|
|
23
23
|
| `web` | `web/firecrawl` | n/a | n/a | n/a | n/a |
|
|
24
24
|
|
|
25
25
|
The table reports the measured Artificial Analysis figures for each assigned
|
|
26
26
|
model and level. It states no motive that the config or omp's own
|
|
27
27
|
documentation does not establish. AA has not measured output speed or latency
|
|
28
|
-
for GPT-6
|
|
29
|
-
|
|
28
|
+
for GPT-6 Luna medium, so that row carries `n/a` for TTFT. AA measures no web
|
|
29
|
+
search provider, so the `web` row carries no figures.
|
|
30
30
|
|
|
31
|
-
The role map carries no Coding Agent Index column. That index
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
lists the entries.
|
|
31
|
+
The role map carries no Coding Agent Index column. That index measures specific
|
|
32
|
+
agent harnesses and model levels, not omp roles. The snapshot section below
|
|
33
|
+
lists the relevant entries, including Codex with GPT-6.1 Sol high.
|
|
35
34
|
|
|
36
35
|
### GPT-6 Sol and GPT-6 Luna availability
|
|
37
36
|
|
|
@@ -56,9 +55,18 @@ omp 18.2.9 and codex-cli 0.153.3:
|
|
|
56
55
|
|
|
57
56
|
On 2026-09-25, omp 18.3.1 listed `gpt-6-sol` and `gpt-6-luna` in
|
|
58
57
|
`omp models openai-codex`. An `omp -p --mode json` run on each selector
|
|
59
|
-
recorded `gpt-6-sol` and `gpt-6-luna` as the serving model, so the
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
recorded `gpt-6-sol` and `gpt-6-luna` as the serving model, so the selected
|
|
59
|
+
omp roles ran GPT-6 on that date.
|
|
60
|
+
|
|
61
|
+
On 2026-09-29, omp 18.4.4 listed `gpt-6.1-sol` at low, medium, high, xhigh,
|
|
62
|
+
and max, with a 272K context window and 128K maximum output. An
|
|
63
|
+
`omp -p --mode json --model openai-codex/gpt-6.1-sol:low` run recorded
|
|
64
|
+
`gpt-6.1-sol` as the serving model. To recheck, run
|
|
65
|
+
`omp models openai-codex`; the `gpt-6.1-sol` row must appear. Codex-cli
|
|
66
|
+
0.159.0 could not complete `codex exec -m gpt-6.1-sol`: the login had ended,
|
|
67
|
+
and the request returned HTTP 401 `refresh_token_invalidated`. The Codex
|
|
68
|
+
model cache was last fetched on 2026-09-22 and does not list `gpt-6.1-sol`,
|
|
69
|
+
so that Codex run did not establish model availability.
|
|
62
70
|
|
|
63
71
|
What omp's settings catalog establishes about these roles:
|
|
64
72
|
|
|
@@ -82,7 +90,7 @@ cross-vendor fallback.
|
|
|
82
90
|
`retry.fallbackChains.fable` holds `openai-codex/gpt-6-astra:xhigh`.
|
|
83
91
|
Each deliberate cycle stop falls to the other vendor. Without these explicit
|
|
84
92
|
chains, `retry.fallbackChains.default` would send either stop to
|
|
85
|
-
`openai-codex/gpt-6-sol:high`.
|
|
93
|
+
`openai-codex/gpt-6.1-sol:high`.
|
|
86
94
|
Chain entries are concrete selectors, not role aliases, so this pair cannot
|
|
87
95
|
recurse. The hidden `switch_fable` chain stays empty.
|
|
88
96
|
|
|
@@ -97,7 +105,11 @@ on `openai-codex/gpt-6-sol:medium` looped. In one session the advisor made
|
|
|
97
105
|
window omp lists for GPT-6 Sol. With the advisor on Opus 5.5 medium, the
|
|
98
106
|
same kind of session made about one advisor request per main-agent request
|
|
99
107
|
and called `advise` normally. The owner excluded GPT-6 Sol from the advisor
|
|
100
|
-
role and its fallback chain.
|
|
108
|
+
role and its fallback chain. On 2026-09-29 the owner extended the exclusion to
|
|
109
|
+
every GPT model, including GPT-6.1 Sol and GPT-6 Astra. No GPT model was
|
|
110
|
+
tested as the advisor again, and Astra costs too much for this role. Do not
|
|
111
|
+
put an `openai-codex/gpt-*` selector in `modelRoles.advisor` or
|
|
112
|
+
`retry.fallbackChains.advisor`.
|
|
101
113
|
|
|
102
114
|
`modelRoles.web` is `web/firecrawl`, and `retry.fallbackChains.web` lists the
|
|
103
115
|
explicit 20-entry provider order that follows it. The two keys replace the
|
|
@@ -124,31 +136,38 @@ The order keeps Firecrawl, Exa, Perplexity, and Codex first. The remaining
|
|
|
124
136
|
|
|
125
137
|
## Artificial Analysis snapshot
|
|
126
138
|
|
|
127
|
-
Source: `https://artificialanalysis.ai`, read on 2026-09-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
and
|
|
140
|
-
|
|
139
|
+
Source: `https://artificialanalysis.ai`, read on 2026-09-29 at Intelligence
|
|
140
|
+
Index v4.3.2 and Coding Agent Index v1.5. Each per-level row comes from the
|
|
141
|
+
metric table of `/models/comparisons/<level-slug>-vs-gpt-5-6-sol-high`.
|
|
142
|
+
Each page title names the requested model and level and prints the same
|
|
143
|
+
Intelligence Index version. AA serves `max` under the bare model slug.
|
|
144
|
+
The GPT-5.6 Sol high self-comparison URL does not load, so that baseline row
|
|
145
|
+
comes from the GPT-5.6 Sol high column of the GPT-6.1 Sol high comparison.
|
|
146
|
+
Index composition changes between versions; figures from an earlier capture
|
|
147
|
+
cannot be mixed with these.
|
|
148
|
+
|
|
149
|
+
The Coding Agent Index page (`/agents/coding-agents`) lists 30 harness, model,
|
|
150
|
+
and level entries. It covers GPT-6.1 Sol with Codex at low, medium, high,
|
|
151
|
+
xhigh, and max; Opus 5.5 and Fable 5.1 with Claude Code at max; and Astra and
|
|
152
|
+
Luna with Codex at max. It also covers Grok Build with Grok 4.7 at xhigh,
|
|
153
|
+
Antigravity SDK with Gemini 3.8 Flash at high, and Opencode with GLM-5.3 and
|
|
154
|
+
Kimi Code CLI with Kimi K3 without levels. The relevant published scores are:
|
|
141
155
|
|
|
142
156
|
| Harness and model | Coding Agent Index |
|
|
143
157
|
|---|---:|
|
|
144
|
-
| Claude Code -
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
| Codex - GPT-6 Sol (
|
|
148
|
-
| Codex - GPT-6
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
| Claude Code - Opus 5.5 (max) | 66 |
|
|
159
|
+
| Claude Code - Fable 5.1 (max, with fallback) | 62 |
|
|
160
|
+
| Codex - GPT-6 Astra (max) | 62 |
|
|
161
|
+
| Codex - GPT-6.1 Sol (xhigh) | 63 |
|
|
162
|
+
| Codex - GPT-6.1 Sol (medium) | 61 |
|
|
163
|
+
| Codex - GPT-6.1 Sol (high) | 60 |
|
|
164
|
+
| Codex - GPT-6.1 Sol (max) | 60 |
|
|
165
|
+
| Codex - GPT-6.1 Sol (low) | 57 |
|
|
166
|
+
| Claude Code - Opus 5 (max) | 60 |
|
|
167
|
+
| Codex - GPT-6 Luna (max) | 41 |
|
|
168
|
+
|
|
169
|
+
These are coding-agent scores for specific harnesses and levels, not scores
|
|
170
|
+
for the omp role map.
|
|
152
171
|
|
|
153
172
|
Column meanings:
|
|
154
173
|
|
|
@@ -167,35 +186,52 @@ Column meanings:
|
|
|
167
186
|
|
|
168
187
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
169
188
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
170
|
-
| max | 58 | $5.98 | 119k | 260M |
|
|
171
|
-
| xhigh | 56 | $3.46 | 66k | 100M |
|
|
172
|
-
| high | 54 | $1.82 | 36k | 53M |
|
|
173
|
-
| medium | 51 | $1.34 | 26k | 38M |
|
|
174
|
-
| low | 42 | $0.55 | 10k | 20M |
|
|
189
|
+
| max | 58 | $5.98 | 119k | 260M | 93 | 692.63 | 60% |
|
|
190
|
+
| xhigh | 56 | $3.46 | 66k | 100M | 80 | 136.30 | 60% |
|
|
191
|
+
| high | 54 | $1.82 | 36k | 53M | 74 | 52.85 | 57% |
|
|
192
|
+
| medium | 51 | $1.34 | 26k | 38M | 74 | 21.87 | 53% |
|
|
193
|
+
| low | 42 | $0.55 | 10k | 20M | 74 | 12.49 | 31% |
|
|
175
194
|
|
|
176
195
|
Price: $4.00 in, $20.00 out, $0.20 cache hit per 1M. The Anthropic platform
|
|
177
|
-
documentation
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
`medium`. All AA levels run with fallback. Max
|
|
182
|
-
Index in this topic at this capture. AA
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`SoT/.omp/models.yml`
|
|
186
|
-
`modelOverrides` block, because the shared catalog
|
|
187
|
-
stub with null limits and zero cost.
|
|
188
|
-
|
|
196
|
+
documentation lists the same input, output, and cache-read prices. It adds a
|
|
197
|
+
$5.00 five-minute cache write and an $8.00 one-hour cache write, which the AA
|
|
198
|
+
comparison table does not show. Context is 1M, with 128K maximum output.
|
|
199
|
+
Adaptive thinking is always on, and the Claude API default effort is
|
|
200
|
+
`medium`. All AA levels run with fallback. Max has the highest Intelligence
|
|
201
|
+
Index in this topic at this capture. AA now measures speed and latency for
|
|
202
|
+
every Opus 5.5 level; medium has a shorter TTFT than high.
|
|
203
|
+
|
|
204
|
+
Until 0.20.1, `SoT/.omp/models.yml` carried the Anthropic limits and prices as
|
|
205
|
+
an `anthropic` `modelOverrides` block, because the shared catalog served this
|
|
206
|
+
id as a stub with null limits and zero cost. On 2026-09-25 the catalog at
|
|
207
|
+
`catalog.stencil.so` published the same context window, output cap, ladder,
|
|
208
|
+
and prices, so the block was removed. Sync prunes the deployed copy only while
|
|
209
|
+
it still equals the shipped block.
|
|
210
|
+
|
|
211
|
+
The removal fixes how the Opus role levels reach the API. The block set
|
|
212
|
+
`thinking.mode: effort`. For that mode, omp 18.3.1 (`packages/ai/src/stream.ts`,
|
|
213
|
+
tag `v18.3.1`) sends `thinking: {type: "enabled", budget_tokens}` and no
|
|
214
|
+
`output_config.effort`. The level only picked the budget from
|
|
215
|
+
`ANTHROPIC_THINKING`: `medium` 8,192, `high` 16,384, and `xhigh` and `max`
|
|
216
|
+
both 32,768 tokens. So before 0.20.1 the levels in the role table above were
|
|
217
|
+
not the effort levels that Artificial Analysis measured, and `xhigh` equaled
|
|
218
|
+
`max`. The catalog row sets `thinking.mode: anthropic-adaptive`, so omp now
|
|
219
|
+
sends `thinking: {type: "adaptive"}` with `output_config.effort` set to the
|
|
220
|
+
role level. The block also set `defaultLevel: high` for a bare
|
|
221
|
+
`claude-opus-5-5` selector. `SoT/.omp/config.yml` names a level on every Opus
|
|
222
|
+
selector, so no kit role depends on that default. Runs on
|
|
223
|
+
`anthropic/claude-opus-5-5:high` and `:max` after the prune answered with
|
|
224
|
+
exit 0.
|
|
189
225
|
|
|
190
226
|
### Claude Fable 5.1 (Anthropic) - `anthropic/claude-fable-5-1`
|
|
191
227
|
|
|
192
228
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
193
229
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
194
|
-
| max | 53 | $7.63 | 78k | 188M |
|
|
195
|
-
| xhigh | 53 | $5.98 | 61k | 121M |
|
|
196
|
-
| high | 51 | $3.91 | 38k | 62M |
|
|
197
|
-
| medium | 49 | $2.98 | 28k | 44M |
|
|
198
|
-
| low | 47 | $2.37 | 22k | 33M |
|
|
230
|
+
| max | 53 | $7.63 | 78k | 188M | 69 | 285.98 | 52% |
|
|
231
|
+
| xhigh | 53 | $5.98 | 61k | 121M | 57 | 104.51 | 55% |
|
|
232
|
+
| high | 51 | $3.91 | 38k | 62M | 52 | 26.01 | 52% |
|
|
233
|
+
| medium | 49 | $2.98 | 28k | 44M | 50 | 8.00 | 45% |
|
|
234
|
+
| low | 47 | $2.37 | 22k | 33M | 48 | 4.83 | 40% |
|
|
199
235
|
|
|
200
236
|
Price: $10.00 in, $50.00 out, $0.25 cache hit per 1M. Context 1M. All levels
|
|
201
237
|
run with fallback.
|
|
@@ -204,62 +240,63 @@ run with fallback.
|
|
|
204
240
|
|
|
205
241
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
206
242
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
207
|
-
| max | 53 | $3.26 | 27k | 60M |
|
|
208
|
-
| xhigh | 52 | $2.31 | 17k | 38M |
|
|
209
|
-
| high | 51 | $1.73 | 12k | 26M | 50 |
|
|
210
|
-
| medium | 50 | $1.54 | 10k | 19M |
|
|
211
|
-
| low | 46 | $0.82 | 4k | 10M |
|
|
243
|
+
| max | 53 | $3.26 | 27k | 60M | 57 | 305.56 | 59% |
|
|
244
|
+
| xhigh | 52 | $2.31 | 17k | 38M | 49 | 126.90 | 60% |
|
|
245
|
+
| high | 51 | $1.73 | 12k | 26M | 50 | 41.09 | 54% |
|
|
246
|
+
| medium | 50 | $1.54 | 10k | 19M | 47 | 4.88 | 49% |
|
|
247
|
+
| low | 46 | $0.82 | 4k | 10M | 49 | 2.81 | 42% |
|
|
212
248
|
|
|
213
249
|
Price: $10.00 in, $50.00 out, $1.00 cache hit per 1M. Context 1M. Knowledge
|
|
214
250
|
cutoff 2026-04-30. AA publishes no non-reasoning Astra row.
|
|
215
251
|
|
|
216
|
-
### GPT-6 Sol (OpenAI) - `openai-codex/gpt-6-sol`
|
|
252
|
+
### GPT-6.1 Sol (OpenAI) - `openai-codex/gpt-6.1-sol`
|
|
217
253
|
|
|
218
254
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
219
255
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
220
|
-
| max |
|
|
221
|
-
| xhigh |
|
|
222
|
-
| high |
|
|
223
|
-
| medium |
|
|
224
|
-
| low |
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
256
|
+
| max | 52 | $0.72 | 38k | 67M | 67 | 267.64 | 56% |
|
|
257
|
+
| xhigh | 51 | $0.39 | 18k | 36M | 64 | 68.65 | 54% |
|
|
258
|
+
| high | 50 | $0.32 | 13k | 25M | 66 | 57.26 | 52% |
|
|
259
|
+
| medium | 48 | $0.21 | 8k | 15M | 62 | 5.29 | 48% |
|
|
260
|
+
| low | 42 | $0.13 | 4k | 9M | 74 | 1.84 | 31% |
|
|
261
|
+
|
|
262
|
+
AA lists $2.00 input, $10.00 output, and $0.10 cached input per 1M tokens.
|
|
263
|
+
OpenAI also lists $2.50 per 1M cache-write tokens, a 1,050,000-token context,
|
|
264
|
+
922,000 maximum input tokens, and 128,000 maximum output tokens. Prompts above
|
|
265
|
+
272K input tokens cost 2x input and cache rates and 1.5x output rates for the
|
|
266
|
+
full request. The knowledge cutoff is 2026-04-30. The API effort ladder is
|
|
267
|
+
`low, medium, high, xhigh, max`, with `medium` as the default. There is no
|
|
268
|
+
`none`, `minimal`, or non-reasoning level.
|
|
233
269
|
|
|
234
270
|
### GPT-6 Luna (OpenAI) - `openai-codex/gpt-6-luna`
|
|
235
271
|
|
|
236
272
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
237
273
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
238
|
-
| max | 37 | $0.07 |
|
|
239
|
-
| xhigh | 34 | $0.04 | 27k |
|
|
240
|
-
| high | 32 | $0.03 | 20k | 47M |
|
|
241
|
-
| medium | 29 | $0.02 | 11k |
|
|
242
|
-
| low | 21 | $0.0045 | 2k | 8M |
|
|
243
|
-
| non-reasoning | 18 | $0.01 | 4k | 7M |
|
|
274
|
+
| max | 37 | $0.07 | 50k | 145M | 148 | 96.96 | 13% |
|
|
275
|
+
| xhigh | 34 | $0.04 | 27k | 69M | 133 | 16.87 | 8% |
|
|
276
|
+
| high | 32 | $0.03 | 20k | 47M | 132 | 10.97 | 5% |
|
|
277
|
+
| medium | 29 | $0.02 | 11k | 29M | n/a | n/a | 3% |
|
|
278
|
+
| low | 21 | $0.0045 | 2k | 8M | 124 | 2.18 | 0% |
|
|
279
|
+
| non-reasoning | 18 | $0.01 | 4k | 7M | 142 | 0.80 | 2% |
|
|
244
280
|
|
|
245
281
|
Price: $0.10 in, $0.50 out, $0.01 cache hit per 1M. OpenAI's model page lists
|
|
246
|
-
a $0.125 cache write, the same context, output, long-prompt billing
|
|
247
|
-
|
|
248
|
-
speed or latency for
|
|
282
|
+
a $0.125 cache write, the same context, output, and long-prompt billing as
|
|
283
|
+
GPT-6.1 Sol, and a 2026-05-18 knowledge cutoff. Luna also offers a
|
|
284
|
+
non-reasoning level. AA has not measured speed or latency for `medium`; it
|
|
285
|
+
has measured both at the other levels.
|
|
249
286
|
|
|
250
287
|
### GPT-5.6 Sol (OpenAI) - previous generation
|
|
251
288
|
|
|
252
289
|
The role map no longer uses GPT-5.6 Sol. This table stays as the measured
|
|
253
|
-
baseline for the
|
|
290
|
+
baseline for the current Sol task role.
|
|
254
291
|
|
|
255
292
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
256
293
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
257
|
-
| max | 47 | $1.99 | 29k | 90M |
|
|
258
|
-
| xhigh | 44 | $1.18 | 20k | 51M |
|
|
259
|
-
| high | 42 | $0.81 | 13k | 34M |
|
|
260
|
-
| medium | 39 | $0.50 | 8k | 21M |
|
|
261
|
-
| low | 33 | $0.26 | 4k | 13M |
|
|
262
|
-
| non-reasoning | 28 (estimated) | n/a | n/a | n/a |
|
|
294
|
+
| max | 47 | $1.99 | 29k | 90M | 85 | 98.68 | 40% |
|
|
295
|
+
| xhigh | 44 | $1.18 | 20k | 51M | 77 | 24.79 | 25% |
|
|
296
|
+
| high | 42 | $0.81 | 13k | 34M | 75 | 9.40 | 21% |
|
|
297
|
+
| medium | 39 | $0.50 | 8k | 21M | 73 | 4.92 | 15% |
|
|
298
|
+
| low | 33 | $0.26 | 4k | 13M | 74 | 2.26 | 1% |
|
|
299
|
+
| non-reasoning | 28 (estimated) | n/a | n/a | n/a | 67 | 1.03 | n/a |
|
|
263
300
|
|
|
264
301
|
Price: $4.00 in, $20.00 out, $0.40 cache hit per 1M. Context 1M. AA marks the
|
|
265
302
|
non-reasoning index score as estimated.
|
|
@@ -271,52 +308,54 @@ baseline for the GPT-6 Luna switch.
|
|
|
271
308
|
|
|
272
309
|
| Level | Index | Cost/task | Tokens/task | Index tokens | Speed t/s | TTFT s | TB 4.0 |
|
|
273
310
|
|---|---:|---:|---:|---:|---:|---:|---:|
|
|
274
|
-
| max | 37 | $0.18 | 41k | 154M |
|
|
275
|
-
| xhigh | 35 | $0.09 | 24k | 85M |
|
|
276
|
-
| high | 32 | $0.04 | 14k | 50M |
|
|
277
|
-
| medium | 25 | $0.02 | 4k | 18M |
|
|
278
|
-
| low | 21 | $0.01 | 3k | 10M |
|
|
279
|
-
| non-reasoning | 16 | $0.01 | 2k | 5M |
|
|
311
|
+
| max | 37 | $0.18 | 41k | 154M | 119 | 106.29 | 12% |
|
|
312
|
+
| xhigh | 35 | $0.09 | 24k | 85M | 115 | 43.42 | 4% |
|
|
313
|
+
| high | 32 | $0.04 | 14k | 50M | 110 | 14.13 | 3% |
|
|
314
|
+
| medium | 25 | $0.02 | 4k | 18M | 114 | 2.28 | 1% |
|
|
315
|
+
| low | 21 | $0.01 | 3k | 10M | 116 | 1.56 | 0% |
|
|
316
|
+
| non-reasoning | 16 | $0.01 | 2k | 5M | 113 | 0.68 | 1% |
|
|
280
317
|
|
|
281
318
|
Price: $0.20 in, $1.20 out, $0.02 cache hit per 1M. Context 1M.
|
|
282
319
|
|
|
283
|
-
## Why `task` runs GPT-6 Sol high
|
|
320
|
+
## Why `task` runs GPT-6.1 Sol high
|
|
284
321
|
|
|
285
|
-
`task` runs `openai-codex/gpt-6-sol:high`, the same level GPT-5.6 Sol ran
|
|
322
|
+
`task` runs `openai-codex/gpt-6.1-sol:high`, the same level GPT-5.6 Sol ran
|
|
286
323
|
before it. The owner uses Astra only for main orchestration, so Astra has a
|
|
287
|
-
dedicated `astra` cycle stop at `xhigh`.
|
|
288
|
-
|
|
324
|
+
dedicated `astra` cycle stop at `xhigh`. This comparison keeps the retired
|
|
325
|
+
Astra-low and GPT-5.6 Sol choices beside the current Sol levels.
|
|
289
326
|
|
|
290
|
-
| Metric | Astra low, retired | GPT-5.6 Sol high, previous | GPT-6 Sol high, current | GPT-6 Sol max | Opus 5.5 high, `default` |
|
|
327
|
+
| Metric | Astra low, retired | GPT-5.6 Sol high, previous generation | GPT-6.1 Sol high, current | GPT-6.1 Sol max | Opus 5.5 high, `default` |
|
|
291
328
|
|---|---:|---:|---:|---:|---:|
|
|
292
|
-
| Intelligence Index | 46 | 42 |
|
|
293
|
-
| Cost per Index task | $0.82 | $0.81 | $0.
|
|
294
|
-
| Output tokens per task | 4k | 13k |
|
|
295
|
-
| Index output tokens | 10M | 34M | 25M |
|
|
296
|
-
| Answer TTFT | 2.
|
|
297
|
-
| End-to-end response time |
|
|
298
|
-
| Time per index task |
|
|
299
|
-
| Terminal-Bench 4.0 | 42% | 21% |
|
|
300
|
-
| AA-Briefcase v1.1 | 1261 | 1370 |
|
|
301
|
-
| AA-Omniscience | 41 | 20 |
|
|
302
|
-
|
|
303
|
-
GPT-6 Sol high scores
|
|
304
|
-
against $0.81 per index task and
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
Astra low
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
$0.
|
|
315
|
-
|
|
329
|
+
| Intelligence Index | 46 | 42 | 50 | 52 | 54 |
|
|
330
|
+
| Cost per Index task | $0.82 | $0.81 | $0.32 | $0.72 | $1.82 |
|
|
331
|
+
| Output tokens per task | 4k | 13k | 13k | 38k | 36k |
|
|
332
|
+
| Index output tokens | 10M | 34M | 25M | 67M | 53M |
|
|
333
|
+
| Answer TTFT | 2.81 s | 9.40 s | 57.26 s | 267.64 s | 52.85 s |
|
|
334
|
+
| End-to-end response time | 13.08 s | 16.04 s | 64.81 s | 275.12 s | 59.60 s |
|
|
335
|
+
| Time per index task | 91.73 s | 176.91 s | 202.65 s | 568.66 s | 294.20 s |
|
|
336
|
+
| Terminal-Bench 4.0 | 42% | 21% | 52% | 56% | 57% |
|
|
337
|
+
| AA-Briefcase v1.1 | 1261 | 1370 | 1471 | 1564 | 1705 |
|
|
338
|
+
| AA-Omniscience | 41 | 20 | 41 | 42 | 41 |
|
|
339
|
+
|
|
340
|
+
GPT-6.1 Sol high scores 50 against GPT-5.6 Sol high at 42. It costs $0.32
|
|
341
|
+
against $0.81 per index task, and both use 13k output tokens per task. It
|
|
342
|
+
scores 52% against 21% on Terminal-Bench 4.0 and 1471 against 1370 on
|
|
343
|
+
AA-Briefcase. The new high level has a longer answer TTFT, 57.26 s against
|
|
344
|
+
9.40 s, and longer end-to-end response time, 64.81 s against 16.04 s.
|
|
345
|
+
|
|
346
|
+
Astra low scores 46 against GPT-6.1 Sol high at 50 and costs $0.82 against
|
|
347
|
+
$0.32 per index task. Astra low has the shorter TTFT, 2.81 s against
|
|
348
|
+
57.26 s. The owner reserves Astra for interactive orchestration.
|
|
349
|
+
|
|
350
|
+
GPT-6.1 Sol max scores two index points above high, at 52 against 50. It
|
|
351
|
+
costs $0.72 against $0.32 per index task, with TTFT of 267.64 s against
|
|
352
|
+
57.26 s. Opus 5.5 high scores 54 against GPT-6.1 Sol high at 50 and costs
|
|
353
|
+
$1.82 against $0.32. Opus is the `default`, `designer`, and fallback model,
|
|
354
|
+
not the `task` model.
|
|
316
355
|
|
|
317
356
|
The `astra` cycle stop runs xhigh: index 52, $2.31 per index task, and
|
|
318
|
-
|
|
319
|
-
|
|
357
|
+
126.90 s TTFT. AA publishes a Coding Agent Index entry for Astra only at
|
|
358
|
+
max with Codex, where it scores 62.
|
|
320
359
|
|
|
321
360
|
## How Astra is selected in practice
|
|
322
361
|
|
|
@@ -334,19 +373,19 @@ quick answer.
|
|
|
334
373
|
|
|
335
374
|
- The bundled `scout` and `sonic` agents carry `model: "@smol"` and
|
|
336
375
|
`thinking-level: medium` in their embedded frontmatter, so they run Luna,
|
|
337
|
-
not Sol or Astra. To move them, change `modelRoles.smol` or add a
|
|
376
|
+
not GPT-6.1 Sol or Astra. To move them, change `modelRoles.smol` or add a
|
|
338
377
|
`task.agentModelOverrides` entry for the agent name.
|
|
339
378
|
- The bundled `task` agent carries `model: "@task"` and
|
|
340
|
-
`thinking-level: auto`. It resolves GPT-6 Sol, and `auto`
|
|
341
|
-
to choose a thinking level.
|
|
379
|
+
`thinking-level: auto`. It resolves GPT-6.1 Sol high, and `auto`
|
|
380
|
+
classifies each prompt to choose a thinking level.
|
|
342
381
|
- `task.enableEffort` is `true`, so a caller can pass `effort: lo`, `med`, or
|
|
343
382
|
`hi`, which overrides `auto`.
|
|
344
383
|
- `task.maxEffort` is `max`, so `scout` and `sonic` run GPT-6 Luna `medium`
|
|
345
384
|
by default and GPT-6 Luna `max` with `effort: hi`.
|
|
346
|
-
- The bundled `reviewer` and `security-reviewer` inherit `@task`, now
|
|
347
|
-
Sol high.
|
|
385
|
+
- The bundled `reviewer` and `security-reviewer` inherit `@task`, now
|
|
386
|
+
GPT-6.1 Sol high.
|
|
348
387
|
- The `code-reviewer` and `plan-reviewer` override entries remain dormant.
|
|
349
|
-
Both point to `@task`, now GPT-6 Sol high. omp's task tool rejects both
|
|
388
|
+
Both point to `@task`, now GPT-6.1 Sol high. omp's task tool rejects both
|
|
350
389
|
names as unknown agents, so neither can spawn.
|
|
351
390
|
|
|
352
391
|
The runtime per-agent measurement from fresh `omp -p` runs on 2026-09-09
|
package/cli/docs/toolchain.md
CHANGED
|
@@ -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.
|
|
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 {
|
|
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
|
|
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`
|
|
3
|
-
* additive:
|
|
4
|
-
* deployed key absent from the SoT to the merged result.
|
|
5
|
-
* `SoT/.omp/config.yml`
|
|
6
|
-
*
|
|
7
|
-
* kit-owned keys on every sync, without `--reconcile`. Message
|
|
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
|
|
126
|
-
|
|
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(
|
|
165
|
+
if (!existsSync(file)) return 0;
|
|
129
166
|
|
|
130
|
-
const doc = parseDocument(readFileSync(
|
|
167
|
+
const doc = parseDocument(readFileSync(file, "utf8"));
|
|
131
168
|
const parseError = doc.errors[0];
|
|
132
169
|
if (parseError !== undefined) {
|
|
133
|
-
warn(`omp
|
|
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,
|
|
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(
|
|
182
|
+
verbose(`omp ${label} carries no retired keys`);
|
|
150
183
|
return 0;
|
|
151
184
|
}
|
|
152
185
|
if (ctx.dryRun) {
|
|
153
|
-
echo(`[dry-run] prune ${
|
|
186
|
+
echo(`[dry-run] prune ${file}: ${pruned.join(", ")}`);
|
|
154
187
|
return pruned.length;
|
|
155
188
|
}
|
|
156
|
-
writeFileSync(
|
|
157
|
-
change(`omp
|
|
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,12 +1,12 @@
|
|
|
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.
|
|
4
|
+
export const GENERATED_PACKAGE_VERSION = "0.20.2"
|
|
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",
|
|
8
|
-
"SoT/models.json": "{\n \"$comment\": \"Curated overlay for docks-kit model listings: aliases (kind alias) and notes always apply; the id rows are the fallback when the harness's live list is unavailable (harness not enabled, no login or cache, offline). Live sources: Claude via the Claude Code login against the Anthropic models API (cached 6 h in ~/.docks-kit/kit.db), Codex via ~/.codex/models_cache.json, omp via omp models --json.\",\n \"claude\": {\n \"verified\": \"2026-09-22\",\n \"models\": [\n { \"id\": \"best\", \"kind\": \"alias\", \"note\": \"Fable 5.1 where the org has access, latest Opus otherwise (Claude Code >=2.1.257; Claude apps gateway sessions still resolve Fable 5)\" },\n { \"id\": \"opus\", \"kind\": \"alias\", \"note\": \"latest Opus — the kit SoT default (Opus 5.5 from Claude Code >=2.1.280)\" },\n { \"id\": \"fable\", \"kind\": \"alias\", \"note\": \"Fable 5.1 — needs org access + Claude Code >=2.1.257 (Claude apps gateway sessions still resolve Fable 5)\" },\n { \"id\": \"sonnet\", \"kind\": \"alias\", \"note\": \"latest Sonnet (currently Sonnet 5)\" },\n { \"id\": \"haiku\", \"kind\": \"alias\", \"note\": \"latest Haiku (currently Haiku 4.5)\" },\n { \"id\": \"default\", \"kind\": \"alias\", \"note\": \"engine pseudo-value: deletes the deployed model key so the account default applies\" },\n { \"id\": \"claude-opus-5-5\", \"kind\": \"id\", \"note\": \"Opus 5.5 — needs Claude Code >=2.1.280\" },\n { \"id\": \"claude-fable-5-1\", \"kind\": \"id\", \"note\": \"Fable 5.1 — needs Claude Code >=2.1.257\" },\n { \"id\": \"claude-fable-5\", \"kind\": \"id\", \"note\": \"Fable 5 (legacy)\" },\n { \"id\": \"claude-opus-5\", \"kind\": \"id\", \"note\": \"Opus 5 (legacy)\" },\n { \"id\": \"claude-opus-4-8\", \"kind\": \"id\", \"note\": \"Opus 4.8 (legacy)\" },\n { \"id\": \"claude-sonnet-5\", \"kind\": \"id\", \"note\": \"Sonnet 5\" },\n { \"id\": \"claude-haiku-4-5-20251001\", \"kind\": \"id\", \"note\": \"Haiku 4.5\" }\n ]\n },\n \"codex\": {\n \"verified\": \"2026-09-
|
|
9
|
-
"SoT/toolchain.json": "{\n \"$comment\": \"Kit toolchain manifest - DATA only (versions, floors, policy); version probing and the doctor report live in cli/src/engine-native/toolchain.ts, and the one managed install lives in cli/src/engine-native/bun.ts bunBootstrap. kind: check (doctor visibility only) | managed (kit installs it when missing) | pin (no binary probe - a version pin for a package the kit installs through another tool, such as npx or `omp install`). policy (managed only): present (install when missing, never upgrade). `verified` = last kit-tested version; `pinnable` marks a tool whose `verified` release the bootstrap can install by exact tag. Supply-chain stance: every kit-driven install is pinned to `verified` - never floating @latest (npm-worm/Shai-Hulud surface). Update `verified` after testing a new release. upstream (optional) names where `docks-kit toolchain outdated` reads the newest release: npm package (optional major line) or GitHub repo releases with a tag prefix; results cache 24 h in ~/.docks-kit/kit.db; the report never installs or edits pins.\",\n \"tools\": {\n \"jq\": { \"kind\": \"check\", \"note\": \"optional operator CLI; EngineNative JSON and Claude runtime do not invoke it\" },\n \"curl\": { \"kind\": \"check\", \"note\": \"POSIX installer transport for the Bun bootstrap\" },\n \"git\": { \"kind\": \"check\", \"note\": \"plugin marketplaces (claude/codex clone them) + kit checkout updates\" },\n \"node\": { \"kind\": \"check\", \"floor\": \"22.22.2\",\n \"note\": \"hosts the npm globals installed for the Claude LSP plugins; the floor is typescript-language-server 6's engines requirement, so an older Node reports `below-floor` in `docks-kit toolchain` instead of silently installing an LSP server that cannot start\" },\n \"npm\": { \"kind\": \"check\", \"note\": \"npm-global installer; also backs the intelephense version probe (`npm ls -g`)\" },\n \"claude\": { \"kind\": \"check\", \"floor\": \"2.1.280\", \"note\": \"kit floor — lets the `opus` alias resolve to Opus 5.5, the default Opus from Claude Code 2.1.280, and subsumes the older Fable 5.1 (>=2.1.257) and Opus 5 (>=2.1.219) requirements (mirrors settings minimumVersion)\" },\n \"codex\": { \"kind\": \"check\", \"floor\": \"0.
|
|
8
|
+
"SoT/models.json": "{\n \"$comment\": \"Curated overlay for docks-kit model listings: aliases (kind alias) and notes always apply; the id rows are the fallback when the harness's live list is unavailable (harness not enabled, no login or cache, offline). Live sources: Claude via the Claude Code login against the Anthropic models API (cached 6 h in ~/.docks-kit/kit.db), Codex via ~/.codex/models_cache.json, omp via omp models --json.\",\n \"claude\": {\n \"verified\": \"2026-09-22\",\n \"models\": [\n { \"id\": \"best\", \"kind\": \"alias\", \"note\": \"Fable 5.1 where the org has access, latest Opus otherwise (Claude Code >=2.1.257; Claude apps gateway sessions still resolve Fable 5)\" },\n { \"id\": \"opus\", \"kind\": \"alias\", \"note\": \"latest Opus — the kit SoT default (Opus 5.5 from Claude Code >=2.1.280)\" },\n { \"id\": \"fable\", \"kind\": \"alias\", \"note\": \"Fable 5.1 — needs org access + Claude Code >=2.1.257 (Claude apps gateway sessions still resolve Fable 5)\" },\n { \"id\": \"sonnet\", \"kind\": \"alias\", \"note\": \"latest Sonnet (currently Sonnet 5)\" },\n { \"id\": \"haiku\", \"kind\": \"alias\", \"note\": \"latest Haiku (currently Haiku 4.5)\" },\n { \"id\": \"default\", \"kind\": \"alias\", \"note\": \"engine pseudo-value: deletes the deployed model key so the account default applies\" },\n { \"id\": \"claude-opus-5-5\", \"kind\": \"id\", \"note\": \"Opus 5.5 — needs Claude Code >=2.1.280\" },\n { \"id\": \"claude-fable-5-1\", \"kind\": \"id\", \"note\": \"Fable 5.1 — needs Claude Code >=2.1.257\" },\n { \"id\": \"claude-fable-5\", \"kind\": \"id\", \"note\": \"Fable 5 (legacy)\" },\n { \"id\": \"claude-opus-5\", \"kind\": \"id\", \"note\": \"Opus 5 (legacy)\" },\n { \"id\": \"claude-opus-4-8\", \"kind\": \"id\", \"note\": \"Opus 4.8 (legacy)\" },\n { \"id\": \"claude-sonnet-5\", \"kind\": \"id\", \"note\": \"Sonnet 5\" },\n { \"id\": \"claude-haiku-4-5-20251001\", \"kind\": \"id\", \"note\": \"Haiku 4.5\" }\n ]\n },\n \"codex\": {\n \"verified\": \"2026-09-29\",\n \"models\": [\n { \"id\": \"gpt-6.1-sol\", \"kind\": \"id\", \"note\": \"GPT-6.1 Sol — complex coding and agentic work, recommended default; the kit SoT pin\" },\n { \"id\": \"gpt-6-sol\", \"kind\": \"id\", \"note\": \"GPT-6 Sol — previous Sol release\" },\n { \"id\": \"gpt-6-luna\", \"kind\": \"id\", \"note\": \"GPT-6 Luna — fast/light tier\" },\n { \"id\": \"gpt-6-astra\", \"kind\": \"id\", \"note\": \"GPT-6 Astra — most capable, highest cost\" },\n { \"id\": \"gpt-5.6-sol\", \"kind\": \"id\", \"note\": \"previous generation\" },\n { \"id\": \"gpt-5.6-terra\", \"kind\": \"id\", \"note\": \"previous generation, balanced tier\" },\n { \"id\": \"gpt-5.6-luna\", \"kind\": \"id\", \"note\": \"previous generation\" },\n { \"id\": \"gpt-5.5\", \"kind\": \"id\", \"note\": \"previous generation\" },\n { \"id\": \"gpt-5.5-codex\", \"kind\": \"id\", \"note\": \"codex-tuned gpt-5.5\" },\n { \"id\": \"gpt-5.1\", \"kind\": \"id\", \"note\": \"previous generation\" },\n { \"id\": \"gpt-5\", \"kind\": \"id\", \"note\": \"previous generation\" },\n { \"id\": \"gpt-5-codex\", \"kind\": \"id\", \"note\": \"codex-tuned gpt-5\" }\n ]\n }\n}\n",
|
|
9
|
+
"SoT/toolchain.json": "{\n \"$comment\": \"Kit toolchain manifest - DATA only (versions, floors, policy); version probing and the doctor report live in cli/src/engine-native/toolchain.ts, and the one managed install lives in cli/src/engine-native/bun.ts bunBootstrap. kind: check (doctor visibility only) | managed (kit installs it when missing) | pin (no binary probe - a version pin for a package the kit installs through another tool, such as npx or `omp install`). policy (managed only): present (install when missing, never upgrade). `verified` = last kit-tested version; `pinnable` marks a tool whose `verified` release the bootstrap can install by exact tag. Supply-chain stance: every kit-driven install is pinned to `verified` - never floating @latest (npm-worm/Shai-Hulud surface). Update `verified` after testing a new release. upstream (optional) names where `docks-kit toolchain outdated` reads the newest release: npm package (optional major line) or GitHub repo releases with a tag prefix; results cache 24 h in ~/.docks-kit/kit.db; the report never installs or edits pins.\",\n \"tools\": {\n \"jq\": { \"kind\": \"check\", \"note\": \"optional operator CLI; EngineNative JSON and Claude runtime do not invoke it\" },\n \"curl\": { \"kind\": \"check\", \"note\": \"POSIX installer transport for the Bun bootstrap\" },\n \"git\": { \"kind\": \"check\", \"note\": \"plugin marketplaces (claude/codex clone them) + kit checkout updates\" },\n \"node\": { \"kind\": \"check\", \"floor\": \"22.22.2\",\n \"note\": \"hosts the npm globals installed for the Claude LSP plugins; the floor is typescript-language-server 6's engines requirement, so an older Node reports `below-floor` in `docks-kit toolchain` instead of silently installing an LSP server that cannot start\" },\n \"npm\": { \"kind\": \"check\", \"note\": \"npm-global installer; also backs the intelephense version probe (`npm ls -g`)\" },\n \"claude\": { \"kind\": \"check\", \"floor\": \"2.1.280\", \"note\": \"kit floor — lets the `opus` alias resolve to Opus 5.5, the default Opus from Claude Code 2.1.280, and subsumes the older Fable 5.1 (>=2.1.257) and Opus 5 (>=2.1.219) requirements (mirrors settings minimumVersion)\" },\n \"codex\": { \"kind\": \"check\", \"floor\": \"0.159.0\", \"note\": \"upstream-owned; standalone installer prints when missing. The floor is the Codex release installed on the owner machine on 2026-09-29, by owner decision; no older release was checked against the keys in SoT/.codex/config.toml\" },\n \"omp\": { \"kind\": \"check\", \"floor\": \"18.4.4\", \"verified\": \"18.4.4\",\n \"upstream\": { \"github\": \"can1357/oh-my-pi\", \"tagPrefix\": \"v\" },\n \"note\": \"Oh My Pi harness (https://github.com/can1357/oh-my-pi); upstream-owned and self-updating through `omp update`, so sync never installs or upgrades it. The floor is the oldest release the kit tested: 18.4.4 lists and serves gpt-6.1-sol. `sync omp` needs the CLI only for the marketplace and plugin passes; the file deploys proceed without it\" },\n \"ffplay\": { \"kind\": \"check\", \"note\": \"Notification hook sound; distro-installed, so no kit floor applies\" },\n \"bwrap\": { \"kind\": \"check\", \"os\": \"linux\", \"floor\": \"0.9.0\",\n \"note\": \"Codex Linux sandbox runtime; sync installs it via the distro package manager, so the floor is the kit-tested baseline (Ubuntu 24.04 LTS) and no verified pin applies\" },\n \"intelephense\": { \"kind\": \"check\", \"floor\": \"1.18.5\", \"verified\": \"1.18.5\",\n \"upstream\": { \"npm\": \"intelephense\" },\n \"note\": \"php-lsp server; `verified` pins claudeSync syncLspServers' npm install. Version comes from `npm ls -g` — its own --version prints minified source\" },\n \"typescript-language-server\": { \"kind\": \"check\", \"floor\": \"6.0.0\", \"verified\": \"6.0.1\",\n \"upstream\": { \"npm\": \"typescript-language-server\" },\n \"note\": \"typescript-lsp server binary; `verified` pins claudeSync syncLspServers' npm install. Version 6 requires Node >=22.22.2 (see the `node` floor)\" },\n \"rust-analyzer\": { \"kind\": \"check\",\n \"note\": \"rust-analyzer-lsp server binary; claudeSync syncLspServers installs it with `rustup component add rust-analyzer` when rustup is present, so the version follows the host Rust toolchain and no verified pin applies (the bubblewrap stance for a tool the kit does not publish). A host without rustup is skipped in silence\" },\n \"tsc\": { \"kind\": \"check\", \"floor\": \"6.0.3\", \"verified\": \"6.0.3\",\n \"upstream\": { \"npm\": \"typescript\", \"line\": \"6\" }, \"note\": \"typescript-lsp dependency (npm package `typescript`); `verified` pins claudeSync syncLspServers' npm install. Deliberately on the 6.x line: typescript-language-server embeds TypeScript's programmatic API, which TS7 (native) doesn't yet expose — the repo's own devDependency runs TS7 for tsc --noEmit\" },\n \"bun\": { \"kind\": \"managed\", \"policy\": \"present\", \"floor\": \"1.4.2\", \"verified\": \"1.4.2\", \"pinnable\": true,\n \"upstream\": { \"github\": \"oven-sh/bun\", \"tagPrefix\": \"bun-v\" },\n \"note\": \"runtime for the docks-kit CLI and the Claude statusline/hook programs; bootstrap installs the verified release (installer takes bun-vX.Y.Z); self-updates via `bun upgrade` when wanted. The floor is 1.4.2 by owner decision (2026-09-25): CI and the verified pin run 1.4.2, and the checkout launchers refuse an older Bun\" },\n \"skills-cli\": { \"kind\": \"pin\", \"verified\": \"1.7.0\",\n \"upstream\": { \"npm\": \"skills\" },\n \"note\": \"the `skills` npm package the kit runs via `npx skills@<verified>` when SoT/.agents/skills.txt names a slug (it is empty by default) — pinned, never @latest\" },\n \"pi-intercom\": { \"kind\": \"pin\", \"verified\": \"0.14.0\",\n \"upstream\": { \"npm\": \"pi-intercom\" },\n \"note\": \"the cross-session messaging plugin ompSync installs with `omp install pi-intercom@<verified>` - pinned, never floating. Its broker runs under Bun because omp's flat plugin store cannot resolve the default `npx --no-install tsx` launcher\" }\n }\n}\n",
|
|
10
10
|
"SoT/.claude/CLAUDE.md": "## Research Before Implementation\n\nBefore writing or modifying code that uses an API, hook, method, or config surface you have not verified in this session, research current documentation first.\n\nResearch workflow:\n1. Prefer official documentation and primary sources for the specific library, framework, or API.\n2. If a local docs or MCP tool is available, use it before broad web search.\n3. Only then proceed to implementation.\n\nResearch when:\n- Installing or configuring a dependency.\n- Using an API, hook, method, or pattern not verified in this session.\n- Upgrading or migrating between versions.\n- Any task where relying on memory could cause stale syntax or behavior.\n\nDo not:\n- Assume API signatures, method names, or config options from memory.\n- Generate framework code without checking current docs first.\n- Skip research because the library seems familiar.\n\n<constraint>\nResearch the codebase before editing. Never change code you have not read.\n</constraint>\n\n## Agentic Harness Heuristics\n\n**1. Persistence.** Keep going until the user's query is completely resolved. Only yield when sure the problem is solved. Before ending a turn, check the last paragraph: if it is a plan, a question you can answer yourself, or a promise of work not done (\"I'll…\"), do that work now.\n\n**2. Default to parallel.** Whenever you have multiple independent operations (reads, greps, web fetches, independent edits), invoke them in a single response with multiple tool-use blocks. Sequential calls only when output of one operation is required as input to the next.\n\n**3. Multi-pass search.** First-pass search often misses — vary the wording (colleague-questions over keywords) before concluding something doesn't exist.\n\n**4. Trace symbols.** Before modifying a symbol, trace it to its definitions and all usages. Don't assume a function's behavior or a type's shape from the call site alone.\n\n**5. Linter-loop 3-strike rule.** Don't loop more than 3 times fixing linter errors on the same file. On the third attempt, stop and ask the user — repeated failure usually means the diagnosis is wrong, not the code.\n\n**6. Read-before-Edit TTL.** If you haven't read a file with the Read tool in the last ~5 messages, re-read it before editing. Cached file content goes stale silently when the user edits between turns.\n\n**7. Big-file rule.** For files >1000 lines, prefer Grep + scoped Read (`offset` + `limit`) over reading the entire file. Whole-file reads bloat context; targeted reads keep the working set small.\n\n**8. Todo hygiene.** Use TaskCreate for items with meaningful outcome (≥5 min, distinct deliverable). Never include operational sub-actions (linting, testing, searching, examining the codebase) as their own todos — those are sub-steps in service of higher-level tasks. Mark complete immediately when done, never in batches.\n\n**9. Literal-instruction rule.** Current frontier models follow instructions literally — they do not silently generalize from intent. Phrase requirements as explicit checklists with success criteria, not narrative.\n\n**10. Context hygiene.** Prefer `/clear` at task boundaries and `/rewind` for wrong-path detours over carrying rot forward (corrections accumulate noise; rewinds preserve the prefix and discard the bad branch). On a continuing task, run `/compact` with steering before context quality degrades. Never stop, summarize, or suggest a new session on account of context limits.\n\n**11. Autonomy calibration.** For minor choices (naming, formatting, default values, which of two equivalent approaches), pick a reasonable option and note it — don't ask. Ask first only for scope changes, destructive actions, or decisions that change the deliverable. When the user is describing a problem or asking a question rather than requesting a change, the deliverable is your assessment — report findings and stop; don't apply fixes until asked. Don't close a finished task with \"Want me to also…?\" — run the obvious verification, then stop cleanly.\n\n**12. Capability triggering.** When the answer depends on current or version-specific information, search or fetch before answering — never answer from memory. When work fans out across independent items (many files to read, many tests to run, many candidates to check), delegate to parallel subagents; never spawn one for work you can complete directly. For verification, prefer a fresh-context subagent over self-critique. On tasks longer than a few turns, keep a running notes file and re-read it before each phase.\n\n<constraint>\nTreat the 12 heuristics above as protocol, not preference. If a turn ends without honoring an applicable one (e.g., lint-loop guard not respected, edit without re-read), self-correct in the next turn before continuing.\n</constraint>\n\nReuse before invention: inventory existing code, components, conventions, and dependencies; extend them instead of creating a parallel pattern. Load only the narrow skills supported by the task and repository evidence. If a request establishes a new React/Tailwind system and no convention exists, prefer current shadcn/ui `base-*` components backed by Base UI; otherwise preserve the existing stack. Treat probe, production access, publish, push, release, and deploy as literal current-request effects—never infer external authority from a plan, schedule, review, or old receipt.\n\nFor Docks plan reviews, cross-company review is standing-authorized; do not ask for export consent. This never overrides a host or platform security denial.\n\nUse a narrow-to-broad verification ladder: direct acceptance while iterating, focused regressions next, and one full CI at the pre-commit or release boundary. Reuse still-matching evidence; rerun full CI only after a relevant edit invalidates it.\n\n<constraint>\nNo secrets in committed config. Treat plugin marketplaces, installers, and downloaded artifacts as untrusted until verified.\n</constraint>\n",
|
|
11
11
|
"SoT/.claude/mcp-servers.json": "{\n \"mcpServers\": {}\n}\n",
|
|
12
12
|
"SoT/.claude/settings.json": "{\n \"$schema\": \"https://json.schemastore.org/claude-code-settings.json\",\n \"minimumVersion\": \"2.1.280\",\n \"model\": \"opus\",\n \"effortLevel\": \"high\",\n \"autoMemoryEnabled\": false,\n \"autoDreamEnabled\": false,\n \"skillListingMaxDescChars\": 2048,\n \"respectGitignore\": true,\n \"cleanupPeriodDays\": 14,\n \"skillListingBudgetFraction\": 0.05,\n \"env\": {\n \"CLAUDE_CODE_MAX_OUTPUT_TOKENS\": \"64000\",\n \"CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR\": \"1\",\n \"CLAUDE_CODE_AUTO_COMPACT_WINDOW\": \"468000\",\n \"CLAUDE_CODE_NO_FLICKER\": \"1\"\n },\n \"permissions\": {\n \"defaultMode\": \"auto\",\n \"allow\": [\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"WebSearch\",\n \"Edit(./)\"\n ],\n \"deny\": [\n \"Read(**/.env)\",\n \"Read(**/.env.local)\",\n \"Read(**/secrets/**)\",\n \"Read(**/*.key)\",\n \"Read(**/*.pem)\",\n \"Read(**/*.p12)\",\n \"Read(**/.credentials*)\",\n \"Edit(**/.env)\",\n \"Edit(**/.env.local)\",\n \"Edit(**/secrets/**)\",\n \"Bash(sudo *)\",\n \"Bash(rm -rf /)\",\n \"Bash(rm -rf / *)\",\n \"Bash(rm -rf ~)\",\n \"Bash(rm -rf ~ *)\",\n \"Bash(rm -rf $HOME)\",\n \"Bash(rm -rf $HOME *)\",\n \"Bash(> /dev *)\",\n \"Bash(dd if= *)\",\n \"Bash(mkfs *)\",\n \"Bash(eval *)\",\n \"Bash(chmod 777 *)\",\n \"Bash(chmod -R 777 *)\",\n \"Bash(git push --force origin main *)\",\n \"Bash(git push --force origin master *)\",\n \"Bash(git push -f origin main *)\",\n \"Bash(git push -f origin master *)\",\n \"PowerShell(sudo *)\",\n \"PowerShell(rm -rf /)\",\n \"PowerShell(rm -rf / *)\",\n \"PowerShell(rm -rf ~)\",\n \"PowerShell(rm -rf ~ *)\",\n \"PowerShell(rm -rf $HOME)\",\n \"PowerShell(rm -rf $HOME *)\",\n \"PowerShell(> /dev *)\",\n \"PowerShell(dd if= *)\",\n \"PowerShell(mkfs *)\",\n \"PowerShell(eval *)\",\n \"PowerShell(chmod 777 *)\",\n \"PowerShell(chmod -R 777 *)\",\n \"PowerShell(git push --force origin main *)\",\n \"PowerShell(git push --force origin master *)\",\n \"PowerShell(git push -f origin main *)\",\n \"PowerShell(git push -f origin master *)\",\n \"PowerShell(Remove-Item *-Recurse* /)\",\n \"PowerShell(Remove-Item *-Recurse* / *)\",\n \"PowerShell(Remove-Item / *-Recurse*)\",\n \"PowerShell(Remove-Item -Path / *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath / *-Recurse*)\",\n \"PowerShell(Remove-Item *-Recurse* ~)\",\n \"PowerShell(Remove-Item *-Recurse* ~ *)\",\n \"PowerShell(Remove-Item ~ *-Recurse*)\",\n \"PowerShell(Remove-Item -Path ~ *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(Remove-Item *-Recurse* $HOME)\",\n \"PowerShell(Remove-Item *-Recurse* $HOME *)\",\n \"PowerShell(Remove-Item $HOME *-Recurse*)\",\n \"PowerShell(Remove-Item -Path $HOME *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(Remove-Item *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(Remove-Item *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(Remove-Item $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(Remove-Item -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(Remove-Item *-Recurse* \\\\\\\\)\",\n \"PowerShell(Remove-Item *-Recurse* \\\\ *)\",\n \"PowerShell(Remove-Item \\\\ *-Recurse*)\",\n \"PowerShell(Remove-Item -Path \\\\ *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(Remove-Item *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(Remove-Item *-Recurse* *:\\\\ *)\",\n \"PowerShell(Remove-Item *:\\\\ *-Recurse*)\",\n \"PowerShell(Remove-Item -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(Remove-Item -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(del *-Recurse* /)\",\n \"PowerShell(del *-Recurse* / *)\",\n \"PowerShell(del / *-Recurse*)\",\n \"PowerShell(del -Path / *-Recurse*)\",\n \"PowerShell(del -LiteralPath / *-Recurse*)\",\n \"PowerShell(del *-Recurse* ~)\",\n \"PowerShell(del *-Recurse* ~ *)\",\n \"PowerShell(del ~ *-Recurse*)\",\n \"PowerShell(del -Path ~ *-Recurse*)\",\n \"PowerShell(del -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(del *-Recurse* $HOME)\",\n \"PowerShell(del *-Recurse* $HOME *)\",\n \"PowerShell(del $HOME *-Recurse*)\",\n \"PowerShell(del -Path $HOME *-Recurse*)\",\n \"PowerShell(del -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(del *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(del *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(del $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(del -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(del -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(del *-Recurse* \\\\\\\\)\",\n \"PowerShell(del *-Recurse* \\\\ *)\",\n \"PowerShell(del \\\\ *-Recurse*)\",\n \"PowerShell(del -Path \\\\ *-Recurse*)\",\n \"PowerShell(del -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(del *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(del *-Recurse* *:\\\\ *)\",\n \"PowerShell(del *:\\\\ *-Recurse*)\",\n \"PowerShell(del -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(del -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(erase *-Recurse* /)\",\n \"PowerShell(erase *-Recurse* / *)\",\n \"PowerShell(erase / *-Recurse*)\",\n \"PowerShell(erase -Path / *-Recurse*)\",\n \"PowerShell(erase -LiteralPath / *-Recurse*)\",\n \"PowerShell(erase *-Recurse* ~)\",\n \"PowerShell(erase *-Recurse* ~ *)\",\n \"PowerShell(erase ~ *-Recurse*)\",\n \"PowerShell(erase -Path ~ *-Recurse*)\",\n \"PowerShell(erase -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(erase *-Recurse* $HOME)\",\n \"PowerShell(erase *-Recurse* $HOME *)\",\n \"PowerShell(erase $HOME *-Recurse*)\",\n \"PowerShell(erase -Path $HOME *-Recurse*)\",\n \"PowerShell(erase -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(erase *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(erase *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(erase $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(erase -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(erase -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(erase *-Recurse* \\\\\\\\)\",\n \"PowerShell(erase *-Recurse* \\\\ *)\",\n \"PowerShell(erase \\\\ *-Recurse*)\",\n \"PowerShell(erase -Path \\\\ *-Recurse*)\",\n \"PowerShell(erase -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(erase *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(erase *-Recurse* *:\\\\ *)\",\n \"PowerShell(erase *:\\\\ *-Recurse*)\",\n \"PowerShell(erase -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(erase -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(rd *-Recurse* /)\",\n \"PowerShell(rd *-Recurse* / *)\",\n \"PowerShell(rd / *-Recurse*)\",\n \"PowerShell(rd -Path / *-Recurse*)\",\n \"PowerShell(rd -LiteralPath / *-Recurse*)\",\n \"PowerShell(rd *-Recurse* ~)\",\n \"PowerShell(rd *-Recurse* ~ *)\",\n \"PowerShell(rd ~ *-Recurse*)\",\n \"PowerShell(rd -Path ~ *-Recurse*)\",\n \"PowerShell(rd -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(rd *-Recurse* $HOME)\",\n \"PowerShell(rd *-Recurse* $HOME *)\",\n \"PowerShell(rd $HOME *-Recurse*)\",\n \"PowerShell(rd -Path $HOME *-Recurse*)\",\n \"PowerShell(rd -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(rd *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(rd *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(rd $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rd -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rd -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rd *-Recurse* \\\\\\\\)\",\n \"PowerShell(rd *-Recurse* \\\\ *)\",\n \"PowerShell(rd \\\\ *-Recurse*)\",\n \"PowerShell(rd -Path \\\\ *-Recurse*)\",\n \"PowerShell(rd -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(rd *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(rd *-Recurse* *:\\\\ *)\",\n \"PowerShell(rd *:\\\\ *-Recurse*)\",\n \"PowerShell(rd -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(rd -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(ri *-Recurse* /)\",\n \"PowerShell(ri *-Recurse* / *)\",\n \"PowerShell(ri / *-Recurse*)\",\n \"PowerShell(ri -Path / *-Recurse*)\",\n \"PowerShell(ri -LiteralPath / *-Recurse*)\",\n \"PowerShell(ri *-Recurse* ~)\",\n \"PowerShell(ri *-Recurse* ~ *)\",\n \"PowerShell(ri ~ *-Recurse*)\",\n \"PowerShell(ri -Path ~ *-Recurse*)\",\n \"PowerShell(ri -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(ri *-Recurse* $HOME)\",\n \"PowerShell(ri *-Recurse* $HOME *)\",\n \"PowerShell(ri $HOME *-Recurse*)\",\n \"PowerShell(ri -Path $HOME *-Recurse*)\",\n \"PowerShell(ri -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(ri *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(ri *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(ri $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(ri -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(ri -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(ri *-Recurse* \\\\\\\\)\",\n \"PowerShell(ri *-Recurse* \\\\ *)\",\n \"PowerShell(ri \\\\ *-Recurse*)\",\n \"PowerShell(ri -Path \\\\ *-Recurse*)\",\n \"PowerShell(ri -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(ri *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(ri *-Recurse* *:\\\\ *)\",\n \"PowerShell(ri *:\\\\ *-Recurse*)\",\n \"PowerShell(ri -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(ri -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(rm *-Recurse* /)\",\n \"PowerShell(rm *-Recurse* / *)\",\n \"PowerShell(rm / *-Recurse*)\",\n \"PowerShell(rm -Path / *-Recurse*)\",\n \"PowerShell(rm -LiteralPath / *-Recurse*)\",\n \"PowerShell(rm *-Recurse* ~)\",\n \"PowerShell(rm *-Recurse* ~ *)\",\n \"PowerShell(rm ~ *-Recurse*)\",\n \"PowerShell(rm -Path ~ *-Recurse*)\",\n \"PowerShell(rm -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(rm *-Recurse* $HOME)\",\n \"PowerShell(rm *-Recurse* $HOME *)\",\n \"PowerShell(rm $HOME *-Recurse*)\",\n \"PowerShell(rm -Path $HOME *-Recurse*)\",\n \"PowerShell(rm -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(rm *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(rm *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(rm $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rm -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rm -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rm *-Recurse* \\\\\\\\)\",\n \"PowerShell(rm *-Recurse* \\\\ *)\",\n \"PowerShell(rm \\\\ *-Recurse*)\",\n \"PowerShell(rm -Path \\\\ *-Recurse*)\",\n \"PowerShell(rm -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(rm *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(rm *-Recurse* *:\\\\ *)\",\n \"PowerShell(rm *:\\\\ *-Recurse*)\",\n \"PowerShell(rm -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(rm -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* /)\",\n \"PowerShell(rmdir *-Recurse* / *)\",\n \"PowerShell(rmdir / *-Recurse*)\",\n \"PowerShell(rmdir -Path / *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath / *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* ~)\",\n \"PowerShell(rmdir *-Recurse* ~ *)\",\n \"PowerShell(rmdir ~ *-Recurse*)\",\n \"PowerShell(rmdir -Path ~ *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath ~ *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* $HOME)\",\n \"PowerShell(rmdir *-Recurse* $HOME *)\",\n \"PowerShell(rmdir $HOME *-Recurse*)\",\n \"PowerShell(rmdir -Path $HOME *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath $HOME *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* $env:USERPROFILE)\",\n \"PowerShell(rmdir *-Recurse* $env:USERPROFILE *)\",\n \"PowerShell(rmdir $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rmdir -Path $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath $env:USERPROFILE *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* \\\\\\\\)\",\n \"PowerShell(rmdir *-Recurse* \\\\ *)\",\n \"PowerShell(rmdir \\\\ *-Recurse*)\",\n \"PowerShell(rmdir -Path \\\\ *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath \\\\ *-Recurse*)\",\n \"PowerShell(rmdir *-Recurse* *:\\\\\\\\)\",\n \"PowerShell(rmdir *-Recurse* *:\\\\ *)\",\n \"PowerShell(rmdir *:\\\\ *-Recurse*)\",\n \"PowerShell(rmdir -Path *:\\\\ *-Recurse*)\",\n \"PowerShell(rmdir -LiteralPath *:\\\\ *-Recurse*)\",\n \"PowerShell(Start-Process *-Verb RunAs*)\",\n \"PowerShell(Invoke-Expression *)\",\n \"PowerShell(iex *)\",\n \"PowerShell(Format-Volume *)\",\n \"PowerShell(icacls */grant*Everyone:F*)\",\n \"PowerShell(icacls */grant*Everyone:(F)*)\"\n ],\n \"ask\": [\n \"Bash(git clean *)\",\n \"Bash(docker volume rm *)\",\n \"Bash(docker system prune *)\",\n \"PowerShell(git clean *)\",\n \"PowerShell(docker volume rm *)\",\n \"PowerShell(docker system prune *)\"\n ]\n },\n \"hooks\": {\n \"SessionStart\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"__DOCKS_KIT_BUN__\",\n \"args\": [\"__DOCKS_KIT_SESSION_START__\"],\n \"timeout\": 5\n }\n ]\n }\n ],\n \"Notification\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"__DOCKS_KIT_BUN__\",\n \"args\": [\"__DOCKS_KIT_NOTIFY__\"],\n \"timeout\": 10,\n \"async\": true\n }\n ]\n }\n ],\n \"PostToolUseFailure\": [\n {\n \"matcher\": \"Bash|PowerShell\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"echo '{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUseFailure\\\",\\\"additionalContext\\\":\\\"Last bash command failed. Repository / file state may have shifted \\u2014 re-read affected files before retrying. If the failure is a missing dependency or env mismatch, surface it to the user rather than retrying blindly.\\\"}}'\",\n \"timeout\": 5\n }\n ]\n }\n ],\n \"SubagentStop\": [\n {\n \"hooks\": [\n {\n \"type\": \"prompt\",\n \"prompt\": \"You are a quality gate for subagent outputs in a multi-agent code-analysis pipeline.\\n\\nEvaluate the subagent's `last_assistant_message` field (in the JSON below) against these requirements:\\n\\n1. ALLOW (return `{}`): Mode-selection or no-issues responses. Examples: \\\"Which mode do you prefer\\\", \\\"select an option\\\", \\\"no issues / problems / violations / blockers found\\\".\\n\\n2. ALLOW (return `{}`): Output contains at least one concrete file:line citation \\u2014 e.g. `src/auth.ts:42`, `lib/db.ts:100-115`, or path references that include line numbers.\\n\\n3. BLOCK (return `{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"<one-line explanation>\\\"}`): Output claims about code or findings WITHOUT concrete file:line citations. Vague references like \\\"the auth handler\\\" or \\\"near the database code\\\" are not acceptable as the only evidence.\\n\\nSubagent invocation JSON:\\n$ARGUMENTS\\n\\nReturn ONLY the JSON decision (no commentary, no markdown fences).\",\n \"timeout\": 30\n }\n ]\n }\n ]\n },\n \"statusLine\": {\n \"type\": \"command\",\n \"command\": \"__DOCKS_KIT_STATUSLINE__\",\n \"refreshInterval\": 5\n },\n \"enabledPlugins\": {\n \"docks@docks\": true,\n \"plan-lifecycle@docks\": true,\n \"php-lsp@claude-plugins-official\": true,\n \"rust-analyzer-lsp@claude-plugins-official\": true,\n \"typescript-lsp@claude-plugins-official\": true\n },\n \"extraKnownMarketplaces\": {\n \"docks\": {\n \"source\": {\n \"source\": \"github\",\n \"repo\": \"DocksDocks/docks\"\n }\n }\n },\n \"alwaysThinkingEnabled\": true,\n \"showThinkingSummaries\": true,\n \"viewMode\": \"default\",\n \"theme\": \"dark-daltonized\",\n \"skipDangerousModePermissionPrompt\": true\n}\n",
|
|
@@ -14,14 +14,14 @@ export const GENERATED_PAYLOAD_TEXT = {
|
|
|
14
14
|
"SoT/.claude/bin/session-start.mjs": "/**\n * @typedef {string | number | boolean | JsonRecord | JsonArray | null | undefined} JsonValue\n * @typedef {{ [key: string]: JsonValue }} JsonRecord\n * @typedef {Array<JsonValue>} JsonArray\n * @typedef {Record<string, string | undefined> | JsonRecord} EnvInput\n * @typedef {object} SessionStartOptions\n * @property {EnvInput} [env]\n * @property {Date} [now]\n * @property {string} [home]\n * @property {(path: string) => string} [readText]\n * @property {(value: string) => void} [writeStdout]\n */\nimport { readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\n\n/**\n * @param {object | string | number | boolean | null | undefined} value\n * @returns {value is JsonRecord}\n */\nfunction isRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\n/**\n * @param {JsonValue} value\n * @param {string} fallback\n * @returns {string}\n */\nfunction nonEmpty(value, fallback) {\n return typeof value === \"string\" && value !== \"\" ? value : fallback\n}\n\n/**\n * @param {number} value\n * @returns {string}\n */\nfunction pad(value) {\n return String(value).padStart(2, \"0\")\n}\n\n/**\n * @param {string} home\n * @param {(path: string) => string} readText\n * @returns {string}\n */\nfunction configuredEffort(home, readText) {\n try {\n const parsed = JSON.parse(readText(`${home}/.claude/settings.json`))\n return isRecord(parsed) ? nonEmpty(parsed.effortLevel, \"default\") : \"default\"\n } catch {\n return \"default\"\n }\n}\n\n/**\n * @param {Date} now\n * @returns {string}\n */\nfunction localZone(now) {\n const part = new Intl.DateTimeFormat(\"en-US\", { timeZoneName: \"short\" })\n .formatToParts(now)\n .find((value) => value.type === \"timeZoneName\")\n return part?.value ?? \"\"\n}\n\n/**\n * @param {SessionStartOptions} [options]\n * @returns {string[]}\n */\nexport function sessionStartLines(options = {}) {\n const env = isRecord(options.env) ? options.env : process.env\n const now = options.now instanceof Date ? options.now : new Date()\n const home = typeof options.home === \"string\" ? options.home : homedir()\n const readText = options.readText ?? ((path) => readFileSync(path, \"utf8\"))\n const weekday = new Intl.DateTimeFormat(\"en-US\", { weekday: \"long\" }).format(now)\n const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`\n const time = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`\n const effort = nonEmpty(env.CLAUDE_CODE_EFFORT_LEVEL, configuredEffort(home, readText))\n const context = env.CLAUDE_CODE_DISABLE_1M_CONTEXT === \"1\" ? \"200K\" : \"1M\"\n const compactWindow = nonEmpty(env.CLAUDE_CODE_AUTO_COMPACT_WINDOW, \"full\")\n const subagent = nonEmpty(env.CLAUDE_CODE_SUBAGENT_MODEL, \"default\")\n return [\n `[CONTEXT] Current date: ${weekday}, ${date} ${time} ${localZone(now)}`,\n `[CONFIG] Context: ${context} | Compact-window: ${compactWindow} | Effort: ${effort} | Thinking: adaptive | Subagent: ${subagent}`\n ]\n}\n\n/**\n * @param {SessionStartOptions} [options]\n * @returns {Promise<number>}\n */\nexport async function main(options = {}) {\n const writeStdout = options.writeStdout ?? ((value) => process.stdout.write(value))\n const output = {\n hookSpecificOutput: {\n hookEventName: \"SessionStart\",\n additionalContext: sessionStartLines(options).join(\"\\n\")\n }\n }\n writeStdout(`${JSON.stringify(output)}\\n`)\n return 0\n}\n\nif (import.meta.main) process.exit(await main())\n",
|
|
15
15
|
"SoT/.claude/bin/notify.mjs": "/**\n * @typedef {(name: string) => string | null | undefined} WhichFn\n * @typedef {(path: string) => Promise<boolean>} FileExistsFn\n * @typedef {object} QuietSpawnOptions\n * @property {\"ignore\" | \"pipe\" | \"inherit\"} [stdin]\n * @property {\"ignore\" | \"pipe\" | \"inherit\"} [stdout]\n * @property {\"ignore\" | \"pipe\" | \"inherit\"} [stderr]\n * @typedef {(argv: string[], options: QuietSpawnOptions) => void} QuietSpawner\n * @typedef {object} PlayerOptions\n * @property {string} [platform]\n * @property {string} [sound]\n * @property {WhichFn} [which]\n * @typedef {object} NotifyOptions\n * @property {string} [platform]\n * @property {string} [sound]\n * @property {WhichFn} [which]\n * @property {FileExistsFn} [fileExists]\n * @property {QuietSpawner} [spawnSync]\n */\nconst DEFAULT_SOUND = `${import.meta.dir}/../notification.mp3`\n\n/**\n * @param {PlayerOptions} [options]\n * @returns {string[] | undefined}\n */\nexport function selectPlayer(options = {}) {\n const platform = options.platform ?? process.platform\n const sound = options.sound ?? DEFAULT_SOUND\n const which = options.which ?? ((name) => Bun.which(name))\n if (platform === \"darwin\") {\n const afplay = which(\"afplay\")\n if (typeof afplay === \"string\" && afplay !== \"\") return [afplay, sound]\n }\n const ffplay = which(\"ffplay\")\n if (typeof ffplay === \"string\" && ffplay !== \"\") {\n return [ffplay, \"-nodisp\", \"-autoexit\", \"-loglevel\", \"quiet\", sound]\n }\n const paplay = which(\"paplay\")\n if (typeof paplay === \"string\" && paplay !== \"\") return [paplay, sound]\n const aplay = which(\"aplay\")\n if (typeof aplay === \"string\" && aplay !== \"\") return [aplay, \"-q\", sound]\n return undefined\n}\n\n/**\n * @param {NotifyOptions} [options]\n * @returns {Promise<number>}\n */\nexport async function main(options = {}) {\n const sound = options.sound ?? DEFAULT_SOUND\n const fileExists = options.fileExists ?? ((path) => Bun.file(path).exists())\n if (!await fileExists(sound)) return 0\n const command = selectPlayer({ ...options, sound })\n if (command === undefined) return 0\n const spawnSync = options.spawnSync ?? ((argv, spawnOptions) => Bun.spawnSync(argv, spawnOptions))\n spawnSync(command, { stdin: \"ignore\", stdout: \"ignore\", stderr: \"ignore\" })\n return 0\n}\n\nif (import.meta.main) process.exit(await main())\n",
|
|
16
16
|
"SoT/.codex/AGENTS.md": "# AGENTS.md\n\n## Research Before Implementation\n\nBefore writing or modifying code that uses an API, hook, method, or config surface you have not verified in this session, research current documentation first.\n\nResearch workflow:\n1. Prefer official documentation and primary sources for the specific library, framework, or API.\n2. If a local docs or MCP tool is available, use it before broad web search.\n3. Only then proceed to implementation.\n\nResearch when:\n- Installing or configuring a dependency.\n- Using an API, hook, method, or pattern not verified in this session.\n- Upgrading or migrating between versions.\n- Any task where relying on memory could cause stale syntax or behavior.\n\nDo not:\n- Assume API signatures, method names, or config options from memory.\n- Generate framework code without checking current docs first.\n- Skip research because the library seems familiar.\n\n<constraint>\nResearch the codebase before editing. Never change code you have not read.\n</constraint>\n\n## Agentic Harness Heuristics\n\nModel-agnostic operating rules for coding-agent work.\n\n1. Persistence. Keep going until the user's request is actually handled. Only yield when the problem is solved or a concrete blocker is identified. Resolve in the fewest useful tool loops — once you can answer the core request with evidence, answer. Before ending a turn, check the last paragraph: if it is a plan, a question you can answer yourself, or a promise of work not done, do that work now.\n2. Default to parallel. When multiple reads, searches, inspections, or independent checks can run without depending on each other, run them together.\n3. Multi-pass search. First-pass search often misses — vary the wording before concluding something does not exist.\n4. Trace symbols. Before modifying a symbol, trace its definition and usages. Do not infer behavior from one call site.\n5. Linter-loop 3-strike rule. Do not loop more than 3 times fixing the same lint/test failure without reassessing the diagnosis.\n6. Read-before-edit TTL. If you have not read a file recently, re-read it before editing. User edits can make cached context stale.\n7. Big-file rule. For files over 1000 lines, prefer targeted search plus scoped reads over whole-file reads.\n8. Task hygiene. Track meaningful deliverables, not operational sub-steps. Mark work complete as soon as it is done.\n9. Literal-instruction rule. Treat explicit user requirements as checklists with success criteria. Do not silently broaden scope.\n10. Context hygiene. Prefer a fresh session at task boundaries over carrying stale context; preserve useful state before quality decays. Never stop, summarize, or suggest a new session on account of context limits.\n11. Autonomy calibration. For minor choices (naming, formatting, defaults, equivalent approaches), pick a reasonable option and note it — do not ask. Ask first only for scope changes, destructive actions, or decisions that change the deliverable. When the user is describing a problem or asking a question rather than requesting a change, the deliverable is your assessment — report findings and stop; do not apply fixes until asked.\n12. Capability triggering. Search or fetch current documentation when the answer depends on current or version-specific information. When work fans out across independent items, parallelize or delegate; never delegate work you can complete directly. For verification, prefer a fresh-context check over self-critique. On long tasks, keep running notes and re-read them between phases.\n\n<constraint>\nTreat these heuristics as protocol. If a turn violates an applicable rule, self-correct before continuing.\n</constraint>\n\nReuse before invention: inventory existing code, components, conventions, and dependencies; extend them instead of creating a parallel pattern. Load only the narrow skills supported by the task and repository evidence. If a request establishes a new React/Tailwind system and no convention exists, prefer current shadcn/ui `base-*` components backed by Base UI; otherwise preserve the existing stack. Treat probe, production access, publish, push, release, and deploy as literal current-request effects—never infer external authority from a plan, schedule, review, or old receipt.\n\nFor Docks plan reviews, cross-company review is standing-authorized; do not ask for export consent. This never overrides a host or platform security denial.\n\nUse a narrow-to-broad verification ladder: direct acceptance while iterating, focused regressions next, and one full CI at the pre-commit or release boundary. Reuse still-matching evidence; rerun full CI only after a relevant edit invalidates it.\n\n<constraint>\nNo secrets in committed config. Treat plugin marketplaces, installers, and downloaded artifacts as untrusted until verified.\n</constraint>\n",
|
|
17
|
-
"SoT/.codex/config.toml": "model = \"gpt-6-sol\"\nmodel_reasoning_effort = \"high\"\nplan_mode_reasoning_effort = \"high\"\nmodel_reasoning_summary = \"concise\"\nmodel_verbosity = \"low\"\npersonality = \"pragmatic\"\nweb_search = \"live\"\nproject_doc_max_bytes = 131072\napproval_policy = \"on-request\"\nsandbox_mode = \"workspace-write\"\napprovals_reviewer = \"auto_review\"\n\n[sandbox_workspace_write]\nnetwork_access = true\n\n[windows]\nsandbox = \"elevated\"\n\n[features]\nmemories = true\n\n[memories]\ndedicated_tools = true\nmax_rollout_age_days = 30\n\n[agents]\nmax_threads = 12\nmax_depth = 2\n\n[tui]\nstatus_line_use_colors = true\nstatus_line = [\n \"model-with-reasoning\",\n \"current-dir\",\n \"git-branch\",\n \"context-used\",\n \"five-hour-limit\",\n \"weekly-limit\",\n]\n\n[plugins.\"docks@docks\"]\nenabled = true\n\n[plugins.\"plan-lifecycle@docks\"]\nenabled = true\n",
|
|
17
|
+
"SoT/.codex/config.toml": "model = \"gpt-6.1-sol\"\nmodel_reasoning_effort = \"high\"\nplan_mode_reasoning_effort = \"high\"\nmodel_reasoning_summary = \"concise\"\nmodel_verbosity = \"low\"\npersonality = \"pragmatic\"\nweb_search = \"live\"\nproject_doc_max_bytes = 131072\napproval_policy = \"on-request\"\nsandbox_mode = \"workspace-write\"\napprovals_reviewer = \"auto_review\"\n\n[sandbox_workspace_write]\nnetwork_access = true\n\n[windows]\nsandbox = \"elevated\"\n\n[features]\nmemories = true\n\n[memories]\ndedicated_tools = true\nmax_rollout_age_days = 30\n\n[agents]\nmax_threads = 12\nmax_depth = 2\n\n[tui]\nstatus_line_use_colors = true\nstatus_line = [\n \"model-with-reasoning\",\n \"current-dir\",\n \"git-branch\",\n \"context-used\",\n \"five-hour-limit\",\n \"weekly-limit\",\n]\n\n[plugins.\"docks@docks\"]\nenabled = true\n\n[plugins.\"plan-lifecycle@docks\"]\nenabled = true\n",
|
|
18
18
|
"SoT/.codex/plugins/marketplace.json": "{\n \"name\": \"docks\",\n \"interface\": {\n \"displayName\": \"DocksDocks\"\n },\n \"plugins\": [\n {\n \"name\": \"docks\",\n \"source\": {\n \"source\": \"git-subdir\",\n \"url\": \"https://github.com/DocksDocks/docks.git\",\n \"path\": \"./plugins/docks\",\n \"ref\": \"main\"\n },\n \"policy\": {\n \"installation\": \"AVAILABLE\",\n \"authentication\": \"ON_INSTALL\"\n },\n \"category\": \"Productivity\"\n },\n {\n \"name\": \"plan-lifecycle\",\n \"source\": {\n \"source\": \"git-subdir\",\n \"url\": \"https://github.com/DocksDocks/docks.git\",\n \"path\": \"./plugins/plan-lifecycle\",\n \"ref\": \"main\"\n },\n \"policy\": {\n \"installation\": \"AVAILABLE\",\n \"authentication\": \"ON_INSTALL\"\n },\n \"category\": \"Productivity\"\n }\n ]\n}\n",
|
|
19
19
|
"SoT/.codex/rules/docks.rules": "prefix_rule(pattern=[\"pwd\"], decision=\"allow\")\nprefix_rule(pattern=[\"ls\"], decision=\"allow\")\nprefix_rule(pattern=[\"cat\"], decision=\"allow\")\nprefix_rule(pattern=[\"head\"], decision=\"allow\")\nprefix_rule(pattern=[\"tail\"], decision=\"allow\")\nprefix_rule(pattern=[\"wc\"], decision=\"allow\")\nprefix_rule(pattern=[\"nl\"], decision=\"allow\")\nprefix_rule(pattern=[\"grep\"], decision=\"allow\")\nprefix_rule(pattern=[\"sort\"], decision=\"allow\")\nprefix_rule(pattern=[\"uniq\"], decision=\"allow\")\nprefix_rule(pattern=[\"diff\"], decision=\"allow\")\nprefix_rule(pattern=[\"which\"], decision=\"allow\")\nprefix_rule(pattern=[\"date\"], decision=\"allow\")\nprefix_rule(pattern=[\"basename\"], decision=\"allow\")\nprefix_rule(pattern=[\"dirname\"], decision=\"allow\")\nprefix_rule(pattern=[\"realpath\"], decision=\"allow\")\nprefix_rule(pattern=[\"readlink\"], decision=\"allow\")\nprefix_rule(pattern=[\"jq\"], decision=\"allow\")\nprefix_rule(pattern=[\"tree\"], decision=\"allow\")\nprefix_rule(pattern=[\"cut\"], decision=\"allow\")\nprefix_rule(pattern=[\"tr\"], decision=\"allow\")\nprefix_rule(pattern=[\"echo\"], decision=\"allow\")\nprefix_rule(pattern=[\"printf\"], decision=\"allow\")\nprefix_rule(pattern=[\"printenv\"], decision=\"allow\")\nprefix_rule(pattern=[\"uname\"], decision=\"allow\")\nprefix_rule(pattern=[\"file\"], decision=\"allow\")\nprefix_rule(pattern=[\"stat\"], decision=\"allow\")\nprefix_rule(pattern=[\"du\"], decision=\"allow\")\nprefix_rule(pattern=[\"id\"], decision=\"allow\")\nprefix_rule(pattern=[\"whoami\"], decision=\"allow\")\n\nprefix_rule(pattern=[\"git\", \"status\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"diff\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"log\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"show\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"blame\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"rev-parse\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"ls-files\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"grep\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"ls-tree\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"branch\", \"--show-current\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"branch\", \"-vv\"], decision=\"allow\")\nprefix_rule(pattern=[\"git\", \"mv\"], decision=\"allow\")\n\nprefix_rule(pattern=[\"gh\", \"pr\", \"view\"], decision=\"allow\")\nprefix_rule(pattern=[\"gh\", \"pr\", \"list\"], decision=\"allow\")\nprefix_rule(pattern=[\"gh\", \"pr\", \"diff\"], decision=\"allow\")\nprefix_rule(pattern=[\"gh\", \"pr\", \"status\"], decision=\"allow\")\nprefix_rule(pattern=[\"gh\", \"pr\", \"checks\"], decision=\"allow\")\n\nprefix_rule(pattern=[\"docker\", \"ps\"], decision=\"allow\")\n\nprefix_rule(pattern=[\"git\", \"push\"], decision=\"prompt\")\nprefix_rule(pattern=[\"git\", \"reset\"], decision=\"prompt\")\nprefix_rule(pattern=[\"git\", \"clean\"], decision=\"prompt\")\nprefix_rule(pattern=[\"git\", \"merge\"], decision=\"prompt\")\nprefix_rule(pattern=[\"git\", \"rebase\"], decision=\"prompt\")\nprefix_rule(pattern=[\"git\", \"checkout\"], decision=\"prompt\")\n\nprefix_rule(pattern=[\"rm\"], decision=\"prompt\")\nprefix_rule(pattern=[\"mv\"], decision=\"prompt\")\nprefix_rule(pattern=[\"chmod\"], decision=\"prompt\")\nprefix_rule(pattern=[\"chown\"], decision=\"prompt\")\nprefix_rule(pattern=[\"kill\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pkill\"], decision=\"prompt\")\n\nprefix_rule(pattern=[\"npm\", \"install\"], decision=\"prompt\")\nprefix_rule(pattern=[\"npm\", \"uninstall\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pnpm\", \"add\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pnpm\", \"remove\"], decision=\"prompt\")\nprefix_rule(pattern=[\"yarn\", \"add\"], decision=\"prompt\")\nprefix_rule(pattern=[\"yarn\", \"remove\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pip\", \"install\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pip\", \"uninstall\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pip3\", \"install\"], decision=\"prompt\")\nprefix_rule(pattern=[\"pip3\", \"uninstall\"], decision=\"prompt\")\n\nprefix_rule(pattern=[\"docker\", \"run\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"rm\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"stop\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"volume\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"system\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"compose\", \"up\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"compose\", \"down\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"compose\", \"rm\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker\", \"compose\", \"stop\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker-compose\", \"up\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker-compose\", \"down\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker-compose\", \"rm\"], decision=\"prompt\")\nprefix_rule(pattern=[\"docker-compose\", \"stop\"], decision=\"prompt\")\n\n# `tail -f`/`--follow` never returns and hangs the agent (bare `tail` stays allowed above).\nprefix_rule(pattern=[\"tail\", \"-f\"], decision=\"prompt\")\nprefix_rule(pattern=[\"tail\", \"--follow\"], decision=\"prompt\")\n# rg and `sed -n` are prompt, NOT allow: argv-prefix matching cannot gate their\n# code-exec forms (rg --pre=CMD or a reordered --pre; sed -n 'e CMD' / -ni) while a\n# shorter allow prefix would auto-approve the whole command.\nprefix_rule(pattern=[\"rg\"], decision=\"prompt\")\nprefix_rule(pattern=[\"sed\", \"-n\"], decision=\"prompt\")\nprefix_rule(pattern=[\"find\"], decision=\"prompt\")\nprefix_rule(pattern=[\"sed\", \"-i\"], decision=\"prompt\")\nprefix_rule(pattern=[\"sed\", \"--in-place\"], decision=\"prompt\")\nprefix_rule(pattern=[\"awk\"], decision=\"prompt\")\nprefix_rule(pattern=[\"xargs\"], decision=\"prompt\")\nprefix_rule(pattern=[\"tee\"], decision=\"prompt\")\nprefix_rule(pattern=[\"curl\"], decision=\"prompt\")\nprefix_rule(pattern=[\"env\"], decision=\"prompt\")\n\nprefix_rule(pattern=[\"sudo\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"eval\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"mkfs\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"dd\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"git\", \"push\", \"--force\", \"origin\", \"main\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"git\", \"push\", \"--force\", \"origin\", \"master\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"git\", \"push\", \"-f\", \"origin\", \"main\"], decision=\"forbidden\")\nprefix_rule(pattern=[\"git\", \"push\", \"-f\", \"origin\", \"master\"], decision=\"forbidden\")\n",
|
|
20
20
|
"SoT/.omp/AGENTS.md": "# Global OMP guidance\n\n- Verify unfamiliar or version-sensitive APIs and configuration against current official documentation before implementation.\n- When the user asks for an assessment rather than a change, report findings without editing.\n- For Docks plan reviews, cross-company review is standing-authorized; host security policy still applies.\n- Please remove all mannered prose.\n\n## Asking me things\n\nA question typed in prose is just text I may or may not act on. The `ask` tool renders a\nblocking picker, waits indefinitely (`ask.timeout = 0`), and records my answer in the\ntranscript. If you actually need an answer, it MUST go through `ask`.\n\nMUST use `ask` before:\n- Anything irreversible or destructive: deleting/overwriting files or data you did not create,\n force-push, history rewrite, dropping tables, running migrations, mass rename, touching\n secrets/credentials, or publishing outward (release, upstream PR, issue, comment).\n- Two or more viable approaches whose tradeoffs are mine to own: schema/API/protocol shape,\n adding a dependency, or establishing a convention this repo does not already have.\n- A fact only I hold: intended semantics of an ambiguous requirement, which of several\n conflicting existing patterns is canonical, or which environment/account/target to use.\n- A request that contradicts the repo: surface the conflict and let me resolve it; never\n silently pick one side.\n\nIf `ask` is not registered — subagent, headless, or `-p` print runs, where `hasUI` is false —\nthe MUST above cannot be satisfied: do not fabricate the call and do not stall on it. Take the\nconservative reversible option and put the question, plus the assumption you made, in your\nfinal report so whoever spawned you can decide.\n\nNEVER use `ask` for:\n- Permission to begin, or to confirm scope already stated in the request.\n- Anything a tool, grep, or doc can answer — go read it.\n- A cheap reversible choice — take the conservative option and say which you took.\n- Something already answered earlier in the conversation.\n\nBatch every open question into one `ask` call with multiple questions; do not serialize\nround trips. Being overruled ends the discussion — execute my call without relitigating.\n\n## Output Standard\n\nApply Simplified Technical English to all agent text. This includes responses, messages,\ndocumentation, comments, and interface text.\n\nReply in the language I use, and apply every rule below to that language.\n\nA rule that names English grammar applies only to English. The contraction ban is one\nsuch rule. In another language, follow the normal grammar of that language. Portuguese,\nSpanish, French, Italian, and German merge a preposition with an article, and that merge\nis required, not optional.\n\nTreat the word limits as approximate outside English. Some languages need more words to\ncarry the same content.\n\n- Use the simplest precise technical term.\n- Use each term consistently.\n- Expand an abbreviation at its first occurrence.\n- Explain a technical term when I ask for an explanation.\n- Write complete and grammatically correct sentences.\n- Use active voice and identify the actor.\n- Use the imperative form for instructions.\n- Put only one action in each instruction sentence.\n- Put a necessary condition before its instruction.\n- Use simple verb tenses.\n- Do not use contractions, idioms, or slang. Avoid humor and rhetorical questions.\n- Keep procedural sentences to 20 words or fewer.\n- Keep descriptive sentences to 25 words or fewer.\n- Keep each paragraph to one topic and six sentences or fewer.\n- Do not use more than three nouns together.\n- Use vertical lists for complex information.\n- Put a warning or caution before a related hazardous instruction.\n\n### Naming\n\n- Say what the thing does before you name it. Put the technical term after the plain\n description, once, in parentheses.\n- Do not use a technical term as the only name for something you just introduced.\n- Prefer the short common word. Use \"use\", not \"utilize\". Use \"set up\", not \"provision\".\n- Do not explain by metaphor alone. A metaphor may follow a literal statement.\n",
|
|
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",
|
|
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.1-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.1-sol:high\n advisor: []\n task:\n - anthropic/claude-opus-5-5:high\n vision:\n - openai-codex/gpt-6.1-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
|
|
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 = "
|
|
53
|
+
export const GENERATED_PAYLOAD_HASH = "8e424ac754febd4df7181a749b2dcf93340532371edcda83801ffd3717fe592c"
|
package/package.json
CHANGED