@fairmint/captable-ai 0.1.4 → 0.1.6

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +631 -68
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -88,7 +88,7 @@ automated, but a few habits make extraction faster and more accurate:
88
88
  | `documents upload\|list\|download\|delete` | Manage source documents |
89
89
  | `documents trigger-extraction\|cancel-extraction\|restart-extraction\|reprocess` | Control the OCF extraction pipeline |
90
90
  | `documents processing-status\|classification-types\|classification-update` | Inspect document status / classification |
91
- | `objects list\|get\|update\|patch\|revert\|versions\|delete` | Work with extracted OCF objects |
91
+ | `objects list\|get\|dump\|update\|patch\|revert\|versions\|delete` | Work with extracted OCF objects (`list` supports `--document`, `--stakeholder`, `--all`, `--max-confidence`; `dump` writes engine-shaped `ocf.json`) |
92
92
  | `schemas list\|get` | Browse the OCF object-type registry |
93
93
  | `commit` | Commit drafts to the cap table — `--all` or `--objects id1,id2` (`--dry-run` to preview) |
94
94
  | `summary` | Full cap table snapshot |
package/dist/index.js CHANGED
@@ -543,7 +543,7 @@ var COMMAND_REGISTRY = [
543
543
  name: "objects list",
544
544
  group: "captable",
545
545
  description: "List OCF objects with filtering and pagination.",
546
- usage: "captable-ai objects list [--type TYPE] [--subtype SUBTYPE] [--status STATUS] [--limit N] [--cursor C] [--q QUERY] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--ids IDS] [--json]",
546
+ usage: "captable-ai objects list [--type TYPE] [--subtype SUBTYPE] [--status STATUS] [--limit N] [--cursor C] [--q QUERY] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--ids IDS] [--stakeholder ID] [--document ID] [--all] [--max-confidence N] [--json]",
547
547
  requiresAuth: true,
548
548
  requiresPortal: true,
549
549
  flags: [
@@ -576,7 +576,27 @@ var COMMAND_REGISTRY = [
576
576
  description: "Filter objects with date <= (YYYY-MM-DD, inclusive).",
577
577
  type: "string"
578
578
  },
579
- { name: "ids", description: "Batch fetch by comma-separated IDs.", type: "string" }
579
+ { name: "ids", description: "Batch fetch by comma-separated IDs.", type: "string" },
580
+ {
581
+ name: "stakeholder",
582
+ description: "Filter by OCF stakeholder id.",
583
+ type: "string"
584
+ },
585
+ {
586
+ name: "document",
587
+ description: "Filter by source document s3 asset id.",
588
+ type: "string"
589
+ },
590
+ {
591
+ name: "all",
592
+ description: "Follow pagination cursors until every matching object is returned.",
593
+ type: "boolean"
594
+ },
595
+ {
596
+ name: "max-confidence",
597
+ description: "Keep objects with extraction confidence <= N. Requires --all.",
598
+ type: "number"
599
+ }
580
600
  ]
581
601
  },
582
602
  {
@@ -587,6 +607,27 @@ var COMMAND_REGISTRY = [
587
607
  requiresAuth: true,
588
608
  requiresPortal: true
589
609
  },
610
+ {
611
+ name: "objects dump",
612
+ group: "captable",
613
+ description: "Write engine-shaped ocf.json from object ocf payloads.",
614
+ usage: "captable-ai objects dump [--status committed|draft] [--output path]",
615
+ requiresAuth: true,
616
+ requiresPortal: true,
617
+ flags: [
618
+ {
619
+ name: "status",
620
+ description: "Filter by status: draft or committed. Default committed.",
621
+ type: "string",
622
+ enum: ["draft", "committed"]
623
+ },
624
+ {
625
+ name: "output",
626
+ description: "Write JSON to this file (global --output; implies --json).",
627
+ type: "string"
628
+ }
629
+ ]
630
+ },
590
631
  {
591
632
  name: "schemas list",
592
633
  group: "captable",
@@ -1127,7 +1168,7 @@ var COMMAND_REGISTRY = [
1127
1168
  }
1128
1169
  ];
1129
1170
  async function runCommands(_args) {
1130
- printJson({ schemaVersion: "6", version: "0.0.1", commands: COMMAND_REGISTRY });
1171
+ printJson({ schemaVersion: "8", version: "0.0.1", commands: COMMAND_REGISTRY });
1131
1172
  }
1132
1173
 
1133
1174
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -16023,6 +16064,235 @@ var exportResultSchema = external_exports.object({
16023
16064
  }).optional().describe("Present when pro-forma sheets were requested but engine refused.")
16024
16065
  });
16025
16066
 
16067
+ // ../captable-ai-core/dist/objects-dump.js
16068
+ var DumpAssemblyError = class extends Error {
16069
+ constructor(message) {
16070
+ super(message);
16071
+ this.name = "DumpAssemblyError";
16072
+ }
16073
+ };
16074
+ var ISSUANCE_TYPES = /* @__PURE__ */ new Set([
16075
+ "TX_STOCK_ISSUANCE",
16076
+ "TX_CONVERTIBLE_ISSUANCE",
16077
+ "TX_WARRANT_ISSUANCE",
16078
+ "TX_EQUITY_COMPENSATION_ISSUANCE",
16079
+ "TX_PLAN_SECURITY_ISSUANCE"
16080
+ ]);
16081
+ var CONVERSION_PARENT_TYPES = /* @__PURE__ */ new Set([
16082
+ "TX_CONVERTIBLE_CONVERSION",
16083
+ "TX_WARRANT_EXERCISE",
16084
+ "TX_EQUITY_COMPENSATION_EXERCISE",
16085
+ "TX_EQUITY_COMPENSATION_RELEASE",
16086
+ "TX_PLAN_SECURITY_RELEASE",
16087
+ "TX_STOCK_TRANSFER",
16088
+ "TX_STOCK_CONVERSION",
16089
+ "TX_CONVERTIBLE_TRANSFER",
16090
+ "TX_WARRANT_TRANSFER",
16091
+ "TX_EQUITY_COMPENSATION_TRANSFER",
16092
+ "TX_PLAN_SECURITY_TRANSFER",
16093
+ "TX_STOCK_REISSUANCE"
16094
+ ]);
16095
+ function isRecord(value) {
16096
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16097
+ }
16098
+ function canonicalType(obj) {
16099
+ const type = String(obj.type ?? "").toUpperCase();
16100
+ if (type === "OBJECT")
16101
+ return String(obj.subtype ?? "").toUpperCase();
16102
+ return type;
16103
+ }
16104
+ function issuerForEngine(payload) {
16105
+ if (payload.initial_shares_authorized == null && payload.authorized_shares != null) {
16106
+ return { ...payload, initial_shares_authorized: payload.authorized_shares };
16107
+ }
16108
+ return payload;
16109
+ }
16110
+ function payloadId(payload, fallback) {
16111
+ return typeof payload.id === "string" && payload.id.length > 0 ? payload.id : fallback;
16112
+ }
16113
+ function pushByOcfId(bucket, payload, fallback) {
16114
+ bucket.set(payloadId(payload, fallback), payload);
16115
+ }
16116
+ function timestampMs(input, defaultValue) {
16117
+ if (input == null)
16118
+ return defaultValue;
16119
+ const ms = typeof input === "number" ? input : new Date(String(input)).getTime();
16120
+ return Number.isNaN(ms) ? defaultValue : ms;
16121
+ }
16122
+ function dumpTxWeight(tx, conversionResultSecurityIds) {
16123
+ const objectType = String(tx.object_type ?? "");
16124
+ if (conversionResultSecurityIds.size > 0 && ISSUANCE_TYPES.has(objectType) && typeof tx.security_id === "string" && conversionResultSecurityIds.has(tx.security_id)) {
16125
+ return 36;
16126
+ }
16127
+ switch (objectType) {
16128
+ case "TX_ISSUER_AUTHORIZED_SHARES_ADJUSTMENT":
16129
+ case "TX_STOCK_CLASS_AUTHORIZED_SHARES_ADJUSTMENT":
16130
+ case "TX_STOCK_PLAN_POOL_ADJUSTMENT":
16131
+ return 5;
16132
+ case "TX_STOCK_REISSUANCE":
16133
+ return 9;
16134
+ case "TX_STOCK_ISSUANCE":
16135
+ case "TX_EQUITY_COMPENSATION_ISSUANCE":
16136
+ case "TX_WARRANT_ISSUANCE":
16137
+ case "TX_CONVERTIBLE_ISSUANCE":
16138
+ case "TX_PLAN_SECURITY_ISSUANCE":
16139
+ return 10;
16140
+ case "TX_STOCK_ACCEPTANCE":
16141
+ case "TX_WARRANT_ACCEPTANCE":
16142
+ case "TX_EQUITY_COMPENSATION_ACCEPTANCE":
16143
+ case "TX_PLAN_SECURITY_ACCEPTANCE":
16144
+ return 11;
16145
+ case "TX_VESTING_START":
16146
+ return 12;
16147
+ case "TX_VESTING_EVENT":
16148
+ return 13;
16149
+ case "TX_VESTING_ACCELERATION":
16150
+ return 14;
16151
+ case "TX_STOCK_CLASS_SPLIT":
16152
+ return 15;
16153
+ case "TX_STOCK_RETRACTION":
16154
+ case "TX_CONVERTIBLE_RETRACTION":
16155
+ case "TX_WARRANT_RETRACTION":
16156
+ case "TX_EQUITY_COMPENSATION_RETRACTION":
16157
+ return 16;
16158
+ case "TX_STOCK_CONSOLIDATION":
16159
+ return 17;
16160
+ case "TX_STOCK_CLASS_CONVERSION_RATIO_ADJUSTMENT":
16161
+ return 18;
16162
+ case "TX_EQUITY_COMPENSATION_REPRICING":
16163
+ return 19;
16164
+ case "TX_STOCK_TRANSFER":
16165
+ case "TX_WARRANT_TRANSFER":
16166
+ case "TX_CONVERTIBLE_TRANSFER":
16167
+ case "TX_EQUITY_COMPENSATION_TRANSFER":
16168
+ case "TX_PLAN_SECURITY_TRANSFER":
16169
+ return 20;
16170
+ case "TX_CONVERTIBLE_ACCEPTANCE":
16171
+ return 22;
16172
+ case "TX_EQUITY_COMPENSATION_EXERCISE":
16173
+ case "TX_WARRANT_EXERCISE":
16174
+ return 30;
16175
+ case "TX_CONVERTIBLE_CONVERSION":
16176
+ return 35;
16177
+ case "TX_STOCK_REPURCHASE":
16178
+ case "TX_STOCK_CANCELLATION":
16179
+ case "TX_EQUITY_COMPENSATION_CANCELLATION":
16180
+ case "TX_WARRANT_CANCELLATION":
16181
+ case "TX_CONVERTIBLE_CANCELLATION":
16182
+ case "TX_EQUITY_COMPENSATION_RETURN_TO_POOL":
16183
+ return 40;
16184
+ default:
16185
+ return 50;
16186
+ }
16187
+ }
16188
+ function dumpTransactionSortKey(tx, issuanceDates, conversionResultSecurityIds) {
16189
+ let day = new Date(timestampMs(tx.date, 0) ?? 0).toISOString().slice(0, 10);
16190
+ const objectType = String(tx.object_type ?? "");
16191
+ if (objectType === "TX_VESTING_START" && typeof tx.security_id === "string") {
16192
+ const issuanceDate = issuanceDates.get(tx.security_id);
16193
+ if (issuanceDate && String(tx.date) < issuanceDate) {
16194
+ day = new Date(timestampMs(issuanceDate, 0) ?? 0).toISOString().slice(0, 10);
16195
+ }
16196
+ }
16197
+ const weight = String(dumpTxWeight(tx, conversionResultSecurityIds)).padStart(3, "0");
16198
+ const group = typeof tx.security_id === "string" && tx.security_id ? tx.security_id : "_no_security_";
16199
+ const createdMs = timestampMs(tx.createdAt ?? tx.created_at, null);
16200
+ const created = createdMs !== null ? new Date(createdMs).toISOString() : "9999-12-31T23:59:59.999Z";
16201
+ const id = String(tx._id ?? tx.id ?? "");
16202
+ return `${day}|${weight}|${group}|${created}|${id}`;
16203
+ }
16204
+ function sortDumpTransactions(transactions) {
16205
+ const issuanceDates = /* @__PURE__ */ new Map();
16206
+ const conversionResultSecurityIds = /* @__PURE__ */ new Set();
16207
+ for (const tx of transactions) {
16208
+ const objectType = String(tx.object_type ?? "");
16209
+ if (ISSUANCE_TYPES.has(objectType) && typeof tx.security_id === "string" && typeof tx.date === "string") {
16210
+ issuanceDates.set(tx.security_id, tx.date);
16211
+ }
16212
+ if (!CONVERSION_PARENT_TYPES.has(objectType))
16213
+ continue;
16214
+ if (Array.isArray(tx.resulting_security_ids)) {
16215
+ for (const id of tx.resulting_security_ids) {
16216
+ if (typeof id === "string" && id)
16217
+ conversionResultSecurityIds.add(id);
16218
+ }
16219
+ }
16220
+ if (typeof tx.balance_security_id === "string" && tx.balance_security_id) {
16221
+ conversionResultSecurityIds.add(tx.balance_security_id);
16222
+ }
16223
+ }
16224
+ return [...transactions].sort((a, b) => {
16225
+ const ka = dumpTransactionSortKey(a, issuanceDates, conversionResultSecurityIds);
16226
+ const kb = dumpTransactionSortKey(b, issuanceDates, conversionResultSecurityIds);
16227
+ if (ka < kb)
16228
+ return -1;
16229
+ if (ka > kb)
16230
+ return 1;
16231
+ return 0;
16232
+ });
16233
+ }
16234
+ function assembleEngineOcfDump(objects) {
16235
+ const issuers = [];
16236
+ const stockClasses = /* @__PURE__ */ new Map();
16237
+ const stockPlans = /* @__PURE__ */ new Map();
16238
+ const stakeholders = /* @__PURE__ */ new Map();
16239
+ const transactions = /* @__PURE__ */ new Map();
16240
+ const vestingTerms = /* @__PURE__ */ new Map();
16241
+ let index = 0;
16242
+ for (const obj of objects) {
16243
+ if (!isRecord(obj))
16244
+ continue;
16245
+ const type = canonicalType(obj);
16246
+ const payload = isRecord(obj.ocf) ? obj.ocf : null;
16247
+ index += 1;
16248
+ switch (type) {
16249
+ case "ISSUER":
16250
+ if (!payload) {
16251
+ throw new DumpAssemblyError("ISSUER object is missing an ocf payload.");
16252
+ }
16253
+ issuers.push(issuerForEngine(payload));
16254
+ break;
16255
+ case "STOCK_CLASS":
16256
+ if (payload)
16257
+ pushByOcfId(stockClasses, payload, `anon-stock-class-${index}`);
16258
+ break;
16259
+ case "STOCK_PLAN":
16260
+ if (payload)
16261
+ pushByOcfId(stockPlans, payload, `anon-stock-plan-${index}`);
16262
+ break;
16263
+ case "STAKEHOLDER":
16264
+ if (payload)
16265
+ pushByOcfId(stakeholders, payload, `anon-stakeholder-${index}`);
16266
+ break;
16267
+ case "TRANSACTION":
16268
+ if (payload)
16269
+ pushByOcfId(transactions, payload, `anon-transaction-${index}`);
16270
+ break;
16271
+ case "VESTING_TERMS":
16272
+ if (payload)
16273
+ pushByOcfId(vestingTerms, payload, `anon-vesting-terms-${index}`);
16274
+ break;
16275
+ default:
16276
+ break;
16277
+ }
16278
+ }
16279
+ if (issuers.length === 0) {
16280
+ throw new DumpAssemblyError("Dump requires exactly one ISSUER object; none found.");
16281
+ }
16282
+ if (issuers.length > 1) {
16283
+ throw new DumpAssemblyError(`Dump requires exactly one ISSUER object; found ${issuers.length}.`);
16284
+ }
16285
+ return {
16286
+ issuer: issuers[0],
16287
+ stockClasses: [...stockClasses.values()],
16288
+ stockPlans: [...stockPlans.values()],
16289
+ stakeholders: [...stakeholders.values()],
16290
+ transactions: sortDumpTransactions([...transactions.values()]),
16291
+ vestingTerms: [...vestingTerms.values()],
16292
+ sharePrices: []
16293
+ };
16294
+ }
16295
+
16026
16296
  // ../captable-ai-core/dist/scopes.js
16027
16297
  var CAPTABLE_AI_SCOPES = {
16028
16298
  READ: "read",
@@ -16183,14 +16453,14 @@ var summarySchema = external_exports.object({
16183
16453
  });
16184
16454
 
16185
16455
  // src/api.ts
16186
- function isRecord(value) {
16456
+ function isRecord2(value) {
16187
16457
  return typeof value === "object" && value !== null && !Array.isArray(value);
16188
16458
  }
16189
16459
  function coerceDetails(raw) {
16190
16460
  if (!Array.isArray(raw)) return void 0;
16191
16461
  const details = [];
16192
16462
  for (const entry of raw) {
16193
- if (!isRecord(entry)) continue;
16463
+ if (!isRecord2(entry)) continue;
16194
16464
  const message = typeof entry.message === "string" ? entry.message : void 0;
16195
16465
  if (!message) continue;
16196
16466
  const path = typeof entry.path === "string" ? entry.path : void 0;
@@ -16381,9 +16651,9 @@ async function handleResponse(res) {
16381
16651
  }
16382
16652
  if (!res.ok) {
16383
16653
  const exitCode = exitCodeForStatus(res.status);
16384
- const obj = isRecord(parsed) ? parsed : {};
16654
+ const obj = isRecord2(parsed) ? parsed : {};
16385
16655
  const nested = obj.error;
16386
- if (isRecord(nested)) {
16656
+ if (isRecord2(nested)) {
16387
16657
  const code = typeof nested.code === "string" && nested.code.trim() ? nested.code : void 0;
16388
16658
  const details = coerceDetails(nested.details);
16389
16659
  exitWithError(String(nested.message ?? `HTTP ${res.status}`), code, details, exitCode);
@@ -16486,24 +16756,54 @@ Usage:
16486
16756
  captable-ai objects list [options]
16487
16757
 
16488
16758
  Filters:
16489
- --type TYPE Top-level OCF types (comma-separated)
16490
- --subtype STYPE TRANSACTION subtypes (comma-separated)
16491
- --status STATUS draft | committed
16492
- --q QUERY Full-text search
16493
- --from DATE YYYY-MM-DD (inclusive lower bound on object date)
16494
- --to DATE YYYY-MM-DD (inclusive upper bound on object date)
16495
- --ids ID,ID,... Batch fetch by object IDs
16759
+ --type TYPE Top-level OCF types (comma-separated)
16760
+ --subtype STYPE TRANSACTION subtypes (comma-separated)
16761
+ --status STATUS draft | committed
16762
+ --q QUERY Full-text search
16763
+ --from DATE YYYY-MM-DD (inclusive lower bound on object date)
16764
+ --to DATE YYYY-MM-DD (inclusive upper bound on object date)
16765
+ --ids ID,ID,... Batch fetch by object IDs
16766
+ --stakeholder ID Filter by OCF stakeholder id
16767
+ --document S3_ASSET_ID Filter by source document
16768
+ --max-confidence N Keep objects with confidence <= N (requires --all)
16496
16769
 
16497
16770
  Pagination:
16498
- --limit N Page size (1\u2013250; omit for server default, typically 100)
16499
- --cursor C Opaque continuation cursor from prior response
16771
+ --limit N Page size (1\u2013250; omit for server default, typically 100)
16772
+ --cursor C Opaque continuation cursor from prior response
16773
+ --all Follow cursors until every matching object is returned
16774
+
16775
+ Human table sorts lowest extraction confidence first. Conf markers:
16776
+ !N red (<65) ~N amber (65\u201384) N green (\u226585)
16500
16777
 
16501
16778
  Global:
16502
- --json Machine-readable JSON output`;
16779
+ --json Machine-readable JSON output (API order, not confidence-sorted)`;
16503
16780
  var HELP_OBJECTS_GET = `objects get \u2014 Show one OCF object
16504
16781
 
16505
16782
  Usage:
16506
16783
  captable-ai objects get <object-id> [--json]`;
16784
+ var HELP_OBJECTS_DUMP = `objects dump \u2014 Engine-shaped ocf.json
16785
+
16786
+ Assembles each row's ocf payload into the shape processCapTable consumes:
16787
+ { issuer, stockClasses, stockPlans, stakeholders, transactions, vestingTerms, sharePrices }
16788
+
16789
+ Fails if ISSUER is missing or duplicated. Not an OCF zip and not expected.json.
16790
+ Drains up to 400 pages (100,000 objects). Large tables: write a file with --output.
16791
+
16792
+ The list API picks the latest row per object id, then optionally filters status.
16793
+ --status committed therefore omits an object when a newer draft exists.
16794
+ --status draft dumps that latest-row working set (drafts win) so the engine
16795
+ still sees the committed ISSUER and other unchanged baseline objects.
16796
+
16797
+ Usage:
16798
+ captable-ai objects dump [--status committed|draft] [--output path]
16799
+
16800
+ Flags:
16801
+ --status STATUS committed = latest committed-only rows (default).
16802
+ draft = pending working set (latest row per object).
16803
+ --output PATH Write JSON to file (global flag; implies --json)
16804
+
16805
+ Global:
16806
+ --json Machine-readable JSON (dump is always JSON)`;
16507
16807
  var HELP_OBJECTS_UPDATE = `objects update \u2014 Update an OCF object
16508
16808
 
16509
16809
  Usage:
@@ -16592,6 +16892,8 @@ ${HELP_OBJECTS_LIST}
16592
16892
 
16593
16893
  ${HELP_OBJECTS_GET}
16594
16894
 
16895
+ ${HELP_OBJECTS_DUMP}
16896
+
16595
16897
  ${HELP_OBJECTS_UPDATE}
16596
16898
 
16597
16899
  ${HELP_OBJECTS_PATCH}
@@ -17686,11 +17988,11 @@ var JOBS_FILE = join2(CONFIG_DIR2, "jobs.jsonl");
17686
17988
  var LOCK_DIR = join2(CONFIG_DIR2, "jobs.lock");
17687
17989
  var VALID_JOB_STATUSES = /* @__PURE__ */ new Set(["submitted", "running", "complete", "failed"]);
17688
17990
  var VALID_JOB_KINDS = /* @__PURE__ */ new Set(["extraction"]);
17689
- function isRecord2(v) {
17991
+ function isRecord3(v) {
17690
17992
  return typeof v === "object" && v !== null;
17691
17993
  }
17692
17994
  function isJobEntry(value) {
17693
- if (!isRecord2(value)) return false;
17995
+ if (!isRecord3(value)) return false;
17694
17996
  return typeof value.id === "string" && typeof value.kind === "string" && VALID_JOB_KINDS.has(value.kind) && typeof value.portalId === "string" && typeof value.submittedAt === "string" && typeof value.status === "string" && VALID_JOB_STATUSES.has(value.status);
17695
17997
  }
17696
17998
  async function ensureDir() {
@@ -18241,11 +18543,11 @@ async function readEntries() {
18241
18543
  }
18242
18544
  return entries;
18243
18545
  }
18244
- function isRecord3(v) {
18546
+ function isRecord4(v) {
18245
18547
  return typeof v === "object" && v !== null;
18246
18548
  }
18247
18549
  function isFeedbackEntry(value) {
18248
- if (!isRecord3(value)) return false;
18550
+ if (!isRecord4(value)) return false;
18249
18551
  return typeof value.ts === "string" && typeof value.text === "string" && typeof value.sent === "boolean";
18250
18552
  }
18251
18553
 
@@ -18462,7 +18764,7 @@ function successHtml() {
18462
18764
  h1{font-size:1.5rem;color:#111}p{color:#666}</style></head>
18463
18765
  <body><div class="card"><h1>Login successful</h1><p>You can close this window and return to the terminal.</p></div></body></html>`;
18464
18766
  }
18465
- function isRecord4(value) {
18767
+ function isRecord5(value) {
18466
18768
  return typeof value === "object" && value !== null && !Array.isArray(value);
18467
18769
  }
18468
18770
  function readStr(obj, ...keys) {
@@ -18483,7 +18785,7 @@ function parsePortalsFromExchange(raw) {
18483
18785
  }
18484
18786
  if (!Array.isArray(parsed)) return [];
18485
18787
  return parsed.flatMap((p) => {
18486
- if (!isRecord4(p)) return [];
18788
+ if (!isRecord5(p)) return [];
18487
18789
  if (typeof p.id !== "string" || p.id.length === 0) return [];
18488
18790
  return [
18489
18791
  {
@@ -18527,7 +18829,7 @@ function tryParseLoginPaste(line, expectedState) {
18527
18829
  } catch {
18528
18830
  return null;
18529
18831
  }
18530
- if (!isRecord4(obj)) return null;
18832
+ if (!isRecord5(obj)) return null;
18531
18833
  if (typeof obj.state !== "string" || !pastedStateMatches(expectedState, obj.state)) return null;
18532
18834
  const accessToken = readStr(obj, "access_token", "accessToken");
18533
18835
  const refreshToken = readStr(obj, "refresh_token", "refreshToken");
@@ -18892,6 +19194,105 @@ async function runObjectsDelete(args, rawArgv) {
18892
19194
  );
18893
19195
  }
18894
19196
 
19197
+ // src/objects-pages.ts
19198
+ var OBJECTS_LIST_MAX_PAGES = 100;
19199
+ var OBJECTS_DUMP_MAX_PAGES = 400;
19200
+ async function fetchAllObjectPages(portalId, query, options) {
19201
+ const maxPages = options?.maxPages ?? OBJECTS_LIST_MAX_PAGES;
19202
+ const objects = [];
19203
+ const documentsById = /* @__PURE__ */ new Map();
19204
+ let cursor = typeof query.cursor === "string" ? query.cursor : void 0;
19205
+ let total = 0;
19206
+ let pages = 0;
19207
+ while (true) {
19208
+ pages += 1;
19209
+ if (pages > maxPages) {
19210
+ exitWithError(
19211
+ `Exceeded max object-list pages (${maxPages}). Narrow the query or raise the page size.`,
19212
+ "ERROR",
19213
+ void 0,
19214
+ EXIT.SERVER_ERROR
19215
+ );
19216
+ }
19217
+ const pageQuery = { ...query };
19218
+ if (cursor !== void 0) pageQuery.cursor = cursor;
19219
+ else delete pageQuery.cursor;
19220
+ const res = await apiRequest(`/${portalId}/objects`, { query: pageQuery });
19221
+ const pageObjects = res.data?.objects ?? [];
19222
+ const pageDocs = res.data?.documents ?? [];
19223
+ objects.push(...pageObjects);
19224
+ for (const doc of pageDocs) {
19225
+ documentsById.set(doc.id, doc);
19226
+ }
19227
+ if (res.meta?.total != null) total = res.meta.total;
19228
+ if (!res.meta?.hasMore) break;
19229
+ if (!res.meta.cursor) {
19230
+ exitWithError(
19231
+ "Pagination response has more results but no continuation cursor.",
19232
+ "ERROR",
19233
+ void 0,
19234
+ EXIT.SERVER_ERROR
19235
+ );
19236
+ }
19237
+ if (cursor !== void 0 && res.meta.cursor === cursor) {
19238
+ exitWithError(
19239
+ "Pagination cursor did not advance; stopped draining object pages.",
19240
+ "ERROR",
19241
+ void 0,
19242
+ EXIT.SERVER_ERROR
19243
+ );
19244
+ }
19245
+ cursor = res.meta.cursor;
19246
+ }
19247
+ return {
19248
+ data: { objects, documents: Array.from(documentsById.values()) },
19249
+ meta: { cursor: null, total: total || objects.length, hasMore: false }
19250
+ };
19251
+ }
19252
+
19253
+ // src/commands/objects-dump.ts
19254
+ var DUMP_PAGE_LIMIT = 250;
19255
+ function dumpStatus(raw) {
19256
+ const status = raw ?? "committed";
19257
+ if (status === "committed" || status === "draft") return status;
19258
+ exitWithError(
19259
+ `--status must be one of: draft, committed (got: "${status}")`,
19260
+ "VALIDATION_FAILED",
19261
+ void 0,
19262
+ EXIT.VALIDATION
19263
+ );
19264
+ }
19265
+ async function runObjectsDump(args, rawArgv) {
19266
+ if (argvRequestsHelp(rawArgv)) {
19267
+ process.stdout.write(`${HELP_OBJECTS_DUMP}
19268
+ `);
19269
+ process.exit(0);
19270
+ }
19271
+ validateFlags(args, { flags: ["status"], booleans: [] });
19272
+ if (args.positional.length > 0) {
19273
+ exitWithError(
19274
+ `Unexpected argument: ${args.positional[0]}. objects dump takes flags only.`,
19275
+ "USAGE",
19276
+ void 0,
19277
+ EXIT.USAGE
19278
+ );
19279
+ }
19280
+ const status = dumpStatus(getFlagValue(args, "status"));
19281
+ const portalId = await getActivePortalId();
19282
+ const query = { limit: DUMP_PAGE_LIMIT };
19283
+ if (status === "committed") query.status = "committed";
19284
+ const page = await fetchAllObjectPages(portalId, query, { maxPages: OBJECTS_DUMP_MAX_PAGES });
19285
+ try {
19286
+ const objects = Array.isArray(page.data?.objects) ? page.data.objects : [];
19287
+ printJson(assembleEngineOcfDump(objects));
19288
+ } catch (err) {
19289
+ if (err instanceof DumpAssemblyError) {
19290
+ exitWithError(err.message, "VALIDATION_FAILED", void 0, EXIT.VALIDATION);
19291
+ }
19292
+ throw err;
19293
+ }
19294
+ }
19295
+
18895
19296
  // src/commands/objects-get.ts
18896
19297
  function shellQuote2(value) {
18897
19298
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -19020,6 +19421,106 @@ function validateIsoDateRange(fromRaw, toRaw) {
19020
19421
  }
19021
19422
 
19022
19423
  // src/commands/objects-list.ts
19424
+ var CONFIDENCE_RED_MAX = 64;
19425
+ var CONFIDENCE_AMBER_MAX = 84;
19426
+ function isRecord6(value) {
19427
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19428
+ }
19429
+ function getValidatedMaxConfidence(raw) {
19430
+ if (raw === void 0) return void 0;
19431
+ const trimmed = raw.trim();
19432
+ if (!/^\d+$/.test(trimmed)) {
19433
+ exitWithError(
19434
+ "--max-confidence must be an integer between 0 and 100",
19435
+ "VALIDATION_FAILED",
19436
+ void 0,
19437
+ EXIT.VALIDATION
19438
+ );
19439
+ }
19440
+ const n = Number.parseInt(trimmed, 10);
19441
+ if (n < 0 || n > 100) {
19442
+ exitWithError(
19443
+ "--max-confidence must be an integer between 0 and 100",
19444
+ "VALIDATION_FAILED",
19445
+ void 0,
19446
+ EXIT.VALIDATION
19447
+ );
19448
+ }
19449
+ return n;
19450
+ }
19451
+ function objectConfidence(obj) {
19452
+ const n = obj.extraction?.confidence;
19453
+ return typeof n === "number" && Number.isFinite(n) ? n : void 0;
19454
+ }
19455
+ function formatConfidence(confidence) {
19456
+ if (confidence === void 0) return "\u2014";
19457
+ if (confidence <= CONFIDENCE_RED_MAX) return `!${confidence}`;
19458
+ if (confidence <= CONFIDENCE_AMBER_MAX) return `~${confidence}`;
19459
+ return String(confidence);
19460
+ }
19461
+ function stakeholderDisplayName(ocf) {
19462
+ if (!ocf) return null;
19463
+ if (typeof ocf.name === "string" && ocf.name.trim()) return ocf.name.trim();
19464
+ if (typeof ocf.legal_name === "string" && ocf.legal_name.trim()) return ocf.legal_name.trim();
19465
+ if (isRecord6(ocf.name)) {
19466
+ const legal = ocf.name.legal_name;
19467
+ if (typeof legal === "string" && legal.trim()) return legal.trim();
19468
+ const parts = [ocf.name.first_name, ocf.name.last_name].filter(
19469
+ (p) => typeof p === "string" && p.trim().length > 0
19470
+ );
19471
+ if (parts.length > 0) return parts.join(" ");
19472
+ }
19473
+ return null;
19474
+ }
19475
+ function stakeholderNamesById(objects) {
19476
+ const names = /* @__PURE__ */ new Map();
19477
+ for (const obj of objects) {
19478
+ if (obj.type !== "STAKEHOLDER") continue;
19479
+ const name = stakeholderDisplayName(obj.ocf);
19480
+ if (name) names.set(obj.id, name);
19481
+ }
19482
+ return names;
19483
+ }
19484
+ function compareConfidenceAsc(a, b) {
19485
+ const ca = objectConfidence(a);
19486
+ const cb = objectConfidence(b);
19487
+ if (ca === void 0 && cb === void 0) return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
19488
+ if (ca === void 0) return 1;
19489
+ if (cb === void 0) return -1;
19490
+ if (ca !== cb) return ca - cb;
19491
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
19492
+ }
19493
+ function shellQuote3(value) {
19494
+ return `'${value.replace(/'/g, `'\\''`)}'`;
19495
+ }
19496
+ function nextPageHint(query, cursor) {
19497
+ const parts = ["captable-ai objects list"];
19498
+ const flagNames = [
19499
+ { queryKey: "type", flag: "type" },
19500
+ { queryKey: "subtype", flag: "subtype" },
19501
+ { queryKey: "status", flag: "status" },
19502
+ { queryKey: "q", flag: "q" },
19503
+ { queryKey: "from", flag: "from" },
19504
+ { queryKey: "to", flag: "to" },
19505
+ { queryKey: "ids", flag: "ids" },
19506
+ { queryKey: "stakeholderId", flag: "stakeholder" },
19507
+ { queryKey: "documentId", flag: "document" },
19508
+ { queryKey: "limit", flag: "limit" }
19509
+ ];
19510
+ for (const { queryKey, flag } of flagNames) {
19511
+ const value = query[queryKey];
19512
+ if (value !== void 0) parts.push(`--${flag} ${shellQuote3(String(value))}`);
19513
+ }
19514
+ parts.push(`--cursor ${shellQuote3(cursor)}`);
19515
+ return parts.join(" ");
19516
+ }
19517
+ function documentsReferencedBy(documents, objects) {
19518
+ const ids = /* @__PURE__ */ new Set();
19519
+ for (const obj of objects) {
19520
+ if (typeof obj.documentId === "string" && obj.documentId.length > 0) ids.add(obj.documentId);
19521
+ }
19522
+ return documents.filter((doc) => ids.has(doc.id));
19523
+ }
19023
19524
  async function runObjectsList(args, rawArgv) {
19024
19525
  if (argvRequestsHelp(rawArgv)) {
19025
19526
  process.stdout.write(`${HELP_OBJECTS_LIST}
@@ -19027,14 +19528,45 @@ async function runObjectsList(args, rawArgv) {
19027
19528
  process.exit(0);
19028
19529
  }
19029
19530
  validateFlags(args, {
19030
- flags: ["type", "subtype", "status", "limit", "cursor", "q", "from", "to", "ids"],
19031
- booleans: []
19531
+ flags: [
19532
+ "type",
19533
+ "subtype",
19534
+ "status",
19535
+ "limit",
19536
+ "cursor",
19537
+ "q",
19538
+ "from",
19539
+ "to",
19540
+ "ids",
19541
+ "stakeholder",
19542
+ "document",
19543
+ "max-confidence"
19544
+ ],
19545
+ booleans: ["all"]
19032
19546
  });
19547
+ if (args.positional.length > 0) {
19548
+ exitWithError(
19549
+ `Unexpected argument: ${args.positional[0]}. This command takes no positional arguments.`,
19550
+ "UNEXPECTED_ARGUMENT",
19551
+ void 0,
19552
+ EXIT.USAGE
19553
+ );
19554
+ }
19033
19555
  const portalId = await getActivePortalId();
19034
19556
  const from = getFlagValue(args, "from");
19035
19557
  const to = getFlagValue(args, "to");
19036
19558
  validateIsoDateRange(from, to);
19037
19559
  const limit = getValidatedLimit(getFlagValue(args, "limit"));
19560
+ const drainAll = hasFlag(args, "all");
19561
+ const maxConfidence = getValidatedMaxConfidence(getFlagValue(args, "max-confidence"));
19562
+ if (maxConfidence !== void 0 && !drainAll) {
19563
+ exitWithError(
19564
+ "--max-confidence requires --all so the review queue is not a single page.",
19565
+ "VALIDATION_FAILED",
19566
+ void 0,
19567
+ EXIT.VALIDATION
19568
+ );
19569
+ }
19038
19570
  const type = getFlagValue(args, "type");
19039
19571
  const subtype = getFlagValue(args, "subtype");
19040
19572
  const status = getFlagValue(args, "status");
@@ -19049,6 +19581,8 @@ async function runObjectsList(args, rawArgv) {
19049
19581
  const q = getFlagValue(args, "q");
19050
19582
  const cursor = getFlagValue(args, "cursor");
19051
19583
  const ids = getFlagValue(args, "ids");
19584
+ const stakeholderId = getFlagValue(args, "stakeholder");
19585
+ const documentId = getFlagValue(args, "document");
19052
19586
  const query = {
19053
19587
  type,
19054
19588
  subtype,
@@ -19058,51 +19592,75 @@ async function runObjectsList(args, rawArgv) {
19058
19592
  cursor,
19059
19593
  from,
19060
19594
  to,
19061
- ids
19595
+ ids,
19596
+ stakeholderId,
19597
+ documentId
19062
19598
  };
19063
- const res = await apiRequest(`/${portalId}/objects`, { query });
19599
+ let page;
19600
+ if (drainAll) {
19601
+ page = await fetchAllObjectPages(portalId, query);
19602
+ } else {
19603
+ const res = await apiRequest(`/${portalId}/objects`, { query });
19604
+ page = {
19605
+ data: { objects: res.data?.objects ?? [], documents: res.data?.documents ?? [] },
19606
+ meta: res.meta ?? {}
19607
+ };
19608
+ }
19609
+ let objects = page.data.objects;
19610
+ let documents = page.data.documents;
19611
+ if (maxConfidence !== void 0) {
19612
+ objects = objects.filter((obj) => {
19613
+ const confidence = objectConfidence(obj);
19614
+ return confidence !== void 0 && confidence <= maxConfidence;
19615
+ });
19616
+ documents = documentsReferencedBy(documents, objects);
19617
+ }
19064
19618
  if (isJsonMode()) {
19065
- const out = { data: res.data };
19066
- if (res.meta !== void 0) out.meta = res.meta;
19619
+ const out = {
19620
+ data: { objects, documents }
19621
+ };
19622
+ if (page.meta !== void 0) {
19623
+ out.meta = maxConfidence !== void 0 ? { ...page.meta, total: objects.length, hasMore: false, cursor: null } : page.meta;
19624
+ }
19067
19625
  printJson(out);
19068
19626
  return;
19069
19627
  }
19070
- const objects = res.data?.objects ?? [];
19071
- const meta3 = res.meta;
19628
+ const documentsById = new Map(documents.map((d) => [d.id, d.name]));
19629
+ const namesByStakeholderId = stakeholderNamesById(page.data.objects);
19630
+ const sorted = [...objects].sort(compareConfidenceAsc);
19631
+ const meta3 = page.meta;
19632
+ const totalLabel = maxConfidence !== void 0 ? ` (${objects.length} matching)` : meta3?.total != null && objects.length !== meta3.total ? ` (${objects.length} shown, ${meta3.total} total)` : meta3?.total != null ? ` (${meta3.total} total)` : "";
19072
19633
  printLine(`
19073
- Objects${meta3?.total != null ? ` (${meta3.total} total)` : ""}:
19634
+ Objects${totalLabel}:
19074
19635
  `);
19075
19636
  printTable(
19076
- objects.map((o) => ({
19077
- id: o.id,
19078
- type: o.subtype ?? o.type,
19079
- status: o.status,
19080
- date: o.date ?? "",
19081
- version: o.version
19082
- })),
19637
+ sorted.map((o) => {
19638
+ const stakeholderIdValue = o.type === "STAKEHOLDER" ? o.id : o.stakeholderId ?? "";
19639
+ const stakeholderName = stakeholderIdValue ? namesByStakeholderId.get(stakeholderIdValue) ?? stakeholderIdValue : "";
19640
+ return {
19641
+ id: o.id,
19642
+ type: o.subtype ?? o.type,
19643
+ status: o.status,
19644
+ conf: formatConfidence(objectConfidence(o)),
19645
+ document: o.documentId ? documentsById.get(o.documentId) ?? o.documentId : "",
19646
+ stakeholder: stakeholderName,
19647
+ date: o.date ?? ""
19648
+ };
19649
+ }),
19083
19650
  [
19084
19651
  { key: "id", label: "ID", width: 38 },
19085
- { key: "type", label: "Type", width: 30 },
19652
+ { key: "type", label: "Type", width: 28 },
19086
19653
  { key: "status", label: "Status", width: 10 },
19087
- { key: "date", label: "Date", width: 12 },
19088
- { key: "version", label: "Version", width: 8 }
19654
+ { key: "conf", label: "Conf", width: 6 },
19655
+ { key: "document", label: "Document", width: 24 },
19656
+ { key: "stakeholder", label: "Stakeholder", width: 22 },
19657
+ { key: "date", label: "Date", width: 12 }
19089
19658
  ]
19090
19659
  );
19091
- if (meta3?.hasMore && meta3.cursor) {
19092
- const shQ = (v) => `'${v.replace(/'/g, `'\\''`)}'`;
19093
- const parts = ["captable-ai objects list"];
19094
- if (type !== void 0) parts.push(`--type ${shQ(type)}`);
19095
- if (subtype !== void 0) parts.push(`--subtype ${shQ(subtype)}`);
19096
- if (status !== void 0) parts.push(`--status ${shQ(status)}`);
19097
- if (q !== void 0) parts.push(`--q ${shQ(q)}`);
19098
- if (from !== void 0) parts.push(`--from ${shQ(from)}`);
19099
- if (to !== void 0) parts.push(`--to ${shQ(to)}`);
19100
- if (ids !== void 0) parts.push(`--ids ${shQ(ids)}`);
19101
- if (limit !== void 0) parts.push(`--limit ${shQ(String(limit))}`);
19102
- parts.push(`--cursor ${shQ(meta3.cursor)}`);
19660
+ if (!drainAll && meta3?.hasMore && meta3.cursor) {
19103
19661
  printLine(`
19104
19662
  More results available. Next page:
19105
- ${parts.join(" ")}`);
19663
+ ${nextPageHint(query, meta3.cursor)}`);
19106
19664
  }
19107
19665
  printLine();
19108
19666
  }
@@ -19116,7 +19674,7 @@ async function readStdin() {
19116
19674
  }
19117
19675
  return Buffer.concat(chunks).toString("utf-8");
19118
19676
  }
19119
- function isRecord5(value) {
19677
+ function isRecord7(value) {
19120
19678
  return typeof value === "object" && value !== null && !Array.isArray(value);
19121
19679
  }
19122
19680
  function parsePatchPayload(raw) {
@@ -19131,7 +19689,7 @@ function parsePatchPayload(raw) {
19131
19689
  EXIT.VALIDATION
19132
19690
  );
19133
19691
  }
19134
- if (!isRecord5(parsed)) {
19692
+ if (!isRecord7(parsed)) {
19135
19693
  exitWithError(
19136
19694
  "OCF patch payload must be a JSON object.",
19137
19695
  "VALIDATION_FAILED",
@@ -19351,7 +19909,7 @@ async function readStdin2() {
19351
19909
  }
19352
19910
  return Buffer.concat(chunks).toString("utf-8");
19353
19911
  }
19354
- function isRecord6(value) {
19912
+ function isRecord8(value) {
19355
19913
  return typeof value === "object" && value !== null && !Array.isArray(value);
19356
19914
  }
19357
19915
  function parseOcfPayload(raw) {
@@ -19366,7 +19924,7 @@ function parseOcfPayload(raw) {
19366
19924
  EXIT.VALIDATION
19367
19925
  );
19368
19926
  }
19369
- if (!isRecord6(parsed)) {
19927
+ if (!isRecord8(parsed)) {
19370
19928
  exitWithError(
19371
19929
  "OCF payload must be a JSON object.",
19372
19930
  "VALIDATION_FAILED",
@@ -19376,7 +19934,7 @@ function parseOcfPayload(raw) {
19376
19934
  }
19377
19935
  return parsed;
19378
19936
  }
19379
- function shellQuote3(value) {
19937
+ function shellQuote4(value) {
19380
19938
  return `'${value.replace(/'/g, `'\\''`)}'`;
19381
19939
  }
19382
19940
  async function runObjectsUpdate(args, rawArgv) {
@@ -19501,7 +20059,7 @@ Updated object: ${obj.id}
19501
20059
  printKeyValue([["Key", obj.schemaKey]]);
19502
20060
  printLine(
19503
20061
  `
19504
- Run: captable-ai schemas get ${shellQuote3(obj.schemaKey)} to view the exact schema.`
20062
+ Run: captable-ai schemas get ${shellQuote4(obj.schemaKey)} to view the exact schema.`
19505
20063
  );
19506
20064
  }
19507
20065
  printLine();
@@ -19735,20 +20293,20 @@ import { homedir as homedir4 } from "os";
19735
20293
  import { join as join4 } from "path";
19736
20294
  var CONFIG_DIR4 = join4(homedir4(), ".captable-ai");
19737
20295
  var PROFILES_FILE = join4(CONFIG_DIR4, "profiles.json");
19738
- function isRecord7(value) {
20296
+ function isRecord9(value) {
19739
20297
  return typeof value === "object" && value !== null && !Array.isArray(value);
19740
20298
  }
19741
20299
  function isErrno3(err, code) {
19742
- return isRecord7(err) && err.code === code;
20300
+ return isRecord9(err) && err.code === code;
19743
20301
  }
19744
20302
  function parseProfiles(raw) {
19745
20303
  const parsed = JSON.parse(raw);
19746
- if (!isRecord7(parsed) || !isRecord7(parsed.profiles)) {
20304
+ if (!isRecord9(parsed) || !isRecord9(parsed.profiles)) {
19747
20305
  throw new Error("profiles.json must contain a profiles object.");
19748
20306
  }
19749
20307
  const profiles = {};
19750
20308
  for (const [name, value] of Object.entries(parsed.profiles)) {
19751
- if (!isRecord7(value) || typeof value.company !== "string" || !value.company.trim()) {
20309
+ if (!isRecord9(value) || typeof value.company !== "string" || !value.company.trim()) {
19752
20310
  throw new Error(`Profile "${name}" must include a non-empty company string.`);
19753
20311
  }
19754
20312
  const stage = typeof value.stage === "string" && value.stage.trim() ? value.stage : void 0;
@@ -20429,9 +20987,11 @@ Cap Table (read):
20429
20987
  Options: --as-of, --include-pending, --skip-stakeholders, --page
20430
20988
  objects list List OCF objects
20431
20989
  Filters: --type, --subtype, --status, --q, --from, --to, --ids
20432
- Pagination: --limit (1-250), --cursor
20990
+ Review: --stakeholder, --document, --max-confidence N (requires --all)
20991
+ Pagination: --limit (1-250), --cursor, --all
20433
20992
  Dates: --from / --to as YYYY-MM-DD
20434
20993
  objects get <id> Show a single OCF object
20994
+ objects dump Engine-shaped ocf.json (default --status committed; --output path)
20435
20995
  schemas list List OCF object types
20436
20996
  schemas get <type> Show schema for an OCF type
20437
20997
 
@@ -20718,6 +21278,9 @@ async function main() {
20718
21278
  case "get":
20719
21279
  await runObjectsGet(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
20720
21280
  break;
21281
+ case "dump":
21282
+ await runObjectsDump(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
21283
+ break;
20721
21284
  case "update":
20722
21285
  await runObjectsUpdate(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
20723
21286
  break;
@@ -20735,7 +21298,7 @@ async function main() {
20735
21298
  break;
20736
21299
  default:
20737
21300
  exitWithError(
20738
- `Unknown objects command: ${sub ?? "(none)"}. Try: objects list | get | update | patch | revert | versions | delete`,
21301
+ `Unknown objects command: ${sub ?? "(none)"}. Try: objects list | get | dump | update | patch | revert | versions | delete`,
20739
21302
  "UNKNOWN_COMMAND",
20740
21303
  void 0,
20741
21304
  EXIT.USAGE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairmint/captable-ai",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Agent-native CLI for Captable AI — manage companies, upload documents, run OCF extraction, and commit cap tables from the terminal.",
5
5
  "keywords": [
6
6
  "captable",