monday-cli 0.5.0 → 0.7.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +665 -0
  2. package/README.md +209 -35
  3. package/dist/api/column-types.d.ts +81 -19
  4. package/dist/api/column-types.d.ts.map +1 -1
  5. package/dist/api/column-types.js +44 -11
  6. package/dist/api/column-types.js.map +1 -1
  7. package/dist/api/column-values.d.ts +22 -10
  8. package/dist/api/column-values.d.ts.map +1 -1
  9. package/dist/api/column-values.js +50 -20
  10. package/dist/api/column-values.js.map +1 -1
  11. package/dist/api/file-column-set.d.ts +613 -0
  12. package/dist/api/file-column-set.d.ts.map +1 -0
  13. package/dist/api/file-column-set.js +568 -0
  14. package/dist/api/file-column-set.js.map +1 -0
  15. package/dist/api/raw-write.d.ts +38 -17
  16. package/dist/api/raw-write.d.ts.map +1 -1
  17. package/dist/api/raw-write.js +62 -25
  18. package/dist/api/raw-write.js.map +1 -1
  19. package/dist/api/resolver-error-fold.d.ts +25 -0
  20. package/dist/api/resolver-error-fold.d.ts.map +1 -1
  21. package/dist/api/resolver-error-fold.js +56 -0
  22. package/dist/api/resolver-error-fold.js.map +1 -1
  23. package/dist/commands/board/column-create.d.ts +13 -3
  24. package/dist/commands/board/column-create.d.ts.map +1 -1
  25. package/dist/commands/board/column-create.js +27 -8
  26. package/dist/commands/board/column-create.js.map +1 -1
  27. package/dist/commands/item/create.d.ts +24 -8
  28. package/dist/commands/item/create.d.ts.map +1 -1
  29. package/dist/commands/item/create.js +601 -44
  30. package/dist/commands/item/create.js.map +1 -1
  31. package/dist/commands/item/set.d.ts +33 -3
  32. package/dist/commands/item/set.d.ts.map +1 -1
  33. package/dist/commands/item/set.js +193 -15
  34. package/dist/commands/item/set.js.map +1 -1
  35. package/dist/commands/item/update.d.ts +203 -3
  36. package/dist/commands/item/update.d.ts.map +1 -1
  37. package/dist/commands/item/update.js +1015 -68
  38. package/dist/commands/item/update.js.map +1 -1
  39. package/dist/commands/item/upload.d.ts.map +1 -1
  40. package/dist/commands/item/upload.js +16 -69
  41. package/dist/commands/item/upload.js.map +1 -1
  42. package/dist/commands/update/upload.d.ts.map +1 -1
  43. package/dist/commands/update/upload.js +9 -59
  44. package/dist/commands/update/upload.js.map +1 -1
  45. package/dist/utils/file-source.d.ts +93 -0
  46. package/dist/utils/file-source.d.ts.map +1 -0
  47. package/dist/utils/file-source.js +140 -0
  48. package/dist/utils/file-source.js.map +1 -0
  49. package/package.json +1 -1
@@ -0,0 +1,613 @@
1
+ /**
2
+ * Files-shaped friendly `--set` dispatch (`cli-design.md` §5.3
3
+ * writer-expansion roadmap "files" row + §13 v0.6 entry,
4
+ * `v0.6-plan.md` §3 M38).
5
+ *
6
+ * **Status: runtime bodies shipped at v0.6-M38 IMPL.** The dispatch
7
+ * type signatures + the per-mutex-rejection error shape + the
8
+ * fetcher wrapping M31's `addFileToColumn` all landed at pre-flight;
9
+ * IMPL swaps the c8-ignored stub bodies for runtime logic. No new
10
+ * wire fetcher (M38 reuses the v0.4-M31 multipart wire verbatim);
11
+ * no new transport seam.
12
+ *
13
+ * **Wire surface.** Zero net change. When `monday item set <iid>
14
+ * <file-col>=<path>` OR `monday item update <iid> --set
15
+ * <file-col>=<path>` resolves to a `file`-typed column, the
16
+ * command action body branches OFF the standard JSON-translator
17
+ * path INTO M31's multipart `addFileToColumn` fetcher via
18
+ * `executeFileColumnSet` below. The translator
19
+ * (`translateColumnValueAsync` in `column-values.ts`) stays
20
+ * JSON-output-shaped for the 13 existing writable types — the
21
+ * file-column dispatch is a SIBLING leg routed at the command
22
+ * action body level, NOT a new payload format inside the
23
+ * translator union.
24
+ *
25
+ * **Why a sibling leg, not a translator widening.** Three reasons
26
+ * pin the design (cli-design §5.3 step 4 + step 5 prose):
27
+ *
28
+ * 1. The wire surface is fundamentally different — multipart
29
+ * `add_file_to_column` vs JSON `change_column_value` /
30
+ * `change_multiple_column_values`. Folding the file payload
31
+ * into `ColumnValuePayload` would require a `format: 'file'`
32
+ * union variant that `selectMutation` can't bundle into the
33
+ * multi-mutation (each `add_file_to_column` is a single
34
+ * per-column multipart round-trip; bundling N file uploads
35
+ * into one mutation isn't a Monday wire shape).
36
+ * 2. The atomicity contract differs — the 13 existing types
37
+ * bundle atomically via `change_multiple_column_values` when
38
+ * ≥2 columns target the same item. File-column writes are
39
+ * single-column-per-call only on Monday's wire; mixing a
40
+ * file-column `--set` with any value `--set` / `--set-raw` /
41
+ * `--name` in the same call would force a multi-leg dispatch
42
+ * that breaks the existing atomicity guarantee. M38 enforces
43
+ * single-file-only via the mutex rules below (D2 closure) —
44
+ * the existing atomicity contract stays intact.
45
+ * 3. The translator's input contract is "value-string-to-JSON-
46
+ * payload" — file columns take a file path, not a value
47
+ * string. Path validation + `fs.stat` + `fs.access(R_OK)` +
48
+ * Blob construction don't fit the translator's pure-function
49
+ * shape; routing the path through the sibling leg keeps each
50
+ * helper focused.
51
+ *
52
+ * **Reuse from v0.4-M31.** The wire dispatch reuses
53
+ * `addFileToColumn` from `src/api/assets.ts` verbatim — same
54
+ * `MultipartTransport.request(...)` round-trip, same `withRetry`
55
+ * shape, same `file_too_large` rewrap-inside-retry-thunk pattern
56
+ * (R-v0.4-W2 axis 7 "non-retryable rewrap placement" carries
57
+ * through safely-by-construction since the dispatch goes through
58
+ * the existing fetcher rather than a re-implementation).
59
+ *
60
+ * **Consumer counts post v0.6-M38 IMPL close** (runtime bodies
61
+ * shipped at `e749931` + the R-v0.6-NEW-1 lift at `3c2a9b0`;
62
+ * pre-flight stubs collapsed):
63
+ *
64
+ * - `addFileToColumn` (M31): 2 consumers (M31's `item upload`
65
+ * action body + M38's `executeFileColumnSet` runtime body).
66
+ * - `MultipartTransport` via `ResolvedClient.multipart`: 2
67
+ * consumers (the same test seam pattern; M31's two upload
68
+ * verbs + M38's dispatch share the slot).
69
+ * - `sniffContentType` from `src/utils/mime.ts`: 2 consumers
70
+ * post-lift (M31's `item upload` + M31's `update upload` —
71
+ * both via {@link buildBlobFromPath}; M38 routes through
72
+ * `buildBlobFromPath` rather than calling `sniffContentType`
73
+ * directly).
74
+ * - **R-v0.6-NEW-1 SHIPPED at IMPL kickoff**: the file-pre-check
75
+ * + Blob-construction pattern lifted to `src/utils/file-source
76
+ * .ts` (`precheckLocalFile` + `buildBlobFromPath` — 3 consumers
77
+ * post-lift: M31's `item upload`, M31's `update upload`, M38's
78
+ * `executeFileColumnSet`).
79
+ *
80
+ * **Mutex rules (D2 closure).** Enforced at the column-resolution
81
+ * boundary (parse-time can't know — column types only resolve
82
+ * after metadata loads). When any resolved column has `type ===
83
+ * 'file'`:
84
+ *
85
+ * - Exactly ONE file `--set` entry allowed per call (single-
86
+ * file scope; multi-file dispatch defers to v0.7.x — Monday's
87
+ * `add_file_to_column` is single-column per call on the wire
88
+ * regardless of how many items the dispatch fans out across,
89
+ * so this rule is universal).
90
+ * - NO other value `--set` / `--set-raw` / `--name` flags
91
+ * allowed (mixing would force non-atomic multi-leg dispatch
92
+ * across the multipart + JSON wire surfaces).
93
+ * - Bulk `item update --where ... --set <file-col>=<path>` —
94
+ * **CARVED OUT at v0.7-M42** (D5 fold). At v0.6-M38 this was
95
+ * REJECTED with `'file_set_on_bulk_unsupported'`; v0.7-M42's
96
+ * pre-flight contract diff returns
97
+ * `{ kind: 'file_bulk', columnId, rawValue }` from
98
+ * {@link enforceSingleFileColumnSet} on the clean dispatch
99
+ * path so the action body can branch into the per-item
100
+ * multipart fan-out. Multi-file / mixed mutex rules STILL
101
+ * apply on bulk (those are universal).
102
+ * - `item create --set <file-col>=<path>` — **CARVED OUT at
103
+ * v0.7-M43** (D6 fold). At v0.6-M38 this was REJECTED with
104
+ * `'file_set_on_create_unsupported'`; v0.7-M43's pre-flight
105
+ * contract diff returns
106
+ * `{ kind: 'file_create', columnId, rawValue }` from
107
+ * {@link enforceSingleFileColumnSet} on the clean dispatch
108
+ * path so the action body can branch into the two-leg
109
+ * dispatch (`create_item` then `add_file_to_column`).
110
+ * Multi-file mutex rule STILL applies on create (universal).
111
+ * The mixed rule is callShape-aware: on `'item_create'` the
112
+ * `--name` arm + non-file value `--set` / `--set-raw` arms
113
+ * are SUPPRESSED (leg-1 `create_item` natively bundles
114
+ * `column_values` atomically + `item_name` is required on
115
+ * create); the D3 `--set-raw <file-col>=<json>` rejection
116
+ * at `raw-write.ts:translateRawColumnValue` stays in force
117
+ * (separate enforcement layer).
118
+ *
119
+ * Rejection surfaces share the `usage_error.details.reason`
120
+ * discriminator pattern from M14 / M27 / M31:
121
+ *
122
+ * - `'mixed_file_and_value_sets'` — file `--set` + any value
123
+ * `--set` / `--set-raw` / `--name` in same call. Applies on
124
+ * single-item AND bulk call shapes (universal mutex rule).
125
+ * - `'multi_file_set_unsupported'` — 2+ file `--set` entries
126
+ * in same call. Applies on single-item AND bulk call shapes
127
+ * (universal mutex rule).
128
+ * - `'file_set_on_bulk_unsupported'` — **NO LONGER SURFACES**
129
+ * at v0.7-M42 onwards. Historical reference only; the
130
+ * discriminator literal stays reserved across the codebase
131
+ * (do not reuse for a different rejection reason).
132
+ * - `'file_set_on_create_unsupported'` — **NO LONGER SURFACES**
133
+ * at v0.7-M43 onwards. Historical reference only; the
134
+ * discriminator literal stays reserved across the codebase
135
+ * (do not reuse for a different rejection reason).
136
+ *
137
+ * **D3 closure — `--set-raw <file-col>=<json>` STAYS REJECTED.**
138
+ * Files have no JSON wire shape Monday's `change_column_value`
139
+ * accepts; the escape-hatch contract "user supplies the JSON
140
+ * `change_column_value` accepts" doesn't compose with the
141
+ * multipart wire. The existing rejection at
142
+ * `raw-write.ts:translateRawColumnValue` stays unchanged; the
143
+ * prose enumerates every shipped friendly write path (v0.6-M38
144
+ * single-item, v0.7-M42 bulk, v0.7-M43 create-time, v0.4-M31
145
+ * verb-shaped upload) so agents reading the `--set-raw`
146
+ * rejection see the full set of working alternatives rather
147
+ * than just the M38 single-item form.
148
+ *
149
+ * **D7 closure — `<path>='-'` stdin support OUT OF SCOPE.**
150
+ * Mirrors M31 `monday item upload`'s rejection rationale — no
151
+ * clean `--filename` companion shape pinned for `--set
152
+ * <file-col>=-` syntax (stdin reads byte-anonymously; the
153
+ * filename is the load-bearing handle for Monday's wire
154
+ * `Asset.name` slot). Carry-forward candidate for v0.7.x once a
155
+ * `--filename` companion shape is pinned.
156
+ *
157
+ * **No new ERROR_CODE (D8 closure; registry stays at 29).** All
158
+ * M38-specific rejections route through existing `usage_error`
159
+ * with `details.reason` discrimination.
160
+ *
161
+ * **R-NEW-41 4th supporting site filed at M38 pre-flight.** The
162
+ * `--set` syntax is type-uniform from the agent's view
163
+ * (`<col>=<value>`), but for file columns the value is a path
164
+ * and the dispatch transitions silently from JSON to multipart at
165
+ * the translator boundary. The asymmetry is at the AGENT-INPUT
166
+ * boundary, NOT at the wire boundary (M31's multipart-vs-JSON
167
+ * asymmetry #3 is wire-boundary-only). See `docs/architecture.md`
168
+ * "Wire-vs-CLI semantics documentation conventions" for the
169
+ * canonical cross-link.
170
+ */
171
+ import { z } from 'zod';
172
+ import { type Asset } from './assets.js';
173
+ import { type ResolverWarning } from './columns.js';
174
+ import type { Complexity } from '../utils/output/envelope.js';
175
+ import type { MondayClient } from './client.js';
176
+ import type { MultipartTransport } from './multipart-transport.js';
177
+ /**
178
+ * Post-resolution entry shape for a file-column `--set <col>=<path>`
179
+ * dispatch leg. Produced by the action body's column-resolution +
180
+ * file-pre-check pipeline; consumed by {@link executeFileColumnSet}.
181
+ *
182
+ * The `columnId` slot carries the RESOLVED Monday column ID (not
183
+ * the argv token); the `rawValue` slot preserves the argv-derived
184
+ * path (preserved for dry-run envelope echo per D4 — mirrors M31
185
+ * `item upload`'s `parsed.file` argv-derived shape per the round-2
186
+ * P3-2 fix).
187
+ *
188
+ * `filename` is `basename(filePath)` — the load-bearing handle for
189
+ * Monday's wire `Asset.name` slot.
190
+ *
191
+ * `fileSizeBytes` is the local `fs.stat()` measurement captured at
192
+ * pre-check time. Echoed in the dry-run envelope + threaded into
193
+ * the `file_too_large` rewrap's `details.file_size_bytes` slot on
194
+ * Monday's server-side size-cap rejection (mirrors M31's pattern).
195
+ */
196
+ export interface FileColumnSetEntry {
197
+ /** Resolved Monday column ID (post-`resolveColumnWithRefresh`). */
198
+ readonly columnId: string;
199
+ /** Resolved column type — narrowed to the files-shaped literal. */
200
+ readonly columnType: 'file';
201
+ /** The argv-derived path token (relative or absolute as the agent typed it). */
202
+ readonly rawValue: string;
203
+ /** Resolved absolute path (post `path.resolve(process.cwd(), rawValue)`). */
204
+ readonly filePath: string;
205
+ /** `basename(filePath)` — Monday's wire `Asset.name` source. */
206
+ readonly filename: string;
207
+ /** Local `fs.stat()` size at pre-check time. */
208
+ readonly fileSizeBytes: number;
209
+ }
210
+ /**
211
+ * Output envelope shape for the file-column `--set` dispatch leg.
212
+ * Mirrors `itemUploadOutputSchema` from `src/api/assets.ts` so the
213
+ * envelope shape is byte-equivalent to M31 `monday item upload` for
214
+ * an agent reading the result — the dispatch source differs
215
+ * (`monday item set` / `monday item update` vs `monday item upload`)
216
+ * but the envelope payload structure is identical.
217
+ *
218
+ * The `operation` slot pins `'add_file_to_column'` literally
219
+ * (mirroring M31's envelope discriminator); agents reading
220
+ * `data.operation` can branch uniformly on the wire mutation
221
+ * regardless of which CLI verb routed there.
222
+ */
223
+ export declare const fileColumnSetOutputSchema: z.ZodObject<{
224
+ operation: z.ZodLiteral<"add_file_to_column">;
225
+ item_id: z.ZodString;
226
+ column_id: z.ZodString;
227
+ filename: z.ZodString;
228
+ file_size_bytes: z.ZodNumber;
229
+ asset: z.ZodObject<{
230
+ id: z.ZodString;
231
+ name: z.ZodString;
232
+ url: z.ZodString;
233
+ public_url: z.ZodString;
234
+ file_extension: z.ZodString;
235
+ file_size: z.ZodNumber;
236
+ created_at: z.ZodNullable<z.ZodString>;
237
+ uploaded_by: z.ZodObject<{
238
+ id: z.ZodString;
239
+ name: z.ZodString;
240
+ }, z.core.$strict>;
241
+ original_geometry: z.ZodNullable<z.ZodString>;
242
+ url_thumbnail: z.ZodNullable<z.ZodString>;
243
+ }, z.core.$strict>;
244
+ }, z.core.$strict>;
245
+ export type FileColumnSetOutput = z.infer<typeof fileColumnSetOutputSchema>;
246
+ /**
247
+ * Inputs for the M38 file-column dispatch fetcher. Wraps M31's
248
+ * `addFileToColumn` (`src/api/assets.ts`) verbatim — no new wire
249
+ * mutation, no new transport seam.
250
+ *
251
+ * The runtime body (below in this module) reads:
252
+ *
253
+ * 1. Construct a `Blob` from the local file at
254
+ * `inputs.entry.filePath` via {@link buildBlobFromPath} (read
255
+ * bytes via `fs/promises.readFile` + sniff content-type from
256
+ * filename); the caller already ran {@link precheckLocalFile}
257
+ * so the path is known good + size known non-zero.
258
+ * 2. Call `addFileToColumn({client, multipart, itemId, columnId,
259
+ * file, filename, signal, retries})` — M31's fetcher already
260
+ * wraps the multipart dispatch in `withRetry(...)` + handles
261
+ * the file_too_large rewrap-inside-retry-thunk pattern.
262
+ * 3. Project the result into {@link FileColumnSetOutput} shape
263
+ * with the `operation: 'add_file_to_column'` literal +
264
+ * agent-supplied slots (item_id, column_id, filename,
265
+ * file_size_bytes) — emitted by the action body after this
266
+ * fetcher returns.
267
+ */
268
+ export interface ExecuteFileColumnSetInputs {
269
+ readonly client: MondayClient;
270
+ readonly multipart: MultipartTransport;
271
+ readonly itemId: string;
272
+ readonly entry: FileColumnSetEntry;
273
+ /** Combined runner signal — same threading as M31's `addFileToColumn`. */
274
+ readonly signal: AbortSignal;
275
+ /** Retry budget — threaded into `withRetry(...)` at IMPL via M31's fetcher. */
276
+ readonly retries: number;
277
+ }
278
+ /**
279
+ * Result of the M38 file-column dispatch fetcher. Mirrors M31's
280
+ * `AddFileToColumnResult` shape — the dispatch is a thin wrapper
281
+ * around M31's existing fetcher so the result projection stays
282
+ * identical.
283
+ */
284
+ export interface ExecuteFileColumnSetResult {
285
+ readonly asset: Asset;
286
+ readonly source: 'live';
287
+ readonly cacheAgeSeconds: null;
288
+ readonly complexity: Complexity | null;
289
+ }
290
+ /**
291
+ * Reads the local file at `inputs.entry.filePath`, constructs a Blob
292
+ * via {@link buildBlobFromPath} (with `Content-Type` sniffed from the
293
+ * filename), and dispatches the multipart upload through M31's
294
+ * {@link addFileToColumn} fetcher (cli-design §5.3 step 5 + the
295
+ * module docstring above pin the load-bearing design).
296
+ *
297
+ * **Status: runtime body shipped at v0.6-M38 IMPL.** Wraps M31's
298
+ * fetcher verbatim — same `operationName: 'AddFileToColumn'`, same
299
+ * `withRetry(...)` retry semantics, same rewrap-inside-retry-thunk
300
+ * pattern for `file_too_large` (R-v0.4-W2 axis 7 carries through
301
+ * safely-by-construction since the dispatch goes through the
302
+ * existing fetcher rather than a re-implementation).
303
+ *
304
+ * The action-body caller (in `item set` / `item update`) is
305
+ * responsible for:
306
+ *
307
+ * 1. Parsing argv + collecting `--set` / `--set-raw` / `--name`
308
+ * entries.
309
+ * 2. Resolving columns via `resolveColumnWithRefresh`.
310
+ * 3. Calling {@link enforceSingleFileColumnSet} to detect the
311
+ * file-column dispatch leg + enforce the mutex rules.
312
+ * 4. Running {@link precheckLocalFile} from
313
+ * `src/utils/file-source.ts` on the agent-supplied path to
314
+ * build a {@link FileColumnSetEntry} (the precheck surfaces
315
+ * `usage_error.details.reason: 'file_not_readable'` /
316
+ * `'file_empty'` before any wire activity per the M31
317
+ * ordering invariant).
318
+ * 5. Calling this fetcher for the wire dispatch.
319
+ * 6. Emitting the envelope per `fileColumnSetOutputSchema`
320
+ * (mirrors M31 `item upload` envelope verbatim).
321
+ */
322
+ export declare const executeFileColumnSet: (inputs: ExecuteFileColumnSetInputs) => Promise<ExecuteFileColumnSetResult>;
323
+ /**
324
+ * Mutex enforcement at the column-resolution boundary. Takes the
325
+ * resolved column-type information for every `--set` / `--set-raw`
326
+ * entry + the `--name` presence flag + the call shape (single-item
327
+ * vs bulk vs create), and either:
328
+ *
329
+ * - Returns `{ kind: 'json' }` when NO file-column entries are
330
+ * present in `setEntries` — the standard JSON translator path
331
+ * applies and the action body proceeds unchanged.
332
+ * - Returns `{ kind: 'file', columnId, rawValue }` when a clean
333
+ * file-column dispatch path applies on a single-item non-
334
+ * create call (exactly one file `--set`, no other value
335
+ * flags). The caller runs {@link buildBlobFromPath} via
336
+ * {@link precheckLocalFile} from `src/utils/file-source.ts`
337
+ * to build a {@link FileColumnSetEntry} + invokes
338
+ * {@link executeFileColumnSet}.
339
+ * - Returns `{ kind: 'file_bulk', columnId, rawValue }` when a
340
+ * clean bulk file-column dispatch path applies (v0.7-M42 D5
341
+ * carve-out fold). Action body branches into the per-item
342
+ * multipart fan-out helper.
343
+ * - Returns `{ kind: 'file_create', columnId, rawValue }` when a
344
+ * clean create-time file-column dispatch path applies
345
+ * (v0.7-M43 D6 carve-out fold). Action body branches into the
346
+ * two-leg `create_item` then `add_file_to_column` dispatch
347
+ * helper.
348
+ * - Throws `ApiError('usage_error', ...)` with a
349
+ * `details.reason` discriminator when a mutex violation is
350
+ * detected: `'multi_file_set_unsupported'` (D2 multi-file leg
351
+ * — universal; applies on single + bulk + create) OR
352
+ * `'mixed_file_and_value_sets'` (D2 mixed leg — universal on
353
+ * non-create callShapes; SUPPRESSED on `'item_create'` per
354
+ * the D6 mixed-rule asymmetry since `create_item` natively
355
+ * bundles `column_values` atomically + `item_name` is
356
+ * required on create).
357
+ *
358
+ * Both `'file_set_on_bulk_unsupported'` (v0.6-M38 D5) and
359
+ * `'file_set_on_create_unsupported'` (v0.6-M38 D6) literals NO
360
+ * LONGER SURFACE from this function as of v0.7-M42 / v0.7-M43
361
+ * respectively — the carve-out folds return
362
+ * `kind: 'file_bulk'` / `kind: 'file_create'` on clean dispatch
363
+ * paths instead. The literals stay RESERVED in docstrings as
364
+ * historical reference; do not re-introduce as runtime rejections
365
+ * without fresh contract decisions.
366
+ *
367
+ * Pure synchronous check — no I/O, no side effects. The caller
368
+ * resolves columns first (via `resolveColumnWithRefresh` or the
369
+ * existing `resolveAndTranslate` helper's resolution leg) and
370
+ * passes the resolved column types here.
371
+ *
372
+ * **Status: runtime body shipped at v0.6-M38 IMPL; extended at
373
+ * v0.7-M42 pre-flight contract diff for the D5 carve-out fold.**
374
+ * Per R-NEW-76 graduated discipline, callers invoke `parseArgv`
375
+ * BEFORE this function so argv-level failures surface as
376
+ * `usage_error` from the parse boundary (this function itself
377
+ * runs AFTER argv parse + column resolution).
378
+ */
379
+ export type FileColumnSetEnforcementResult = {
380
+ readonly kind: 'json';
381
+ } | {
382
+ readonly kind: 'file';
383
+ readonly columnId: string;
384
+ readonly rawValue: string;
385
+ } | {
386
+ readonly kind: 'file_bulk';
387
+ readonly columnId: string;
388
+ readonly rawValue: string;
389
+ } | {
390
+ readonly kind: 'file_create';
391
+ readonly columnId: string;
392
+ readonly rawValue: string;
393
+ };
394
+ export interface EnforceSingleFileColumnSetInputs {
395
+ /**
396
+ * The call shape — determines which mutex rejections apply.
397
+ *
398
+ * - `'item_set'` — single-column `monday item set`. Only the
399
+ * single positional `<col>=<value>` is in play; the rejection
400
+ * surface is limited to the file-vs-set-raw mutex (`--set-raw
401
+ * <file-col>=<json>` stays rejected by `raw-write.ts:
402
+ * translateRawColumnValue` per D3 — no new mutex needed here).
403
+ * - `'item_update_single'` — single-item `monday item update
404
+ * <iid>`. Multiple `--set` + `--set-raw` + `--name` flags are
405
+ * accepted; M38 mutex enforces "single file `--set` + no
406
+ * other value flags".
407
+ * - `'item_update_bulk'` — `monday item update --where ...`.
408
+ * At v0.6-M38 this rejected with `'file_set_on_bulk_unsupported'`;
409
+ * v0.7-M42 carves out the D5 closure — clean single-file
410
+ * bulk-file dispatch returns `kind: 'file_bulk'` for the
411
+ * action body's per-item multipart fan-out. Multi-file +
412
+ * mixed gates STILL reject (those mutex rules are
413
+ * universal — file column dispatch is single-column per
414
+ * wire call regardless of how many items the fan-out
415
+ * spans).
416
+ * - `'item_create'` — `monday item create`. At v0.6-M38 this
417
+ * rejected with `'file_set_on_create_unsupported'`;
418
+ * v0.7-M43 carves out the D6 closure — clean single-file
419
+ * create-time dispatch returns `kind: 'file_create'` for the
420
+ * action body's two-leg `create_item` then
421
+ * `add_file_to_column` helper. Multi-file gate STILL rejects
422
+ * (universal). Mixed-rule SUPPRESSED on create per D6
423
+ * asymmetry (`create_item` natively bundles non-file
424
+ * `column_values` atomically + `--name` is required on
425
+ * create). `--set-raw <file-col>=<json>` stays rejected at
426
+ * `raw-write.ts:translateRawColumnValue` per D3 (separate
427
+ * enforcement layer).
428
+ */
429
+ readonly callShape: 'item_set' | 'item_update_single' | 'item_update_bulk' | 'item_create';
430
+ /**
431
+ * Resolved column entries — one per `--set` token, in argv order.
432
+ * Each carries the resolved column ID + type discriminator + the
433
+ * agent-supplied raw value (path or value-string).
434
+ */
435
+ readonly setEntries: readonly {
436
+ readonly columnId: string;
437
+ readonly columnType: string;
438
+ readonly rawValue: string;
439
+ }[];
440
+ /**
441
+ * Resolved `--set-raw` entries — one per `--set-raw` token, in
442
+ * argv order. Carries the resolved column ID + type (after
443
+ * `resolveColumnWithRefresh`). Used for the mutex check ONLY —
444
+ * the actual `--set-raw` rejection for file types stays in
445
+ * `raw-write.ts:translateRawColumnValue` per D3.
446
+ */
447
+ readonly setRawEntries: readonly {
448
+ readonly columnId: string;
449
+ readonly columnType: string;
450
+ }[];
451
+ /** True when `--name <n>` was passed (`item update` only). */
452
+ readonly hasName: boolean;
453
+ }
454
+ /**
455
+ * Iterates `inputs.setEntries`, identifies entries with
456
+ * `columnType === 'file'`, applies the mutex rules per D2 / D5 / D6
457
+ * closures, and returns either `{ kind: 'json' }` (no file entries),
458
+ * `{ kind: 'file', columnId, rawValue }` (clean dispatch path), or
459
+ * throws `ApiError('usage_error', ...)` on a mutex violation.
460
+ *
461
+ * Mutex priority (ratified at M38 pre-flight; updated at v0.7-M42
462
+ * + v0.7-M43 pre-flights to fold the D5 bulk + D6 create carve-outs):
463
+ *
464
+ * 1. **callShape gate — NONE remaining post-v0.7-M43** — both
465
+ * `'item_update_bulk'` (D5 fold at v0.7-M42) and `'item_create'`
466
+ * (D6 fold at v0.7-M43) short-circuit-throws have been removed.
467
+ * Every callShape falls through to the universal multi-file
468
+ * gate + a callShape-aware mixed gate, then returns a per-
469
+ * callShape `kind` on the clean path.
470
+ * 2. **multi-file leg** — 2+ file `--set` entries (any callShape)
471
+ * surface `'multi_file_set_unsupported'`. Universal rule:
472
+ * Monday's `add_file_to_column` is single-column per call on
473
+ * the wire regardless of fan-out shape.
474
+ * 3. **mixed leg** — 1 file `--set` + any value `--set` /
475
+ * `--set-raw` / `--name` surfaces `'mixed_file_and_value_sets'`
476
+ * on `'item_set'` / `'item_update_single'` / `'item_update_bulk'`.
477
+ * Universal rule on those callShapes: mixing forces non-atomic
478
+ * multi-leg dispatch across the multipart + JSON wire surfaces.
479
+ * **SUPPRESSED on `'item_create'`** per v0.7-M43 D6 mixed-rule
480
+ * asymmetry — `create_item` natively bundles non-file
481
+ * `column_values` atomically into leg-1, and `--name` is
482
+ * required on create.
483
+ * 4. **clean leg** — 1 file `--set`, no mutex violation:
484
+ * - `'item_update_single'` / `'item_set'` → return
485
+ * `{ kind: 'file', columnId, rawValue }` for downstream
486
+ * {@link precheckLocalFile} + {@link executeFileColumnSet}
487
+ * (M38 path; unchanged).
488
+ * - `'item_update_bulk'` → return `{ kind: 'file_bulk',
489
+ * columnId, rawValue }` for the action body's per-item
490
+ * multipart fan-out (v0.7-M42 D5 carve-out fold).
491
+ * - `'item_create'` → return `{ kind: 'file_create', columnId,
492
+ * rawValue }` for the action body's two-leg `create_item`
493
+ * then `add_file_to_column` helper (v0.7-M43 D6 carve-out
494
+ * fold).
495
+ *
496
+ * The function is sync + pure. No I/O. Path validation lives at a
497
+ * SEPARATE step (`precheckLocalFile` from `src/utils/file-source.ts`)
498
+ * that the caller runs AFTER this function returns a `kind: 'file'`
499
+ * result.
500
+ */
501
+ export declare const enforceSingleFileColumnSet: (inputs: EnforceSingleFileColumnSetInputs) => FileColumnSetEnforcementResult;
502
+ /**
503
+ * Argv-level setEntry shape (`<token>=<value>` split, pre-resolution).
504
+ * Used as input to {@link preCheckM38FileDispatch}.
505
+ */
506
+ export interface ArgvSetEntry {
507
+ readonly token: string;
508
+ readonly value: string;
509
+ }
510
+ /**
511
+ * Result of {@link preCheckM38FileDispatch}. On the `'json'` branch
512
+ * the action body proceeds with the standard `resolveAndTranslate` /
513
+ * `planChanges` path (cache is warm from this pre-check). On the
514
+ * `'file'` branch the action body runs {@link precheckLocalFile} +
515
+ * {@link executeFileColumnSet} for the live path, or emits the D4
516
+ * dry-run envelope.
517
+ *
518
+ * `warnings` + `source` + `cacheAgeSeconds` aggregate the
519
+ * resolveColumnWithRefresh legs the pre-check fired; callers thread
520
+ * these into the downstream success envelope (json branch into the
521
+ * standard path's existing aggregation seeds; file branch into the
522
+ * file-dispatch envelope's `warnings` + `meta.source` slots).
523
+ */
524
+ export type PreCheckM38FileDispatchResult = {
525
+ readonly kind: 'json';
526
+ readonly warnings: readonly ResolverWarning[];
527
+ readonly source: 'live' | 'cache' | 'mixed' | undefined;
528
+ readonly cacheAgeSeconds: number | null;
529
+ } | {
530
+ readonly kind: 'file';
531
+ readonly columnId: string;
532
+ readonly rawValue: string;
533
+ readonly token: string;
534
+ readonly warnings: readonly ResolverWarning[];
535
+ readonly source: 'live' | 'cache' | 'mixed' | undefined;
536
+ readonly cacheAgeSeconds: number | null;
537
+ } | {
538
+ readonly kind: 'file_bulk';
539
+ readonly columnId: string;
540
+ readonly rawValue: string;
541
+ readonly token: string;
542
+ readonly warnings: readonly ResolverWarning[];
543
+ readonly source: 'live' | 'cache' | 'mixed' | undefined;
544
+ readonly cacheAgeSeconds: number | null;
545
+ } | {
546
+ readonly kind: 'file_create';
547
+ readonly columnId: string;
548
+ readonly rawValue: string;
549
+ readonly token: string;
550
+ readonly warnings: readonly ResolverWarning[];
551
+ readonly source: 'live' | 'cache' | 'mixed' | undefined;
552
+ readonly cacheAgeSeconds: number | null;
553
+ };
554
+ export interface PreCheckM38FileDispatchInputs {
555
+ readonly client: MondayClient;
556
+ readonly boardId: string;
557
+ readonly setEntries: readonly ArgvSetEntry[];
558
+ /**
559
+ * Count of `--set-raw` entries the call carries. Only the count
560
+ * matters for the mutex check ("file --set + ANY --set-raw"); the
561
+ * setRawEntries' column types do NOT need pre-resolution here.
562
+ * `--set-raw <file-col>=<json>` rejection stays at
563
+ * `translateRawColumnValue` per D3 (permanent rejection); the
564
+ * pre-check never routes a `--set-raw` path through M38 dispatch.
565
+ */
566
+ readonly setRawCount: number;
567
+ readonly hasName: boolean;
568
+ readonly callShape: 'item_update_single' | 'item_update_bulk' | 'item_create';
569
+ readonly env?: NodeJS.ProcessEnv;
570
+ readonly noCache?: boolean;
571
+ }
572
+ /**
573
+ * Resolves `setEntries` column types and runs the v0.6-M38 mutex
574
+ * check (per cli-design §5.3 step 5 "File-column dispatch leg —
575
+ * mutex rules"). The discipline: **enforce mutex at the column-
576
+ * resolution boundary**, not at the translator-rejection boundary.
577
+ * Pre-flight P2-1 + IMPL round-1 P2-2 both surfaced the
578
+ * translator-order-dependent priority drift that this resolution-
579
+ * boundary check fixes.
580
+ *
581
+ * **Why the pre-check fires at the action-body level rather than
582
+ * inside `resolveAndTranslate`.** The shared resolver helper is
583
+ * used by 5 sites (item set, item update single + bulk, item
584
+ * create); the M38 dispatch only applies to 3 (item update single
585
+ * + bulk + item create — item set has its own column resolution at
586
+ * the action body level for the single-positional shape). Folding
587
+ * M38 dispatch into `resolveAndTranslate` would couple the
588
+ * resolver helper to the file-dispatch leg; the action-body level
589
+ * pre-check keeps `resolveAndTranslate` translator-only.
590
+ *
591
+ * **Discriminating friendly `--set` vs `--set-raw`** — the
592
+ * pre-check operates on setEntries only. `--set-raw <file-col>=<json>`
593
+ * rejections come from `translateRawColumnValue` (D3 permanent
594
+ * rejection); the pre-check returns `kind: 'json'` for `--set-raw`
595
+ * file paths and the standard path's `resolveAndTranslate` /
596
+ * `planChanges` then surfaces the D3 `unsupported_column_type`
597
+ * rejection. The pre-check NEVER hijacks `--set-raw` paths into
598
+ * M38 dispatch.
599
+ *
600
+ * **Source aggregation contract.** Each resolveColumnWithRefresh
601
+ * call returns its own `source` / `cacheAgeSeconds`; the pre-check
602
+ * aggregates across `setEntries`. On the `'json'` branch the
603
+ * downstream `resolveAndTranslate` will re-resolve setEntries
604
+ * (cache hit) and produce another aggregation leg — the action
605
+ * body merges both aggregations so the final envelope reflects
606
+ * every wire / cache leg that fired. The `meta.source` of a
607
+ * non-file path with a single `--set` may surface as `'mixed'`
608
+ * (live pre-check + cache downstream) rather than `'live'`; this
609
+ * is correct per §6.1 source-aggregation rules — the second leg
610
+ * IS a cache hit.
611
+ */
612
+ export declare const preCheckM38FileDispatch: (inputs: PreCheckM38FileDispatchInputs) => Promise<PreCheckM38FileDispatchResult>;
613
+ //# sourceMappingURL=file-column-set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-column-set.d.ts","sourceRoot":"","sources":["../../src/api/file-column-set.ts"],"names":[],"mappings":"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"}