pm-csv 2026.6.2 → 2026.6.4

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/CHANGELOG.md CHANGED
@@ -1,6 +1,34 @@
1
1
  # Changelog
2
2
 
3
- ## 2026.6.2 - 2026-06-02
3
+ ## 2026.6.4 - 2026-06-04
4
+
5
+ ### Other
6
+
7
+ - Import row-filtering \(--status/--type/--priority\) and custom-field export discovery \(--all-fields\) ([pm-csv-dk6h](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-dk6h.toon))
8
+
9
+ ## 2026.06.02-1 - 2026-06-02
10
+
11
+ ### Added
12
+
13
+ - Deepen SDK surface: relational columns, validate, encoding, excel, csv\_source schema field ([pm-csv-aoox](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/features/pm-csv-aoox.toon))
14
+ - New command: pm csv validate <file\> ([pm-csv-rq5q](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-rq5q.toon))
15
+
16
+ ### Fixed
17
+
18
+ - Fix --key dedup duplication \(pm tag case-folding\) ([pm-csv-bvz5](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-bvz5.toon))
19
+
20
+ ### Other
21
+
22
+ - validate exit-code policy ([pm-csv-yhp9](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/decisions/pm-csv-yhp9.toon))
23
+ - csv\_source persisted as tag, not scalar field ([pm-csv-vp1u](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/decisions/pm-csv-vp1u.toon))
24
+ - Which extra pm fields to round-trip ([pm-csv-ry94](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/decisions/pm-csv-ry94.toon))
25
+ - Unit tests + functional test with real data ([pm-csv-z5f5](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-z5f5.toon))
26
+ - Register csv\_source schema field \(schema capability\) ([pm-csv-w1k3](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-w1k3.toon))
27
+ - Export --excel \(CRLF + UTF-8 BOM\) ([pm-csv-vxz6](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-vxz6.toon))
28
+ - Import --encoding \(utf-8/utf16le/latin1\) ([pm-csv-z3lo](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-z3lo.toon))
29
+ - Round-trip parent/assignee/sprint/release/blocked\_by columns ([pm-csv-6kyh](https://github.com/unbraind/pm-csv/blob/main/.agents/pm/tasks/pm-csv-6kyh.toon))
30
+
31
+ ## 2026.06.02 - 2026-06-02
4
32
 
5
33
  ### Added
6
34
 
package/README.md CHANGED
@@ -29,6 +29,11 @@ Read a CSV file and create or update pm items.
29
29
  ```
30
30
  pm csv import tasks.csv
31
31
  pm csv import backlog.csv --delimiter ';'
32
+ pm csv import data.tsv --delimiter tab
33
+ pm csv import jira.csv --map 'Summary=title,Owner=assignee'
34
+ pm csv import items.csv --key title # idempotent re-import (no duplicates)
35
+ pm csv import legacy.csv --encoding latin1 # non-UTF-8 source
36
+ pm csv import sprint12.csv --source 'jira-export-2026-06'
32
37
  pm csv import items.csv --dry-run
33
38
  ```
34
39
 
@@ -36,12 +41,60 @@ pm csv import items.csv --dry-run
36
41
 
37
42
  | Flag | Type | Default | Description |
38
43
  |---|---|---|---|
39
- | `--delimiter <char>` | string | `,` | CSV field delimiter |
44
+ | `--delimiter <char>` | string | `,` | Field delimiter, or alias `tab` / `comma` / `semicolon` / `pipe` |
45
+ | `--map <col=field>` | string | — | Remap a CSV header to a pm field (repeatable, comma-joined), e.g. `--map 'Summary=title'` |
46
+ | `--key <field>` | string | — | Dedup key column: a re-import **updates** the matching item instead of creating a duplicate |
47
+ | `--encoding <enc>` | string | `utf-8` | Source file encoding: `utf-8` \| `utf16le` \| `latin1` |
48
+ | `--source <label>` | string | — | Record an import-provenance label in the `csv_source` field of created/updated items |
49
+ | `--status <filter>` | string | — | Import **only** rows whose (normalized) status matches; non-matching rows are skipped |
50
+ | `--type <type>` | string | — | Import **only** rows whose type matches (case-insensitive) |
51
+ | `--priority <n>` | integer | — | Import **only** rows whose integer priority equals this value |
40
52
  | `--dry-run` | boolean | false | Preview what would be imported without writing any data |
41
53
 
54
+ #### Row filtering on import
55
+
56
+ `--status`, `--type` and `--priority` filter the CSV rows **before** any items
57
+ are created — non-matching rows are skipped, never written. They mirror the
58
+ `csv export` filter semantics exactly (status is normalized through the same
59
+ alias table, so `--status open` matches a row whose status cell is `todo`).
60
+ Multiple criteria are ANDed. The result reports how many rows were filtered out:
61
+
62
+ ```
63
+ pm csv import tasks.csv --status open # import open rows only
64
+ pm csv import tasks.csv --type Feature --priority 1 # AND: Feature *and* priority 1
65
+ # → Imported 1, updated 0, skipped 5 (5 filtered out).
66
+ ```
67
+
42
68
  **Required column:** `title`
43
69
 
44
- **Optional columns:** `type`, `status`, `priority`, `tags`, `milestone`, `due_date`, `body`
70
+ **Optional columns:** `type`, `status`, `priority`, `tags`, `deadline`, `body`, `parent`, `assignee`, `sprint`, `release`, `blocked_by`
71
+
72
+ ---
73
+
74
+ ### `pm csv validate <file>`
75
+
76
+ Parse a CSV and report data-quality issues **without importing**. Exits non-zero
77
+ (usage error) when there is a structural problem (no `title` column after `--map`
78
+ or an empty file); otherwise exits `0` even when it reports row-level warnings.
79
+
80
+ ```
81
+ pm csv validate tasks.csv
82
+ pm csv validate jira.csv --map 'Summary=title'
83
+ pm csv validate data.tsv --delimiter tab --json
84
+ ```
85
+
86
+ The report includes: row count, detected columns, mapped columns (after `--map`),
87
+ whether the required `title` column is present, and counts of rows missing a
88
+ title, rows with an unrecognized status, and rows with a non-integer priority.
89
+
90
+ **Flags**
91
+
92
+ | Flag | Type | Default | Description |
93
+ |---|---|---|---|
94
+ | `--delimiter <char>` | string | `,` | Field delimiter, or alias `tab` / `comma` / `semicolon` / `pipe` |
95
+ | `--map <col=field>` | string | — | Remap a CSV header to a pm field before validating |
96
+ | `--encoding <enc>` | string | `utf-8` | Source file encoding: `utf-8` \| `utf16le` \| `latin1` |
97
+ | `--json` | boolean | false | Emit the report as JSON |
45
98
 
46
99
  ---
47
100
 
@@ -53,8 +106,9 @@ Export all pm items (or a filtered subset) to CSV. Without `--output` the CSV is
53
106
  pm csv export
54
107
  pm csv export --output items.csv
55
108
  pm csv export --output backlog.csv --delimiter ';'
56
- pm csv export --status todo --output todos.csv
109
+ pm csv export --status open --output todos.csv
57
110
  pm csv export --type Feature --output features.csv
111
+ pm csv export --excel --output for-excel.csv
58
112
  ```
59
113
 
60
114
  **Flags**
@@ -62,12 +116,36 @@ pm csv export --type Feature --output features.csv
62
116
  | Flag | Type | Default | Description |
63
117
  |---|---|---|---|
64
118
  | `--output <file>` | string | — | Write CSV to this file path instead of returning it |
65
- | `--delimiter <char>` | string | `,` | CSV field delimiter |
66
- | `--status <status>` | string | — | Filter: `todo`, `wip`, `done`, `blocked` |
119
+ | `--delimiter <char>` | string | `,` | Field delimiter, or alias `tab` / `comma` / `semicolon` / `pipe` |
120
+ | `--status <status>` | string | — | Filter: `open` \| `in_progress` \| `blocked` \| `closed` \| `canceled` \| `draft` |
67
121
  | `--type <type>` | string | — | Filter by item type |
122
+ | `--columns <list>` | string | all | Comma-separated columns to export, in order (custom fields selectable when `--all-fields` is set) |
123
+ | `--all-fields` | boolean | false | Discover custom item fields registered in the workspace schema and append them as columns |
124
+ | `--discover-fields` | boolean | false | Alias for `--all-fields` |
125
+ | `--no-header` | boolean | false | Omit the CSV header row |
126
+ | `--crlf` | boolean | false | Use CRLF line endings (RFC-4180 / Excel) |
127
+ | `--excel` | boolean | false | Excel-friendly output: CRLF line endings **and** a UTF-8 BOM prefix |
68
128
 
69
129
  **Export columns (fixed order):**
70
- `id, title, type, status, priority, tags, milestone, due_date, body, created_at, updated_at`
130
+ `id, title, type, status, priority, tags, deadline, body, parent, assignee, sprint, release, blocked_by, csv_source, created_at, updated_at`
131
+
132
+ #### Custom-field discovery (`--all-fields`)
133
+
134
+ By default only the built-in columns above are exported. `--all-fields` (alias
135
+ `--discover-fields`) discovers any **custom item fields** registered in the
136
+ workspace runtime schema and appends them as extra columns — the default column
137
+ set is otherwise unchanged, so the flag is strictly additive.
138
+
139
+ Discovery reads the same inputs the SDK's `resolveRuntimeFieldRegistry` consumes
140
+ (the workspace `settings.json` `schema.fields` plus the file it points at via
141
+ `schema.files.fields`, default `schema/fields.json`). A standalone-installed
142
+ extension only loads its own `dist/`, so the SDK function isn't importable at
143
+ runtime; reading its inputs directly is the runtime-safe equivalent.
144
+
145
+ ```bash
146
+ pm csv export --all-fields --output full.csv
147
+ # header gains your custom columns, e.g. …,updated_at,story_points,team
148
+ ```
71
149
 
72
150
  ---
73
151
 
@@ -94,7 +172,11 @@ Register the importer in your pm-cli config to automatically pull from a CSV fil
94
172
  | Key | Type | Required | Description |
95
173
  |---|---|---|---|
96
174
  | `file` | string | yes | Path to the CSV file to import |
97
- | `delimiter` | string | no (default `,`) | CSV field delimiter |
175
+ | `delimiter` | string | no (default `,`) | CSV field delimiter (or alias `tab`/`comma`/`semicolon`/`pipe`) |
176
+ | `map` | string | no | Header remap, e.g. `Summary=title` |
177
+ | `key` | string | no | Dedup key column for idempotent re-import |
178
+ | `encoding` | string | no (default `utf-8`) | `utf-8` \| `utf16le` \| `latin1` |
179
+ | `source` | string | no | Provenance label recorded in `csv_source` |
98
180
 
99
181
  ---
100
182
 
@@ -105,10 +187,10 @@ Register the importer in your pm-cli config to automatically pull from a CSV fil
105
187
  The first row must be a header row. Column names are **case-insensitive**. Column order does not matter. Only `title` is required.
106
188
 
107
189
  ```csv
108
- title,type,status,priority,tags,milestone,due_date,body
109
- "Add login page",Feature,open,2,"auth,ui",v1.0,2026-05-30,"Landing page with email+password login"
110
- "Fix navbar bug",Issue,in_progress,1,"bug,ui",,,"Navbar collapses on mobile Safari"
111
- "Write API docs",Task,todo,3,docs,,,
190
+ title,type,status,priority,tags,deadline,body,parent,assignee,sprint,release,blocked_by
191
+ "Add login page",Feature,open,2,"auth,ui",2026-05-30,"Landing page with email+password login",,alice,Sprint-12,v1.0,
192
+ "Fix navbar bug",Issue,in_progress,1,"bug,ui",,"Navbar collapses on mobile Safari",,bob,Sprint-12,v1.0,
193
+ "Write API docs",Task,open,3,docs,,,,,Sprint-13,v1.1,Fix navbar bug
112
194
  ```
113
195
 
114
196
  ### Column reference
@@ -116,13 +198,19 @@ title,type,status,priority,tags,milestone,due_date,body
116
198
  | Column | Description | Notes |
117
199
  |---|---|---|
118
200
  | `title` | Item title | **Required** |
119
- | `type` | Item type | Any string, e.g. `Feature`, `Bug`, `Task` |
201
+ | `type` | Item type | Any string, e.g. `Feature`, `Issue`, `Task` |
120
202
  | `status` | Item status | See status mapping below |
121
203
  | `priority` | Numeric priority | Integer |
122
204
  | `tags` | Comma-separated tags | Quote the field if tags contain commas |
123
- | `milestone` | Milestone name | Any string |
124
- | `due_date` | Due date | ISO 8601 format recommended, e.g. `2026-05-30` |
205
+ | `deadline` | Deadline | ISO 8601, e.g. `2026-05-30` (legacy `due_date` header accepted) |
125
206
  | `body` | Description / body text | Supports multiline when quoted |
207
+ | `parent` | Parent item id | Maps to `pm create --parent` |
208
+ | `assignee` | Assignee | Maps to `pm create --assignee` |
209
+ | `sprint` | Sprint identifier | Maps to `pm create --sprint` |
210
+ | `release` | Release identifier | Maps to `pm create --release` |
211
+ | `blocked_by` | Blocked-by item id or reason | Maps to `pm create --blocked-by` (legacy `blocked-by` header accepted) |
212
+
213
+ All columns except `title` are optional. Round-tripping (`export` then `import --key`) is lossless for these fields.
126
214
 
127
215
  ### Status mapping
128
216
 
@@ -130,24 +218,50 @@ The importer accepts common status strings and maps them to pm-cli statuses:
130
218
 
131
219
  | Input values | pm-cli status |
132
220
  |---|---|
133
- | `todo`, `open`, `new` | `todo` |
134
- | `done`, `closed`, `complete`, `completed` | `done` |
135
- | `wip`, `in_progress`, `in progress`, `doing` | `wip` |
221
+ | `open`, `todo`, `new` | `open` |
222
+ | `in_progress`, `wip`, `in progress`, `doing` | `in_progress` |
136
223
  | `blocked`, `on_hold`, `on hold` | `blocked` |
224
+ | `closed`, `done`, `complete`, `completed` | `closed` |
225
+ | `canceled`, `cancelled` | `canceled` |
226
+ | `draft` | `draft` |
137
227
 
138
- Unrecognized values default to `todo`.
228
+ Unrecognized values default to `open`.
139
229
 
140
230
  ### Export format
141
231
 
142
- Exports use the same CSV format and can be re-imported:
232
+ Exports use the same CSV format and can be re-imported. An extra read-only
233
+ `csv_source` column surfaces the import-provenance label (see `--source`); it is
234
+ ignored on import.
143
235
 
144
236
  ```csv
145
- id,title,type,status,priority,tags,milestone,due_date,body,created_at,updated_at
146
- item-abc123,Add login page,Feature,todo,2,"auth,ui",v1.0,2026-05-30,Landing page with email+password login,2026-05-01T10:00:00Z,2026-05-09T12:00:00Z
237
+ id,title,type,status,priority,tags,deadline,body,parent,assignee,sprint,release,blocked_by,csv_source,created_at,updated_at
238
+ pm-abc123,Add login page,Feature,open,2,"auth,ui",2026-05-30,Landing page,,alice,Sprint-12,v1.0,,jira-export,2026-05-01T10:00:00Z,2026-05-09T12:00:00Z
147
239
  ```
148
240
 
149
241
  ---
150
242
 
243
+ ## Idempotent re-import (`--key`)
244
+
245
+ `--key <field>` makes re-imports update existing items instead of creating
246
+ duplicates. The first import tags each created item with an internal
247
+ `csv-key:<value>` provenance tag; a later import keyed on the same column finds
248
+ and updates the matching item. Key matching is case-insensitive (pm folds tag
249
+ case on storage). The internal `csv-key:` and `csv-source:` tags are stripped
250
+ from exports so round-trips stay clean.
251
+
252
+ ## Provenance & the `csv_source` schema field (`--source`)
253
+
254
+ The extension registers an optional `csv_source` schema item field (via the
255
+ `schema` capability). When you import with `--source <label>`, the label is
256
+ recorded on each created/updated item and is surfaced back in the `csv_source`
257
+ export column. Note: as of pm 2026.5.31 the CLI does not expose a scalar setter
258
+ for extension-registered fields, so the value is persisted as an internal
259
+ `csv-source:<label>` tag (stripped from the normal `tags` export column). On
260
+ hosts whose SDK lacks `registerItemFields`, schema registration degrades to a
261
+ no-op without breaking any other behavior.
262
+
263
+ ---
264
+
151
265
  ## CSV parsing rules
152
266
 
153
267
  - Fields containing the delimiter, double-quotes, or newlines must be wrapped in double-quotes.
@@ -178,7 +292,7 @@ pm csv export --columns id,title,status --output todos.csv
178
292
  pm csv-export export --columns title,priority # native export pipeline
179
293
  ```
180
294
 
181
- Valid columns: id, title, type, status, priority, tags, deadline, body, created_at, updated_at.
295
+ Valid columns: id, title, type, status, priority, tags, deadline, body, parent, assignee, sprint, release, blocked_by, csv_source, created_at, updated_at.
182
296
 
183
297
  ## License
184
298
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,196 @@
1
+ type ItemStatus = "open" | "in_progress" | "blocked" | "closed" | "canceled" | "draft";
2
+ interface PmItem {
3
+ id: string;
4
+ title: string;
5
+ body?: string;
6
+ status: ItemStatus;
7
+ priority?: number;
8
+ type?: string;
9
+ tags?: string[];
10
+ created_at?: string;
11
+ updated_at?: string;
12
+ deadline?: string;
13
+ parent?: string;
14
+ assignee?: string;
15
+ sprint?: string;
16
+ release?: string;
17
+ blocked_by?: string;
18
+ /** Derived on export from the csv-source: provenance tag (not a stored field). */
19
+ csv_source?: string;
20
+ }
21
+ declare const IMPORT_COLUMNS: readonly ["title", "type", "status", "priority", "tags", "deadline", "body", "parent", "assignee", "sprint", "release", "blocked_by"];
22
+ declare const EXPORT_COLUMNS: Array<keyof PmItem>;
23
+ /** Supported file encodings for `--encoding` on import. */
24
+ declare const SUPPORTED_ENCODINGS: readonly ["utf-8", "utf8", "utf16le", "latin1"];
25
+ type SupportedEncoding = (typeof SUPPORTED_ENCODINGS)[number];
26
+ /**
27
+ * Parse a full CSV string into rows of string arrays.
28
+ * Handles:
29
+ * - Quoted fields (double-quotes), including embedded newlines inside quotes
30
+ * - Escaped quotes ("" inside a quoted field → single ")
31
+ * - Custom delimiter
32
+ * - CRLF and LF line endings
33
+ */
34
+ declare function parseCSV(text: string, delimiter?: string): string[][];
35
+ /**
36
+ * Strip a leading UTF-8 BOM (U+FEFF) if present. Files exported by Excel and
37
+ * many Windows tools start with a BOM; without removing it the first header
38
+ * name silently becomes "title" and the required-column check fails.
39
+ */
40
+ declare function stripBOM(text: string): string;
41
+ /**
42
+ * Serialize a single field value for CSV output.
43
+ * Wraps in double-quotes when the value contains the delimiter, quotes, or newlines.
44
+ */
45
+ declare function serializeField(value: string, delimiter: string): string;
46
+ interface SerializeOptions {
47
+ delimiter: string;
48
+ /** Line terminator. RFC-4180 mandates CRLF; we default to LF for unix-friendliness. */
49
+ eol?: "\n" | "\r\n";
50
+ }
51
+ /**
52
+ * Serialize a full array of rows into a CSV string.
53
+ */
54
+ declare function serializeCSV(rows: string[][], delimiterOrOpts: string | SerializeOptions): string;
55
+ /**
56
+ * Resolve a user-supplied delimiter, accepting friendly aliases so TSV is easy:
57
+ * --delimiter tab --delimiter "\t" --delimiter ";"
58
+ * A literal backslash-t is interpreted as a tab.
59
+ */
60
+ declare function resolveDelimiter(raw: string | undefined): string;
61
+ /**
62
+ * Normalize a dedup key value for stable matching. pm lower-cases tags on
63
+ * storage, so a `csv-key:` tag written from "Fix Bug" comes back as
64
+ * "fix bug"; we therefore fold the key to lower-case on BOTH write and lookup
65
+ * so re-imports match (and thus update) instead of duplicating.
66
+ */
67
+ declare function normalizeKeyValue(value: string): string;
68
+ declare function encodeKeyTagValue(value: string): string;
69
+ declare function decodeKeyTagValue(value: string): string;
70
+ /**
71
+ * Parse a `--map csvHeader=field` spec (repeatable / comma-joined) into a
72
+ * lookup from a normalized CSV header name to the canonical pm field name.
73
+ * Example: `--map "Summary=title,Owner=tags"`.
74
+ */
75
+ declare function parseFieldMap(spec: string | string[] | undefined): Record<string, string>;
76
+ /**
77
+ * Apply a field map to a list of header names, producing the effective
78
+ * (canonical) header used for column lookup.
79
+ */
80
+ declare function applyFieldMap(headers: string[], fieldMap: Record<string, string>): string[];
81
+ /**
82
+ * Map an arbitrary status string (from the CSV) to a valid SDK status.
83
+ * Falls back to "open".
84
+ */
85
+ declare function normalizeStatus(raw: string): ItemStatus;
86
+ /**
87
+ * Parse a comma-separated tags string into an array, stripping whitespace.
88
+ */
89
+ declare function parseTags(raw: string): string[];
90
+ /**
91
+ * Stringify a tags array back to a semicolon-free comma-separated string
92
+ * (safe to embed in a single CSV field).
93
+ */
94
+ declare function stringifyTags(tags: string[] | undefined): string;
95
+ /**
96
+ * Validate and normalize a user-supplied `--encoding` value to a Node-supported
97
+ * BufferEncoding. Accepts utf-8/utf8, utf16le, latin1. Throws USAGE otherwise.
98
+ */
99
+ declare function resolveEncoding(raw: string | undefined): SupportedEncoding;
100
+ /**
101
+ * Row-level import filter. Mirrors the `csv export` filter semantics exactly:
102
+ * - `status` matches the row's *normalized* SDK status (so `done` matches
103
+ * `--status closed`, just like export filters on the stored status).
104
+ * - `type` matches the row's raw `type` value case-insensitively.
105
+ * - `priority` matches the row's parsed integer priority.
106
+ * Any unset criterion is a wildcard. Rows that fail are skipped (not imported)
107
+ * and counted in the result's `skipped` total.
108
+ */
109
+ interface ImportRowFilter {
110
+ status?: ItemStatus;
111
+ type?: string;
112
+ priority?: number;
113
+ }
114
+ interface ParsedRow {
115
+ title: string;
116
+ status: ItemStatus;
117
+ priority?: number;
118
+ tags: string[];
119
+ type?: string;
120
+ deadline?: string;
121
+ body?: string;
122
+ parent?: string;
123
+ assignee?: string;
124
+ sprint?: string;
125
+ release?: string;
126
+ blocked_by?: string;
127
+ }
128
+ /**
129
+ * Parse the `--status`/`--type`/`--priority` import filter flags into a
130
+ * normalized {@link ImportRowFilter}. Mirrors export filter semantics:
131
+ * - status is normalized through {@link normalizeStatus} so the same alias
132
+ * vocabulary as a CSV `status` cell applies (e.g. `--status done` matches
133
+ * rows whose status normalizes to `closed`).
134
+ * - priority must be an integer; a non-integer is a USAGE error.
135
+ * - type is matched case-insensitively (lower-cased here and at compare time).
136
+ * Returns `undefined` when no filter flag is set (the common no-filter path).
137
+ */
138
+ declare function parseImportFilter(statusRaw: string | undefined, typeRaw: string | undefined, priorityRaw: string | undefined): ImportRowFilter | undefined;
139
+ /**
140
+ * Pure predicate: does a parsed row satisfy every set filter criterion?
141
+ * Unset criteria are wildcards. Exposed for unit testing.
142
+ */
143
+ declare function rowMatchesFilter(row: ParsedRow, filter: ImportRowFilter | undefined): boolean;
144
+ interface CsvValidateReport {
145
+ ok: boolean;
146
+ rowCount: number;
147
+ detectedColumns: string[];
148
+ mappedColumns: string[];
149
+ hasTitleColumn: boolean;
150
+ rowsMissingTitle: number;
151
+ rowsWithUnknownStatus: number;
152
+ rowsWithNonIntegerPriority: number;
153
+ issues: string[];
154
+ }
155
+ /**
156
+ * Core validation logic over already-parsed headers + rows. Pure and
157
+ * side-effect-free so it can be unit tested directly.
158
+ */
159
+ declare function validateParsedCSV(rawHeaders: string[], dataRows: string[][], fieldMap: Record<string, string>): CsvValidateReport;
160
+ /**
161
+ * A custom (workspace-registered) item field discovered from the runtime
162
+ * schema. `key` is the human-facing column name; `metadataKey` is the property
163
+ * name the value is stored under on the item JSON (usually identical).
164
+ */
165
+ interface DiscoveredField {
166
+ key: string;
167
+ metadataKey: string;
168
+ }
169
+ /**
170
+ * Discover custom item fields registered in the workspace runtime schema and
171
+ * return those that are NOT already covered by the built-in export columns
172
+ * (or the provenance `csv_source` column).
173
+ *
174
+ * This is the standalone-extension-safe equivalent of the SDK's
175
+ * `resolveRuntimeFieldRegistry(settings.schema)`: a standalone-installed
176
+ * extension only loads its own `dist/`, so `@unbrained/pm-cli` is not
177
+ * resolvable at runtime and the SDK function cannot be imported. We instead
178
+ * read the very same inputs that function consumes — the workspace
179
+ * `settings.json` `schema.fields` plus the file it points at
180
+ * (`schema.files.fields`, default `schema/fields.json`) — and merge them by
181
+ * field key. The shape matches the SDK `RuntimeFieldDefinition` type.
182
+ *
183
+ * Never throws: any read/parse problem yields an empty list so export still
184
+ * works on hosts without a runtime field schema.
185
+ */
186
+ declare function discoverCustomFields(pmRoot: string): DiscoveredField[];
187
+ declare function selectExportColumns(spec: string | undefined, extraValid?: ReadonlyArray<string>): string[];
1
188
  declare const _default: {
2
189
  name: string;
3
190
  version: string;
4
191
  activate(api: import("@unbrained/pm-cli/sdk").ExtensionApi): void;
5
192
  };
6
193
  export default _default;
194
+ export { parseCSV, serializeCSV, serializeField, stripBOM, resolveDelimiter, parseFieldMap, applyFieldMap, normalizeStatus, parseTags, stringifyTags, encodeKeyTagValue, decodeKeyTagValue, normalizeKeyValue, selectExportColumns, resolveEncoding, validateParsedCSV, parseImportFilter, rowMatchesFilter, discoverCustomFields, EXPORT_COLUMNS, IMPORT_COLUMNS, };
195
+ export type { ParsedRow, ImportRowFilter, DiscoveredField };
7
196
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;AA8UA,wBA4SG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}