docks-kit 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -8
- package/README.md +3 -20
- package/cli/docs/flags.md +0 -20
- package/cli/docs/models.md +0 -27
- package/cli/docs/modifiers.md +0 -33
- package/cli/src/commands/models.ts +3 -7
- package/cli/src/engine-native/claudeSync.ts +1 -2
- package/cli/src/engine-native/codexSync.ts +1 -2
- package/cli/src/engine-native/index.ts +1 -16
- package/cli/src/engine-native/parseArgs.ts +0 -63
- package/cli/src/engine-native/sessionRelayCli.ts +17 -13
- package/cli/src/generated/sotPayload.ts +6 -6
- package/cli/src/main.ts +3 -54
- package/package.json +1 -1
- package/cli/src/engine-native/workflowDeploy.ts +0 -139
- package/cli/src/workflowModels.ts +0 -452
package/AGENTS.md
CHANGED
|
@@ -20,9 +20,9 @@ launcher can fall back to Bun source.
|
|
|
20
20
|
| Path | Purpose |
|
|
21
21
|
|------|---------|
|
|
22
22
|
| `docks-kit` | CLI launcher: on supported hosts, runs the platform binary in `cli/dist/` only when its `--version` matches `package.json`, otherwise Bun-from-source (auto-installs Bun + `node_modules`). Unsupported hosts fail before source fallback. No-Bun recovery is the standalone platform release binary |
|
|
23
|
-
| `cli/src/engine-native/` | EngineNative implementation for `sync`, `model`,
|
|
23
|
+
| `cli/src/engine-native/` | EngineNative implementation for `sync`, `model`, and `toolchain`; idempotent, flag-gated for destructive reconciliation |
|
|
24
24
|
| `cli/` | Effect-TS CLI + bundled docs topics |
|
|
25
|
-
| `SoT/models.json` | Kit-verified
|
|
25
|
+
| `SoT/models.json` | Kit-verified Claude and Codex model catalog |
|
|
26
26
|
| `SoT/toolchain.json` | Toolchain floors manifest (verified pins consumed by EngineNative) |
|
|
27
27
|
| `SoT/.claude/bin/` | Dependency-free Bun runtime programs for Claude's statusline, SessionStart, and Notification |
|
|
28
28
|
| `install.sh` | Global installer |
|
|
@@ -42,8 +42,6 @@ Codex SoT notes:
|
|
|
42
42
|
- `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.
|
|
43
43
|
- `docks-kit status` verifies Session Relay only through the supported `codex plugin list --json` inventory. `ready` means installed and enabled for a newly started Codex session; it is not evidence about an old process, lifecycle state, receive-path health, or worker quiescence. The global prompt SoTs carry the owner's standing authorization for Docks cross-company plan review, which never overrides host or platform denial.
|
|
44
44
|
- Claude and Codex sync call `sessionRelayCli.ts ensureSessionRelayCli` immediately before their plugin passes. It installs the exact source-pinned precompiled command at `~/.local/bin/session-relay` for Linux/macOS x64/arm64 only, requires committed digest = same-release `SHA256SUMS` row = downloaded bytes, smoke-tests the staged version, and atomically replaces the stable path. `agents`-only sync never enters this boundary. The four pinned production digests correspond to the stable `session-relay--v0.12.0` assets and its `SHA256SUMS`.
|
|
45
|
-
- Both global prompt SoTs carry one byte-identical compact `Docks-workflow-models:` record. Root `--model-orchestrator` / `--model-reviewer` / `--model-implementer` / review-bound flags update only that deployed record; `docks-kit models workflow` lists the closed selectors, and a flag-less sync restores defaults.
|
|
46
|
-
- Codex workflow selectors use the closed `<tool>:<model>@<effort>[+fast]` routing grammar. Fast is intentionally absent from the global SoT: no suffix means Standard and keeps the backward-compatible schema-1 record; `+fast` emits a schema-2 candidate with `service_tier: "fast"`. Docks and Session Relay consumers must explicitly launch unsuffixed Codex roles with the default service tier so a user's global Fast preference cannot leak into workflows.
|
|
47
45
|
- 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.
|
|
48
46
|
- Neither global prompt SoT imports `@RTK.md`; Claude uses the hook-backed RTK integration, while Codex has no kit-managed RTK integration.
|
|
49
47
|
- 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.
|
|
@@ -93,11 +91,9 @@ When a kit-mechanic skill, its `references/`, or a wrapper agent (`.claude/agent
|
|
|
93
91
|
|
|
94
92
|
## Plans
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
Multi-commit work plans live in `docs/plans/active/` (status is a frontmatter field) and `docs/plans/finished/` (archive). Every plan file is a complete cold-handoff document — goal, context & rationale, environment & how-to-run, steps with exact paths, executable acceptance criteria, and a binary cold-handoff checklist — so any agent (or a weaker model) can pick one up cold without guessing. Skills handle every operation: `plan-init` (bootstrap/migrate), `plan-manager` (list/show/start/block/ship/new, auto-commit on transition, self-review on draft), `plan-review` (verification). Trigger by natural language or the matching `plan-*` skill. `active/` is multi-occupancy.
|
|
98
|
-
</constraint>
|
|
94
|
+
Canonical plans live in `docs/plans/active/`; status is frontmatter and `docs/plans/finished/` is terminal. Exactly three skills are live: `plan-workspace` maintains the workspace; main-context `plan-manager` classifies, drafts, reviews, repairs once, executes, verifies, and archives; internal `plan-reviewer` returns read-only `PlanReviewV1` evidence from one immutable bundle. Only the reviewer has Claude/Codex wrappers.
|
|
99
95
|
|
|
100
|
-
|
|
96
|
+
Current plans carry one compact-JCS `Plan-run: PlanRunV1` record. Schemas 1–6 are historical validation/quarantine only and never authorize current dispatch or external effects. Persisted requested effects are intent, not authority; any probe, production access, publish, push, release, or deploy requires matching live authority from the exact current-user request. The full contract lives in `docs/plans/AGENTS.md`.
|
|
101
97
|
|
|
102
98
|
Distinct from per-tool **Open Concerns** sections (wait-on-upstream
|
|
103
99
|
blockers tied to a vendor shipping a fix — these live inside the per-tool
|
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ RTK/Bun download boundaries, not as a global sync prerequisite.
|
|
|
43
43
|
docks-kit sync [claude] [codex] [agents] deploy the SoT (default: all three)
|
|
44
44
|
docks-kit update [--no-sync] self-update the kit (autodetects checkout vs global install), then sync
|
|
45
45
|
docks-kit model <claude|codex> [value] get/set the DEPLOYED model (TTY picker)
|
|
46
|
-
docks-kit models [claude|codex
|
|
46
|
+
docks-kit models [claude|codex] model catalogs (`--json`)
|
|
47
47
|
docks-kit toolchain [check|ensure <tool>] verified-version floors for external tools
|
|
48
48
|
docks-kit status [--json] deployed-vs-SoT drift + toolchain + counts
|
|
49
49
|
docks-kit plugins list [--json] enabledPlugins tri-state vs installed
|
|
@@ -76,23 +76,6 @@ golden-regression coverage for dry-run output, mutation snapshots, and argv logs
|
|
|
76
76
|
and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
|
|
77
77
|
(includes the old→new rename table for the pre-CLI `sync.sh` flags).
|
|
78
78
|
|
|
79
|
-
### Docks workflow roles (root flags)
|
|
80
|
-
|
|
81
|
-
| Flag | Effect |
|
|
82
|
-
|------|--------|
|
|
83
|
-
| `--model-orchestrator=<selector>` | Override the Docks orchestrator candidate/profile |
|
|
84
|
-
| `--model-reviewer=<selector>` | Override the Docks reviewer candidate/profile |
|
|
85
|
-
| `--model-implementer=<selector>` | Override the Docks implementer candidate/profile |
|
|
86
|
-
| `--review-min-score=<0..100>` | Override the completion-review target |
|
|
87
|
-
| `--review-max-rounds=<1..10>` | Bound completion-review batches |
|
|
88
|
-
|
|
89
|
-
Selectors are strict `profile:<name>` or `<tool>:<model>@<effort>[+fast]`
|
|
90
|
-
values from `docks-kit models workflow`; `+fast` is Codex-only. A selector
|
|
91
|
-
without `+fast` means Standard, while `+fast` writes a schema-2 candidate with
|
|
92
|
-
`service_tier: "fast"`. These root flags update only the identical compact record
|
|
93
|
-
in `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`; omitted fields retain their
|
|
94
|
-
current valid values, while a later flag-less sync restores all defaults.
|
|
95
|
-
|
|
96
79
|
## How syncing works
|
|
97
80
|
|
|
98
81
|
- **Additive by default** — user-only settings keys, plugins, and skills
|
|
@@ -112,7 +95,7 @@ current valid values, while a later flag-less sync restores all defaults.
|
|
|
112
95
|
command. The four production digests are pinned for the stable
|
|
113
96
|
`session-relay--v0.12.0` assets and match the same-release `SHA256SUMS`.
|
|
114
97
|
- **Model catalog** — `SoT/models.json` is the research-verified source for
|
|
115
|
-
model validation, listings,
|
|
98
|
+
model validation, listings, and pickers.
|
|
116
99
|
- **Claude runtime** — sync materializes three dependency-free Bun `.mjs`
|
|
117
100
|
programs for statusline, SessionStart, and Notification. Quota display uses
|
|
118
101
|
Claude's native `rate_limits`; there is no OAuth fetch, shared usage cache,
|
|
@@ -126,7 +109,7 @@ current valid values, while a later flag-less sync restores all defaults.
|
|
|
126
109
|
| `SoT/.claude/` | Claude Code SoT (settings template, Bun runtime programs, CLAUDE.md) |
|
|
127
110
|
| `SoT/.codex/` | Codex SoT (config.toml, rules, AGENTS.md, marketplace) |
|
|
128
111
|
| `SoT/.agents/` | Universal-skill manifest |
|
|
129
|
-
| `SoT/models.json` | Kit-verified
|
|
112
|
+
| `SoT/models.json` | Kit-verified Claude and Codex model catalog |
|
|
130
113
|
| `SoT/toolchain.json` | Verified-version floors |
|
|
131
114
|
| `cli/src/engine-native/` | EngineNative sync/model/toolchain implementation |
|
|
132
115
|
| `cli/src/generated/sotPayload.ts` | Generated in-memory payload used by standalone and npm installs |
|
package/cli/docs/flags.md
CHANGED
|
@@ -40,26 +40,6 @@ Bare model, effort, or advisor modifiers print the relevant valid-value catalog
|
|
|
40
40
|
and exit 2. A modifier for a target not selected by the positional arguments is
|
|
41
41
|
ignored with a warning; Claude modifiers never touch Codex config and vice versa.
|
|
42
42
|
|
|
43
|
-
## Docks workflow root flags
|
|
44
|
-
|
|
45
|
-
These flags belong at the root (`docks-kit --model-reviewer=...`), not after
|
|
46
|
-
`sync`. They update only the shared deployed workflow record.
|
|
47
|
-
|
|
48
|
-
| Flag | Accepted value |
|
|
49
|
-
|------|----------------|
|
|
50
|
-
| `--model-orchestrator=<selector>` | `profile:<name>` or `<tool>:<model>@<effort>[+fast]` |
|
|
51
|
-
| `--model-reviewer=<selector>` | same strict selector grammar |
|
|
52
|
-
| `--model-implementer=<selector>` | same strict selector grammar |
|
|
53
|
-
| `--review-min-score=<n>` | base-10 integer `0..100` |
|
|
54
|
-
| `--review-max-rounds=<n>` | base-10 integer `1..10` |
|
|
55
|
-
|
|
56
|
-
Use `docks-kit models workflow [--json]` for the closed registry. Bare, empty,
|
|
57
|
-
unknown, or malformed values print that helper and exit 2 before either prompt
|
|
58
|
-
file changes. `+fast` is accepted only on Codex exact targets and writes
|
|
59
|
-
`service_tier: "fast"` in workflow record schema 2. Without `+fast`, the role is
|
|
60
|
-
Standard and the record remains schema 1 unless another role is Fast. Shell
|
|
61
|
-
quotes are optional but recommended around selectors containing `+fast`.
|
|
62
|
-
|
|
63
43
|
## Renamed legacy flags (pre-CLI sync.sh)
|
|
64
44
|
|
|
65
45
|
Old flags exit with a rename hint — there is no compat behavior.
|
package/cli/docs/models.md
CHANGED
|
@@ -31,35 +31,8 @@ docks-kit models claude --json # machine-readable
|
|
|
31
31
|
docks-kit model claude # current deployed + SoT + picker (TTY)
|
|
32
32
|
docks-kit model claude opus # per-machine override from the Fable SoT
|
|
33
33
|
docks-kit sync claude --claude-model=opus # same, as part of a sync
|
|
34
|
-
docks-kit models workflow # Docks workflow profiles and defaults
|
|
35
|
-
docks-kit models workflow --json # closed machine-readable registry
|
|
36
34
|
```
|
|
37
35
|
|
|
38
|
-
## Docks workflow-role registry
|
|
39
|
-
|
|
40
|
-
The `workflow` section is strict even though ordinary tool-model modifiers are
|
|
41
|
-
forward-compatible. It accepts only known `profile:<name>` values or exact
|
|
42
|
-
`<tool>:<model>@<effort>[+fast]` targets whose model and effort both appear in
|
|
43
|
-
the catalog. `+fast` is accepted only for Codex exact targets. The defaults are:
|
|
44
|
-
|
|
45
|
-
- orchestrator: `profile:claude-best`, ordered as `claude:fable@high` then
|
|
46
|
-
`claude:opus@xhigh`;
|
|
47
|
-
- reviewer and implementer: `codex:gpt-5.6-sol@high`;
|
|
48
|
-
- review minimum score 90 and maximum 3 rounds.
|
|
49
|
-
|
|
50
|
-
`claude:best@high` is Claude's native one-model alias. It is deliberately not
|
|
51
|
-
the same as the Docks-managed `profile:claude-best` candidate chain.
|
|
52
|
-
Availability is `checked_when_used`: Docks classifies each launch attempt;
|
|
53
|
-
docks-kit neither probes providers nor promises provider-wide fallback.
|
|
54
|
-
|
|
55
|
-
The default and every unsuffixed selector emit the backward-compatible schema-1
|
|
56
|
-
record with no service-tier field; absence means Standard. A `+fast` selector
|
|
57
|
-
promotes the complete record to schema 2 and adds `service_tier: "fast"` only to
|
|
58
|
-
the selected Codex candidate. Replacing the last Fast selector with an
|
|
59
|
-
unsuffixed selector demotes the record back to schema 1. Docks and Session Relay
|
|
60
|
-
must support schema 2 before `+fast` is deployed, and must explicitly select the
|
|
61
|
-
default tier for unsuffixed roles so global Codex configuration cannot leak in.
|
|
62
|
-
|
|
63
36
|
## Advisor pairing note (Claude)
|
|
64
37
|
|
|
65
38
|
The SoT ships `model: fable` with advisor off (`advisorModel` unset).
|
package/cli/docs/modifiers.md
CHANGED
|
@@ -33,13 +33,6 @@ owns that key for the run: `on` writes `fable`; `off` and `default` delete it.
|
|
|
33
33
|
Codex has no advisor modifier because its documented config has no advisor
|
|
34
34
|
setting; `review_model` applies only to `/review`.
|
|
35
35
|
|
|
36
|
-
Codex Fast mode is intentionally not a global SoT default or per-machine
|
|
37
|
-
modifier. It is role-scoped through the root workflow flags: append `+fast` to a
|
|
38
|
-
Codex exact selector to emit `service_tier: "fast"` in record schema 2. Without
|
|
39
|
-
the suffix, the role means Standard and emits no tier field. Docks and Session
|
|
40
|
-
Relay consumers must map that absence to an explicit default-tier process
|
|
41
|
-
override rather than inherit a user's global Fast preference.
|
|
42
|
-
|
|
43
36
|
## Standalone get/set (no full sync)
|
|
44
37
|
|
|
45
38
|
```
|
|
@@ -52,32 +45,6 @@ docks-kit model codex gpt-5.5 # codex flavor
|
|
|
52
45
|
The set path calls the same engine functions as the sync flags —
|
|
53
46
|
one implementation, two entry points.
|
|
54
47
|
|
|
55
|
-
## Workflow-role overrides (root, no full sync)
|
|
56
|
-
|
|
57
|
-
The root workflow flags are deployed modifiers for Docks rather than one tool:
|
|
58
|
-
|
|
59
|
-
```text
|
|
60
|
-
docks-kit --model-orchestrator=profile:claude-best \
|
|
61
|
-
--model-reviewer="codex:gpt-5.6-sol@high+fast" \
|
|
62
|
-
--model-implementer=codex:gpt-5.6-sol@high \
|
|
63
|
-
--review-min-score=80 --review-max-rounds=5
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
They atomically write one byte-identical complete record to
|
|
67
|
-
`~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`. Omitted fields retain the
|
|
68
|
-
current valid record; a missing side is repaired. Invalid or conflicting state
|
|
69
|
-
stops before mutation, a repeated request is a no-op, and failure on the second
|
|
70
|
-
atomic write restores both snapshots. A later flag-less sync restores the
|
|
71
|
-
embedded defaults. Start fresh sessions after changing the record.
|
|
72
|
-
|
|
73
|
-
Selectors are strict `profile:<name>` or `<tool>:<model>@<effort>[+fast]`
|
|
74
|
-
entries from `docks-kit models workflow`. `+fast` is Codex-only and quotes are
|
|
75
|
-
optional; its absence means Standard. `profile:claude-best` is the ordered Docks
|
|
76
|
-
Fable-high then Opus-xhigh chain; `claude:best@high` is instead Claude's native
|
|
77
|
-
single-model alias. Docks checks each candidate when used—there is no docks-kit
|
|
78
|
-
provider preflight. Install schema-2 support in Docks and Session Relay before
|
|
79
|
-
using a Fast selector.
|
|
80
|
-
|
|
81
48
|
## Sticky opt-ins are NOT modifiers
|
|
82
49
|
|
|
83
50
|
`--claude-plugin=<name>` installs+enables an optional plugin and it STAYS
|
|
@@ -2,10 +2,9 @@ import { Args, Command, Options } from "@effect/cli"
|
|
|
2
2
|
import { Console, Effect, Option } from "effect"
|
|
3
3
|
import { bail } from "../engine"
|
|
4
4
|
import { modelCatalog, type Tool } from "../manifests"
|
|
5
|
-
import { workflowCatalog, workflowRegistryJson } from "../workflowModels"
|
|
6
5
|
|
|
7
6
|
const tool = Args.text({ name: "tool" }).pipe(
|
|
8
|
-
Args.withDescription("claude | codex
|
|
7
|
+
Args.withDescription("claude | codex (omit for both tool catalogs)"),
|
|
9
8
|
Args.optional
|
|
10
9
|
)
|
|
11
10
|
const json = Options.boolean("json").pipe(
|
|
@@ -25,11 +24,8 @@ const renderTool = (t: Tool) =>
|
|
|
25
24
|
export const modelsCommand = Command.make("models", { tool, json }, (config) =>
|
|
26
25
|
Effect.gen(function* () {
|
|
27
26
|
const requested = Option.getOrUndefined(config.tool)
|
|
28
|
-
if (requested === "workflow") {
|
|
29
|
-
return yield* Console.log(config.json ? workflowRegistryJson() : workflowCatalog())
|
|
30
|
-
}
|
|
31
27
|
if (requested !== undefined && requested !== "claude" && requested !== "codex") {
|
|
32
|
-
return yield* bail(`Unknown tool '${requested}' (valid: claude, codex
|
|
28
|
+
return yield* bail(`Unknown tool '${requested}' (valid: claude, codex)`)
|
|
33
29
|
}
|
|
34
30
|
const tools: Array<Tool> = requested !== undefined ? [requested as Tool] : ["claude", "codex"]
|
|
35
31
|
|
|
@@ -46,5 +42,5 @@ export const modelsCommand = Command.make("models", { tool, json }, (config) =>
|
|
|
46
42
|
)
|
|
47
43
|
})
|
|
48
44
|
).pipe(
|
|
49
|
-
Command.withDescription("List kit-verified
|
|
45
|
+
Command.withDescription("List kit-verified Claude and Codex models (SoT/models.json).")
|
|
50
46
|
)
|
|
@@ -31,7 +31,6 @@ import { ExitError } from "./parseArgs"
|
|
|
31
31
|
import { mergeSettings, reconcileSettings } from "./settings"
|
|
32
32
|
import { ensure, field } from "./toolchain"
|
|
33
33
|
import { payloadBytes, payloadDisplayPath, payloadText } from "../payload"
|
|
34
|
-
import { renderDefaultWorkflowInstructions } from "./workflowDeploy"
|
|
35
34
|
import { ensureSessionRelayCli } from "./sessionRelayCli"
|
|
36
35
|
|
|
37
36
|
export type ClaudeRuntimeState =
|
|
@@ -207,7 +206,7 @@ function syncClaudeMd(ctx: Ctx, claudeDir: string): void {
|
|
|
207
206
|
return
|
|
208
207
|
}
|
|
209
208
|
|
|
210
|
-
const source =
|
|
209
|
+
const source = payloadText("SoT/.claude/CLAUDE.md")
|
|
211
210
|
if (writeTextIfChanged(p(claudeDir, "CLAUDE.md"), source)) {
|
|
212
211
|
change("CLAUDE.md synced")
|
|
213
212
|
} else {
|
|
@@ -12,7 +12,6 @@ import type { Ctx } from "./index"
|
|
|
12
12
|
import { compareCodepoints, isObject, jqStringify, parseJson, type Json } from "./jq"
|
|
13
13
|
import { sessionRelayReadiness } from "./sessionRelayReadiness"
|
|
14
14
|
import { payloadBytes, payloadDisplayPath, payloadPaths, payloadText, type PayloadPath } from "../payload"
|
|
15
|
-
import { renderDefaultWorkflowInstructions } from "./workflowDeploy"
|
|
16
15
|
import { ensureSessionRelayCli } from "./sessionRelayCli"
|
|
17
16
|
|
|
18
17
|
export function codexSync(ctx: Ctx): void {
|
|
@@ -26,7 +25,7 @@ export function codexSync(ctx: Ctx): void {
|
|
|
26
25
|
syncCodexModel(ctx, ctx.codexModel)
|
|
27
26
|
syncCodexEffort(ctx, ctx.codexEffort)
|
|
28
27
|
syncRules(ctx, payloadPaths("SoT/.codex/rules/"), p(codexDir, "rules"))
|
|
29
|
-
syncAgentsMd(ctx,
|
|
28
|
+
syncAgentsMd(ctx, payloadText("SoT/.codex/AGENTS.md"), p(codexDir, "AGENTS.md"))
|
|
30
29
|
syncMarketplace(ctx, payloadText("SoT/.codex/plugins/marketplace.json"), p(ctx.agentsDir, "plugins", "marketplace.json"))
|
|
31
30
|
removeLegacyDocksMarketplace(ctx, userConfig)
|
|
32
31
|
ensureSessionRelayCli(ctx)
|
|
@@ -15,8 +15,7 @@ import { claudeNextSteps, claudeSummary, claudeSync } from "./claudeSync"
|
|
|
15
15
|
import { codexNextSteps, codexSummary, codexSync } from "./codexSync"
|
|
16
16
|
import { skillsNextSteps, skillsSummary, skillsSync } from "./skillsSync"
|
|
17
17
|
import { modeModel, modeToolchain } from "./modes"
|
|
18
|
-
import { ExitError, parseArgs,
|
|
19
|
-
import { deployWorkflowOverrides } from "./workflowDeploy"
|
|
18
|
+
import { ExitError, parseArgs, validateModifierFlags } from "./parseArgs"
|
|
20
19
|
|
|
21
20
|
export type ModifierFlag =
|
|
22
21
|
| "--claude-model"
|
|
@@ -127,18 +126,6 @@ function engineSync(ctx: Ctx, args: ReadonlyArray<string>): number {
|
|
|
127
126
|
return 0
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
function engineWorkflow(ctx: Ctx, args: ReadonlyArray<string>): number {
|
|
131
|
-
try {
|
|
132
|
-
const overrides = parseWorkflowArgs(ctx, args)
|
|
133
|
-
deployWorkflowOverrides(ctx, overrides)
|
|
134
|
-
return 0
|
|
135
|
-
} catch (error) {
|
|
136
|
-
if (error instanceof ExitError) throw error
|
|
137
|
-
printWorkflowUsage(ctx)
|
|
138
|
-
ctx.services.logger.err(error instanceof Error ? error.message : String(error))
|
|
139
|
-
throw new ExitError(2)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
129
|
|
|
143
130
|
export function runEngineNative(argv: ReadonlyArray<string>, services?: EngineServices): number {
|
|
144
131
|
let ctx!: Ctx
|
|
@@ -165,8 +152,6 @@ export function runEngineNative(argv: ReadonlyArray<string>, services?: EngineSe
|
|
|
165
152
|
return modeModel(ctx, argv.slice(1))
|
|
166
153
|
case "toolchain":
|
|
167
154
|
return modeToolchain(ctx, argv.slice(1))
|
|
168
|
-
case "workflow":
|
|
169
|
-
return engineWorkflow(ctx, argv.slice(1))
|
|
170
155
|
case "sync":
|
|
171
156
|
return engineSync(ctx, argv.slice(1))
|
|
172
157
|
default:
|
|
@@ -16,11 +16,6 @@ import {
|
|
|
16
16
|
isEffortModifierValue
|
|
17
17
|
} from "../efforts"
|
|
18
18
|
import { printModels, validateClaudeModel, validateCodexModel } from "./models"
|
|
19
|
-
import {
|
|
20
|
-
buildWorkflowRecord,
|
|
21
|
-
workflowCatalog,
|
|
22
|
-
type WorkflowOverrides
|
|
23
|
-
} from "../workflowModels"
|
|
24
19
|
|
|
25
20
|
export class ExitError extends Error {
|
|
26
21
|
constructor(readonly code: number) {
|
|
@@ -268,64 +263,6 @@ function printCatalog(ctx: Ctx, catalog: string): void {
|
|
|
268
263
|
for (const line of catalog.split("\n")) ctx.services.logger.echo(line)
|
|
269
264
|
}
|
|
270
265
|
|
|
271
|
-
const WORKFLOW_FLAGS = {
|
|
272
|
-
"--model-orchestrator": "orchestrator",
|
|
273
|
-
"--model-reviewer": "reviewer",
|
|
274
|
-
"--model-implementer": "implementer",
|
|
275
|
-
"--review-min-score": "minimumScore",
|
|
276
|
-
"--review-max-rounds": "maxRounds"
|
|
277
|
-
} as const satisfies Readonly<Record<string, keyof WorkflowOverrides>>
|
|
278
|
-
|
|
279
|
-
function workflowUsage(ctx: Ctx): void {
|
|
280
|
-
printCatalog(ctx, workflowCatalog())
|
|
281
|
-
ctx.services.logger.echo("")
|
|
282
|
-
ctx.services.logger.echo("Workflow override flags:")
|
|
283
|
-
ctx.services.logger.echo(" --model-orchestrator=<profile:name|tool:model@effort[+fast]>")
|
|
284
|
-
ctx.services.logger.echo(" --model-reviewer=<profile:name|tool:model@effort[+fast]>")
|
|
285
|
-
ctx.services.logger.echo(" --model-implementer=<profile:name|tool:model@effort[+fast]>")
|
|
286
|
-
ctx.services.logger.echo(" --review-min-score=<0..100>")
|
|
287
|
-
ctx.services.logger.echo(" --review-max-rounds=<1..10>")
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export function parseWorkflowArgs(ctx: Ctx, args: ReadonlyArray<string>): WorkflowOverrides {
|
|
291
|
-
const overrides: Partial<Record<keyof WorkflowOverrides, string>> = {}
|
|
292
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
293
|
-
const arg = args[index] ?? ""
|
|
294
|
-
if (arg === "-h" || arg === "--help") {
|
|
295
|
-
workflowUsage(ctx)
|
|
296
|
-
throw new ExitError(0)
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const equals = arg.indexOf("=")
|
|
300
|
-
const flag = equals === -1 ? arg : arg.slice(0, equals)
|
|
301
|
-
const key = WORKFLOW_FLAGS[flag as keyof typeof WORKFLOW_FLAGS]
|
|
302
|
-
if (key === undefined) throw new Error(`Unknown workflow arg: ${arg}`)
|
|
303
|
-
|
|
304
|
-
let value: string
|
|
305
|
-
if (equals !== -1) {
|
|
306
|
-
value = arg.slice(equals + 1)
|
|
307
|
-
} else {
|
|
308
|
-
const next = args[index + 1]
|
|
309
|
-
if (next === undefined || next.startsWith("--")) {
|
|
310
|
-
throw new Error(`${flag} requires a value: ${flag}=<value>`)
|
|
311
|
-
}
|
|
312
|
-
value = next
|
|
313
|
-
index += 1
|
|
314
|
-
}
|
|
315
|
-
if (value === "") throw new Error(`${flag} requires a value: ${flag}=<value>`)
|
|
316
|
-
overrides[key] = value
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (Object.keys(overrides).length === 0) {
|
|
320
|
-
throw new Error("At least one workflow override flag is required")
|
|
321
|
-
}
|
|
322
|
-
buildWorkflowRecord(overrides)
|
|
323
|
-
return overrides
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export function printWorkflowUsage(ctx: Ctx): void {
|
|
327
|
-
workflowUsage(ctx)
|
|
328
|
-
}
|
|
329
266
|
|
|
330
267
|
export function validateModifierFlags(ctx: Ctx): void {
|
|
331
268
|
const { err, warn } = ctx.services.logger
|
|
@@ -16,9 +16,7 @@ import type { Ctx } from "./index"
|
|
|
16
16
|
import { ExitError } from "./parseArgs"
|
|
17
17
|
import { payloadText } from "../payload"
|
|
18
18
|
|
|
19
|
-
const VERSION = "0.12.0"
|
|
20
19
|
const REPOSITORY = "DocksDocks/docks"
|
|
21
|
-
const TAG = "session-relay--v0.12.0"
|
|
22
20
|
const PLUGIN_ID = "session-relay@docks"
|
|
23
21
|
const INSTALL_PATH = "~/.local/bin/session-relay"
|
|
24
22
|
const TARGETS = [
|
|
@@ -33,11 +31,11 @@ export type SessionRelayTarget = typeof TARGETS[number]
|
|
|
33
31
|
export interface SessionRelayManifest {
|
|
34
32
|
readonly kind: "managed-release"
|
|
35
33
|
readonly policy: "exact"
|
|
36
|
-
readonly verified:
|
|
34
|
+
readonly verified: string
|
|
37
35
|
readonly repository: typeof REPOSITORY
|
|
38
|
-
readonly tag:
|
|
36
|
+
readonly tag: string
|
|
39
37
|
readonly plugin_id: typeof PLUGIN_ID
|
|
40
|
-
readonly plugin_version:
|
|
38
|
+
readonly plugin_version: string
|
|
41
39
|
readonly install_path: typeof INSTALL_PATH
|
|
42
40
|
readonly assets: Readonly<Record<SessionRelayTarget, string>>
|
|
43
41
|
}
|
|
@@ -83,14 +81,18 @@ export function parseSessionRelayManifest(text: string): SessionRelayManifest {
|
|
|
83
81
|
["kind", "policy", "verified", "repository", "tag", "plugin_id", "plugin_version", "install_path", "assets"],
|
|
84
82
|
"Session Relay manifest"
|
|
85
83
|
)
|
|
84
|
+
const version = value["verified"]
|
|
85
|
+
if (typeof version !== "string" || !/^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/.test(version)) {
|
|
86
|
+
throw new Error("Session Relay manifest verified must be a canonical stable SemVer core")
|
|
87
|
+
}
|
|
86
88
|
const expected = {
|
|
87
89
|
kind: "managed-release",
|
|
88
90
|
policy: "exact",
|
|
89
|
-
verified:
|
|
91
|
+
verified: version,
|
|
90
92
|
repository: REPOSITORY,
|
|
91
|
-
tag:
|
|
93
|
+
tag: `session-relay--v${version}`,
|
|
92
94
|
plugin_id: PLUGIN_ID,
|
|
93
|
-
plugin_version:
|
|
95
|
+
plugin_version: version,
|
|
94
96
|
install_path: INSTALL_PATH
|
|
95
97
|
} as const
|
|
96
98
|
for (const [key, wanted] of Object.entries(expected)) {
|
|
@@ -132,9 +134,9 @@ function trimOneLineEnding(text: string): string {
|
|
|
132
134
|
return text
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
function exactVersion(ops: SessionRelayInstallOps, path: string): boolean {
|
|
137
|
+
function exactVersion(ops: SessionRelayInstallOps, path: string, version: string): boolean {
|
|
136
138
|
const result = ops.runVersion(path)
|
|
137
|
-
return result.ok && trimOneLineEnding(result.stdout) === `session-relay ${
|
|
139
|
+
return result.ok && trimOneLineEnding(result.stdout) === `session-relay ${version}`
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
function selectedChecksum(text: string, assetName: string): string {
|
|
@@ -182,7 +184,7 @@ export function installSessionRelayCli(
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
const stable = join(input.home, ".local", "bin", "session-relay")
|
|
185
|
-
if (existsSync(stable) && exactVersion(ops, stable)) return
|
|
187
|
+
if (existsSync(stable) && exactVersion(ops, stable, manifest.verified)) return
|
|
186
188
|
|
|
187
189
|
const parent = dirname(stable)
|
|
188
190
|
try {
|
|
@@ -221,13 +223,15 @@ export function installSessionRelayCli(
|
|
|
221
223
|
} catch (error) {
|
|
222
224
|
fail(input, `Failed to chmod staged Session Relay CLI: ${error instanceof Error ? error.message : String(error)}`)
|
|
223
225
|
}
|
|
224
|
-
if (!exactVersion(ops, stage))
|
|
226
|
+
if (!exactVersion(ops, stage, manifest.verified)) {
|
|
227
|
+
fail(input, `Staged Session Relay CLI did not report exact version session-relay ${manifest.verified}`)
|
|
228
|
+
}
|
|
225
229
|
try {
|
|
226
230
|
ops.rename(stage, stable)
|
|
227
231
|
} catch (error) {
|
|
228
232
|
fail(input, `Failed to atomically replace Session Relay CLI: ${error instanceof Error ? error.message : String(error)}`)
|
|
229
233
|
}
|
|
230
|
-
input.log(`Session Relay CLI ready (${
|
|
234
|
+
input.log(`Session Relay CLI ready (${manifest.verified})`)
|
|
231
235
|
} finally {
|
|
232
236
|
try {
|
|
233
237
|
rmSync(stage, { force: true })
|