zinkee 0.1.43 → 0.1.45
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 +9 -4
- package/dist/chunk-MHEVRMDX.js +1230 -0
- package/dist/chunk-MHEVRMDX.js.map +1 -0
- package/{src/utils/examples.ts → dist/examples-E6FFEVBE.js} +856 -1141
- package/dist/examples-E6FFEVBE.js.map +1 -0
- package/dist/index.js +1145 -8456
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/.github/workflows/npm-publish.yml +0 -77
- package/.github/workflows/pr-checks.yml +0 -36
- package/AGENTS.md +0 -110
- package/docs/cli-contract.md +0 -41
- package/docs/npm-release.md +0 -64
- package/docs/superpowers/plans/2026-03-24-zinkee-cli-implementation.md +0 -837
- package/docs/superpowers/plans/2026-03-25-cli-backend-error-contract.md +0 -503
- package/docs/superpowers/plans/2026-03-26-display-freeform-create.md +0 -389
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-backend-blockers.md +0 -172
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-design.md +0 -1576
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-checklist.md +0 -215
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-design.md +0 -492
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-status.md +0 -307
- package/docs/superpowers/specs/2026-07-30-cli-pr-checks-design.md +0 -37
- package/src/api/automations.ts +0 -404
- package/src/api/comments.ts +0 -51
- package/src/api/displays.ts +0 -337
- package/src/api/document-templates.ts +0 -110
- package/src/api/files.ts +0 -50
- package/src/api/formulas.test.ts +0 -65
- package/src/api/formulas.ts +0 -67
- package/src/api/logs.ts +0 -34
- package/src/api/navigation.ts +0 -70
- package/src/api/records.ts +0 -184
- package/src/api/schemas.ts +0 -148
- package/src/api/teamspace.ts +0 -110
- package/src/cli-examples.ts +0 -130
- package/src/cli-runner.ts +0 -95
- package/src/client.test.ts +0 -189
- package/src/client.ts +0 -269
- package/src/command-registry.ts +0 -882
- package/src/commands/automations.test.ts +0 -1030
- package/src/commands/automations.ts +0 -2102
- package/src/commands/comments.test.ts +0 -214
- package/src/commands/comments.ts +0 -303
- package/src/commands/config.test.ts +0 -81
- package/src/commands/config.ts +0 -150
- package/src/commands/displays.test.ts +0 -1105
- package/src/commands/displays.ts +0 -1442
- package/src/commands/document-templates.test.ts +0 -569
- package/src/commands/document-templates.ts +0 -563
- package/src/commands/files.test.ts +0 -284
- package/src/commands/files.ts +0 -280
- package/src/commands/formulas.test.ts +0 -194
- package/src/commands/formulas.ts +0 -243
- package/src/commands/logs.test.ts +0 -123
- package/src/commands/logs.ts +0 -159
- package/src/commands/navigation.test.ts +0 -211
- package/src/commands/navigation.ts +0 -348
- package/src/commands/profiles.test.ts +0 -191
- package/src/commands/profiles.ts +0 -303
- package/src/commands/records.test.ts +0 -860
- package/src/commands/records.ts +0 -883
- package/src/commands/schemas.test.ts +0 -1252
- package/src/commands/schemas.ts +0 -890
- package/src/commands/teamspace.test.ts +0 -229
- package/src/commands/teamspace.ts +0 -546
- package/src/completion/engine.test.ts +0 -138
- package/src/completion/engine.ts +0 -168
- package/src/completion/install.test.ts +0 -179
- package/src/completion/install.ts +0 -260
- package/src/completion/runtime.ts +0 -150
- package/src/completion/scripts.ts +0 -91
- package/src/config.test.ts +0 -362
- package/src/config.ts +0 -294
- package/src/index.test.ts +0 -217
- package/src/index.ts +0 -8
- package/src/parsers/expressions.test.ts +0 -95
- package/src/parsers/expressions.ts +0 -128
- package/src/parsers/kv.test.ts +0 -35
- package/src/parsers/kv.ts +0 -49
- package/src/parsers/selectors.test.ts +0 -23
- package/src/parsers/selectors.ts +0 -29
- package/src/program.ts +0 -64
- package/src/runtime-context.ts +0 -103
- package/src/types.ts +0 -76
- package/src/utils/argv-rewrite.test.ts +0 -149
- package/src/utils/argv-rewrite.ts +0 -269
- package/src/utils/errors.test.ts +0 -85
- package/src/utils/errors.ts +0 -191
- package/src/utils/examples.test.ts +0 -374
- package/src/utils/output.test.ts +0 -65
- package/src/utils/output.ts +0 -154
- package/src/utils/schema-fields.ts +0 -1016
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -13
|
@@ -1,837 +0,0 @@
|
|
|
1
|
-
# Zinkee CLI Implementation Plan
|
|
2
|
-
|
|
3
|
-
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
-
|
|
5
|
-
**Goal:** Build a complete Zinkee API v2 CLI from scratch, with backward-compatible profile config, agent-friendly JSON output, and full domain coverage matching the approved design spec.
|
|
6
|
-
|
|
7
|
-
**Architecture:** The CLI will follow the `store-manager` reference structure: a thin `commander` entrypoint, domain command modules in `src/commands`, REST transport modules in `src/api`, a shared runtime layer for config/output/errors/parsing, and a central command registry that powers read-only enforcement and example support. Domain implementation should proceed from core runtime outward so later domain workers can plug into stable shared contracts.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Node.js 20+, TypeScript, ESM, commander, chalk, cli-table3, tsup, tsx, vitest, native fetch, TOML parser/stringifier dependency.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### Task 1: Bootstrap Project Tooling
|
|
14
|
-
|
|
15
|
-
**Files:**
|
|
16
|
-
- Create: `package.json`
|
|
17
|
-
- Create: `tsconfig.json`
|
|
18
|
-
- Create: `tsup.config.ts`
|
|
19
|
-
- Create: `src/index.ts`
|
|
20
|
-
- Create: `src/types.ts`
|
|
21
|
-
- Test: `src/index.test.ts`
|
|
22
|
-
|
|
23
|
-
- [ ] **Step 1: Add the base project files and first smoke test**
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
// src/index.test.ts
|
|
27
|
-
import { describe, expect, it } from "vitest";
|
|
28
|
-
|
|
29
|
-
describe("project bootstrap", () => {
|
|
30
|
-
it("loads the CLI entry module", async () => {
|
|
31
|
-
const mod = await import("./index.js");
|
|
32
|
-
expect(mod).toBeTruthy();
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
- [ ] **Step 2: Run the targeted bootstrap test and capture the current failure**
|
|
38
|
-
|
|
39
|
-
Run: `npm test -- src/index.test.ts`
|
|
40
|
-
Expected: failure because the package, scripts, and entrypoint do not exist yet
|
|
41
|
-
|
|
42
|
-
- [ ] **Step 3: Create the package, build config, and entrypoint scaffold**
|
|
43
|
-
|
|
44
|
-
```ts
|
|
45
|
-
// src/index.ts
|
|
46
|
-
#!/usr/bin/env node
|
|
47
|
-
|
|
48
|
-
import chalk from "chalk";
|
|
49
|
-
import { Command } from "commander";
|
|
50
|
-
|
|
51
|
-
export function buildProgram(): Command {
|
|
52
|
-
return new Command()
|
|
53
|
-
.name("zinkee")
|
|
54
|
-
.description("CLI for Zinkee API v2")
|
|
55
|
-
.showHelpAfterError();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
59
|
-
try {
|
|
60
|
-
await buildProgram().parseAsync(process.argv);
|
|
61
|
-
} catch (error) {
|
|
62
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
63
|
-
process.stderr.write(`${chalk.red("Error:")} ${message}\n`);
|
|
64
|
-
process.exitCode = 1;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
- [ ] **Step 4: Run bootstrap verification**
|
|
70
|
-
|
|
71
|
-
Run:
|
|
72
|
-
- `npm run build`
|
|
73
|
-
- `npm run typecheck`
|
|
74
|
-
- `npm test -- src/index.test.ts`
|
|
75
|
-
|
|
76
|
-
Expected:
|
|
77
|
-
- build succeeds
|
|
78
|
-
- typecheck succeeds
|
|
79
|
-
- bootstrap test passes
|
|
80
|
-
|
|
81
|
-
- [ ] **Step 5: Commit**
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
git add package.json tsconfig.json tsup.config.ts src/index.ts src/types.ts src/index.test.ts
|
|
85
|
-
git commit -m "chore: bootstrap zinkee cli project"
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Task 2: Build Config Compatibility and Runtime Context
|
|
89
|
-
|
|
90
|
-
**Files:**
|
|
91
|
-
- Create: `src/config.ts`
|
|
92
|
-
- Create: `src/config.test.ts`
|
|
93
|
-
- Create: `src/runtime-context.ts`
|
|
94
|
-
- Modify: `src/types.ts`
|
|
95
|
-
- Modify: `src/index.ts`
|
|
96
|
-
|
|
97
|
-
- [ ] **Step 1: Add tests for TOML compatibility and runtime context resolution**
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
// src/config.test.ts
|
|
101
|
-
import { describe, expect, it } from "vitest";
|
|
102
|
-
|
|
103
|
-
import { parseConfig, resolveProfile } from "./config.js";
|
|
104
|
-
|
|
105
|
-
describe("parseConfig", () => {
|
|
106
|
-
it("reads the legacy config shape without migration", () => {
|
|
107
|
-
const config = parseConfig(`
|
|
108
|
-
default_profile = "prod"
|
|
109
|
-
|
|
110
|
-
[profiles.prod]
|
|
111
|
-
api_key = "token"
|
|
112
|
-
base_url = "https://api.zinkee.com"
|
|
113
|
-
`);
|
|
114
|
-
|
|
115
|
-
expect(config.defaultProfile).toBe("prod");
|
|
116
|
-
expect(config.profiles.prod?.apiKey).toBe("token");
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe("resolveProfile", () => {
|
|
121
|
-
it("prefers explicit profile over default_profile", () => {
|
|
122
|
-
const config = {
|
|
123
|
-
defaultProfile: "prod",
|
|
124
|
-
profiles: {
|
|
125
|
-
prod: { apiKey: "a" },
|
|
126
|
-
local: { apiKey: "b", baseUrl: "http://localhost:8088" },
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
expect(resolveProfile(config, { profile: "local" }).name).toBe("local");
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
- [ ] **Step 2: Run the config test and capture the failure**
|
|
136
|
-
|
|
137
|
-
Run: `npm test -- src/config.test.ts`
|
|
138
|
-
Expected: failure because config parsing/resolution does not exist yet
|
|
139
|
-
|
|
140
|
-
- [ ] **Step 3: Implement TOML-backed config reading and runtime context resolution**
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
// src/types.ts
|
|
144
|
-
export interface ProfileConfig {
|
|
145
|
-
apiKey: string;
|
|
146
|
-
baseUrl?: string;
|
|
147
|
-
name?: string;
|
|
148
|
-
description?: string;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export interface AppConfig {
|
|
152
|
-
defaultProfile?: string;
|
|
153
|
-
profiles: Record<string, ProfileConfig>;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface RuntimeOverrides {
|
|
157
|
-
profile?: string;
|
|
158
|
-
baseUrl?: string;
|
|
159
|
-
apiKey?: string;
|
|
160
|
-
readOnly?: boolean;
|
|
161
|
-
json?: boolean;
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
- [ ] **Step 4: Verify config compatibility and root wiring**
|
|
166
|
-
|
|
167
|
-
Run:
|
|
168
|
-
- `npm test -- src/config.test.ts`
|
|
169
|
-
- `npm run typecheck`
|
|
170
|
-
|
|
171
|
-
Expected:
|
|
172
|
-
- legacy TOML parsing passes
|
|
173
|
-
- runtime context resolution is typed and working
|
|
174
|
-
|
|
175
|
-
- [ ] **Step 5: Commit**
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
git add src/config.ts src/config.test.ts src/runtime-context.ts src/types.ts src/index.ts
|
|
179
|
-
git commit -m "feat: add config compatibility and runtime context"
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Task 3: Add Shared Output, Error, and Command Registry Infrastructure
|
|
183
|
-
|
|
184
|
-
**Files:**
|
|
185
|
-
- Create: `src/utils/output.ts`
|
|
186
|
-
- Create: `src/utils/errors.ts`
|
|
187
|
-
- Create: `src/utils/examples.ts`
|
|
188
|
-
- Create: `src/command-registry.ts`
|
|
189
|
-
- Create: `src/utils/output.test.ts`
|
|
190
|
-
- Modify: `src/index.ts`
|
|
191
|
-
- Modify: `src/types.ts`
|
|
192
|
-
|
|
193
|
-
- [ ] **Step 1: Add tests for JSON envelope, error mapping, and registry lookup**
|
|
194
|
-
|
|
195
|
-
```ts
|
|
196
|
-
// src/utils/output.test.ts
|
|
197
|
-
import { describe, expect, it } from "vitest";
|
|
198
|
-
|
|
199
|
-
import { buildJsonSuccess, buildJsonError } from "./output.js";
|
|
200
|
-
|
|
201
|
-
describe("buildJsonSuccess", () => {
|
|
202
|
-
it("wraps data in the standard success envelope", () => {
|
|
203
|
-
expect(buildJsonSuccess([{ id: "1" }], { command: "schemas list" })).toEqual({
|
|
204
|
-
data: [{ id: "1" }],
|
|
205
|
-
meta: { command: "schemas list" },
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe("buildJsonError", () => {
|
|
211
|
-
it("wraps error details in the standard error envelope", () => {
|
|
212
|
-
expect(buildJsonError({ reason: "invalid_request", message: "Bad request" }, {})).toMatchObject({
|
|
213
|
-
error: { reason: "invalid_request" },
|
|
214
|
-
meta: {},
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
- [ ] **Step 2: Run the targeted shared-runtime test**
|
|
221
|
-
|
|
222
|
-
Run: `npm test -- src/utils/output.test.ts`
|
|
223
|
-
Expected: failure because the shared output/error helpers do not exist yet
|
|
224
|
-
|
|
225
|
-
- [ ] **Step 3: Implement envelope rendering, exit code mapping, and command metadata**
|
|
226
|
-
|
|
227
|
-
```ts
|
|
228
|
-
// src/command-registry.ts
|
|
229
|
-
export type CommandAccessLevel = "read" | "write" | "destructive";
|
|
230
|
-
|
|
231
|
-
export interface CommandMeta {
|
|
232
|
-
command: string;
|
|
233
|
-
accessLevel: CommandAccessLevel;
|
|
234
|
-
supportsExample?: boolean;
|
|
235
|
-
supportsRaw?: boolean;
|
|
236
|
-
output: "table-json" | "json-only" | "binary";
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
- [ ] **Step 4: Verify the shared runtime layer**
|
|
241
|
-
|
|
242
|
-
Run:
|
|
243
|
-
- `npm test -- src/utils/output.test.ts`
|
|
244
|
-
- `npm run typecheck`
|
|
245
|
-
|
|
246
|
-
Expected:
|
|
247
|
-
- JSON envelope helpers pass
|
|
248
|
-
- error mapping is typed
|
|
249
|
-
- command registry compiles and can be consumed by the root program
|
|
250
|
-
|
|
251
|
-
- [ ] **Step 5: Commit**
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
git add src/utils/output.ts src/utils/errors.ts src/utils/examples.ts src/utils/output.test.ts src/command-registry.ts src/index.ts src/types.ts
|
|
255
|
-
git commit -m "feat: add output error and command registry runtime"
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### Task 4: Add REST Client and Shared Parsers
|
|
259
|
-
|
|
260
|
-
**Files:**
|
|
261
|
-
- Create: `src/client.ts`
|
|
262
|
-
- Create: `src/client.test.ts`
|
|
263
|
-
- Create: `src/parsers/expressions.ts`
|
|
264
|
-
- Create: `src/parsers/expressions.test.ts`
|
|
265
|
-
- Create: `src/parsers/kv.ts`
|
|
266
|
-
- Create: `src/parsers/kv.test.ts`
|
|
267
|
-
- Create: `src/parsers/selectors.ts`
|
|
268
|
-
- Create: `src/parsers/selectors.test.ts`
|
|
269
|
-
|
|
270
|
-
- [ ] **Step 1: Add transport and parser tests**
|
|
271
|
-
|
|
272
|
-
```ts
|
|
273
|
-
// src/parsers/kv.test.ts
|
|
274
|
-
import { describe, expect, it } from "vitest";
|
|
275
|
-
|
|
276
|
-
import { parseKeyValue, parseJsonAssignment } from "./kv.js";
|
|
277
|
-
|
|
278
|
-
describe("parseKeyValue", () => {
|
|
279
|
-
it("splits field=value pairs", () => {
|
|
280
|
-
expect(parseKeyValue("status=active")).toEqual({ key: "status", value: "active" });
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
describe("parseJsonAssignment", () => {
|
|
285
|
-
it("parses field=json pairs", () => {
|
|
286
|
-
expect(parseJsonAssignment('payload={"a":1}')).toEqual({ key: "payload", value: { a: 1 } });
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
- [ ] **Step 2: Run parser and client checks to capture the failure**
|
|
292
|
-
|
|
293
|
-
Run:
|
|
294
|
-
- `npm test -- src/parsers/kv.test.ts`
|
|
295
|
-
- `npm test -- src/parsers/expressions.test.ts`
|
|
296
|
-
- `npm test -- src/client.test.ts`
|
|
297
|
-
|
|
298
|
-
Expected: failures because parsers and transport do not exist yet
|
|
299
|
-
|
|
300
|
-
- [ ] **Step 3: Implement the shared client and parser layer**
|
|
301
|
-
|
|
302
|
-
```ts
|
|
303
|
-
// src/client.ts
|
|
304
|
-
export interface ApiClientOptions {
|
|
305
|
-
baseUrl: string;
|
|
306
|
-
apiKey: string;
|
|
307
|
-
timeoutMs?: number;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
export class ApiClient {
|
|
311
|
-
constructor(private readonly options: ApiClientOptions) {}
|
|
312
|
-
|
|
313
|
-
async getJson<T>(path: string): Promise<T> {
|
|
314
|
-
return this.requestJson<T>(path, { method: "GET" });
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
async requestJson<T>(path: string, init: RequestInit): Promise<T> {
|
|
318
|
-
// fetch + auth header + timeout + JSON/error normalization
|
|
319
|
-
throw new Error("not implemented");
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
- [ ] **Step 4: Verify the transport and parser contracts**
|
|
325
|
-
|
|
326
|
-
Run:
|
|
327
|
-
- `npm test -- src/parsers/kv.test.ts`
|
|
328
|
-
- `npm test -- src/parsers/expressions.test.ts`
|
|
329
|
-
- `npm test -- src/parsers/selectors.test.ts`
|
|
330
|
-
- `npm test -- src/client.test.ts`
|
|
331
|
-
- `npm run typecheck`
|
|
332
|
-
|
|
333
|
-
Expected:
|
|
334
|
-
- assignment parsing works
|
|
335
|
-
- expression parsing works
|
|
336
|
-
- selector normalization works
|
|
337
|
-
- client error handling and timeout behavior are covered
|
|
338
|
-
|
|
339
|
-
- [ ] **Step 5: Commit**
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
git add src/client.ts src/client.test.ts src/parsers/expressions.ts src/parsers/expressions.test.ts src/parsers/kv.ts src/parsers/kv.test.ts src/parsers/selectors.ts src/parsers/selectors.test.ts
|
|
343
|
-
git commit -m "feat: add shared rest client and parsers"
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### Task 5: Implement `profiles` and `config` Commands
|
|
347
|
-
|
|
348
|
-
**Files:**
|
|
349
|
-
- Create: `src/commands/profiles.ts`
|
|
350
|
-
- Create: `src/commands/config.ts`
|
|
351
|
-
- Create: `src/commands/profiles.test.ts`
|
|
352
|
-
- Create: `src/commands/config.test.ts`
|
|
353
|
-
- Modify: `src/index.ts`
|
|
354
|
-
- Modify: `src/command-registry.ts`
|
|
355
|
-
|
|
356
|
-
- [ ] **Step 1: Add command tests for profile and config management**
|
|
357
|
-
|
|
358
|
-
```ts
|
|
359
|
-
// src/commands/profiles.test.ts
|
|
360
|
-
import { describe, expect, it } from "vitest";
|
|
361
|
-
|
|
362
|
-
import { buildProgram } from "../index.js";
|
|
363
|
-
|
|
364
|
-
describe("profiles commands", () => {
|
|
365
|
-
it("registers the profiles command group", () => {
|
|
366
|
-
const program = buildProgram();
|
|
367
|
-
expect(program.commands.some((command) => command.name() === "profiles")).toBe(true);
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
- [ ] **Step 2: Run the profiles/config command tests**
|
|
373
|
-
|
|
374
|
-
Run:
|
|
375
|
-
- `npm test -- src/commands/profiles.test.ts`
|
|
376
|
-
- `npm test -- src/commands/config.test.ts`
|
|
377
|
-
|
|
378
|
-
Expected: failure because the command groups are not registered yet
|
|
379
|
-
|
|
380
|
-
- [ ] **Step 3: Implement profile mutation commands and config inspection commands**
|
|
381
|
-
|
|
382
|
-
```ts
|
|
383
|
-
// src/commands/config.ts
|
|
384
|
-
export function registerConfigCommands(program: Command): void {
|
|
385
|
-
program.command("config").description("Inspect CLI configuration");
|
|
386
|
-
}
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
- [ ] **Step 4: Verify command registration and local behavior**
|
|
390
|
-
|
|
391
|
-
Run:
|
|
392
|
-
- `npm test -- src/commands/profiles.test.ts`
|
|
393
|
-
- `npm test -- src/commands/config.test.ts`
|
|
394
|
-
- `npm run typecheck`
|
|
395
|
-
|
|
396
|
-
Expected:
|
|
397
|
-
- both groups are registered
|
|
398
|
-
- read/write commands are tagged in the command registry
|
|
399
|
-
|
|
400
|
-
- [ ] **Step 5: Commit**
|
|
401
|
-
|
|
402
|
-
```bash
|
|
403
|
-
git add src/commands/profiles.ts src/commands/config.ts src/commands/profiles.test.ts src/commands/config.test.ts src/index.ts src/command-registry.ts
|
|
404
|
-
git commit -m "feat: add profiles and config commands"
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Task 6: Implement `schemas` Commands and Schema API Module
|
|
408
|
-
|
|
409
|
-
**Files:**
|
|
410
|
-
- Create: `src/api/schemas.ts`
|
|
411
|
-
- Create: `src/commands/schemas.ts`
|
|
412
|
-
- Create: `src/commands/schemas.test.ts`
|
|
413
|
-
- Modify: `src/index.ts`
|
|
414
|
-
- Modify: `src/command-registry.ts`
|
|
415
|
-
|
|
416
|
-
- [ ] **Step 1: Add schema command tests**
|
|
417
|
-
|
|
418
|
-
```ts
|
|
419
|
-
// src/commands/schemas.test.ts
|
|
420
|
-
import { describe, expect, it } from "vitest";
|
|
421
|
-
|
|
422
|
-
import { normalizeUuidOrSlug } from "../parsers/selectors.js";
|
|
423
|
-
|
|
424
|
-
describe("schema selector parsing", () => {
|
|
425
|
-
it("keeps UUIDs as UUID selectors", () => {
|
|
426
|
-
expect(normalizeUuidOrSlug("550e8400-e29b-41d4-a716-446655440000").kind).toBe("uuid");
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
- [ ] **Step 2: Run the schemas test and capture the current failure**
|
|
432
|
-
|
|
433
|
-
Run: `npm test -- src/commands/schemas.test.ts`
|
|
434
|
-
Expected: failure because schema API and command group do not exist yet
|
|
435
|
-
|
|
436
|
-
- [ ] **Step 3: Implement schema CRUD and field CRUD commands**
|
|
437
|
-
|
|
438
|
-
```ts
|
|
439
|
-
// src/api/schemas.ts
|
|
440
|
-
export async function listSchemas(client: ApiClient) {
|
|
441
|
-
return client.getJson("/api/v2/schemas");
|
|
442
|
-
}
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
- [ ] **Step 4: Verify schema behavior**
|
|
446
|
-
|
|
447
|
-
Run:
|
|
448
|
-
- `npm test -- src/commands/schemas.test.ts`
|
|
449
|
-
- `npm run typecheck`
|
|
450
|
-
|
|
451
|
-
Expected:
|
|
452
|
-
- schema selectors resolve by UUID or slug
|
|
453
|
-
- commands register and map to `/api/v2/schemas` and `/fields`
|
|
454
|
-
|
|
455
|
-
- [ ] **Step 5: Commit**
|
|
456
|
-
|
|
457
|
-
```bash
|
|
458
|
-
git add src/api/schemas.ts src/commands/schemas.ts src/commands/schemas.test.ts src/index.ts src/command-registry.ts
|
|
459
|
-
git commit -m "feat: add schemas command surface"
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### Task 7: Implement `records` and `comments`
|
|
463
|
-
|
|
464
|
-
**Files:**
|
|
465
|
-
- Create: `src/api/records.ts`
|
|
466
|
-
- Create: `src/api/comments.ts`
|
|
467
|
-
- Create: `src/commands/records.ts`
|
|
468
|
-
- Create: `src/commands/comments.ts`
|
|
469
|
-
- Create: `src/commands/records.test.ts`
|
|
470
|
-
- Create: `src/commands/comments.test.ts`
|
|
471
|
-
- Modify: `src/index.ts`
|
|
472
|
-
- Modify: `src/command-registry.ts`
|
|
473
|
-
|
|
474
|
-
- [ ] **Step 1: Add tests for query parsing and record mutation flags**
|
|
475
|
-
|
|
476
|
-
```ts
|
|
477
|
-
// src/commands/records.test.ts
|
|
478
|
-
import { describe, expect, it } from "vitest";
|
|
479
|
-
|
|
480
|
-
import { parseKeyValue } from "../parsers/kv.js";
|
|
481
|
-
|
|
482
|
-
describe("record write flags", () => {
|
|
483
|
-
it("parses --set assignments", () => {
|
|
484
|
-
expect(parseKeyValue("status=active")).toEqual({ key: "status", value: "active" });
|
|
485
|
-
});
|
|
486
|
-
});
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
- [ ] **Step 2: Run records/comments targeted tests**
|
|
490
|
-
|
|
491
|
-
Run:
|
|
492
|
-
- `npm test -- src/commands/records.test.ts`
|
|
493
|
-
- `npm test -- src/commands/comments.test.ts`
|
|
494
|
-
|
|
495
|
-
Expected: failure because records/comments command groups do not exist yet
|
|
496
|
-
|
|
497
|
-
- [ ] **Step 3: Implement list/query/get/create/update/delete records and list/create comments**
|
|
498
|
-
|
|
499
|
-
```ts
|
|
500
|
-
// src/api/records.ts
|
|
501
|
-
export async function queryRecords(client: ApiClient, schemaId: string, body: unknown) {
|
|
502
|
-
return client.requestJson(`/api/v2/schemas/${schemaId}/records:query`, {
|
|
503
|
-
method: "POST",
|
|
504
|
-
body: JSON.stringify(body),
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
- [ ] **Step 4: Verify record and comment behavior**
|
|
510
|
-
|
|
511
|
-
Run:
|
|
512
|
-
- `npm test -- src/commands/records.test.ts`
|
|
513
|
-
- `npm test -- src/commands/comments.test.ts`
|
|
514
|
-
- `npm run typecheck`
|
|
515
|
-
|
|
516
|
-
Expected:
|
|
517
|
-
- `--set`, `--set-json`, and `--unset` map correctly
|
|
518
|
-
- `records list` and `records query` share the same query model
|
|
519
|
-
- comments stay text-first with raw fallback
|
|
520
|
-
|
|
521
|
-
- [ ] **Step 5: Commit**
|
|
522
|
-
|
|
523
|
-
```bash
|
|
524
|
-
git add src/api/records.ts src/api/comments.ts src/commands/records.ts src/commands/comments.ts src/commands/records.test.ts src/commands/comments.test.ts src/index.ts src/command-registry.ts
|
|
525
|
-
git commit -m "feat: add records and comments commands"
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
### Task 8: Implement `files`, `navigation`, and `teamspace`
|
|
529
|
-
|
|
530
|
-
**Files:**
|
|
531
|
-
- Create: `src/api/files.ts`
|
|
532
|
-
- Create: `src/api/navigation.ts`
|
|
533
|
-
- Create: `src/api/teamspace.ts`
|
|
534
|
-
- Create: `src/commands/files.ts`
|
|
535
|
-
- Create: `src/commands/navigation.ts`
|
|
536
|
-
- Create: `src/commands/teamspace.ts`
|
|
537
|
-
- Create: `src/commands/files.test.ts`
|
|
538
|
-
- Create: `src/commands/navigation.test.ts`
|
|
539
|
-
- Create: `src/commands/teamspace.test.ts`
|
|
540
|
-
- Modify: `src/index.ts`
|
|
541
|
-
- Modify: `src/command-registry.ts`
|
|
542
|
-
|
|
543
|
-
- [ ] **Step 1: Add command tests for binary/download rules and folder resolution**
|
|
544
|
-
|
|
545
|
-
```ts
|
|
546
|
-
// src/commands/files.test.ts
|
|
547
|
-
import { describe, expect, it } from "vitest";
|
|
548
|
-
|
|
549
|
-
import { buildJsonError } from "../utils/output.js";
|
|
550
|
-
|
|
551
|
-
describe("files download json mode", () => {
|
|
552
|
-
it("requires --output when --json is used", () => {
|
|
553
|
-
const result = buildJsonError({ reason: "output_required", message: "Use --output with --json." }, {});
|
|
554
|
-
expect(result.error.reason).toBe("output_required");
|
|
555
|
-
});
|
|
556
|
-
});
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
- [ ] **Step 2: Run the targeted tests**
|
|
560
|
-
|
|
561
|
-
Run:
|
|
562
|
-
- `npm test -- src/commands/files.test.ts`
|
|
563
|
-
- `npm test -- src/commands/navigation.test.ts`
|
|
564
|
-
- `npm test -- src/commands/teamspace.test.ts`
|
|
565
|
-
|
|
566
|
-
Expected: failure because these domains are not implemented yet
|
|
567
|
-
|
|
568
|
-
- [ ] **Step 3: Implement file, folder, move, publish, and unpublish commands**
|
|
569
|
-
|
|
570
|
-
```ts
|
|
571
|
-
// src/api/files.ts
|
|
572
|
-
export async function downloadFile(client: ApiClient, fileId: string) {
|
|
573
|
-
return client.requestBinary(`/api/v2/files/${fileId}`, { method: "GET" });
|
|
574
|
-
}
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
- [ ] **Step 4: Verify organization-domain behavior**
|
|
578
|
-
|
|
579
|
-
Run:
|
|
580
|
-
- `npm test -- src/commands/files.test.ts`
|
|
581
|
-
- `npm test -- src/commands/navigation.test.ts`
|
|
582
|
-
- `npm test -- src/commands/teamspace.test.ts`
|
|
583
|
-
- `npm run typecheck`
|
|
584
|
-
|
|
585
|
-
Expected:
|
|
586
|
-
- files support upload/download/delete/storage
|
|
587
|
-
- folder selectors resolve by UUID or exact name with ambiguity failures
|
|
588
|
-
- teamspace/resource verbs map cleanly to publish/unpublish
|
|
589
|
-
|
|
590
|
-
- [ ] **Step 5: Commit**
|
|
591
|
-
|
|
592
|
-
```bash
|
|
593
|
-
git add src/api/files.ts src/api/navigation.ts src/api/teamspace.ts src/commands/files.ts src/commands/navigation.ts src/commands/teamspace.ts src/commands/files.test.ts src/commands/navigation.test.ts src/commands/teamspace.test.ts src/index.ts src/command-registry.ts
|
|
594
|
-
git commit -m "feat: add files navigation and teamspace commands"
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### Task 9: Implement `displays`
|
|
598
|
-
|
|
599
|
-
**Files:**
|
|
600
|
-
- Create: `src/api/displays.ts`
|
|
601
|
-
- Create: `src/commands/displays.ts`
|
|
602
|
-
- Create: `src/commands/displays.test.ts`
|
|
603
|
-
- Modify: `src/index.ts`
|
|
604
|
-
- Modify: `src/command-registry.ts`
|
|
605
|
-
|
|
606
|
-
- [ ] **Step 1: Add tests for widget flag normalization and nested subresource registration**
|
|
607
|
-
|
|
608
|
-
```ts
|
|
609
|
-
// src/commands/displays.test.ts
|
|
610
|
-
import { describe, expect, it } from "vitest";
|
|
611
|
-
|
|
612
|
-
import { buildProgram } from "../index.js";
|
|
613
|
-
|
|
614
|
-
describe("displays command group", () => {
|
|
615
|
-
it("registers widget and variable subresources", () => {
|
|
616
|
-
const program = buildProgram();
|
|
617
|
-
const displays = program.commands.find((command) => command.name() === "displays");
|
|
618
|
-
expect(displays).toBeTruthy();
|
|
619
|
-
});
|
|
620
|
-
});
|
|
621
|
-
```
|
|
622
|
-
|
|
623
|
-
- [ ] **Step 2: Run the displays test**
|
|
624
|
-
|
|
625
|
-
Run: `npm test -- src/commands/displays.test.ts`
|
|
626
|
-
Expected: failure because the displays domain does not exist yet
|
|
627
|
-
|
|
628
|
-
- [ ] **Step 3: Implement display, layout, tabs, variables, widgets, navigation-targets, and cross-widget-filter**
|
|
629
|
-
|
|
630
|
-
```ts
|
|
631
|
-
// src/api/displays.ts
|
|
632
|
-
export async function listDisplays(client: ApiClient) {
|
|
633
|
-
return client.getJson("/api/v2/displays");
|
|
634
|
-
}
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
- [ ] **Step 4: Verify displays behavior**
|
|
638
|
-
|
|
639
|
-
Run:
|
|
640
|
-
- `npm test -- src/commands/displays.test.ts`
|
|
641
|
-
- `npm run typecheck`
|
|
642
|
-
|
|
643
|
-
Expected:
|
|
644
|
-
- widget commands use `--type`
|
|
645
|
-
- `--widget-read-only` does not collide with root `--read-only`
|
|
646
|
-
- complex sections support `--raw` and JSON file helpers
|
|
647
|
-
|
|
648
|
-
- [ ] **Step 5: Commit**
|
|
649
|
-
|
|
650
|
-
```bash
|
|
651
|
-
git add src/api/displays.ts src/commands/displays.ts src/commands/displays.test.ts src/index.ts src/command-registry.ts
|
|
652
|
-
git commit -m "feat: add displays command surface"
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
### Task 10: Implement `automations`
|
|
656
|
-
|
|
657
|
-
**Files:**
|
|
658
|
-
- Create: `src/api/automations.ts`
|
|
659
|
-
- Create: `src/commands/automations.ts`
|
|
660
|
-
- Create: `src/commands/automations.test.ts`
|
|
661
|
-
- Modify: `src/index.ts`
|
|
662
|
-
- Modify: `src/command-registry.ts`
|
|
663
|
-
|
|
664
|
-
- [ ] **Step 1: Add tests for trigger/action polymorphism and flow flag parsing**
|
|
665
|
-
|
|
666
|
-
```ts
|
|
667
|
-
// src/commands/automations.test.ts
|
|
668
|
-
import { describe, expect, it } from "vitest";
|
|
669
|
-
|
|
670
|
-
import { parseKeyValue } from "../parsers/kv.js";
|
|
671
|
-
|
|
672
|
-
describe("automation action args", () => {
|
|
673
|
-
it("parses key=value mappings for action config", () => {
|
|
674
|
-
expect(parseKeyValue("status=active")).toEqual({ key: "status", value: "active" });
|
|
675
|
-
});
|
|
676
|
-
});
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
- [ ] **Step 2: Run the automations test**
|
|
680
|
-
|
|
681
|
-
Run: `npm test -- src/commands/automations.test.ts`
|
|
682
|
-
Expected: failure because the automations domain does not exist yet
|
|
683
|
-
|
|
684
|
-
- [ ] **Step 3: Implement folders, automations, trigger, actions, flow, webhook, plugins, and connections**
|
|
685
|
-
|
|
686
|
-
```ts
|
|
687
|
-
// src/api/automations.ts
|
|
688
|
-
export async function listAutomations(client: ApiClient, query: URLSearchParams) {
|
|
689
|
-
return client.getJson(`/api/v2/automations?${query.toString()}`);
|
|
690
|
-
}
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
- [ ] **Step 4: Verify the automations domain**
|
|
694
|
-
|
|
695
|
-
Run:
|
|
696
|
-
- `npm test -- src/commands/automations.test.ts`
|
|
697
|
-
- `npm run typecheck`
|
|
698
|
-
|
|
699
|
-
Expected:
|
|
700
|
-
- triggers and actions are modeled generically with `--type`
|
|
701
|
-
- flow parsing supports repeated `--entry` and `--transition`
|
|
702
|
-
- connections separate `config` and `secret` semantics
|
|
703
|
-
|
|
704
|
-
- [ ] **Step 5: Commit**
|
|
705
|
-
|
|
706
|
-
```bash
|
|
707
|
-
git add src/api/automations.ts src/commands/automations.ts src/commands/automations.test.ts src/index.ts src/command-registry.ts
|
|
708
|
-
git commit -m "feat: add automations command surface"
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
### Task 11: Add Examples, Help Text, and Agent-Facing Docs
|
|
712
|
-
|
|
713
|
-
**Files:**
|
|
714
|
-
- Modify: `src/commands/config.ts`
|
|
715
|
-
- Modify: `src/commands/profiles.ts`
|
|
716
|
-
- Modify: `src/commands/schemas.ts`
|
|
717
|
-
- Modify: `src/commands/records.ts`
|
|
718
|
-
- Modify: `src/commands/comments.ts`
|
|
719
|
-
- Modify: `src/commands/files.ts`
|
|
720
|
-
- Modify: `src/commands/navigation.ts`
|
|
721
|
-
- Modify: `src/commands/teamspace.ts`
|
|
722
|
-
- Modify: `src/commands/displays.ts`
|
|
723
|
-
- Modify: `src/commands/automations.ts`
|
|
724
|
-
- Create: `README.md`
|
|
725
|
-
- Create: `AGENTS.md`
|
|
726
|
-
- Create: `docs/cli-contract.md`
|
|
727
|
-
|
|
728
|
-
- [ ] **Step 1: Add or adjust example rendering coverage**
|
|
729
|
-
|
|
730
|
-
```ts
|
|
731
|
-
// docs/cli-contract.md
|
|
732
|
-
// Capture the true command contract order:
|
|
733
|
-
// 1. live --help
|
|
734
|
-
// 2. command modules
|
|
735
|
-
// 3. docs
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
- [ ] **Step 2: Run a help/example validation pass**
|
|
739
|
-
|
|
740
|
-
Run:
|
|
741
|
-
- `npm run build`
|
|
742
|
-
- `node dist/index.js --help`
|
|
743
|
-
- `node dist/index.js records query --help`
|
|
744
|
-
- `node dist/index.js records query --example --json`
|
|
745
|
-
|
|
746
|
-
Expected:
|
|
747
|
-
- help is present
|
|
748
|
-
- examples are realistic
|
|
749
|
-
- JSON examples use the standard envelope
|
|
750
|
-
|
|
751
|
-
- [ ] **Step 3: Implement example registration and docs**
|
|
752
|
-
|
|
753
|
-
```ts
|
|
754
|
-
// src/utils/examples.ts
|
|
755
|
-
export interface CommandExample {
|
|
756
|
-
description: string;
|
|
757
|
-
command: string;
|
|
758
|
-
}
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
- [ ] **Step 4: Verify docs/help consistency**
|
|
762
|
-
|
|
763
|
-
Run:
|
|
764
|
-
- `npm run typecheck`
|
|
765
|
-
- `npm test`
|
|
766
|
-
|
|
767
|
-
Expected:
|
|
768
|
-
- all registered commands expose aligned help and examples
|
|
769
|
-
- docs reflect the real command surface
|
|
770
|
-
|
|
771
|
-
- [ ] **Step 5: Commit**
|
|
772
|
-
|
|
773
|
-
```bash
|
|
774
|
-
git add src/commands/*.ts src/utils/examples.ts README.md AGENTS.md docs/cli-contract.md
|
|
775
|
-
git commit -m "docs: add examples help text and agent docs"
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
### Task 12: Final Integration Verification
|
|
779
|
-
|
|
780
|
-
**Files:**
|
|
781
|
-
- Modify: `src/index.ts`
|
|
782
|
-
- Modify: `src/utils/errors.ts`
|
|
783
|
-
- Modify: `src/utils/output.ts`
|
|
784
|
-
- Modify: `src/command-registry.ts`
|
|
785
|
-
- Modify: `src/client.ts`
|
|
786
|
-
|
|
787
|
-
- [ ] **Step 1: Add final verification coverage for root behavior**
|
|
788
|
-
|
|
789
|
-
```ts
|
|
790
|
-
// Verify root behaviors:
|
|
791
|
-
// - read-only blocking
|
|
792
|
-
// - JSON-only stdout
|
|
793
|
-
// - exit code mapping
|
|
794
|
-
// - binary command JSON constraints
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
- [ ] **Step 2: Run the full verification suite**
|
|
798
|
-
|
|
799
|
-
Run:
|
|
800
|
-
- `npm run build`
|
|
801
|
-
- `npm run typecheck`
|
|
802
|
-
- `npm test`
|
|
803
|
-
|
|
804
|
-
Expected:
|
|
805
|
-
- all tests pass
|
|
806
|
-
- build succeeds
|
|
807
|
-
- typecheck succeeds
|
|
808
|
-
|
|
809
|
-
- [ ] **Step 3: Exercise representative commands locally**
|
|
810
|
-
|
|
811
|
-
Run:
|
|
812
|
-
- `node dist/index.js profiles list --json`
|
|
813
|
-
- `node dist/index.js schemas list --json --read-only`
|
|
814
|
-
- `node dist/index.js files storage --json`
|
|
815
|
-
|
|
816
|
-
Expected:
|
|
817
|
-
- stable JSON envelope
|
|
818
|
-
- read-only respected
|
|
819
|
-
- no stray stdout text in JSON mode
|
|
820
|
-
|
|
821
|
-
- [ ] **Step 4: Fix any final root-contract regressions**
|
|
822
|
-
|
|
823
|
-
Run:
|
|
824
|
-
- `npm run build`
|
|
825
|
-
- `npm run typecheck`
|
|
826
|
-
- `npm test`
|
|
827
|
-
|
|
828
|
-
Expected:
|
|
829
|
-
- green final verification
|
|
830
|
-
|
|
831
|
-
- [ ] **Step 5: Commit**
|
|
832
|
-
|
|
833
|
-
```bash
|
|
834
|
-
git add src/index.ts src/utils/errors.ts src/utils/output.ts src/command-registry.ts src/client.ts
|
|
835
|
-
git commit -m "test: finalize root contract verification"
|
|
836
|
-
```
|
|
837
|
-
|