@elmundi/ship-cli 0.8.1 → 0.12.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/README.md +651 -25
- package/bin/shipctl.mjs +168 -0
- package/lib/adapters/_fs.mjs +165 -0
- package/lib/adapters/agents/index.mjs +26 -0
- package/lib/adapters/ci/azure-pipelines.mjs +23 -0
- package/lib/adapters/ci/buildkite.mjs +24 -0
- package/lib/adapters/ci/circleci.mjs +23 -0
- package/lib/adapters/ci/gh-actions.mjs +29 -0
- package/lib/adapters/ci/gitlab-ci.mjs +23 -0
- package/lib/adapters/ci/jenkins.mjs +23 -0
- package/lib/adapters/ci/manual.mjs +18 -0
- package/lib/adapters/index.mjs +122 -0
- package/lib/adapters/language/dart.mjs +23 -0
- package/lib/adapters/language/go.mjs +23 -0
- package/lib/adapters/language/java.mjs +27 -0
- package/lib/adapters/language/js.mjs +32 -0
- package/lib/adapters/language/kotlin.mjs +48 -0
- package/lib/adapters/language/py.mjs +34 -0
- package/lib/adapters/language/rust.mjs +23 -0
- package/lib/adapters/language/swift.mjs +37 -0
- package/lib/adapters/language/ts.mjs +35 -0
- package/lib/adapters/trackers/azure-boards.mjs +49 -0
- package/lib/adapters/trackers/clickup.mjs +43 -0
- package/lib/adapters/trackers/github-issues.mjs +52 -0
- package/lib/adapters/trackers/jira.mjs +72 -0
- package/lib/adapters/trackers/linear.mjs +62 -0
- package/lib/adapters/trackers/none.mjs +18 -0
- package/lib/adapters/trackers/spreadsheet.mjs +28 -0
- package/lib/artifacts/fs-index.mjs +230 -0
- package/lib/bootstrap/render.mjs +422 -0
- package/lib/cache/store.mjs +422 -0
- package/lib/commands/bootstrap.mjs +4 -0
- package/lib/commands/callback.mjs +742 -0
- package/lib/commands/config.mjs +257 -0
- package/lib/commands/docs.mjs +4 -4
- package/lib/commands/doctor.mjs +583 -0
- package/lib/commands/feedback.mjs +355 -0
- package/lib/commands/help.mjs +159 -24
- package/lib/commands/init.mjs +830 -158
- package/lib/commands/kickoff.mjs +192 -0
- package/lib/commands/knowledge.mjs +562 -0
- package/lib/commands/lanes.mjs +527 -0
- package/lib/commands/manifest-catalog.mjs +106 -42
- package/lib/commands/migrate.mjs +204 -0
- package/lib/commands/new.mjs +452 -0
- package/lib/commands/patterns.mjs +14 -48
- package/lib/commands/run.mjs +857 -0
- package/lib/commands/search.mjs +2 -2
- package/lib/commands/sync.mjs +824 -0
- package/lib/commands/telemetry.mjs +390 -0
- package/lib/commands/trigger.mjs +196 -0
- package/lib/commands/verify.mjs +187 -0
- package/lib/config/io.mjs +232 -0
- package/lib/config/migrate.mjs +223 -0
- package/lib/config/schema.mjs +901 -0
- package/lib/detect.mjs +162 -19
- package/lib/feedback/drafts.mjs +129 -0
- package/lib/find-ship-root.mjs +16 -10
- package/lib/http.mjs +237 -11
- package/lib/state/idempotency.mjs +183 -0
- package/lib/state/lockfile.mjs +180 -0
- package/lib/telemetry/outbox.mjs +224 -0
- package/lib/templates.mjs +53 -65
- package/lib/verify/checks/agents-on-disk.mjs +58 -0
- package/lib/verify/checks/api-reachable.mjs +39 -0
- package/lib/verify/checks/artifacts-up-to-date.mjs +78 -0
- package/lib/verify/checks/bootstrap-files.mjs +67 -0
- package/lib/verify/checks/cache-integrity.mjs +51 -0
- package/lib/verify/checks/ci-secrets.mjs +86 -0
- package/lib/verify/checks/config-present.mjs +39 -0
- package/lib/verify/checks/gitignore-cache.mjs +51 -0
- package/lib/verify/checks/rules-markers.mjs +135 -0
- package/lib/verify/checks/stack-enums.mjs +33 -0
- package/lib/verify/checks/tracker-labels.mjs +91 -0
- package/lib/verify/registry.mjs +120 -0
- package/lib/version.mjs +34 -0
- package/package.json +10 -3
- package/bin/ship.mjs +0 -68
package/README.md
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
# @elmundi/ship-cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
`shipctl` is the command-line interface to **Ship**. Three jobs:
|
|
4
|
+
|
|
5
|
+
1. **Bootstrap a repo** so its agents (Cursor, Codex, Claude, Aider, Cline,
|
|
6
|
+
Continue, Windsurf, Zed, Gemini, OpenCode, Copilot, …) can consume Ship
|
|
7
|
+
artifacts the same way every other client does.
|
|
8
|
+
2. **Sync the catalog** of `pattern` / `tool` / `collection` artifacts into
|
|
9
|
+
`.ship/cache/` and pin versions for reproducible runs.
|
|
10
|
+
3. **Run lanes** (one-shot dispatch + GitHub Actions wrappers) and
|
|
11
|
+
**report Runs** so the operator console can render outcomes and route any
|
|
12
|
+
escalations into the Inbox.
|
|
13
|
+
|
|
14
|
+
Published as **`@elmundi/ship-cli`** under the [elmundi](https://www.npmjs.com/org/elmundi) org; the binary name is **`shipctl`**.
|
|
15
|
+
|
|
16
|
+
> **Vocabulary.** The CLI speaks the protocol layer, the operator console
|
|
17
|
+
> speaks the product layer. Both are correct; they refer to the same things.
|
|
18
|
+
>
|
|
19
|
+
> | CLI / YAML / API (literal) | Operator console (prose) |
|
|
20
|
+
> |----------------------------|--------------------------|
|
|
21
|
+
> | `lanes:` entries in `.ship/config.yml`, `--lane <id>` | **Automations** |
|
|
22
|
+
> | `pattern:` artifacts (RFC-0001) | **Plays** |
|
|
23
|
+
> | `pipeline_runs` rows + `shipctl callback` payloads | **Runs** |
|
|
24
|
+
> | clarifications / improvements / approvals queue | **Inbox** items |
|
|
25
|
+
>
|
|
26
|
+
> The CLI keeps `lanes:` / `pattern:` / `--lane` literal forever; we are
|
|
27
|
+
> never going to break the YAML and flag surface. Help text and prose
|
|
28
|
+
> reach for the operator nouns when describing what users see.
|
|
6
29
|
|
|
7
30
|
## Requirements
|
|
8
31
|
|
|
@@ -18,15 +41,15 @@ npx @elmundi/ship-cli help
|
|
|
18
41
|
|
|
19
42
|
## Bring Ship into your project (main path)
|
|
20
43
|
|
|
21
|
-
You **do not** need the Ship monorepo cloned for day-to-day use. Work in **your product repo** and wire agents to the same
|
|
44
|
+
You **do not** need the Ship monorepo cloned for day-to-day use. Work in **your product repo** and wire agents to the same artifacts protocol the CLI uses.
|
|
22
45
|
|
|
23
46
|
### 1. Pick the API URL
|
|
24
47
|
|
|
25
48
|
- **`SHIP_API_BASE`** — env var the CLI and injected snippets use (no trailing slash).
|
|
26
49
|
- Or pass **`--base-url`** on each command.
|
|
27
|
-
- Default matches other Ship tooling (public
|
|
50
|
+
- Default matches other Ship tooling (public host unless you override for local FastAPI).
|
|
28
51
|
|
|
29
|
-
### 2. Preview what `
|
|
52
|
+
### 2. Preview what `shipctl init` will change
|
|
30
53
|
|
|
31
54
|
From the **root of the repo** you want agents to use:
|
|
32
55
|
|
|
@@ -35,21 +58,42 @@ cd /path/to/your-product
|
|
|
35
58
|
npx @elmundi/ship-cli init --dry-run
|
|
36
59
|
```
|
|
37
60
|
|
|
38
|
-
`
|
|
61
|
+
`shipctl init` **detects what is already in the tree** and only plans injections for those stacks:
|
|
39
62
|
|
|
40
|
-
| If the repo has… | `
|
|
41
|
-
|
|
42
|
-
| `.cursor/` | Cursor rule **`.cursor/rules/ship-
|
|
63
|
+
| If the repo has… | `shipctl init` can add… |
|
|
64
|
+
|------------------|-------------------------|
|
|
65
|
+
| `.cursor/` | Cursor rule **`.cursor/rules/ship-artifacts-protocol.mdc`** |
|
|
43
66
|
| **`AGENTS.md`** | Appended section (Codex-style / generic agents file) |
|
|
44
67
|
| **`CLAUDE.md`** | Appended section |
|
|
45
68
|
| **`.codex/`** | **`SHIP_API.md`** under `.codex/` |
|
|
46
69
|
| **`.github/copilot-instructions.md`** | Appended section |
|
|
70
|
+
| **`.aider.conf.yml`** / `AIDER.md` | **`AIDER.md`** section |
|
|
71
|
+
| **`.clinerules`** / `.rooignore` | **`.clinerules`** section |
|
|
72
|
+
| **`.continue/`** | **`.continue/ship.md`** side-file |
|
|
73
|
+
| **`.windsurfrules`** | **`.windsurfrules`** section |
|
|
74
|
+
| **`.zed/`** | **`.zed/ship.md`** |
|
|
75
|
+
| **`GEMINI.md`** / `.gemini/` | **`GEMINI.md`** section |
|
|
76
|
+
| **`.opencode/`** | **`.opencode/ship.md`** |
|
|
77
|
+
| **`.cursor/environments.json`** | Marker-guarded update to existing file |
|
|
47
78
|
|
|
48
79
|
If **none** of the above exist, init offers a **standalone** **`SHIP_AGENT_API.md`** in the repo root so humans can copy the contract into whatever system you use later.
|
|
49
80
|
|
|
50
|
-
Use **`--
|
|
81
|
+
Use **`--agents <csv>`** to limit targets and **`--cwd <dir>`** to point at another root. Example:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx @elmundi/ship-cli init --agents cursor,codex,claude --dry-run
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3. Stack hints
|
|
51
88
|
|
|
52
|
-
|
|
89
|
+
`init` also accepts `--tracker`, `--ci`, `--preset` (per RFC-0002 stack block). For now they land in the plan payload and are echoed back; a future release writes them into `.ship/config.yml` and triggers the bootstrap adapters (RFC-0004).
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx @elmundi/ship-cli init --yes \
|
|
93
|
+
--agents cursor,codex --tracker linear --ci gh-actions --preset web-app
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. Apply with confirmation (recommended)
|
|
53
97
|
|
|
54
98
|
Interactive run prints the plan and asks **Apply these changes? [y/N]**:
|
|
55
99
|
|
|
@@ -57,9 +101,9 @@ Interactive run prints the plan and asks **Apply these changes? [y/N]**:
|
|
|
57
101
|
npx @elmundi/ship-cli init
|
|
58
102
|
```
|
|
59
103
|
|
|
60
|
-
After you confirm **`y`**, it writes/updates the files above. Injected content tells agents to **
|
|
104
|
+
After you confirm **`y`**, it writes/updates the files above. Injected content tells agents to **resolve Ship artifacts before use** via the CLI: **search → fetch → record `kind:id@version`** workflow, **`shipctl docs fetch`** for documentation paths, **`shipctl pattern|tool|collection`** for catalog bodies, and **`shipctl docs feedback`** for safe retro notes.
|
|
61
105
|
|
|
62
|
-
###
|
|
106
|
+
### 5. Non-interactive (CI or scripts)
|
|
63
107
|
|
|
64
108
|
Only after you are happy with **`--dry-run`**:
|
|
65
109
|
|
|
@@ -69,23 +113,605 @@ npx @elmundi/ship-cli init --yes
|
|
|
69
113
|
|
|
70
114
|
**`--force`** replaces blocks that were already injected (same marker). Without **`--force`**, existing injections are skipped.
|
|
71
115
|
|
|
116
|
+
## Init flow
|
|
117
|
+
|
|
118
|
+
`shipctl init` is the primary adoption entrypoint. It composes four steps in one
|
|
119
|
+
command:
|
|
120
|
+
|
|
121
|
+
1. **Config** — creates `.ship/config.yml` (via `DEFAULT_CONFIG`), seeds an
|
|
122
|
+
anonymous telemetry id, writes `.ship/state.json`, and appends
|
|
123
|
+
`.ship/cache/` to `.gitignore`. Existing configs are respected and only
|
|
124
|
+
updated with the flags/doctor proposal.
|
|
125
|
+
2. **Telemetry** — prompts once for opt-in (default **OFF**). Non-TTY runs and
|
|
126
|
+
`--yes` default to OFF. `--telemetry on|off|ask` overrides the prompt.
|
|
127
|
+
3. **Doctor (no network)** — runs the adapter detect-layer to propose
|
|
128
|
+
`tracker / ci / agents / language` values for gaps the user didn't set
|
|
129
|
+
explicitly via flags. Detection never overrides explicit flags.
|
|
130
|
+
4. **Sync** — calls `syncArtifacts()` to pull the derived collection artifacts
|
|
131
|
+
(`collection/agent-rules-<agent>`, `collection/preset-<preset>`, optionally
|
|
132
|
+
`collection/adoption-playbook`) into `.ship/cache/`.
|
|
133
|
+
|
|
134
|
+
Optional post-steps:
|
|
135
|
+
|
|
136
|
+
- **`--copy-rules`** — for every agent in `stack.agents`, reads the cached
|
|
137
|
+
`agent-rules-<agent>` artifact, extracts `install_target` + `marker` from the
|
|
138
|
+
front-matter, and writes (or upserts) the rules file at the target path.
|
|
139
|
+
A `<!-- ship-cli: installed-from collection/agent-rules-<agent>@<version> -->`
|
|
140
|
+
footer is appended so re-runs can detect the installed version. Downgrades /
|
|
141
|
+
different versions are skipped unless `--force` is passed.
|
|
142
|
+
- **`--bootstrap`** — renders CI + tracker + secrets scaffolding. v1 special-
|
|
143
|
+
cases `mobile-app + gh-actions + linear` (writes `.github/workflows/ship-pilot.yml`
|
|
144
|
+
skeleton, `.ship/labels.yml`, and a `# --- ship-managed ---` block appended to
|
|
145
|
+
`.env.example`). All other combinations emit `SHIP_BOOTSTRAP_PLAN.md` with a
|
|
146
|
+
TODO checklist pointing at the preset artifact for full details.
|
|
147
|
+
- **`--copy-playbook`** — fetches `collection/adoption-playbook` when
|
|
148
|
+
published; a 404 is silently skipped (does not fail the command).
|
|
149
|
+
|
|
150
|
+
### Three primary invocations
|
|
151
|
+
|
|
152
|
+
**MVP (dry-run preview, recommended first run):**
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
shipctl init --dry-run --agents cursor --preset adoption-minimum --tracker none --ci manual
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Pilot (apply, no scaffolding):**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
shipctl init --yes \
|
|
162
|
+
--agents cursor,claude-md \
|
|
163
|
+
--preset web-app --tracker linear --ci gh-actions \
|
|
164
|
+
--copy-rules --telemetry off
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Full bootstrap (mobile-app, with scaffolding skeletons):**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
shipctl init --bootstrap --yes \
|
|
171
|
+
--agents cursor,claude-md,codex \
|
|
172
|
+
--tracker linear --ci gh-actions --preset mobile-app \
|
|
173
|
+
--copy-rules --telemetry off
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Full flag surface
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
shipctl init
|
|
180
|
+
[--yes] [--force] [--dry-run] [--cwd DIR] [--json]
|
|
181
|
+
[--agents cursor,codex,claude-md] # preferred, csv
|
|
182
|
+
[--tracker linear] # linear|jira|github-issues|…|none
|
|
183
|
+
[--ci gh-actions] # gh-actions|gitlab-ci|…|manual
|
|
184
|
+
[--preset mobile-app] # web-app|api-backend|mobile-app|…
|
|
185
|
+
[--language ts] # ts|js|py|go|rust|…|multi
|
|
186
|
+
[--channel stable|edge] # override api.channel
|
|
187
|
+
[--copy-rules] # install agent-rules-<agent> files
|
|
188
|
+
[--copy-playbook] # fetch adoption-playbook into cache
|
|
189
|
+
[--bootstrap] # render CI/tracker scaffolding from preset
|
|
190
|
+
[--telemetry on|off|ask] # override the interactive prompt
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Example output
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
Ship init complete
|
|
197
|
+
-----------------
|
|
198
|
+
Config: .ship/config.yml
|
|
199
|
+
Agents: cursor, claude-md
|
|
200
|
+
Tracker: linear
|
|
201
|
+
CI: gh-actions
|
|
202
|
+
Preset: mobile-app
|
|
203
|
+
Channel: stable
|
|
204
|
+
Telemetry: off
|
|
205
|
+
|
|
206
|
+
Installed rules:
|
|
207
|
+
- .cursor/rules/ship-artifacts-protocol.mdc (from collection/agent-rules-cursor@1.0.0) [wrote]
|
|
208
|
+
- CLAUDE.md (from collection/agent-rules-claude-md@1.0.0) [wrote]
|
|
209
|
+
|
|
210
|
+
Bootstrap (preset=mobile-app):
|
|
211
|
+
- wrote SHIP_BOOTSTRAP_PLAN.md
|
|
212
|
+
- wrote .github/workflows/ship-pilot.yml
|
|
213
|
+
- wrote .ship/labels.yml
|
|
214
|
+
- appended .env.example
|
|
215
|
+
|
|
216
|
+
Next:
|
|
217
|
+
shipctl sync # keep artifacts fresh
|
|
218
|
+
shipctl verify # check tracker labels, CI secrets, rules markers
|
|
219
|
+
shipctl feedback draft # submit improvement idea
|
|
220
|
+
```
|
|
221
|
+
|
|
72
222
|
## Commands (quick reference)
|
|
73
223
|
|
|
74
|
-
| Command | Role |
|
|
75
|
-
|
|
76
|
-
| **`
|
|
77
|
-
| **`
|
|
78
|
-
| **`
|
|
79
|
-
| **`
|
|
224
|
+
| Command | Role | Manual |
|
|
225
|
+
|---------|------|--------|
|
|
226
|
+
| **`shipctl init`** | Bootstrap an existing repo: agent rules, `.ship/config.yml`, optional CI scaffolding. | `documentation/discovery.md` |
|
|
227
|
+
| **`shipctl new`** | Greenfield: `git init` + minimal README + `init`. | this README, `New & Verify` |
|
|
228
|
+
| **`shipctl doctor`** | Inspect repo, propose stack, optionally write `.ship/inventory.json`. | this README, `Doctor` |
|
|
229
|
+
| **`shipctl config`** | Safe edits to `.ship/config.yml` (`init` / `get` / `set` / `validate` / `show` / `path`). | `documentation/configuration.md` |
|
|
230
|
+
| **`shipctl search`** | Vector search over docs + prompts (`POST /search`). | `documentation/discovery.md` |
|
|
231
|
+
| **`shipctl docs fetch`**, **`shipctl docs feedback`** | Documentation file fetch and retro feedback. | `documentation/discovery.md` |
|
|
232
|
+
| **`shipctl pattern\|tool\|collection`** **`list \| show \| fetch \| search`** | Versioned artifact bodies; plural aliases (`patterns`, `tools`, `collections`) work. | `documentation/authoring.md` |
|
|
233
|
+
| **`shipctl sync`** | Pull artifacts into `.ship/cache/`; with `--lock` writes `.ship/shipctl.lock.json` covering every Play the declared lanes depend on. | this README, `Config & Sync` |
|
|
234
|
+
| **`shipctl run`** | One-shot dispatch entry point. `kind: once` runs locally; other lane kinds are queued for the workspace runner. Reports its terminal status via the callback URL Ship injected. | `documentation/automations.md`, this README |
|
|
235
|
+
| **`shipctl lanes`** | Generate / inspect / delete the `.github/workflows/ship-<lane>.yml` thin wrappers (`install` / `list` / `remove`). | `documentation/automations.md`, this README |
|
|
236
|
+
| **`shipctl kickoff`** | Print a Play's pattern body for piping into the customer's agent in CI. | `documentation/automations.md` |
|
|
237
|
+
| **`shipctl callback`** | Pattern-side: report a Run's terminal status + RunSummary outcome so Ship can render the row and route escalations into the Inbox. | this README |
|
|
238
|
+
| **`shipctl knowledge init`** | Open a PR that seeds `.ship/knowledge/*.md` starter buckets. | `documentation/knowledge-buckets.md` |
|
|
239
|
+
| **`shipctl telemetry`** | Opt-in anonymous usage events (default OFF). | this README, `Telemetry & Feedback` |
|
|
240
|
+
| **`shipctl feedback`** | Local markdown drafts → POST `/feedback` → GitHub issue. | this README |
|
|
241
|
+
| **`shipctl verify`** | Post-adoption liveness checks (local + config + network). | this README, `New & Verify` |
|
|
242
|
+
| **`shipctl migrate`** | Upgrade `.ship/config.yml` from v1 to v2 (lanes-as-config). | `documentation/configuration.md` |
|
|
243
|
+
| **`shipctl help`** | Top-level command list with the same vocabulary callout. | — |
|
|
244
|
+
|
|
245
|
+
**Maintainers / full Ship checkout:** if the current directory (or **`SHIP_REPO`**) is inside the Ship monorepo, **`list` / `show` / `fetch`** for catalogs can read manifests from **disk** instead of HTTP. **`shipctl search`** always uses HTTP.
|
|
246
|
+
|
|
247
|
+
Run **`shipctl help`** for the operator-first overview with the same vocabulary callout printed at the top.
|
|
248
|
+
|
|
249
|
+
## Doctor
|
|
250
|
+
|
|
251
|
+
**`shipctl doctor`** inspects a repository using the pluggable adapter registry
|
|
252
|
+
(`cli/lib/adapters/`) and proposes a best-guess Ship stack. It runs every
|
|
253
|
+
tracker / CI / language / agent adapter's `detect(cwd)` hook, scores the
|
|
254
|
+
findings, and infers a preset from repository structure (e.g. `pubspec.yaml`
|
|
255
|
+
or `react-native` in deps → `mobile-app`; `packages/` or `pnpm-workspace.yaml`
|
|
256
|
+
→ `monorepo`). Nothing is ever written without **`--write-inventory`**.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
shipctl doctor # human report
|
|
260
|
+
shipctl doctor --json # machine-readable
|
|
261
|
+
shipctl doctor --cwd /path/to/other-repo # inspect elsewhere
|
|
262
|
+
shipctl doctor --write-inventory # persist .ship/inventory.json
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Example output (trimmed):
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
Ship doctor — inspecting /path/to/your-product
|
|
269
|
+
|
|
270
|
+
Tracker: linear (0.95) · evidence: .env (LINEAR_API_KEY), package.json (@linear/sdk)
|
|
271
|
+
CI: gh-actions (1.00) · evidence: .github/workflows/ (3 workflow(s))
|
|
272
|
+
Language: ts (1.00) · evidence: tsconfig.json (present)
|
|
273
|
+
Agents: cursor (1.00), claude-md (1.00)
|
|
274
|
+
|
|
275
|
+
Inferred preset: web-app (evidence: next.config.ts)
|
|
276
|
+
|
|
277
|
+
Existing Ship artifacts:
|
|
278
|
+
.ship/config.yml missing
|
|
279
|
+
.ship/cache/ missing
|
|
280
|
+
.ship/inventory.json missing
|
|
281
|
+
.cursor/rules/ship-* missing
|
|
282
|
+
|
|
283
|
+
Recommendations:
|
|
284
|
+
1. shipctl config init
|
|
285
|
+
2. shipctl init --bootstrap --tracker linear --ci gh-actions --agents cursor,claude-md --preset web-app
|
|
286
|
+
3. shipctl sync
|
|
287
|
+
4. shipctl verify
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Passing **`--write-inventory`** persists the findings to `.ship/inventory.json`
|
|
291
|
+
so that `shipctl init --bootstrap` can pick up the inferred stack without
|
|
292
|
+
re-running detection.
|
|
293
|
+
|
|
294
|
+
## Config & Sync
|
|
295
|
+
|
|
296
|
+
Ship stores local state under **`.ship/`**. Methodology bodies never live in your
|
|
297
|
+
repo git history — `shipctl sync` caches them in `.ship/cache/`, which is
|
|
298
|
+
`.gitignore`d by default.
|
|
299
|
+
|
|
300
|
+
### `.ship/` layout
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
.ship/
|
|
304
|
+
├── config.yml # RFC-0002 schema; committed. `lanes:` entries
|
|
305
|
+
│ # are what the operator console renders as
|
|
306
|
+
│ # Automations.
|
|
307
|
+
├── state.json # last_sync_at, last_manifest_hash; gitignored
|
|
308
|
+
├── shipctl.lock.json # set by `shipctl sync --lock`; pins every
|
|
309
|
+
│ # pattern the declared lanes depend on
|
|
310
|
+
├── cache/ # per-repo artifact cache (gitignored)
|
|
311
|
+
│ ├── pattern/<id>@<v>/
|
|
312
|
+
│ │ ├── ARTIFACT.md # full body (frontmatter + content), per RFC-0005
|
|
313
|
+
│ │ └── .meta.json # source, sha256, fetched_at, etc.
|
|
314
|
+
│ ├── tool/<id>@<v>/…
|
|
315
|
+
│ ├── collection/<id>@<v>/…
|
|
316
|
+
│ └── doc/…
|
|
317
|
+
├── knowledge/ # operator-edited markdown buckets, committed
|
|
318
|
+
├── telemetry-outbox.jsonl # buffered telemetry events (gitignored)
|
|
319
|
+
└── feedback-drafts/ # feedback draft markdowns (gitignored)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### `shipctl config`
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
shipctl config init # bootstrap .ship/config.yml + state.json + cache/
|
|
326
|
+
shipctl config path # print absolute path to config.yml
|
|
327
|
+
shipctl config show # pretty-print effective YAML
|
|
328
|
+
shipctl config get <dotted.key> # e.g. shipctl config get api.channel
|
|
329
|
+
shipctl config set <k> <value> # atomic write, validates before saving
|
|
330
|
+
shipctl config validate # exit 10 on invalid enum / bad URL / bad pin key
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Value parsing for `config set`:
|
|
334
|
+
|
|
335
|
+
- Bare `true|false|null` → booleans / null.
|
|
336
|
+
- `-?\d+(.\d+)?` → number.
|
|
337
|
+
- `[a,b,c]` → array of strings (quotes optional).
|
|
338
|
+
- Anything else → string.
|
|
339
|
+
|
|
340
|
+
Dotted keys under `artifacts.pins` preserve the embedded slash:
|
|
341
|
+
`artifacts.pins.pattern/role-developer`.
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
shipctl config set stack.agents [cursor,codex]
|
|
345
|
+
shipctl config set api.channel edge
|
|
346
|
+
shipctl config set artifacts.pins.pattern/role-developer 1.4.2
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### `shipctl sync`
|
|
80
350
|
|
|
81
|
-
|
|
351
|
+
```bash
|
|
352
|
+
shipctl sync # pull latest for this stack
|
|
353
|
+
shipctl sync --check-only # report changes without writing cache
|
|
354
|
+
shipctl sync --dry-run # --check-only + planned HTTP calls
|
|
355
|
+
shipctl sync --only pattern:role-developer [--only tool:gh-actions]
|
|
356
|
+
shipctl sync --channel edge
|
|
357
|
+
shipctl sync --force-unpin # temporarily ignore version pins
|
|
358
|
+
shipctl sync --lock # write .ship/shipctl.lock.json after sync
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Summary format:
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
up_to_date: 12
|
|
365
|
+
updated: 3
|
|
366
|
+
skipped_pin: 2
|
|
367
|
+
deprecated: 1 (…)
|
|
368
|
+
yanked: 0
|
|
369
|
+
failed: 0
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Pins are honoured: an entry whose manifest version does not satisfy the pin is
|
|
373
|
+
reported as `skipped_pin` unless `--force-unpin` is set. After a successful
|
|
374
|
+
sync, `.ship/state.json` records `last_sync_at` and `last_manifest_hash`. With
|
|
375
|
+
`--lock`, `shipctl sync` also writes `.ship/shipctl.lock.json` covering every
|
|
376
|
+
Play that the declared lanes depend on, so subsequent `shipctl run` invocations
|
|
377
|
+
can refuse to drift off the pinned set.
|
|
378
|
+
|
|
379
|
+
> Methodology docs never live in your repo. `shipctl sync` caches them in
|
|
380
|
+
> `.ship/cache/`, sealed by `content_sha256` from the Ship manifest.
|
|
82
381
|
|
|
83
|
-
Run
|
|
382
|
+
## Run
|
|
84
383
|
|
|
85
|
-
|
|
384
|
+
`shipctl run` is the **one-shot dispatch entry point** for an Automation
|
|
385
|
+
(YAML key: `lanes:`). What it does depends on the lane's `kind`:
|
|
86
386
|
|
|
87
|
-
|
|
387
|
+
| `kind:` value | Behaviour of `shipctl run` |
|
|
388
|
+
|---------------|----------------------------|
|
|
389
|
+
| `once` | Executes the lane fully on the local machine (the pattern body is fed to the configured agent; the result is reported back via `shipctl callback`). |
|
|
390
|
+
| `lane` / `event` / `schedule` | Refuses to execute locally; the workspace's GitHub Actions runner picks the lane up via `.github/workflows/run-agent.yml`. The CLI exits with a clear message naming the lane id and its kind. |
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
# preview which patterns + parameters the lane would dispatch with
|
|
394
|
+
shipctl run --lane pr-self-review --dry-run
|
|
395
|
+
|
|
396
|
+
# fanout: the same pattern over every repo in the workspace
|
|
397
|
+
shipctl run --lane fleet-mobile-knowledge-refresh \
|
|
398
|
+
--pattern fleet-knowledge-pack \
|
|
399
|
+
--fanout matrix \
|
|
400
|
+
--trigger event \
|
|
401
|
+
--json
|
|
402
|
+
|
|
403
|
+
# CI usage: shipctl injects --ship-run-id / --ship-callback-url / --ship-run-token
|
|
404
|
+
# automatically; you only set them by hand when running outside the workspace runner
|
|
405
|
+
shipctl run --lane release-cut \
|
|
406
|
+
--ship-run-id "$SHIP_RUN_ID" \
|
|
407
|
+
--ship-callback-url "$SHIP_CALLBACK_URL" \
|
|
408
|
+
--ship-run-token "$SHIP_RUN_TOKEN"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Important flags:
|
|
412
|
+
|
|
413
|
+
- `--pattern <id>` — override the lane's default pattern (a composite Play may
|
|
414
|
+
declare several; this lets you target one specifically).
|
|
415
|
+
- `--fanout matrix|sequential|concurrent` — only meaningful for fleet-scope
|
|
416
|
+
lanes that target multiple repos.
|
|
417
|
+
- `--trigger event|schedule|manual|once` — the trigger the lane was wired for;
|
|
418
|
+
used to choose the payload shape.
|
|
419
|
+
- `--offline` — skip every HTTP probe (resolves patterns from `.ship/cache/`
|
|
420
|
+
only); useful for hermetic CI.
|
|
421
|
+
- `--dry-run` — print the dispatch plan and exit 0; no agent invocation.
|
|
422
|
+
|
|
423
|
+
A full Run lifecycle in production looks like: console (or schedule) creates a
|
|
424
|
+
`pipeline_run` row → workspace runner is dispatched → runner calls
|
|
425
|
+
`shipctl run --lane <id>` for `kind: once` lanes (or invokes the agent
|
|
426
|
+
directly for `kind: lane`) → the pattern calls `shipctl callback` with the
|
|
427
|
+
RunSummary → console renders the outcome row in `/runs` and any escalations
|
|
428
|
+
land in `/inbox`.
|
|
429
|
+
|
|
430
|
+
## Lanes
|
|
431
|
+
|
|
432
|
+
`shipctl lanes` manages the **thin GitHub Actions wrappers** that delegate to
|
|
433
|
+
the reusable `run-agent.yml` workflow. Each lane in `.ship/config.yml`
|
|
434
|
+
generates one `.github/workflows/ship-<lane>.yml` file. The file itself is a
|
|
435
|
+
~12-line yaml that does nothing more than `uses: ./.github/workflows/run-agent.yml`
|
|
436
|
+
with the right `lane:` input — all the logic lives in the reusable workflow,
|
|
437
|
+
so wrappers can be regenerated without touching execution semantics.
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
# write workflow files for every lane in config.yml
|
|
441
|
+
shipctl lanes install --dry-run
|
|
442
|
+
shipctl lanes install --yes
|
|
443
|
+
|
|
444
|
+
# only one lane (or a few)
|
|
445
|
+
shipctl lanes install --only pr-self-review,release-cut
|
|
446
|
+
|
|
447
|
+
# wire to a specific shipctl version pin
|
|
448
|
+
shipctl lanes install --shipctl-version 0.12.0 \
|
|
449
|
+
--owner elmundi --repo ship --ref v0.12.0
|
|
450
|
+
|
|
451
|
+
# inspect what's on disk vs config.yml
|
|
452
|
+
shipctl lanes list --json
|
|
453
|
+
|
|
454
|
+
# remove generated wrappers (does NOT touch lanes: config)
|
|
455
|
+
shipctl lanes remove --dry-run
|
|
456
|
+
shipctl lanes remove --only deprecated-lane --yes
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Notes:
|
|
460
|
+
|
|
461
|
+
- `lanes install` writes files **only** for lanes with a configured trigger
|
|
462
|
+
(`on.push`, `on.schedule`, `on.workflow_dispatch`). `kind: once` lanes
|
|
463
|
+
intended to run only via `shipctl run` don't get a wrapper.
|
|
464
|
+
- The same wrapper covers a fleet-scope lane (one workflow file in your
|
|
465
|
+
pilot repo, fanout happens server-side via the matrix Ship dispatches).
|
|
466
|
+
- Removing a wrapper does **not** remove the lane from `.ship/config.yml`;
|
|
467
|
+
to fully retire an Automation, drop the `lanes.<id>` block from the YAML
|
|
468
|
+
and re-run `shipctl lanes install` so the file is reconciled.
|
|
469
|
+
|
|
470
|
+
## Callback
|
|
471
|
+
|
|
472
|
+
`shipctl callback` is what a Play's pattern calls to **close the loop on a
|
|
473
|
+
Run**. It POSTs a structured payload to the URL Ship injected into the
|
|
474
|
+
runner (`SHIP_CALLBACK_URL` env or `--callback-url`) so the operator console
|
|
475
|
+
can render an outcome-first row in `/runs` and route any escalations into
|
|
476
|
+
`/inbox`.
|
|
477
|
+
|
|
478
|
+
The flag surface is **protocol-stable** (the workspace API depends on it);
|
|
479
|
+
the help is grouped by intent.
|
|
480
|
+
|
|
481
|
+
### Identity (one of these is required)
|
|
482
|
+
|
|
483
|
+
```
|
|
484
|
+
--run-id <uuid> # falls back to SHIP_RUN_ID
|
|
485
|
+
--callback-url <url> # falls back to SHIP_CALLBACK_URL
|
|
486
|
+
SHIP_RUN_TOKEN=<jwt> # bearer for the callback URL (CI sets this)
|
|
487
|
+
SHIP_API_BASE=<url> # base for {api}/v1/runs/<id>/callback when only --run-id is set
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Status & summary
|
|
491
|
+
|
|
492
|
+
```
|
|
493
|
+
--status ok|fail|cancelled # required terminal state
|
|
494
|
+
--summary "Free text" # short human readout (kept in addition to outcome)
|
|
495
|
+
--metric key=value # repeatable; persisted as-is
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### RunSummary outcome (Phase 3)
|
|
499
|
+
|
|
500
|
+
These map 1:1 to the `outcome:` JSONB column on `pipeline_runs` and to what
|
|
501
|
+
the console renders:
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
--outcome-text "Reviewed PR · 3 suggestions · 1 fix applied"
|
|
505
|
+
--findings-count 3
|
|
506
|
+
--severity high=1 --severity medium=2 # repeatable; map of sev → count
|
|
507
|
+
--artifact pr:"Auto-fix: typo":"https://...": # repeatable; type:title[:ref]
|
|
508
|
+
--artifact comment:"Self-review summary":"https://github.com/.../pull/42#…"
|
|
509
|
+
--escalation clarification:"agent_low_confidence" # repeatable; type:reason
|
|
510
|
+
--requires-approval # toggle the approval gate
|
|
511
|
+
--approval-payload '{"...": "..."}' # JSON forwarded to the Inbox item
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
You can also pass the full RunSummary as JSON via:
|
|
515
|
+
|
|
516
|
+
- `SHIP_RUN_OUTCOME=$JSON_STRING`
|
|
517
|
+
- `SHIP_RUN_OUTCOME_FILE=/path/to/outcome.json`
|
|
518
|
+
|
|
519
|
+
Flags merge on top of the env / file payload (CLI wins).
|
|
520
|
+
|
|
521
|
+
### Example (canonical pattern recipe)
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
shipctl callback --status ok \
|
|
525
|
+
--outcome-text "Reviewed PR · 3 suggestions · 1 fix applied" \
|
|
526
|
+
--findings-count 3 \
|
|
527
|
+
--severity high=1 --severity medium=2 \
|
|
528
|
+
--artifact comment:"PR self-review summary":"https://github.com/elmundi/ship/pull/42#issuecomment-…" \
|
|
529
|
+
--artifact pr:"Auto-fix: typo in README":"https://github.com/elmundi/ship/pull/43"
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
The same `## Reporting` block lives at the bottom of every top-Play pattern
|
|
533
|
+
(see `artifacts/patterns/flow-pr-self-review/ARTIFACT.md` for the canonical
|
|
534
|
+
example). When you author a new Play, copy that block as the contract you
|
|
535
|
+
expect runners to honour.
|
|
536
|
+
|
|
537
|
+
## Knowledge
|
|
538
|
+
|
|
539
|
+
`shipctl knowledge init` opens a PR in the target repo that seeds the
|
|
540
|
+
`.ship/knowledge/` starter buckets (e.g. `code-style.md`, `ui-runbook.md`).
|
|
541
|
+
The PR is intentionally minimal — operators are expected to fill the buckets
|
|
542
|
+
in over time.
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
# requires SHIP_API_TOKEN; targets the workspace's wired GitHub installation
|
|
546
|
+
shipctl knowledge init \
|
|
547
|
+
--workspace 11111111-1111-1111-1111-111111111111 \
|
|
548
|
+
--repo elmundi/ship-pilot \
|
|
549
|
+
--only code-style,ui-runbook \
|
|
550
|
+
--json
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Behind the scenes, this hits the workspace API which uses the GitHub App
|
|
554
|
+
installation to open the PR. The buckets the Plays read at runtime live
|
|
555
|
+
under the same `.ship/knowledge/` tree the PR seeds.
|
|
556
|
+
|
|
557
|
+
## Telemetry & Feedback
|
|
558
|
+
|
|
559
|
+
Anonymous telemetry is **opt-in and OFF by default** (RFC-0003). Nothing leaves
|
|
560
|
+
the repo until you explicitly flip the switch with `shipctl telemetry on`.
|
|
561
|
+
Events are first buffered to `.ship/telemetry-outbox.jsonl`; flushing to
|
|
562
|
+
`POST /telemetry` is a deliberate, retry-safe step.
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
# inspect current state
|
|
566
|
+
shipctl telemetry status # share=..., anonymous_id=..., outbox_pending=N
|
|
567
|
+
|
|
568
|
+
# opt in, with a narrow scope, non-interactively
|
|
569
|
+
shipctl telemetry on --scope artifact_usage,improvement_drafts --yes
|
|
570
|
+
|
|
571
|
+
# look at what's queued locally before sending
|
|
572
|
+
shipctl telemetry buffer --limit 10
|
|
573
|
+
|
|
574
|
+
# send any queued events (batches of 100); succeeded lines are removed
|
|
575
|
+
shipctl telemetry flush
|
|
576
|
+
shipctl telemetry flush --dry-run # preview only
|
|
577
|
+
|
|
578
|
+
# data rights: export or delete by anonymous_id
|
|
579
|
+
shipctl telemetry export --out telemetry.json
|
|
580
|
+
shipctl telemetry delete-my-data # interactive confirmation required
|
|
581
|
+
|
|
582
|
+
# rotate identity (server treats the previous id as a separate adopter)
|
|
583
|
+
shipctl telemetry reset-id
|
|
584
|
+
|
|
585
|
+
# fully disable
|
|
586
|
+
shipctl telemetry off
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Allowed event types: `artifact.fetch`, `artifact.use`, `artifact.sync`,
|
|
590
|
+
`feedback.submit`, `doctor.result`. Payload keys in the RFC-0003 denylist
|
|
591
|
+
(`path, code, diff, branch, remote, email`) are stripped client-side before
|
|
592
|
+
anything is appended to the outbox.
|
|
593
|
+
|
|
594
|
+
Feedback is always drafted locally as a markdown file before it is sent
|
|
595
|
+
anywhere:
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
# create a draft
|
|
599
|
+
shipctl feedback draft --kind pattern --id role-developer --version 1.4.2 \
|
|
600
|
+
--title "Missing mobile preview step" \
|
|
601
|
+
--summary "Evidence checklist misses mobile preview" \
|
|
602
|
+
--recommendation "Add a bullet under Evidence"
|
|
603
|
+
|
|
604
|
+
# review / edit (uses $EDITOR)
|
|
605
|
+
shipctl feedback list
|
|
606
|
+
shipctl feedback show .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md
|
|
607
|
+
shipctl feedback edit .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md
|
|
608
|
+
|
|
609
|
+
# submit → POST /feedback → GitHub issue URL; draft moves to sent/
|
|
610
|
+
shipctl feedback submit .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md --yes
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Submission requires `kind`, `id`, `title`, and `summary`; missing fields fail
|
|
614
|
+
with exit 1 (nothing sent). When `telemetry.share=true` and
|
|
615
|
+
`scope.improvement_drafts=true`, a `feedback.submit` event is appended to the
|
|
616
|
+
telemetry outbox on successful submission.
|
|
617
|
+
|
|
618
|
+
## New & Verify
|
|
619
|
+
|
|
620
|
+
### `shipctl new <name>`
|
|
621
|
+
|
|
622
|
+
Scaffolds a fresh repo with the Ship wiring already in place: creates the
|
|
623
|
+
target directory, runs `git init -q`, drops a minimal `README.md`, seeds
|
|
624
|
+
`.ship/config.yml` via `shipctl config init`, applies the provided stack
|
|
625
|
+
flags via `shipctl config set`, and (when `--agents` is supplied) runs
|
|
626
|
+
`shipctl init --yes --copy-rules …` to install the agent rule files.
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
shipctl new pharma-pilot \
|
|
630
|
+
--preset mobile-app --tracker linear --ci gh-actions \
|
|
631
|
+
--agents cursor,claude,codex --yes
|
|
632
|
+
cd pharma-pilot
|
|
633
|
+
shipctl verify --no-network
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
Common flags:
|
|
637
|
+
|
|
638
|
+
- `--here` — initialize in the current directory instead of creating `<name>/`.
|
|
639
|
+
- `--preset / --tracker / --ci / --agents / --language / --channel` —
|
|
640
|
+
forwarded to `config set` + `init`.
|
|
641
|
+
- `--yes` — non-interactive (required for CI / dry-run).
|
|
642
|
+
- `--dry-run` — describe the plan without touching disk.
|
|
643
|
+
- `--json` — machine-readable summary of created files.
|
|
644
|
+
|
|
645
|
+
### `shipctl verify`
|
|
646
|
+
|
|
647
|
+
Post-adoption liveness check. A collection of independent checks under
|
|
648
|
+
`cli/lib/verify/checks/` grouped by category:
|
|
649
|
+
|
|
650
|
+
- **local** — `.ship/config.yml` present, `.gitignore` excludes
|
|
651
|
+
`.ship/cache/`, agent rule files have the
|
|
652
|
+
`<!-- ship-cli: artifacts-protocol v1 -->` marker and `installed-from`
|
|
653
|
+
footer, cached artifacts match their `.meta.json` sha256, bootstrap
|
|
654
|
+
scaffolding (mobile-app + gh-actions + linear) carries
|
|
655
|
+
`ship-managed` markers.
|
|
656
|
+
- **config** — `stack.*` enum re-validation, declared agents have
|
|
657
|
+
on-disk signals.
|
|
658
|
+
- **network** (skip with `--no-network`) — `/health` (or `/patterns` as a
|
|
659
|
+
fallback) reachable, local cache matches the channel catalog aggregated
|
|
660
|
+
across `/patterns`, `/tools`, `/collections`, Linear labels exist (needs
|
|
661
|
+
`LINEAR_API_KEY`), every `${{ secrets.X }}` reference in gh-actions
|
|
662
|
+
workflows is declared in `.env.example`.
|
|
663
|
+
|
|
664
|
+
Exit `0` when no check returned `fail`; warnings do not fail.
|
|
665
|
+
|
|
666
|
+
```bash
|
|
667
|
+
shipctl verify # full run
|
|
668
|
+
shipctl verify --no-network # skip HTTP + Linear calls
|
|
669
|
+
shipctl verify --check rules-markers,cache-integrity
|
|
670
|
+
shipctl verify --severity warn # hide pass rows
|
|
671
|
+
shipctl verify --json # { checks:[…], summary:{…}, exit_code }
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## Versioning
|
|
675
|
+
|
|
676
|
+
`shipctl --version` (or `shipctl version`) prints the running release. The
|
|
677
|
+
version is part of every outbound `User-Agent` header so the methodology API
|
|
678
|
+
can correlate adoption metrics with the client release.
|
|
679
|
+
|
|
680
|
+
This package follows the **monorepo-wide** Ship version: a single `VERSION`
|
|
681
|
+
file at the repo root drives `cli/package.json`, `landing/package.json`,
|
|
682
|
+
`backend/app/main.py`, and the root `package.json` in lockstep via
|
|
683
|
+
`scripts/version.mjs` (`npm run version:bump -- patch|minor|major|x.y.z`).
|
|
684
|
+
See the root [`README.md`](../README.md#versioning--releases) for the full
|
|
685
|
+
release recipe.
|
|
88
686
|
|
|
89
687
|
## Publishing (maintainers)
|
|
90
688
|
|
|
91
|
-
GitHub Action **Publish @elmundi/ship-cli to npm**
|
|
689
|
+
The GitHub Action **Publish @elmundi/ship-cli to npm** is triggered by either
|
|
690
|
+
the unified `v<x.y.z>` tag (preferred — bumps every component in lockstep) or
|
|
691
|
+
the legacy `cli-v<x.y.z>` tag (escape hatch for CLI-only patches). It runs
|
|
692
|
+
`scripts/version.mjs check` before publishing so an out-of-sync tree never
|
|
693
|
+
ships to npm.
|
|
694
|
+
|
|
695
|
+
```bash
|
|
696
|
+
npm run version:bump -- minor # 0.10.0 → 0.11.0, syncs everything
|
|
697
|
+
git commit -am "release v$(cat VERSION)"
|
|
698
|
+
git tag "v$(cat VERSION)"
|
|
699
|
+
git push --follow-tags # publish workflow picks up v0.11.0
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
Repository secret **`NPM_TOKEN`** is required. Publish from the monorepo
|
|
703
|
+
root: **`npm publish -w @elmundi/ship-cli`** — not `npm publish --prefix cli`
|
|
704
|
+
(the root package is private).
|
|
705
|
+
|
|
706
|
+
## Reference
|
|
707
|
+
|
|
708
|
+
Protocol-stable surfaces:
|
|
709
|
+
|
|
710
|
+
- **Artifacts protocol** (`POST /search`, `POST /fetch`) — RFC-0001.
|
|
711
|
+
- **Stack block + presets + adapters** — RFCs 0002 / 0004 / 0006.
|
|
712
|
+
- **Telemetry** — RFC-0003.
|
|
713
|
+
- **Operator IA** (Plays / Automations / Runs / Inbox) — RFC-0010.
|
|
714
|
+
- **HTTP schemas live next to the source**: `artifacts/tools/methodology-api/ARTIFACT.md`.
|
|
715
|
+
|
|
716
|
+
Every consumed artifact should be recorded in the PR or commit log as
|
|
717
|
+
`<kind>:<id>@<version>` so reviewers can replay what the agent saw.
|