docks-kit 0.15.5 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -4,17 +4,20 @@ Canonical instructions for coding agents working on this project. Compatible wit
4
4
 
5
5
  ## Repository purpose
6
6
 
7
- Portable configuration kit for AI coding agents. Per-tool Single Source of Truth
8
- (SoT) directories deploy to each tool's user-config location through
9
- `./docks-kit sync`. Clone once to get a consistent AI-assisted environment on
10
- supported Linux, macOS, and Windows hosts. The kit focuses on **token efficiency
11
- without sacrificing quality**. Every setting and hook minimizes token use while
7
+ Portable configuration kit for AI coding agents. The kit manages three coding
8
+ harnesses: Claude Code, Codex, and Oh My Pi (`omp`). Per-tool Single Source of
9
+ Truth (SoT) directories deploy to each harness's user-config location through
10
+ `./docks-kit sync`. The kit also deploys shared [agentskills.io](https://agentskills.io)
11
+ skills. Clone once to get a consistent AI-assisted environment on supported
12
+ Linux, macOS, and Windows hosts. The kit focuses on **token efficiency without
13
+ sacrificing quality**. Every setting and hook minimizes token use while
12
14
  preserving rigorous output. When you add or edit anything, ask: *does this
13
15
  change reduce tokens without weakening correctness?*
14
16
 
15
17
  Tool-specific instructions live alongside this file:
16
18
  - **`CLAUDE.md`** — Claude Code SoT (`SoT/.claude/`), env vars, hooks, plugins, status line, session management, permission mode, open concerns.
17
19
  - Codex uses this `AGENTS.md` file plus the Codex SoT under `SoT/.codex/`; no separate root `CODEX.md` is needed.
20
+ - omp uses this `AGENTS.md` file plus the omp SoT under `SoT/.omp/`.
18
21
 
19
22
 
20
23
  docks-kit runtime and standalone binary support covers Linux x64/arm64, macOS
@@ -27,17 +30,19 @@ launcher can fall back to Bun source.
27
30
  |------|---------|
28
31
  | `docks-kit` / `docks-kit.ps1` | POSIX and Windows CLI launchers. On supported hosts, each runs the matching binary in `cli/dist/` only when its `--version` matches `package.json`. Otherwise it runs Bun-from-source and auto-installs Bun plus `node_modules`. Hosts outside the support matrix fail before source fallback. The standalone platform release binary provides no-Bun recovery. |
29
32
  | `cli/src/engine-native/` | EngineNative implementation for `sync`, `model`, and `toolchain`; idempotent, flag-gated for destructive reconciliation |
33
+ | `cli/src/engine-native/ompSync.ts` | omp file deployment, marketplace registration, and plugin synchronization |
30
34
  | `cli/` | Effect 4 RC CLI + bundled docs topics |
31
35
  | `SoT/models.json` | Kit-verified Claude and Codex model catalog |
32
36
  | `SoT/toolchain.json` | Toolchain floors manifest (verified pins consumed by EngineNative) |
33
37
  | `SoT/.claude/bin/` | Dependency-free Bun runtime programs for Claude's statusline, SessionStart, and Notification |
38
+ | `SoT/.omp/` | Kit-owned omp SoT: `AGENTS.md`, `config.yml`, `mcp.json`, and `intercom.json` |
34
39
  | `install.sh` / `install.ps1` | POSIX and Windows global installers |
35
40
  | `.github/workflows/release-cli.yml` | `cli-v*` release: six binaries for Linux, macOS, and Windows on x64 and arm64, plus `SHA256SUMS` and npm publish |
36
41
  | `README.md` | Front door |
37
42
  | `package.json` / `bun.lock` | npm package: `bin` = `cli/src/main.ts`; bundles `cli/` with the generated in-memory SoT payload |
38
43
  | `SoT/.agents/skills.txt` | Universal-skill manifest, intentionally empty by default. Adding an [agentskills.io](https://agentskills.io/specification) slug opts it into EngineNative's shared `~/.agents/skills/` bootstrap and Claude symlink. |
39
44
  | `notification.mp3` | Audio asset for Notification hooks (consumed by Claude Code today; tool-agnostic file) |
40
- | `docs/plans/` | Multi-commit work-item plans (`active/` with status in frontmatter, plus `finished/` archive). Convention: `docs/plans/AGENTS.md` |
45
+ | `docs/PLAN.md` | Plan record standard. The plan record is a GitHub issue; no plan markdown is tracked. `docs/AGENTS.md` routes to it and `docs/CLAUDE.md` contains only `@AGENTS.md`. |
41
46
  | `CLAUDE.md` | Claude-specific instructions; imports this `AGENTS.md` |
42
47
  | `AGENTS.md` | This file — tool-agnostic instructions |
43
48
 
@@ -46,12 +51,24 @@ Codex SoT notes:
46
51
  - `SoT/.codex/config.toml` pins Codex to `model = "gpt-5.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).
47
52
  - `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.
48
53
  - `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.
54
+ - 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.
55
+ - Codex limits the initial skill list to 2% of the model context and shortens descriptions first; it still reads a selected skill's full `SKILL.md`. Additive sync preserves user-added plugins, so their skill count and malformed cached `SKILL.md` files remain plugin-owned. Sync never patches a plugin cache in place.
49
56
  - The global prompt SoTs carry the owner's standing authorization for Docks cross-company plan review, which never overrides host or platform denial.
50
57
  - The `codex` CLI binary is upstream-owned, not kit-owned. The official standalone installer keeps package metadata under `$CODEX_HOME/packages/standalone` and places the `codex` symlink in `~/.local/bin` by default; sync only warns with a download-then-run installer command when the CLI is missing. Existing installs can self-update with `codex update`; npm and Homebrew remain upstream alternatives.
58
+
51
59
  - Claude runtime settings are an authoring template with sentinels. `claudeRuntime.ts` materializes absolute Bun/script paths only after the shared `bun.ts` bootstrap is ready; `claudeSync.ts` writes all runtime assets before atomically committing settings, then prunes the legacy shell scripts and Stop hook. Native `rate_limits` is the sole quota source, so jq/curl/OAuth caches are not runtime dependencies. A missing Bun defers only this cutover and preserves legacy pointers/files.
52
60
  - Claude's deployed SoT defaults are `model: opus` and `effortLevel: high`; `advisorModel` is deliberately absent/off. `--claude-advisor=on` is the per-machine opt-in and writes `advisorModel: fable` after the settings merge. `opus` is the alias, not a pinned id: the `minimumVersion` floor of 2.1.219 ensures Claude Code can resolve it to the newest Opus its provider offers — Opus 5 on the Anthropic API or Opus 4.6 on Microsoft Foundry — instead of silently capping Anthropic API users at Opus 4.8 under the former 2.1.170 floor. Keeping the alias provides provider portability and tracks future Opus releases; the literal `claude-opus-5` is unavailable on Foundry. The floor also subsumes Fable 5's older 2.1.170 requirement.
61
+ - Claude permission rules are pruned, not host-scoped. The kit deploys its `PowerShell(...)` deny and ask rules on every host, because Claude Code leaves the PowerShell tool opt-in off Windows rather than unavailable, and a host that enables it must already carry the guards. `claudeRetired.ts RETIRED_PERMISSION_RULES, exact retired-rule inventory` lists the rules the kit no longer ships. `claudeSync.ts syncRemovals, retired-permission pass` force-prunes those exact strings from the kit-managed `~/.claude/settings.json` on every sync, because `settings.ts mergeSettings, permission-array union` would otherwise keep a dropped rule forever. A different user-authored rule survives. To restore an exact retired rule for one checkout, put it in that checkout's `.claude/settings.local.json`. Claude Code resolves that file against the working directory and merges it over user settings. Sync never reads or writes the checkout-local file. Claude Code has no user-scope local settings file. For a machine-wide restoration, add the rule to `SoT/.claude/settings.json`. At the same time, remove the exact string from `claudeRetired.ts RETIRED_PERMISSION_RULES, exact retired-rule inventory`. `permissions.allow` holds four read-only entries (`Read`, `Glob`, `Grep`, and `WebSearch`) plus the working-directory edit rule `Edit(./)`. Broad shell allow rules are not restored, because an allow rule resolves before Claude Code's read-only command analyzer and the auto-mode classifier. `autoMemoryEnabled` and `autoDreamEnabled` are both `false`.
62
+
63
+ omp SoT notes:
64
+ - `SoT/.omp/AGENTS.md`, `config.yml`, and `mcp.json` deploy to `~/.omp/agent/`.
65
+ - `SoT/.omp/intercom.json` deploys to `$PI_CODING_AGENT_DIR/intercom/config.json`. The default root is `~/.pi/agent`.
66
+ - `ompSync.ts syncConfig` deep-merges `config.yml` through `mergeOmpConfig`.
67
+ - Sync registers the `docks` marketplace. It installs or upgrades `docks@docks` and `plan-lifecycle@docks` at user scope.
68
+ - Sync installs `pi-intercom` at the verified version from `SoT/toolchain.json`.
69
+ - The omp CLI is upstream-owned and self-updating through `omp update`. Sync never installs or upgrades the CLI.
53
70
 
54
- For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`), see the matching SoT directory.
71
+ For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`, `SoT/.omp/`), see the matching SoT directory.
55
72
 
56
73
  ## Engineering rules
57
74
 
@@ -59,19 +76,20 @@ For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`), see the matching SoT d
59
76
  - **Removed bash engine.** The bash engine was removed after the `bash-engine-final` tag. `DOCKS_KIT_ENGINE=bash` must fail with the removed-engine message; engine bugs are fixed forward in EngineNative.
60
77
  - **Effect 4 CLI stack.** The CLI pins `effect@4.0.0-rc.109` (including `effect/unstable/cli`), `@effect/platform-bun@4.0.0-rc.109` (`BunServices.layer`, `BunRuntime.runMain`), `@effect/vitest@4.0.0-rc.109`, and `vitest@4.1.10` (required by the `@effect/vitest` peer range). `@effect/cli` and `@effect/platform` are removed and must not be reintroduced.
61
78
  - **Effect skill routing.** Effect work in this checkout must verify migration and API call shapes against the installed declarations under `node_modules/effect/dist/unstable/cli/`, never from memory or a mutable dist-tag. The `effect-ts-setup`, `effect-ts-port`, and `effect-ts-specialist` skills target Effect 3.x and do not apply.
62
- - **Targeted syncs.** `./docks-kit sync` accepts positional targets: `claude`, `codex`, and `agents`. Use the narrowest target that matches the SoT change (for example, `./docks-kit sync codex` for Codex-only config edits); targets can be combined with `--dry-run`, `--skip-bubblewrap` (skip optional bubblewrap bootstrap for the Codex Linux sandbox), `--skip-plugin-refresh` (install missing plugins without refreshing existing caches; used by `docks-kit update`), `--reconcile`, `--prune`, and the deploy-time modifiers `--claude-compact-window=<tokens>` / `--claude-permissive` / `--claude-model=<m>` / `--claude-effort=<level>` / `--claude-advisor=<on|off|default>` / `--codex-model=<m>` / `--codex-effort=<level>` (see `CLAUDE.md` § Deploy-time modifiers).
79
+ - **Targeted syncs.** `./docks-kit sync` accepts positional targets: `claude`, `codex`, `agents`, and `omp`. Use the narrowest target that matches the SoT change (for example, `./docks-kit sync omp` for omp-only config edits); targets can be combined with `--dry-run`, `--skip-bubblewrap` (skip optional bubblewrap bootstrap for the Codex Linux sandbox), `--skip-plugin-refresh` (install missing plugins without refreshing existing caches; used by `docks-kit update`), `--reconcile`, `--prune`, and the deploy-time modifiers `--claude-compact-window=<tokens>` / `--claude-permissive` / `--claude-model=<m>` / `--claude-effort=<level>` / `--claude-advisor=<on|off|default>` / `--codex-model=<m>` / `--codex-effort=<level>` (see `CLAUDE.md` § Deploy-time modifiers).
80
+ - **Per-machine harness selection.** `~/.docks-kit/state.json` drives a flag-less sync. A missing file selects `claude`, `codex`, and `agents`; it never selects `omp` implicitly. `sync` never prompts and never writes the selection file. `docks-kit harnesses` is the only command that writes the selection.
63
81
  - **Additive by default.** Keys present in deployed config but absent from SoT are preserved on default sync. This protects user-only additions, but means drift accumulates — neither flag-less reset can clean it up. The one exception is the Claude `removed` manifest (`claude::_removed_manifest`), a curated list of unambiguous kit-owned artifacts that `claude::sync_removals` force-prunes on every sync, including the home-relative `~/.local/bin/session-relay` artifact installed outside `~/.claude`; see `CLAUDE.md` § Pruning stale artifacts.
64
82
  - **`--reconcile` / `--prune` are the kit-owned reconcile flags.** Orthogonal — `--reconcile` reconciles the settings layer (SoT-declared keys/tables/arrays win; user-only keys and nested objects are preserved; permissions arrays are replaced wholesale by SoT). `--prune` uninstalls kit-managed installations not in the SoT (plugins, marketplaces, and `~/.agents/skills/*` entries tracked in `~/.agents/.kit-managed-skills`). Combine for a full reset to SoT's kit-managed scope. User-only additions outside the kit's scope (custom env vars, mcpServers, manually-installed skills, third-party plugins not declared in SoT) are always preserved. Each tool's per-tool file documents the specific paths and diff recipes.
65
- - **SOLID-aligned modules.** `cli/src/engine-native/parseArgs.ts` owns flag parsing/validation. `toolchain.ts` owns verified-version floor reporting over `SoT/toolchain.json`; `bun.ts` owns the shared, memoized Bun bootstrap; `claudeRuntime.ts` owns Claude settings materialization. `claudeSync.ts`, `codexSync.ts`, and `skillsSync.ts` own tool-specific sync logic. `index.ts` is the thin orchestrator. The public CLI seam is `cli/src/engine.ts`.
83
+ - **SOLID-aligned modules.** `cli/src/engine-native/parseArgs.ts` owns flag parsing and validation. `toolchain.ts` owns verified-version floor reporting over `SoT/toolchain.json`; `bun.ts` owns the shared, memoized Bun bootstrap; `claudeRuntime.ts` owns Claude settings materialization. `claudeSync.ts`, `codexSync.ts`, and `skillsSync.ts` own their tool-specific sync logic. `ompSync.ts` owns omp file and plugin sync. `ompYaml.ts` owns the omp YAML merge. `harnesses.ts` owns per-machine harness selection. `index.ts` is the thin orchestrator. The public CLI seam is `cli/src/engine.ts`.
66
84
  - **Small, reviewable changes.** Bundled multi-concern PRs are harder to review and revert. Split an engine/CLI change and a per-tool config change unless the change requires atomicity.
67
85
  - **Dry-run before destructive flags.** Always preview with `./docks-kit sync --dry-run` (or the relevant `diff <(jq -S …)` recipe in the per-tool file) before invoking `--reconcile` or `--prune`. User-added permissions / env vars / plugins absent from SoT will be discarded.
68
- - **SoT prompt files are rules, not explanation.** `SoT/.claude/CLAUDE.md` and `SoT/.codex/AGENTS.md` are loaded into every agent session's prompt context — every line costs prompt tokens on every turn for every user. Restrict their content to rules, heuristics, and `<constraint>` blocks the agent must *act on* during a turn. Do NOT add inline source citations (`Source: …`, attributed quotes), "why this rule exists" preface text, version-watermarking trivia (e.g. "Distilled from X v2.0, captured 2025-11-07"), per-bug workarounds, or installation instructions. Provenance, motivation, and historical context belong in `CLAUDE.md` / `AGENTS.md` at the repo root (humans read once) or in commit messages — never in the SoT. For every line, apply the official test: would removing it cause the agent to make mistakes? If not, cut it — over-instruction degrades adherence on current frontier models.
86
+ - **SoT prompt files are rules, not explanation.** `SoT/.claude/CLAUDE.md`, `SoT/.codex/AGENTS.md`, and `SoT/.omp/AGENTS.md` are loaded into agent sessions' prompt context — every line costs prompt tokens on every turn for every user. Restrict their content to rules, heuristics, and `<constraint>` blocks the agent must *act on* during a turn. Do NOT add inline source citations (`Source: …`, attributed quotes), "why this rule exists" preface text, version-watermarking trivia (e.g. "Distilled from X v2.0, captured 2025-11-07"), per-bug workarounds, or installation instructions. Provenance, motivation, and historical context belong in `CLAUDE.md` / `AGENTS.md` at the repo root (humans read once) or in commit messages — never in the SoT. For every line, apply the official test:
69
87
  - **Cache-invariance for kit-authored prompt surfaces.** Never put timestamps, counters, or mutable state into SoT prompt files, hook outputs that land in the cached prefix, or tool definitions — cache breaks force cold-start writes. Dynamic context belongs in runtime-injected messages (e.g. SessionStart hook output), which is exactly how the kit's date/config injection works.
70
88
 
71
89
  ## Code style
72
90
 
73
91
  - Bash: for launchers/installers/hook assets, use `set -euo pipefail`, quoted variables, `[[ ]]` over `[ ]`, and function-scoped `local`.
74
- - JSON config: edit the SoT (`SoT/<tool>/`) and run `./docks-kit sync`. Never edit deployed config (`~/.claude/`, `~/.codex/`) directly.
92
+ - JSON and YAML config: edit the SoT (`SoT/<tool>/`) and run `./docks-kit sync`. Never edit deployed config under `~/.claude/`, `~/.codex/`, or `~/.omp/agent/` directly.
75
93
 
76
94
  ## Security
77
95
 
@@ -87,7 +105,23 @@ Use direct acceptance and focused regressions while iterating, then run the full
87
105
 
88
106
  ## Skills
89
107
 
90
- This project ships **kit-mechanic skills** under `.claude/skills/` — narrowly-scoped references for how EngineNative works (settings merge, plugin bootstrap, universal-skill install, Codex TOML merge, sync orchestration). They cost prompt tokens only inside this repo's sessions and document regression-prone TypeScript sync logic in `cli/src/engine-native/`. **Pipeline content** (multi-agent slash commands, refactor/security/docs workflows, parallel-scanner agents) belongs in the separate [DocksDocks/docks](https://github.com/DocksDocks/docks) plugin — not here. Project-level agents under `.claude/agents/` follow the same rule: kit-mechanic agents that wrap kit-mechanic skills are permitted; pipeline agents live in the docks plugin.
108
+ **Project-skill scope.** Keep project skills within two classes: kit-mechanic skills and the `unslop` repo-prose skill.
109
+ Canonical project skills live in `.agents/skills/<name>/SKILL.md`.
110
+ Each `.claude/skills/<name>` entry is a relative symlink to its canonical directory.
111
+ Codex reads `.agents/skills/` natively, so one copy serves both tools.
112
+ Kit-mechanic skills document regression-prone TypeScript sync logic in `cli/src/engine-native/`.
113
+ Kit-mechanic skills: `codex-config-merge-context`, `engine-native-context`, `plugin-bootstrap-context`, `settings-merge-context`, `sync-orchestration-context`, `toolchain-context`, `universal-skills-context`, and `omp-sync-context`.
114
+ **Pipeline content** (multi-agent slash commands, refactor/security/docs workflows, parallel-scanner agents) belongs in the separate [DocksDocks/docks](https://github.com/DocksDocks/docks) plugin — not here. Project-level agents under `.claude/agents/` follow the same rule: kit-mechanic agents that wrap kit-mechanic skills are permitted; pipeline agents live in the docks plugin.
115
+
116
+ **Windows checkouts.** These nine entries are the only symlinks this repository tracks. Git for Windows defaults to `core.symlinks=false`, which checks a symlink out as a plain file holding the target path, so Claude Code finds no `SKILL.md` and silently loads no project skill. Codex is unaffected, because it reads the real directories under `.agents/skills/`. To restore Claude Code on Windows, enable Developer Mode or run as administrator, then `git config core.symlinks true` and re-checkout the paths: `git checkout -- .claude/skills`. Never repair this by replacing an entry with a copy; two copies drift, which is the failure the canonical layout removes. This limitation is confined to project skills in this checkout. It does not affect the deployed user-level skills, where `skillsSync.ts linkOrCopyWithWarnings` already falls back from symlink to junction to marked copy.
117
+
118
+ `npx skills add cursor/plugins -s unslop -y -a claude-code codex` installs `unslop`, and root `skills-lock.json` pins it.
119
+ The repository vendors upstream `unslop` text and pins it by the lockfile hash, so never edit it locally.
120
+ Upstream licenses `pstack/` under MIT (Copyright (c) 2026 Lauren Tan), so redistribution is permitted.
121
+ MIT requires the notice to travel with the copy, so `.agents/skills/unslop/LICENSE` vendors it verbatim and must stay beside `SKILL.md`.
122
+ The `unslop` "adding soul" guidance conflicts with the global Simplified Technical English Output Standard.
123
+ The Output Standard wins.
124
+ Use `unslop` only for its pattern-detection lists.
91
125
 
92
126
  <constraint>
93
127
  When a kit-mechanic skill, its `references/`, or a wrapper agent (`.claude/agents/*.md` + its `.codex/agents/*.toml` twin) cites EngineNative internals, name the **module + exported/local function + semantic anchor** (e.g. `claudeSync.ts syncPlugins, pass 5 uninstall guard`) — never a raw `file:NNN` line number, which goes stale on every refactor. Keep exactly one coarse `metadata.source_files[].lines` range per skill file as the sole intentional line-number touchpoint.
@@ -98,42 +132,78 @@ When a kit-mechanic skill, its `references/`, or a wrapper agent (`.claude/agent
98
132
  ## Plans
99
133
 
100
134
  Use direct implementation for one clear, reversible, low-risk local diff with one
101
- bounded acceptance path; it creates no tracked plan, reviewer, or automatic
135
+ bounded acceptance path; it creates no plan issue, reviewer, or automatic
102
136
  commit. Use a canonical plan for explicit planning, multi-commit or
103
137
  cross-repository work, cold handoff, an unresolved decision, a cross-subsystem or
104
138
  public-contract change, security-sensitive or destructive work, or any
105
139
  non-`local` effect.
106
140
 
107
141
  <constraint>
108
- Canonical plans live in `docs/plans/active/`; status is frontmatter and
109
- `docs/plans/finished/` is terminal. Exactly three skills own the workflow:
110
- `plan-workspace` maintains the workspace; main-context `plan-manager` runs six
111
- phases decide, draft, research, one plan review, implement, code review and
112
- archives; internal `plan-reviewer` returns a readable pre-implementation verdict.
113
- Two read-only reviewer wrappers ship, `plan-reviewer` and `code-reviewer`, and
114
- nothing else in the lifecycle has a wrapper.
142
+ The plan record is a GitHub issue. Its body starts with
143
+ `<!-- plan-contract: v3 -->`, then a blank line and the exact eight `##`
144
+ sections; it has no frontmatter. GitHub owns title, open-work phase, owner,
145
+ timestamps, and completion, and no plan markdown is tracked in the repository.
146
+ Exactly three skills own the workflow: `plan-workspace` maintains the workspace;
147
+ main-context `plan-manager` runs six phases - decide, draft, research, plan
148
+ review, implement, code review - with bounded repair and fresh re-review in both
149
+ review phases, then archives; internal `plan-reviewer` returns one readable
150
+ pre-implementation verdict block per round. Two read-only reviewer wrappers
151
+ ship, `plan-reviewer` and `code-reviewer`, and nothing else in the lifecycle has
152
+ a wrapper.
115
153
  </constraint>
116
154
 
117
- The record is markdown only: `plan_contract: v2` frontmatter plus eight `##`
118
- sections — `## Goal`, `## Research`, `## Steps`, `## Acceptance`,
119
- `## Do not touch`, `## Open questions`, `## Review`, `## Verification Results`.
120
- There are no hashes, permits, run identities, locks, bundles, or `v2`/`vN` plan
121
- files, and the `plan.mjs` shipped inside the installed `plan-lifecycle` plugin
122
- is the only lifecycle tool. This lifecycle creates zero commits and never
123
- pushes; commit when the user asks, under `docks:commit-discipline`.
155
+ After the marker and blank line, the record carries exactly `## Goal`,
156
+ `## Research`, `## Steps`, `## Acceptance`, `## Do not touch`,
157
+ `## Open questions`, `## Review`, and `## Verification Results`, in that order
158
+ and once each. `## Goal` carries exactly one mode line. Open-work phase is one
159
+ of `drafting`, `planned`, `ongoing`, or `blocked` in a `plan:<phase>` label; a
160
+ blocked plan starts `## Open questions` with `Blocked: <one-line reason>`.
161
+ Closed completion derives from GitHub `state` and `stateReason`. `## Review`
162
+ contains exactly `_Review records are stored in issue comments._`. Each reviewer
163
+ returns one markdown block, and the manager posts that whole block as one issue
164
+ comment. The latest trusted well-formed record per review kind wins; its author
165
+ must equal the plan's sole assignee. A legacy body verdict is consulted only
166
+ when no trusted comment record exists for that kind. Both review phases use
167
+ fresh inputs and run at most five rounds, stopping on pass, no progress, a
168
+ finding surviving its fix, or `repair` or `fixes-required` in round five. A
169
+ plan-review `blocked` verdict always routes its user-only decision through
170
+ `## Open questions` and `ask`.
171
+
172
+ The record carries no hash, permit, run identity, lock, or bundle, and the
173
+ `plan.mjs` shipped inside the installed `plan-lifecycle` plugin is the only
174
+ lifecycle tool. An `export` writes the sha256 of the body it copied beside the
175
+ copy so a stale copy cannot revert the record; that digest detects staleness and
176
+ authorizes nothing. Routine plan issue publication, implement-start linked
177
+ branch creation, commits, normal pushes, and the closing pull request carry the
178
+ settled mode's authorization and need no repeated prompt. Before any branch
179
+ checkout, including `gh issue develop --checkout`, require
180
+ `git status --porcelain` to be empty. If it is dirty, never stash, move, or
181
+ commit ambient work; set the plan `blocked` and name the dirty paths, or use an
182
+ authorized clean worktree.
183
+ Immediately after setting the plan `ongoing`, every `gh issue develop` call uses
184
+ `--repo`; the manager reuses a linked branch or creates one with
185
+ `--base <default> --checkout`, then re-lists and recovers after failure.
186
+ Implementation stops when no linked branch can be verified; there is no local
187
+ fallback. After the checks policy passes, the manager asks immediately before
188
+ merge. Without a fresh `Merge now` answer, it leaves the pull request and issue
189
+ open. `plan.mjs archive` verifies the latest trusted code-review result and
190
+ merged closing pull request after landing.
124
191
 
125
192
  Every Steps row carries an `Effect` of exactly
126
193
  `local|probe|production_access|publish|push|release|deploy`. A step whose
127
194
  `Effect` is not `local` requires an in-session `ask` confirmation immediately
128
- before it runs; when `ask` is unavailable the step is set `blocked` with
129
- `blocked_reason` naming the unconfirmed effect. Persisted effects record intent
130
- only.
131
-
132
- A plan carrying a `Plan-run:` line is a v1 plan: render it, never parse or
133
- migrate it, and finish it by hand by moving the file byte-unchanged to
134
- `docs/plans/finished/<YYYY-MM-DD>-<slug>.md` with a `## Retirement` section
135
- appended. The complete contract lives in `docs/plans/AGENTS.md`;
136
- `docs/plans/CLAUDE.md` contains only `@AGENTS.md`.
195
+ before it runs; when `ask` is unavailable the step is set `blocked` and the plan
196
+ reason becomes the first `## Open questions` line, `Blocked: <reason>`.
197
+ Persisted effects record intent only. Routine issue publication and landing
198
+ actions are outside the Steps table.
199
+
200
+ Render a plan body verbatim only when the user names that plan and asks to see it. After a write, report the one-line header strip and the changed lines only; a write never re-renders the body.
201
+
202
+ No plan markdown is tracked. The pre-GitHub records under
203
+ `docs/plans/finished/` were deleted; `git log -- docs/plans/finished/` recovers
204
+ them as history, and no lifecycle command restores them. The complete contract
205
+ lives in `docs/PLAN.md`; `docs/AGENTS.md` routes to it and `docs/CLAUDE.md`
206
+ contains only `@AGENTS.md`.
137
207
 
138
208
  Distinct from per-tool **Open Concerns** sections (wait-on-upstream
139
209
  blockers tied to a vendor shipping a fix — these live inside the per-tool
package/README.md CHANGED
@@ -5,15 +5,17 @@ Truth (SoT)** directories deploy to each tool's user-config location. Clone
5
5
  once to get a consistent AI-assisted environment on supported Linux, macOS,
6
6
  and Windows machines. Tuned for **token efficiency without sacrificing quality**.
7
7
 
8
- Supported tools: **Claude Code**, **Codex**, and any agent consuming
9
- [agentskills.io](https://agentskills.io) universal skills.
8
+ Supported harnesses: **Claude Code**, **Codex**, and **Oh My Pi (`omp`)**.
9
+ The kit also deploys [agentskills.io](https://agentskills.io) universal skills.
10
10
 
11
11
  ## Quick start
12
12
 
13
13
  ```bash
14
14
  git clone https://github.com/DocksDocks/public.git ~/projects/public
15
15
  cd ~/projects/public
16
- ./docks-kit sync # deploy everything (Claude Code + Codex + skills)
16
+ ./docks-kit harnesses # choose this machine's flag-less sync harnesses
17
+ ./docks-kit sync # deploy this machine's harness selection
18
+ ./docks-kit sync omp # deploy omp explicitly
17
19
  ./docks-kit status # doctor view: drift, toolchain, plugins, skills
18
20
  ```
19
21
 
@@ -41,15 +43,16 @@ PowerShell.
41
43
  ## CLI
42
44
 
43
45
  ```text
44
- docks-kit sync [claude] [codex] [agents] deploy the SoT (default: all three)
45
- docks-kit update [--no-sync] self-update the kit (autodetects checkout vs global install), then sync
46
- docks-kit model <claude|codex> [value] get/set the DEPLOYED model (TTY picker)
47
- docks-kit models [claude|codex] model catalogs (`--json`)
48
- docks-kit toolchain [check|ensure <tool>] verified-version floors for external tools
49
- docks-kit status [--json] deployed-vs-SoT drift + toolchain + counts
50
- docks-kit plugins list [--json] enabledPlugins tri-state vs installed
51
- docks-kit skills list [--json] universal skills vs manifest
52
- docks-kit docs [topic] self-documentation (9 topics)
46
+ docks-kit sync [claude] [codex] [agents] [omp] deploy explicit targets or the machine selection
47
+ docks-kit harnesses view or change this machine's selection
48
+ docks-kit update [--no-sync] self-update the kit (autodetects checkout vs global install), then sync
49
+ docks-kit model <claude|codex> [value] get/set the DEPLOYED model (TTY picker)
50
+ docks-kit models [claude|codex] model catalogs (`--json`)
51
+ docks-kit toolchain [check|ensure <tool>] verified-version floors for external tools
52
+ docks-kit status [--json] deployed-vs-SoT drift + toolchain + counts
53
+ docks-kit plugins list [--json] enabledPlugins tri-state vs installed
54
+ docks-kit skills list [--json] universal skills vs manifest
55
+ docks-kit docs [topic] self-documentation (9 topics)
53
56
  --help --version --wizard --completions built-in
54
57
  ```
55
58
 
@@ -87,6 +90,9 @@ and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
87
90
  - **Additive by default** — user-only settings keys, plugins, and skills
88
91
  survive a plain sync. Reconciliation toward the SoT is explicit
89
92
  (`--reconcile` / `--prune`).
93
+ - **Per-machine selection** — `~/.docks-kit/state.json` drives a flag-less sync.
94
+ A missing file selects Claude Code, Codex, and universal skills. It does not
95
+ select omp. Use `docks-kit harnesses` to view or change the selection.
90
96
  - **Idempotent** — every step is safe to re-run; no-change syncs are no-ops.
91
97
  - **Toolchain floors** — `SoT/toolchain.json` records the kit-verified version
92
98
  floors for external tools (bun, bwrap, …). `docks-kit toolchain check` prints
@@ -106,6 +112,7 @@ and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
106
112
  |------|---------|
107
113
  | `SoT/.claude/` | Claude Code SoT (settings template, Bun runtime programs, CLAUDE.md) |
108
114
  | `SoT/.codex/` | Codex SoT (config.toml, rules, AGENTS.md, marketplace) |
115
+ | `SoT/.omp/` | omp SoT (AGENTS.md, config.yml, mcp.json, intercom.json) |
109
116
  | `SoT/.agents/` | Universal-skill manifest |
110
117
  | `SoT/models.json` | Kit-verified Claude and Codex model catalog |
111
118
  | `SoT/toolchain.json` | Verified-version floors |
@@ -114,7 +121,7 @@ and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
114
121
  | `cli/` | docks-kit CLI (Effect 4 RC on Bun) + bundled docs topics |
115
122
  | `docks-kit` / `docks-kit.ps1` | POSIX and Windows launchers (binary → Bun-from-source) |
116
123
  | `install.sh` / `install.ps1` | POSIX and Windows global installers |
117
- | `docs/plans/` | Multi-commit work-item plans |
124
+ | `docs/PLAN.md` | Plan record standard; plans are GitHub issues |
118
125
  | `AGENTS.md` / `CLAUDE.md` | Agent-facing engineering rules / Claude Code specifics |
119
126
 
120
127
  ## Platform support
@@ -136,7 +143,7 @@ Tagging `cli-v*` builds six standalone binaries for Linux, macOS, and Windows
136
143
  on x64 and arm64. The workflow attaches them plus `SHA256SUMS` to the GitHub
137
144
  release. npm publishes the exact package tarball through trusted publishing
138
145
  with OIDC provenance.
139
- Package `docks-kit` 0.15.5 bundles the CLI + generated payload, so npm releases
146
+ Package `docks-kit` 0.16.1 bundles the CLI + generated payload, so npm releases
140
147
  are versioned config snapshots without shipping the authoring `SoT/` tree.
141
148
 
142
149
  ## Deeper docs
@@ -1,7 +1,9 @@
1
1
  # Sync layers
2
2
 
3
- `docks-kit sync [claude] [codex] [agents]` — targets are positional words;
4
- no target means all three.
3
+ `docks-kit sync [claude] [codex] [agents] [omp]` — targets are positional
4
+ words; no target means this machine's harness selection in
5
+ `~/.docks-kit/state.json`. The default is `claude codex agents`, and
6
+ `docks-kit harnesses` changes it.
5
7
 
6
8
  ## claude (→ ~/.claude, ~/.claude.json, shell rc)
7
9
 
@@ -46,6 +48,34 @@ and `codex plugin add` refresh.
46
48
  `npx skills add` per missing manifest slug, Claude symlink healing, and the
47
49
  kit-managed snapshot that `--prune` reconciles against.
48
50
 
51
+ ## omp (→ resolved agent dir, intercom root)
52
+
53
+ AGENTS.md, mcp.json, and intercom config.json are whole-file deploys;
54
+ config.yml is deep-merged (SoT keys win, mapping nodes merge, deployed-only
55
+ keys survive, stale slash-bearing `retry.fallbackChains` wildcards pruned).
56
+ Directories are mode 0700 and files mode 0600. Then the `docks` marketplace is
57
+ registered, `docks@docks` and `plan-lifecycle@docks` are installed or upgraded
58
+ through `omp plugin`, and `pi-intercom` is installed at its
59
+ `SoT/toolchain.json` pin. Inventory comes from `omp plugin list --json`, where a
60
+ marketplace row counts as installed only when its `scope` is `user`, so a repeat
61
+ run is a no-op and a project-only row still installs. When just the legacy
62
+ config-root registry lists `docks`, omp copies it forward itself: the sync runs
63
+ `marketplace update`, or the read-only `marketplace list` under
64
+ `--skip-plugin-refresh`, which keeps installs but fetches nothing. A dry run
65
+ invokes no omp subcommand.
66
+
67
+ Paths mirror upstream `dirs.ts` `DirResolver`, resolved from the environment
68
+ plus directory probes, so a dry run still runs no omp subcommand. The agent
69
+ directory is `<config root>/agent`, where the config root is
70
+ `~/<PI_CONFIG_DIR or .omp>` plus `profiles/<name>` under an active profile
71
+ (`OMP_PROFILE`, else legacy `PI_PROFILE`). For the default profile only,
72
+ `PI_CODING_AGENT_DIR` replaces the agent directory outright. The agent
73
+ directory never moves under XDG. Only the data root that holds
74
+ `marketplaces.json` does: on Linux and macOS, with no agent-dir override
75
+ active, an existing `$XDG_DATA_HOME/omp` (or `$XDG_DATA_HOME/omp/profiles/<name>`
76
+ for a named profile) is adopted. The intercom file keeps pi-intercom's own
77
+ root: `$PI_CODING_AGENT_DIR/intercom`, else `~/.pi/agent/intercom`.
78
+
49
79
  ## Reconcile flags
50
80
 
51
81
  - `--reconcile` — settings layer: SoT-declared keys win; user-only preserved.
@@ -0,0 +1,64 @@
1
+ import { Command, Prompt } from "effect/unstable/cli"
2
+ import { Console, Effect } from "effect"
3
+ import { bail } from "../engine"
4
+ import {
5
+ engineHome,
6
+ HARNESSES,
7
+ harnessStateFile,
8
+ LEGACY_SELECTION,
9
+ readHarnessSelection,
10
+ writeHarnessSelection,
11
+ type Harness
12
+ } from "../engine-native/harnesses"
13
+
14
+ const DESCRIPTIONS: Record<Harness, string> = {
15
+ claude: "Claude Code user configuration",
16
+ codex: "Codex user configuration",
17
+ agents: "universal agent skills",
18
+ omp: "Oh My Pi user configuration"
19
+ }
20
+
21
+ export const harnessesCommand = Command.make(
22
+ "harnesses",
23
+ {},
24
+ () =>
25
+ Effect.gen(function* () {
26
+ const home = engineHome(process.env)
27
+ const stored = yield* Effect.sync(() => readHarnessSelection(home))
28
+ const selection = stored ?? LEGACY_SELECTION
29
+ const names = selection.join(", ")
30
+
31
+ if (stored === undefined) {
32
+ yield* Console.log(
33
+ `Harness selection: ${names} (no selection is stored yet; the legacy default applies)`
34
+ )
35
+ } else {
36
+ yield* Console.log(`Harness selection: ${names}`)
37
+ }
38
+
39
+ if (!process.stdout.isTTY) return
40
+
41
+ const answer = yield* Prompt.multiSelect({
42
+ message: "Choose the harnesses for a flag-less docks-kit sync",
43
+ choices: HARNESSES.map((harness) => ({
44
+ title: harness,
45
+ value: harness,
46
+ description: DESCRIPTIONS[harness],
47
+ selected: selection.includes(harness)
48
+ }))
49
+ })
50
+
51
+ if (answer.length === 0) {
52
+ return yield* bail("Select at least one harness. The stored selection was not changed.")
53
+ }
54
+
55
+ yield* Effect.sync(() => writeHarnessSelection(home, answer))
56
+ yield* Console.log(
57
+ `Saved harness selection: ${answer.join(", ")} (${harnessStateFile(home)})`
58
+ )
59
+ })
60
+ ).pipe(
61
+ Command.withDescription(
62
+ "Choose the harness selection that drives a flag-less docks-kit sync."
63
+ )
64
+ )
@@ -29,11 +29,11 @@ const updateNudge = (logger: Logger): void => {
29
29
  }
30
30
  }
31
31
 
32
- const VALID_TARGETS = ["claude", "codex", "agents"]
32
+ const VALID_TARGETS = ["claude", "codex", "agents", "omp"]
33
33
 
34
34
  const targets = Argument.variadic(
35
35
  Argument.string("target").pipe(
36
- Argument.withDescription("Sync targets: claude, codex, agents (default: all three)")
36
+ Argument.withDescription("Sync targets: claude, codex, agents, omp (default: selected harnesses)")
37
37
  )
38
38
  )
39
39
 
@@ -0,0 +1,165 @@
1
+ /** Kit-owned permission rules the SoT no longer ships.
2
+ *
3
+ * `mergeSettings` unions the deployed arrays with the SoT arrays, so dropping a
4
+ * rule from `SoT/.claude/settings.json` never removes it from a file an earlier
5
+ * sync already wrote. `claudeSync.ts syncRemovals` force-prunes this exact-string
6
+ * inventory on every host so the retirement reaches existing installations
7
+ * without `--reconcile`.
8
+ *
9
+ * `allow` holds the shell pre-approvals retired in favour of Claude Code's own
10
+ * read-only command analysis and the auto-mode classifier, plus `WebFetch`.
11
+ * `deny` holds the malformed single-backslash spellings superseded by their
12
+ * escaped `\\)` forms; Claude Code refuses to parse the old text.
13
+ *
14
+ * Exact strings only. A user-authored rule outside this list survives the prune.
15
+ */
16
+ export const RETIRED_PERMISSION_RULES = {
17
+ allow: [
18
+ "Bash(git *)",
19
+ "Bash(git add *)",
20
+ "Bash(git commit *)",
21
+ "Bash(git status *)",
22
+ "Bash(git diff *)",
23
+ "Bash(git log *)",
24
+ "Bash(git branch *)",
25
+ "Bash(git checkout *)",
26
+ "Bash(git switch *)",
27
+ "Bash(git stash *)",
28
+ "Bash(git fetch *)",
29
+ "Bash(git pull *)",
30
+ "Bash(git tag *)",
31
+ "Bash(git show *)",
32
+ "Bash(git blame *)",
33
+ "Bash(git worktree *)",
34
+ "Bash(gh *)",
35
+ "Bash(pnpm *)",
36
+ "Bash(npm *)",
37
+ "Bash(npx *)",
38
+ "Bash(node *)",
39
+ "Bash(docker *)",
40
+ "Bash(docker-compose *)",
41
+ "Bash(ls *)",
42
+ "Bash(cat *)",
43
+ "Bash(find *)",
44
+ "Bash(grep *)",
45
+ "Bash(head *)",
46
+ "Bash(tail *)",
47
+ "Bash(wc *)",
48
+ "Bash(sort *)",
49
+ "Bash(uniq *)",
50
+ "Bash(diff *)",
51
+ "Bash(which *)",
52
+ "Bash(pwd *)",
53
+ "Bash(date *)",
54
+ "Bash(mkdir *)",
55
+ "Bash(basename *)",
56
+ "Bash(dirname *)",
57
+ "Bash(realpath *)",
58
+ "Bash(jq *)",
59
+ "Bash(curl *)",
60
+ "Bash(tree *)",
61
+ "Bash(sed *)",
62
+ "Bash(awk *)",
63
+ "Bash(cut *)",
64
+ "Bash(tr *)",
65
+ "Bash(tee *)",
66
+ "Bash(echo *)",
67
+ "Bash(printf *)",
68
+ "Bash(env *)",
69
+ "Bash(printenv *)",
70
+ "Bash(uname *)",
71
+ "Bash(file *)",
72
+ "Bash(stat *)",
73
+ "Bash(du *)",
74
+ "Bash(id *)",
75
+ "Bash(whoami *)",
76
+ "Bash(php *)",
77
+ "Bash(composer *)",
78
+ "Bash(python3 *)",
79
+ "Bash(python *)",
80
+ "Bash(pip *)",
81
+ "Bash(pip3 *)",
82
+ "PowerShell(git *)",
83
+ "PowerShell(git add *)",
84
+ "PowerShell(git commit *)",
85
+ "PowerShell(git status *)",
86
+ "PowerShell(git diff *)",
87
+ "PowerShell(git log *)",
88
+ "PowerShell(git branch *)",
89
+ "PowerShell(git checkout *)",
90
+ "PowerShell(git switch *)",
91
+ "PowerShell(git stash *)",
92
+ "PowerShell(git fetch *)",
93
+ "PowerShell(git pull *)",
94
+ "PowerShell(git tag *)",
95
+ "PowerShell(git show *)",
96
+ "PowerShell(git blame *)",
97
+ "PowerShell(git worktree *)",
98
+ "PowerShell(gh *)",
99
+ "PowerShell(pnpm *)",
100
+ "PowerShell(npm *)",
101
+ "PowerShell(npx *)",
102
+ "PowerShell(node *)",
103
+ "PowerShell(docker *)",
104
+ "PowerShell(docker-compose *)",
105
+ "PowerShell(ls *)",
106
+ "PowerShell(cat *)",
107
+ "PowerShell(find *)",
108
+ "PowerShell(grep *)",
109
+ "PowerShell(head *)",
110
+ "PowerShell(tail *)",
111
+ "PowerShell(wc *)",
112
+ "PowerShell(sort *)",
113
+ "PowerShell(uniq *)",
114
+ "PowerShell(diff *)",
115
+ "PowerShell(which *)",
116
+ "PowerShell(pwd *)",
117
+ "PowerShell(date *)",
118
+ "PowerShell(mkdir *)",
119
+ "PowerShell(basename *)",
120
+ "PowerShell(dirname *)",
121
+ "PowerShell(realpath *)",
122
+ "PowerShell(jq *)",
123
+ "PowerShell(curl *)",
124
+ "PowerShell(tree *)",
125
+ "PowerShell(sed *)",
126
+ "PowerShell(awk *)",
127
+ "PowerShell(cut *)",
128
+ "PowerShell(tr *)",
129
+ "PowerShell(tee *)",
130
+ "PowerShell(echo *)",
131
+ "PowerShell(printf *)",
132
+ "PowerShell(env *)",
133
+ "PowerShell(printenv *)",
134
+ "PowerShell(uname *)",
135
+ "PowerShell(file *)",
136
+ "PowerShell(stat *)",
137
+ "PowerShell(du *)",
138
+ "PowerShell(id *)",
139
+ "PowerShell(whoami *)",
140
+ "PowerShell(php *)",
141
+ "PowerShell(composer *)",
142
+ "PowerShell(python3 *)",
143
+ "PowerShell(python *)",
144
+ "PowerShell(pip *)",
145
+ "PowerShell(pip3 *)",
146
+ "WebFetch"
147
+ ],
148
+ deny: [
149
+ "PowerShell(Remove-Item *-Recurse* \\)",
150
+ "PowerShell(Remove-Item *-Recurse* *:\\)",
151
+ "PowerShell(del *-Recurse* \\)",
152
+ "PowerShell(del *-Recurse* *:\\)",
153
+ "PowerShell(erase *-Recurse* \\)",
154
+ "PowerShell(erase *-Recurse* *:\\)",
155
+ "PowerShell(rd *-Recurse* \\)",
156
+ "PowerShell(rd *-Recurse* *:\\)",
157
+ "PowerShell(ri *-Recurse* \\)",
158
+ "PowerShell(ri *-Recurse* *:\\)",
159
+ "PowerShell(rm *-Recurse* \\)",
160
+ "PowerShell(rm *-Recurse* *:\\)",
161
+ "PowerShell(rmdir *-Recurse* \\)",
162
+ "PowerShell(rmdir *-Recurse* *:\\)"
163
+ ],
164
+ ask: []
165
+ } as const satisfies Readonly<Record<"allow" | "deny" | "ask", ReadonlyArray<string>>>