@thecorporation/cli 26.3.17 → 26.3.18

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/dist/index.js CHANGED
@@ -10,40 +10,239 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/config.ts
13
- var config_exports = {};
14
- __export(config_exports, {
15
- configForDisplay: () => configForDisplay,
16
- getValue: () => getValue,
17
- loadConfig: () => loadConfig,
18
- maskKey: () => maskKey,
19
- requireConfig: () => requireConfig,
20
- resolveEntityId: () => resolveEntityId,
21
- saveConfig: () => saveConfig,
22
- setValue: () => setValue
23
- });
24
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
25
- import { join } from "path";
13
+ import {
14
+ chmodSync,
15
+ existsSync,
16
+ mkdirSync,
17
+ readFileSync,
18
+ renameSync,
19
+ rmSync,
20
+ writeFileSync
21
+ } from "fs";
26
22
  import { homedir } from "os";
27
- function deepMerge(base, override) {
28
- for (const [key, value] of Object.entries(override)) {
29
- if (key in base && typeof base[key] === "object" && base[key] !== null && !Array.isArray(base[key]) && typeof value === "object" && value !== null && !Array.isArray(value)) {
30
- deepMerge(base[key], value);
31
- } else {
32
- base[key] = value;
23
+ import { join } from "path";
24
+ function sleepSync(ms) {
25
+ Atomics.wait(CONFIG_WAIT_SIGNAL, 0, 0, ms);
26
+ }
27
+ function withConfigLock(fn) {
28
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
29
+ const startedAt = Date.now();
30
+ while (true) {
31
+ try {
32
+ mkdirSync(CONFIG_LOCK_DIR, { mode: 448 });
33
+ break;
34
+ } catch (err) {
35
+ if (err.code !== "EEXIST") {
36
+ throw err;
37
+ }
38
+ if (Date.now() - startedAt >= CONFIG_LOCK_TIMEOUT_MS) {
39
+ throw new Error("timed out waiting for the corp config lock");
40
+ }
41
+ sleepSync(CONFIG_LOCK_RETRY_MS);
33
42
  }
34
43
  }
44
+ try {
45
+ return fn();
46
+ } finally {
47
+ rmSync(CONFIG_LOCK_DIR, { recursive: true, force: true });
48
+ }
35
49
  }
36
- function loadConfig() {
37
- const cfg = structuredClone(DEFAULTS);
50
+ function ensureSecurePermissions() {
51
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
52
+ try {
53
+ chmodSync(CONFIG_DIR, 448);
54
+ } catch {
55
+ }
38
56
  if (existsSync(CONFIG_FILE)) {
39
- const saved = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
40
- deepMerge(cfg, saved);
57
+ try {
58
+ chmodSync(CONFIG_FILE, 384);
59
+ } catch {
60
+ }
61
+ }
62
+ }
63
+ function isObject(value) {
64
+ return typeof value === "object" && value !== null && !Array.isArray(value);
65
+ }
66
+ function isLoopbackHost(hostname) {
67
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
68
+ }
69
+ function validateApiUrl(value) {
70
+ let parsed;
71
+ try {
72
+ parsed = new URL(value.trim());
73
+ } catch {
74
+ throw new Error("api_url must be a valid absolute URL");
75
+ }
76
+ if (parsed.username || parsed.password) {
77
+ throw new Error("api_url must not include embedded credentials");
78
+ }
79
+ const protocol = parsed.protocol.toLowerCase();
80
+ const hostname = parsed.hostname.toLowerCase();
81
+ if (protocol !== "https:" && !(protocol === "http:" && isLoopbackHost(hostname))) {
82
+ throw new Error("api_url must use https, or http only for localhost/loopback development");
83
+ }
84
+ parsed.hash = "";
85
+ return parsed.toString().replace(/\/+$/, "");
86
+ }
87
+ function normalizeString(value) {
88
+ return typeof value === "string" ? value : void 0;
89
+ }
90
+ function normalizeActiveEntityMap(value) {
91
+ if (!isObject(value)) {
92
+ return void 0;
93
+ }
94
+ const entries = Object.entries(value).filter(
95
+ ([workspaceId, entityId]) => typeof workspaceId === "string" && typeof entityId === "string" && entityId.length > 0
96
+ );
97
+ if (entries.length === 0) {
98
+ return void 0;
99
+ }
100
+ return Object.fromEntries(entries);
101
+ }
102
+ function normalizeConfig(raw) {
103
+ const cfg = structuredClone(DEFAULTS);
104
+ if (!isObject(raw)) {
105
+ return cfg;
106
+ }
107
+ const savedApiUrl = normalizeString(raw.api_url);
108
+ if (savedApiUrl) {
109
+ try {
110
+ cfg.api_url = validateApiUrl(savedApiUrl);
111
+ } catch {
112
+ cfg.api_url = DEFAULTS.api_url;
113
+ }
114
+ }
115
+ cfg.api_key = normalizeString(raw.api_key) ?? cfg.api_key;
116
+ cfg.workspace_id = normalizeString(raw.workspace_id) ?? cfg.workspace_id;
117
+ cfg.hosting_mode = normalizeString(raw.hosting_mode) ?? cfg.hosting_mode;
118
+ cfg.active_entity_id = normalizeString(raw.active_entity_id) ?? cfg.active_entity_id;
119
+ if (isObject(raw.llm)) {
120
+ cfg.llm.provider = normalizeString(raw.llm.provider) ?? cfg.llm.provider;
121
+ cfg.llm.api_key = normalizeString(raw.llm.api_key) ?? cfg.llm.api_key;
122
+ cfg.llm.model = normalizeString(raw.llm.model) ?? cfg.llm.model;
123
+ const baseUrl = normalizeString(raw.llm.base_url);
124
+ if (baseUrl && baseUrl.trim()) {
125
+ cfg.llm.base_url = baseUrl.trim();
126
+ }
127
+ }
128
+ if (isObject(raw.user)) {
129
+ cfg.user.name = normalizeString(raw.user.name) ?? cfg.user.name;
130
+ cfg.user.email = normalizeString(raw.user.email) ?? cfg.user.email;
131
+ }
132
+ const activeEntityIds = normalizeActiveEntityMap(raw.active_entity_ids);
133
+ if (activeEntityIds) {
134
+ cfg.active_entity_ids = activeEntityIds;
135
+ }
136
+ if (cfg.workspace_id && cfg.active_entity_id) {
137
+ cfg.active_entity_ids = {
138
+ ...cfg.active_entity_ids ?? {},
139
+ [cfg.workspace_id]: cfg.active_entity_id
140
+ };
41
141
  }
42
142
  return cfg;
43
143
  }
144
+ function serializeConfig(cfg) {
145
+ const normalized = normalizeConfig(cfg);
146
+ const serialized = {
147
+ api_url: normalized.api_url,
148
+ api_key: normalized.api_key,
149
+ workspace_id: normalized.workspace_id,
150
+ hosting_mode: normalized.hosting_mode,
151
+ llm: {
152
+ provider: normalized.llm.provider,
153
+ api_key: normalized.llm.api_key,
154
+ model: normalized.llm.model,
155
+ ...normalized.llm.base_url ? { base_url: normalized.llm.base_url } : {}
156
+ },
157
+ user: {
158
+ name: normalized.user.name,
159
+ email: normalized.user.email
160
+ },
161
+ active_entity_id: normalized.active_entity_id
162
+ };
163
+ if (normalized.active_entity_ids && Object.keys(normalized.active_entity_ids).length > 0) {
164
+ serialized.active_entity_ids = normalized.active_entity_ids;
165
+ }
166
+ return JSON.stringify(serialized, null, 2) + "\n";
167
+ }
168
+ function requireSupportedConfigKey(dotPath) {
169
+ if (!ALLOWED_CONFIG_KEYS.has(dotPath)) {
170
+ throw new Error(`unsupported config key: ${dotPath}`);
171
+ }
172
+ }
173
+ function validateSensitiveConfigUpdate(dotPath, forceSensitive = false) {
174
+ if (SENSITIVE_CONFIG_KEYS.has(dotPath) && !forceSensitive) {
175
+ throw new Error(`refusing to update security-sensitive key '${dotPath}' without --force`);
176
+ }
177
+ }
178
+ function setKnownConfigValue(cfg, dotPath, value) {
179
+ switch (dotPath) {
180
+ case "api_url":
181
+ cfg.api_url = validateApiUrl(value);
182
+ return;
183
+ case "api_key":
184
+ cfg.api_key = value.trim();
185
+ return;
186
+ case "workspace_id":
187
+ cfg.workspace_id = value.trim();
188
+ return;
189
+ case "hosting_mode":
190
+ cfg.hosting_mode = value.trim();
191
+ return;
192
+ case "llm.provider":
193
+ cfg.llm.provider = value.trim();
194
+ return;
195
+ case "llm.api_key":
196
+ cfg.llm.api_key = value.trim();
197
+ return;
198
+ case "llm.model":
199
+ cfg.llm.model = value.trim();
200
+ return;
201
+ case "llm.base_url":
202
+ cfg.llm.base_url = value.trim() || void 0;
203
+ return;
204
+ case "user.name":
205
+ cfg.user.name = value.trim();
206
+ return;
207
+ case "user.email":
208
+ cfg.user.email = value.trim();
209
+ return;
210
+ case "active_entity_id":
211
+ setActiveEntityId(cfg, value.trim());
212
+ return;
213
+ default:
214
+ throw new Error(`unsupported config key: ${dotPath}`);
215
+ }
216
+ }
217
+ function readConfigUnlocked() {
218
+ ensureSecurePermissions();
219
+ if (!existsSync(CONFIG_FILE)) {
220
+ return normalizeConfig(DEFAULTS);
221
+ }
222
+ return normalizeConfig(JSON.parse(readFileSync(CONFIG_FILE, "utf-8")));
223
+ }
224
+ function loadConfig() {
225
+ return readConfigUnlocked();
226
+ }
44
227
  function saveConfig(cfg) {
45
- mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
46
- writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2) + "\n", { mode: 384 });
228
+ withConfigLock(() => {
229
+ ensureSecurePermissions();
230
+ const tempFile = `${CONFIG_FILE}.${process.pid}.tmp`;
231
+ writeFileSync(tempFile, serializeConfig(cfg), { mode: 384 });
232
+ renameSync(tempFile, CONFIG_FILE);
233
+ ensureSecurePermissions();
234
+ });
235
+ }
236
+ function updateConfig(mutator) {
237
+ return withConfigLock(() => {
238
+ const cfg = readConfigUnlocked();
239
+ mutator(cfg);
240
+ const tempFile = `${CONFIG_FILE}.${process.pid}.tmp`;
241
+ writeFileSync(tempFile, serializeConfig(cfg), { mode: 384 });
242
+ renameSync(tempFile, CONFIG_FILE);
243
+ ensureSecurePermissions();
244
+ return cfg;
245
+ });
47
246
  }
48
247
  function getValue(cfg, dotPath) {
49
248
  const keys = dotPath.split(".");
@@ -57,16 +256,10 @@ function getValue(cfg, dotPath) {
57
256
  }
58
257
  return current;
59
258
  }
60
- function setValue(cfg, dotPath, value) {
61
- const keys = dotPath.split(".");
62
- let current = cfg;
63
- for (const key of keys.slice(0, -1)) {
64
- if (!(key in current) || typeof current[key] !== "object" || current[key] === null) {
65
- current[key] = {};
66
- }
67
- current = current[key];
68
- }
69
- current[keys[keys.length - 1]] = value;
259
+ function setValue(cfg, dotPath, value, options = {}) {
260
+ requireSupportedConfigKey(dotPath);
261
+ validateSensitiveConfigUpdate(dotPath, options.forceSensitive);
262
+ setKnownConfigValue(cfg, dotPath, value);
70
263
  }
71
264
  function requireConfig(...fields) {
72
265
  const cfg = loadConfig();
@@ -92,8 +285,24 @@ function configForDisplay(cfg) {
92
285
  }
93
286
  return display;
94
287
  }
288
+ function getActiveEntityId(cfg) {
289
+ if (cfg.workspace_id && cfg.active_entity_ids?.[cfg.workspace_id]) {
290
+ return cfg.active_entity_ids[cfg.workspace_id];
291
+ }
292
+ return cfg.active_entity_id;
293
+ }
294
+ function setActiveEntityId(cfg, entityId) {
295
+ cfg.active_entity_id = entityId;
296
+ if (!cfg.workspace_id) {
297
+ return;
298
+ }
299
+ cfg.active_entity_ids = {
300
+ ...cfg.active_entity_ids ?? {},
301
+ [cfg.workspace_id]: entityId
302
+ };
303
+ }
95
304
  function resolveEntityId(cfg, explicitId) {
96
- const eid = explicitId || cfg.active_entity_id;
305
+ const eid = explicitId || getActiveEntityId(cfg);
97
306
  if (!eid) {
98
307
  console.error(
99
308
  "No entity specified. Use --entity-id or set active_entity_id via 'corp config set active_entity_id <id>'."
@@ -102,21 +311,41 @@ function resolveEntityId(cfg, explicitId) {
102
311
  }
103
312
  return eid;
104
313
  }
105
- var CONFIG_DIR, CONFIG_FILE, DEFAULTS;
314
+ var CONFIG_DIR, CONFIG_FILE, CONFIG_LOCK_DIR, CONFIG_LOCK_TIMEOUT_MS, CONFIG_LOCK_RETRY_MS, CONFIG_WAIT_BUFFER, CONFIG_WAIT_SIGNAL, ALLOWED_CONFIG_KEYS, SENSITIVE_CONFIG_KEYS, DEFAULTS;
106
315
  var init_config = __esm({
107
316
  "src/config.ts"() {
108
317
  "use strict";
109
318
  CONFIG_DIR = process.env.CORP_CONFIG_DIR || join(homedir(), ".corp");
110
319
  CONFIG_FILE = join(CONFIG_DIR, "config.json");
320
+ CONFIG_LOCK_DIR = join(CONFIG_DIR, "config.lock");
321
+ CONFIG_LOCK_TIMEOUT_MS = 5e3;
322
+ CONFIG_LOCK_RETRY_MS = 25;
323
+ CONFIG_WAIT_BUFFER = new SharedArrayBuffer(4);
324
+ CONFIG_WAIT_SIGNAL = new Int32Array(CONFIG_WAIT_BUFFER);
325
+ ALLOWED_CONFIG_KEYS = /* @__PURE__ */ new Set([
326
+ "api_url",
327
+ "api_key",
328
+ "workspace_id",
329
+ "hosting_mode",
330
+ "llm.provider",
331
+ "llm.api_key",
332
+ "llm.model",
333
+ "llm.base_url",
334
+ "user.name",
335
+ "user.email",
336
+ "active_entity_id"
337
+ ]);
338
+ SENSITIVE_CONFIG_KEYS = /* @__PURE__ */ new Set(["api_url", "api_key", "workspace_id"]);
111
339
  DEFAULTS = {
112
340
  api_url: process.env.CORP_API_URL || "https://api.thecorporation.ai",
113
- api_key: "",
114
- workspace_id: "",
341
+ api_key: process.env.CORP_API_KEY || "",
342
+ workspace_id: process.env.CORP_WORKSPACE_ID || "",
115
343
  hosting_mode: "",
116
344
  llm: {
117
345
  provider: "anthropic",
118
- api_key: "",
119
- model: "claude-sonnet-4-6"
346
+ api_key: process.env.CORP_LLM_API_KEY || "",
347
+ model: "claude-sonnet-4-6",
348
+ base_url: process.env.CORP_LLM_BASE_URL || void 0
120
349
  },
121
350
  user: { name: "", email: "" },
122
351
  active_entity_id: ""
@@ -341,12 +570,12 @@ function printSafesTable(safes) {
341
570
  const table = makeTable("SAFE Notes", ["ID", "Investor", "Amount", "Cap", "Discount", "Date"]);
342
571
  for (const s_ of safes) {
343
572
  table.push([
344
- s(s_.safe_id ?? s_.id, 12),
573
+ s(s_.safe_note_id ?? s_.safe_id ?? s_.id, 12),
345
574
  s(s_.investor_name ?? s_.investor),
346
- money(s_.investment_amount ?? s_.amount, false),
347
- s(s_.valuation_cap ?? s_.cap),
575
+ money(s_.principal_amount_cents ?? s_.investment_amount ?? s_.amount, false),
576
+ money(s_.valuation_cap_cents ?? s_.valuation_cap ?? s_.cap, false),
348
577
  s(s_.discount_rate ?? s_.discount),
349
- s(s_.date ?? s_.created_at)
578
+ s(s_.issued_at ?? s_.date ?? s_.created_at)
350
579
  ]);
351
580
  }
352
581
  console.log(table.toString());
@@ -873,12 +1102,16 @@ var status_exports = {};
873
1102
  __export(status_exports, {
874
1103
  statusCommand: () => statusCommand
875
1104
  });
876
- async function statusCommand() {
1105
+ async function statusCommand(opts = {}) {
877
1106
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
878
1107
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
879
1108
  try {
880
1109
  const data = await withSpinner("Loading", () => client.getStatus());
881
- printStatusPanel(data);
1110
+ if (opts.json) {
1111
+ printJson(data);
1112
+ } else {
1113
+ printStatusPanel(data);
1114
+ }
882
1115
  } catch (err) {
883
1116
  printError(`Failed to fetch status: ${err}`);
884
1117
  process.exit(1);
@@ -909,7 +1142,8 @@ async function contextCommand(opts) {
909
1142
  client.getStatus(),
910
1143
  client.listEntities()
911
1144
  ]);
912
- const activeEntity = rawCfg.active_entity_id ? entities.find((entity) => entity.entity_id === rawCfg.active_entity_id) ?? null : null;
1145
+ const activeEntityId = getActiveEntityId(rawCfg);
1146
+ const activeEntity = activeEntityId ? entities.find((entity) => entity.entity_id === activeEntityId) ?? null : null;
913
1147
  const [contactsResult, documentsResult, workItemsResult] = activeEntity ? await Promise.allSettled([
914
1148
  client.listContacts(String(activeEntity.entity_id)),
915
1149
  client.getEntityDocuments(String(activeEntity.entity_id)),
@@ -1034,17 +1268,28 @@ var init_schema = __esm({
1034
1268
  });
1035
1269
 
1036
1270
  // src/commands/config.ts
1037
- var config_exports2 = {};
1038
- __export(config_exports2, {
1271
+ var config_exports = {};
1272
+ __export(config_exports, {
1039
1273
  configGetCommand: () => configGetCommand,
1040
1274
  configListCommand: () => configListCommand,
1041
1275
  configSetCommand: () => configSetCommand
1042
1276
  });
1043
- function configSetCommand(key, value) {
1044
- const cfg = loadConfig();
1045
- setValue(cfg, key, value);
1046
- saveConfig(cfg);
1047
- console.log(`${key} = ${value}`);
1277
+ function configSetCommand(key, value, options = {}) {
1278
+ try {
1279
+ updateConfig((cfg) => {
1280
+ setValue(cfg, key, value, {
1281
+ forceSensitive: options.force
1282
+ });
1283
+ });
1284
+ } catch (err) {
1285
+ printError(`Failed to update config: ${err}`);
1286
+ process.exit(1);
1287
+ }
1288
+ if (key === "api_key" || key === "llm.api_key") {
1289
+ console.log(`${key} updated.`);
1290
+ return;
1291
+ }
1292
+ console.log(`${key} updated.`);
1048
1293
  }
1049
1294
  function configGetCommand(key) {
1050
1295
  const cfg = loadConfig();
@@ -1114,8 +1359,10 @@ async function digestCommand(opts) {
1114
1359
  const value = result.message;
1115
1360
  return typeof value === "string" && value.trim() ? value : null;
1116
1361
  })();
1117
- printSuccess(result.digest_count > 0 ? "Digest triggered." : "Digest trigger accepted.");
1118
- if (message) {
1362
+ if (!opts.json) {
1363
+ printSuccess(result.digest_count > 0 ? "Digest triggered." : "Digest trigger accepted.");
1364
+ }
1365
+ if (message && !opts.json) {
1119
1366
  printWarning(message);
1120
1367
  }
1121
1368
  printJson(result);
@@ -1357,9 +1604,9 @@ async function executeTool(name, args, client) {
1357
1604
  dataDir: join2(homedir2(), ".corp"),
1358
1605
  onEntityFormed: (entityId) => {
1359
1606
  try {
1360
- const cfg = loadConfig();
1361
- cfg.active_entity_id = entityId;
1362
- saveConfig(cfg);
1607
+ updateConfig((cfg) => {
1608
+ setActiveEntityId(cfg, entityId);
1609
+ });
1363
1610
  } catch {
1364
1611
  }
1365
1612
  }
@@ -1388,7 +1635,7 @@ async function chatCommand() {
1388
1635
  const messages = [{ role: "system", content: SYSTEM_PROMPT }];
1389
1636
  let totalTokens = 0;
1390
1637
  const rl = createInterface({ input: process.stdin, output: process.stdout });
1391
- const prompt = () => new Promise((resolve2) => rl.question(chalk3.green.bold("> "), resolve2));
1638
+ const prompt = () => new Promise((resolve3) => rl.question(chalk3.green.bold("> "), resolve3));
1392
1639
  console.log(chalk3.blue.bold("corp chat") + " \u2014 type /help for commands, /quit to exit\n");
1393
1640
  const slashHandlers = {
1394
1641
  "/status": async () => {
@@ -1712,6 +1959,7 @@ async function contactsAddCommand(opts) {
1712
1959
  if (opts.phone) data.phone = opts.phone;
1713
1960
  if (opts.notes) data.notes = opts.notes;
1714
1961
  if (opts.mailingAddress ?? opts.address) data.mailing_address = opts.mailingAddress ?? opts.address;
1962
+ if (opts.capTableAccess) data.cap_table_access = opts.capTableAccess;
1715
1963
  const result = await client.createContact(data);
1716
1964
  printWriteResult(
1717
1965
  result,
@@ -1750,6 +1998,10 @@ async function contactsEditCommand(contactId, opts) {
1750
1998
  data.notes = opts.notes;
1751
1999
  hasUpdates = true;
1752
2000
  }
2001
+ if (opts.capTableAccess != null) {
2002
+ data.cap_table_access = opts.capTableAccess;
2003
+ hasUpdates = true;
2004
+ }
1753
2005
  if (opts.mailingAddress != null || opts.address != null) {
1754
2006
  data.mailing_address = opts.mailingAddress ?? opts.address;
1755
2007
  hasUpdates = true;
@@ -1780,6 +2032,7 @@ __export(cap_table_exports, {
1780
2032
  addSecurityCommand: () => addSecurityCommand,
1781
2033
  approveValuationCommand: () => approveValuationCommand,
1782
2034
  capTableCommand: () => capTableCommand,
2035
+ createInstrumentCommand: () => createInstrumentCommand,
1783
2036
  createValuationCommand: () => createValuationCommand,
1784
2037
  distributeCommand: () => distributeCommand,
1785
2038
  fourOhNineACommand: () => fourOhNineACommand,
@@ -1793,10 +2046,9 @@ __export(cap_table_exports, {
1793
2046
  transfersCommand: () => transfersCommand,
1794
2047
  valuationsCommand: () => valuationsCommand
1795
2048
  });
1796
- import { ensureSafeInstrument } from "@thecorporation/corp-tools";
1797
2049
  import chalk6 from "chalk";
1798
2050
  function normalizedGrantType(grantType) {
1799
- return grantType.trim().toLowerCase().replaceAll("-", "_");
2051
+ return grantType.trim().toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
1800
2052
  }
1801
2053
  function expectedInstrumentKinds(grantType) {
1802
2054
  switch (normalizedGrantType(grantType)) {
@@ -1806,8 +2058,11 @@ function expectedInstrumentKinds(grantType) {
1806
2058
  case "preferred":
1807
2059
  case "preferred_stock":
1808
2060
  return ["preferred_equity"];
2061
+ case "unit":
1809
2062
  case "membership_unit":
1810
2063
  return ["membership_unit"];
2064
+ case "option":
2065
+ case "options":
1811
2066
  case "stock_option":
1812
2067
  case "iso":
1813
2068
  case "nso":
@@ -1818,6 +2073,31 @@ function expectedInstrumentKinds(grantType) {
1818
2073
  return [];
1819
2074
  }
1820
2075
  }
2076
+ function grantRequiresCurrent409a(grantType, instrumentKind) {
2077
+ return instrumentKind?.toLowerCase() === "option_grant" || expectedInstrumentKinds(grantType).includes("option_grant");
2078
+ }
2079
+ function buildInstrumentCreationHint(grantType) {
2080
+ const normalized = normalizedGrantType(grantType);
2081
+ switch (normalized) {
2082
+ case "preferred":
2083
+ case "preferred_stock":
2084
+ return "Create one with: corp cap-table create-instrument --kind preferred_equity --symbol SERIES-A --authorized-units <shares>";
2085
+ case "option":
2086
+ case "options":
2087
+ case "stock_option":
2088
+ case "iso":
2089
+ case "nso":
2090
+ return "Create one with: corp cap-table create-instrument --kind option_grant --symbol OPTION-PLAN --authorized-units <shares>";
2091
+ case "membership_unit":
2092
+ case "unit":
2093
+ return "Create one with: corp cap-table create-instrument --kind membership_unit --symbol UNIT --authorized-units <units>";
2094
+ case "common":
2095
+ case "common_stock":
2096
+ return "Create one with: corp cap-table create-instrument --kind common_equity --symbol COMMON --authorized-units <shares>";
2097
+ default:
2098
+ return "Create a matching instrument first, then pass --instrument-id explicitly.";
2099
+ }
2100
+ }
1821
2101
  function resolveInstrumentForGrant(instruments, grantType, explicitInstrumentId) {
1822
2102
  if (explicitInstrumentId) {
1823
2103
  const explicit = instruments.find((instrument) => instrument.instrument_id === explicitInstrumentId);
@@ -1828,16 +2108,47 @@ function resolveInstrumentForGrant(instruments, grantType, explicitInstrumentId)
1828
2108
  }
1829
2109
  const expectedKinds = expectedInstrumentKinds(grantType);
1830
2110
  if (expectedKinds.length === 0) {
1831
- throw new Error(`No default instrument mapping exists for grant type "${grantType}". Pass --instrument-id explicitly.`);
2111
+ throw new Error(
2112
+ `No default instrument mapping exists for grant type "${grantType}". ${buildInstrumentCreationHint(grantType)}`
2113
+ );
1832
2114
  }
1833
2115
  const match = instruments.find((instrument) => expectedKinds.includes(String(instrument.kind).toLowerCase()));
1834
2116
  if (!match) {
1835
2117
  throw new Error(
1836
- `No instrument found for grant type "${grantType}". Expected one of: ${expectedKinds.join(", ")}.`
2118
+ `No instrument found for grant type "${grantType}". Expected one of: ${expectedKinds.join(", ")}. ${buildInstrumentCreationHint(grantType)}`
1837
2119
  );
1838
2120
  }
1839
2121
  return match;
1840
2122
  }
2123
+ async function entityHasActiveBoard(client, entityId) {
2124
+ const bodies = await client.listGovernanceBodies(entityId);
2125
+ return bodies.some(
2126
+ (body) => String(body.body_type ?? "").toLowerCase() === "board_of_directors" && String(body.status ?? "active").toLowerCase() === "active"
2127
+ );
2128
+ }
2129
+ async function ensureIssuancePreflight(client, entityId, grantType, instrument, meetingId, resolutionId) {
2130
+ if (!meetingId || !resolutionId) {
2131
+ if (await entityHasActiveBoard(client, entityId)) {
2132
+ throw new Error(
2133
+ "Board approval is required before issuing this round. Pass --meeting-id and --resolution-id from a passed board vote."
2134
+ );
2135
+ }
2136
+ }
2137
+ if (!grantRequiresCurrent409a(grantType, instrument?.kind)) {
2138
+ return;
2139
+ }
2140
+ try {
2141
+ await client.getCurrent409a(entityId);
2142
+ } catch (err) {
2143
+ const msg = String(err);
2144
+ if (msg.includes("404")) {
2145
+ throw new Error(
2146
+ "Stock option issuances require a current approved 409A valuation. Create and approve one first with: corp cap-table create-valuation --type four_oh_nine_a --date YYYY-MM-DD --methodology <method>; corp cap-table submit-valuation <id>; corp cap-table approve-valuation <id> --resolution-id <resolution-id>"
2147
+ );
2148
+ }
2149
+ throw err;
2150
+ }
2151
+ }
1841
2152
  async function capTableCommand(opts) {
1842
2153
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
1843
2154
  const eid = resolveEntityId(cfg, opts.entityId);
@@ -1950,7 +2261,7 @@ async function issueEquityCommand(opts) {
1950
2261
  }
1951
2262
  const instruments = capTable.instruments ?? [];
1952
2263
  if (!instruments.length) {
1953
- printError("No instruments found on cap table. Create an instrument first.");
2264
+ printError("No instruments found on cap table. Create one with: corp cap-table create-instrument --kind common_equity --symbol COMMON --authorized-units <shares>");
1954
2265
  process.exit(1);
1955
2266
  }
1956
2267
  const instrument = resolveInstrumentForGrant(instruments, opts.grantType, opts.instrumentId);
@@ -1958,6 +2269,14 @@ async function issueEquityCommand(opts) {
1958
2269
  if (!opts.instrumentId) {
1959
2270
  console.log(`Using instrument: ${instrument.symbol} (${instrument.kind})`);
1960
2271
  }
2272
+ await ensureIssuancePreflight(
2273
+ client,
2274
+ eid,
2275
+ opts.grantType,
2276
+ instrument,
2277
+ opts.meetingId,
2278
+ opts.resolutionId
2279
+ );
1961
2280
  const round = await client.startEquityRound({
1962
2281
  entity_id: eid,
1963
2282
  name: `${opts.grantType} grant \u2014 ${opts.recipient}`,
@@ -2006,33 +2325,25 @@ async function issueSafeCommand(opts) {
2006
2325
  });
2007
2326
  return;
2008
2327
  }
2009
- const capTable = await client.getCapTable(eid);
2010
- const issuerLegalEntityId = capTable.issuer_legal_entity_id;
2011
- if (!issuerLegalEntityId) {
2012
- printError("No issuer legal entity found. Has this entity been formed with a cap table?");
2013
- process.exit(1);
2014
- }
2015
- const safeInstrument = await ensureSafeInstrument(client, eid);
2016
- const round = await client.startEquityRound({
2017
- entity_id: eid,
2018
- name: `SAFE \u2014 ${opts.investor}`,
2019
- issuer_legal_entity_id: issuerLegalEntityId
2020
- });
2021
- const roundId = round.round_id ?? round.equity_round_id;
2022
- const securityData = {
2328
+ await ensureIssuancePreflight(
2329
+ client,
2330
+ eid,
2331
+ opts.safeType,
2332
+ void 0,
2333
+ opts.meetingId,
2334
+ opts.resolutionId
2335
+ );
2336
+ const body = {
2023
2337
  entity_id: eid,
2024
- instrument_id: safeInstrument.instrument_id,
2025
- quantity: opts.amount,
2026
- recipient_name: opts.investor,
2027
- principal_cents: opts.amount,
2028
- grant_type: opts.safeType
2338
+ investor_name: opts.investor,
2339
+ principal_amount_cents: opts.amount,
2340
+ valuation_cap_cents: opts.valuationCap,
2341
+ safe_type: opts.safeType
2029
2342
  };
2030
- if (opts.email) securityData.email = opts.email;
2031
- await client.addRoundSecurity(roundId, securityData);
2032
- const issuePayload = { entity_id: eid };
2033
- if (opts.meetingId) issuePayload.meeting_id = opts.meetingId;
2034
- if (opts.resolutionId) issuePayload.resolution_id = opts.resolutionId;
2035
- const result = await client.issueRound(roundId, issuePayload);
2343
+ if (opts.email) body.email = opts.email;
2344
+ if (opts.meetingId) body.meeting_id = opts.meetingId;
2345
+ if (opts.resolutionId) body.resolution_id = opts.resolutionId;
2346
+ const result = await client.createSafeNote(body);
2036
2347
  if (opts.json) {
2037
2348
  printJson(result);
2038
2349
  return;
@@ -2145,6 +2456,40 @@ async function startRoundCommand(opts) {
2145
2456
  process.exit(1);
2146
2457
  }
2147
2458
  }
2459
+ async function createInstrumentCommand(opts) {
2460
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
2461
+ const eid = resolveEntityId(cfg, opts.entityId);
2462
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
2463
+ try {
2464
+ let issuerLegalEntityId = opts.issuerLegalEntityId;
2465
+ if (!issuerLegalEntityId) {
2466
+ const capTable = await client.getCapTable(eid);
2467
+ issuerLegalEntityId = capTable.issuer_legal_entity_id;
2468
+ }
2469
+ if (!issuerLegalEntityId) {
2470
+ throw new Error("No issuer legal entity found. Has this entity been formed with a cap table?");
2471
+ }
2472
+ const terms = opts.termsJson ? JSON.parse(opts.termsJson) : {};
2473
+ const payload = {
2474
+ entity_id: eid,
2475
+ issuer_legal_entity_id: issuerLegalEntityId,
2476
+ kind: opts.kind,
2477
+ symbol: opts.symbol,
2478
+ terms
2479
+ };
2480
+ if (opts.authorizedUnits != null) payload.authorized_units = opts.authorizedUnits;
2481
+ if (opts.issuePriceCents != null) payload.issue_price_cents = opts.issuePriceCents;
2482
+ if (opts.dryRun) {
2483
+ printDryRun("cap_table.create_instrument", payload);
2484
+ return;
2485
+ }
2486
+ const result = await client.createInstrument(payload);
2487
+ printWriteResult(result, `Instrument created: ${result.instrument_id ?? "OK"}`, opts.json);
2488
+ } catch (err) {
2489
+ printError(`Failed to create instrument: ${err}`);
2490
+ process.exit(1);
2491
+ }
2492
+ }
2148
2493
  async function addSecurityCommand(opts) {
2149
2494
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
2150
2495
  const eid = resolveEntityId(cfg, opts.entityId);
@@ -2177,10 +2522,23 @@ async function issueRoundCommand(opts) {
2177
2522
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
2178
2523
  try {
2179
2524
  if (opts.dryRun) {
2180
- printDryRun("cap_table.issue_round", { entity_id: eid, round_id: opts.roundId });
2525
+ printDryRun("cap_table.issue_round", {
2526
+ entity_id: eid,
2527
+ round_id: opts.roundId,
2528
+ meeting_id: opts.meetingId,
2529
+ resolution_id: opts.resolutionId
2530
+ });
2181
2531
  return;
2182
2532
  }
2183
- const result = await client.issueRound(opts.roundId, { entity_id: eid });
2533
+ if ((!opts.meetingId || !opts.resolutionId) && await entityHasActiveBoard(client, eid)) {
2534
+ throw new Error(
2535
+ "Board approval is required before issuing this round. Pass --meeting-id and --resolution-id from a passed board vote."
2536
+ );
2537
+ }
2538
+ const body = { entity_id: eid };
2539
+ if (opts.meetingId) body.meeting_id = opts.meetingId;
2540
+ if (opts.resolutionId) body.resolution_id = opts.resolutionId;
2541
+ const result = await client.issueRound(opts.roundId, body);
2184
2542
  printWriteResult(result, "Round issued and closed", opts.json);
2185
2543
  } catch (err) {
2186
2544
  printError(`Failed to issue round: ${err}`);
@@ -2307,8 +2665,7 @@ async function financeInvoiceCommand(opts) {
2307
2665
  due_date: opts.dueDate,
2308
2666
  description: opts.description
2309
2667
  });
2310
- printSuccess(`Invoice created: ${result.invoice_id ?? "OK"}`);
2311
- printJson(result);
2668
+ printWriteResult(result, `Invoice created: ${result.invoice_id ?? "OK"}`, opts.json);
2312
2669
  } catch (err) {
2313
2670
  printError(`Failed to create invoice: ${err}`);
2314
2671
  process.exit(1);
@@ -2324,8 +2681,7 @@ async function financePayrollCommand(opts) {
2324
2681
  pay_period_start: opts.periodStart,
2325
2682
  pay_period_end: opts.periodEnd
2326
2683
  });
2327
- printSuccess(`Payroll run created: ${result.payroll_run_id ?? "OK"}`);
2328
- printJson(result);
2684
+ printWriteResult(result, `Payroll run created: ${result.payroll_run_id ?? "OK"}`, opts.json);
2329
2685
  } catch (err) {
2330
2686
  printError(`Failed to run payroll: ${err}`);
2331
2687
  process.exit(1);
@@ -2343,8 +2699,7 @@ async function financePayCommand(opts) {
2343
2699
  payment_method: opts.method,
2344
2700
  description: `Payment via ${opts.method}`
2345
2701
  });
2346
- printSuccess(`Payment submitted: ${result.payment_id ?? "OK"}`);
2347
- printJson(result);
2702
+ printWriteResult(result, `Payment submitted: ${result.payment_id ?? "OK"}`, opts.json);
2348
2703
  } catch (err) {
2349
2704
  printError(`Failed to submit payment: ${err}`);
2350
2705
  process.exit(1);
@@ -2356,8 +2711,7 @@ async function financeOpenAccountCommand(opts) {
2356
2711
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
2357
2712
  try {
2358
2713
  const result = await client.openBankAccount({ entity_id: eid, bank_name: opts.institution });
2359
- printSuccess(`Bank account opened: ${result.account_id ?? "OK"}`);
2360
- printJson(result);
2714
+ printWriteResult(result, `Bank account opened: ${result.account_id ?? "OK"}`, opts.json);
2361
2715
  } catch (err) {
2362
2716
  printError(`Failed to open bank account: ${err}`);
2363
2717
  process.exit(1);
@@ -2377,8 +2731,7 @@ async function financeClassifyContractorCommand(opts) {
2377
2731
  duration_months: opts.duration,
2378
2732
  provides_tools: opts.providesTools
2379
2733
  });
2380
- printSuccess(`Classification: ${result.risk_level ?? "OK"}`);
2381
- printJson(result);
2734
+ printWriteResult(result, `Classification: ${result.risk_level ?? "OK"}`, opts.json);
2382
2735
  } catch (err) {
2383
2736
  printError(`Failed to classify contractor: ${err}`);
2384
2737
  process.exit(1);
@@ -2394,8 +2747,7 @@ async function financeReconcileCommand(opts) {
2394
2747
  start_date: opts.startDate,
2395
2748
  end_date: opts.endDate
2396
2749
  });
2397
- printSuccess(`Ledger reconciled: ${result.reconciliation_id ?? "OK"}`);
2398
- printJson(result);
2750
+ printWriteResult(result, `Ledger reconciled: ${result.reconciliation_id ?? "OK"}`, opts.json);
2399
2751
  } catch (err) {
2400
2752
  printError(`Failed to reconcile ledger: ${err}`);
2401
2753
  process.exit(1);
@@ -3005,7 +3357,8 @@ __export(agents_exports, {
3005
3357
  agentsSkillCommand: () => agentsSkillCommand
3006
3358
  });
3007
3359
  import chalk8 from "chalk";
3008
- import { readFileSync as readFileSync2 } from "fs";
3360
+ import { readFileSync as readFileSync2, realpathSync } from "fs";
3361
+ import { relative, resolve } from "path";
3009
3362
  async function agentsListCommand(opts) {
3010
3363
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
3011
3364
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
@@ -3100,7 +3453,18 @@ function resolveTextInput(inlineText, filePath, label, required = false) {
3100
3453
  throw new Error(`Pass either --${label} or --${label}-file, not both.`);
3101
3454
  }
3102
3455
  if (filePath) {
3103
- return readFileSync2(filePath, "utf8");
3456
+ if (process.env.CORP_ALLOW_UNSAFE_FILE_INPUT === "1") {
3457
+ return readFileSync2(filePath, "utf8");
3458
+ }
3459
+ const resolvedFile = realpathSync(resolve(filePath));
3460
+ const workingTreeRoot = realpathSync(process.cwd());
3461
+ const rel = relative(workingTreeRoot, resolvedFile);
3462
+ if (rel === "" || !rel.startsWith("..") && !rel.startsWith("/")) {
3463
+ return readFileSync2(resolvedFile, "utf8");
3464
+ }
3465
+ throw new Error(
3466
+ `--${label}-file must stay inside the current working directory unless CORP_ALLOW_UNSAFE_FILE_INPUT=1 is set.`
3467
+ );
3104
3468
  }
3105
3469
  if (inlineText) {
3106
3470
  return inlineText;
@@ -3483,10 +3847,18 @@ function normalizeFounderInfo(input3) {
3483
3847
  function parseLegacyMemberSpec(raw) {
3484
3848
  const parts = raw.split(",").map((p) => p.trim());
3485
3849
  if (parts.length < 3) {
3486
- throw new Error(`Invalid member format: ${raw}. Expected: name,email,role[,pct]`);
3850
+ throw new Error(
3851
+ `Invalid member format: ${raw}. Expected: name,email,role[,pct[,address[,officer_title[,is_incorporator]]]]`
3852
+ );
3487
3853
  }
3488
3854
  const founder = { name: parts[0], email: parts[1], role: parts[2] };
3489
3855
  if (parts.length >= 4) founder.ownership_pct = parseFloat(parts[3]);
3856
+ if (parts.length >= 5 && parts[4]) founder.address = parseAddressValue(parts[4]);
3857
+ if (parts.length >= 6 && parts[5]) founder.officer_title = parts[5];
3858
+ if (parts.length >= 7) {
3859
+ const incorporator = parseBoolean(parts[6]);
3860
+ if (incorporator !== void 0) founder.is_incorporator = incorporator;
3861
+ }
3490
3862
  return founder;
3491
3863
  }
3492
3864
  function parseKeyValueMemberSpec(raw) {
@@ -3896,6 +4268,14 @@ async function formFinalizeCommand(entityId, opts) {
3896
4268
  payload.authorized_shares = authorizedShares;
3897
4269
  }
3898
4270
  if (opts.parValue) payload.par_value = opts.parValue;
4271
+ if (opts.boardSize) {
4272
+ const boardSize = parseInt(opts.boardSize, 10);
4273
+ if (!Number.isFinite(boardSize) || boardSize <= 0) {
4274
+ throw new Error(`Invalid board size: ${opts.boardSize}`);
4275
+ }
4276
+ payload.board_size = boardSize;
4277
+ }
4278
+ if (opts.principalName) payload.principal_name = opts.principalName;
3899
4279
  if (opts.registeredAgentName) payload.registered_agent_name = opts.registeredAgentName;
3900
4280
  if (opts.registeredAgentAddress) payload.registered_agent_address = opts.registeredAgentAddress;
3901
4281
  if (opts.formationDate) payload.formation_date = opts.formationDate;
@@ -4040,6 +4420,14 @@ __export(feedback_exports, {
4040
4420
  });
4041
4421
  import chalk12 from "chalk";
4042
4422
  async function feedbackCommand(message, opts) {
4423
+ if (!message || message.trim().length === 0) {
4424
+ printError("Feedback message cannot be empty");
4425
+ process.exit(1);
4426
+ }
4427
+ if (message.length > MAX_FEEDBACK_LENGTH) {
4428
+ printError(`Feedback message must be at most ${MAX_FEEDBACK_LENGTH} characters (got ${message.length})`);
4429
+ process.exit(1);
4430
+ }
4043
4431
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
4044
4432
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
4045
4433
  try {
@@ -4055,12 +4443,14 @@ ${chalk12.green("\u2713")} Feedback submitted (${chalk12.dim(result.feedback_id)
4055
4443
  process.exit(1);
4056
4444
  }
4057
4445
  }
4446
+ var MAX_FEEDBACK_LENGTH;
4058
4447
  var init_feedback = __esm({
4059
4448
  "src/commands/feedback.ts"() {
4060
4449
  "use strict";
4061
4450
  init_config();
4062
4451
  init_api_client();
4063
4452
  init_output();
4453
+ MAX_FEEDBACK_LENGTH = 1e4;
4064
4454
  }
4065
4455
  });
4066
4456
 
@@ -4070,7 +4460,7 @@ __export(serve_exports, {
4070
4460
  serveCommand: () => serveCommand
4071
4461
  });
4072
4462
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
4073
- import { resolve } from "path";
4463
+ import { resolve as resolve2 } from "path";
4074
4464
  import { randomBytes } from "crypto";
4075
4465
  function generateFernetKey() {
4076
4466
  return randomBytes(32).toString("base64url") + "=";
@@ -4122,35 +4512,21 @@ async function serveCommand(opts) {
4122
4512
  console.error(`Error: Invalid port "${opts.port}"`);
4123
4513
  process.exit(1);
4124
4514
  }
4125
- const envPath = resolve(process.cwd(), ".env");
4515
+ const envPath = resolve2(process.cwd(), ".env");
4126
4516
  ensureEnvFile(envPath);
4127
4517
  loadEnvFile(envPath);
4128
4518
  const localUrl = `http://localhost:${port}`;
4129
- const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
4130
- const cfg = loadConfig2();
4131
- const previousUrl = cfg.api_url;
4132
- if (cfg.api_url !== localUrl) {
4133
- cfg.api_url = localUrl;
4134
- saveConfig2(cfg);
4135
- console.log(`CLI configured to use local server: ${localUrl}`);
4136
- console.log(` (previous: ${previousUrl})`);
4137
- console.log(` To revert: corp config set api_url ${previousUrl}
4138
- `);
4139
- }
4140
4519
  console.log(`Starting server on port ${port}...`);
4141
4520
  console.log(`Data directory: ${opts.dataDir}`);
4521
+ console.log(`CLI API URL remains unchanged.`);
4522
+ console.log(` Use CORP_API_URL=${localUrl} for commands against this local server.
4523
+ `);
4142
4524
  const child = server.startServer({
4143
4525
  port,
4144
4526
  dataDir: opts.dataDir
4145
4527
  });
4146
4528
  const shutdown = () => {
4147
4529
  console.log("\nShutting down server...");
4148
- if (previousUrl !== localUrl) {
4149
- const current = loadConfig2();
4150
- current.api_url = previousUrl;
4151
- saveConfig2(current);
4152
- console.log(`CLI restored to: ${previousUrl}`);
4153
- }
4154
4530
  child.kill("SIGTERM");
4155
4531
  };
4156
4532
  process.on("SIGINT", shutdown);
@@ -4233,9 +4609,9 @@ program.command("setup").description("Interactive setup wizard").action(async ()
4233
4609
  const { setupCommand: setupCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
4234
4610
  await setupCommand2();
4235
4611
  });
4236
- program.command("status").description("Workspace summary").action(async () => {
4612
+ program.command("status").description("Workspace summary").option("--json", "Output as JSON").action(async (opts) => {
4237
4613
  const { statusCommand: statusCommand2 } = await Promise.resolve().then(() => (init_status(), status_exports));
4238
- await statusCommand2();
4614
+ await statusCommand2(opts);
4239
4615
  });
4240
4616
  program.command("context").alias("whoami").description("Show the active workspace, user, and entity context").option("--json", "Output as JSON").action(async (opts) => {
4241
4617
  const { contextCommand: contextCommand2 } = await Promise.resolve().then(() => (init_context(), context_exports));
@@ -4246,23 +4622,23 @@ program.command("schema").description("Dump the CLI command catalog as JSON").op
4246
4622
  schemaCommand2(program, opts);
4247
4623
  });
4248
4624
  var configCmd = program.command("config").description("Manage configuration");
4249
- configCmd.command("set <key> <value>").description("Set a config value (dot-path)").action(async (key, value) => {
4250
- const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
4251
- configSetCommand2(key, value);
4625
+ configCmd.command("set <key> <value>").description("Set a config value (dot-path)").option("--force", "Allow updating a security-sensitive config key").action(async (key, value, opts) => {
4626
+ const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
4627
+ configSetCommand2(key, value, opts);
4252
4628
  });
4253
4629
  configCmd.command("get <key>").description("Get a config value (dot-path)").action(async (key) => {
4254
- const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
4630
+ const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
4255
4631
  configGetCommand2(key);
4256
4632
  });
4257
4633
  configCmd.command("list").description("List all config (API keys masked)").action(async () => {
4258
- const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
4634
+ const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
4259
4635
  configListCommand2();
4260
4636
  });
4261
4637
  program.command("obligations").description("List obligations with urgency tiers").option("--tier <tier>", "Filter by urgency tier").option("--json", "Output as JSON").action(async (opts) => {
4262
4638
  const { obligationsCommand: obligationsCommand2 } = await Promise.resolve().then(() => (init_obligations(), obligations_exports));
4263
4639
  await obligationsCommand2(opts);
4264
4640
  });
4265
- program.command("digest").description("View or trigger daily digests").option("--trigger", "Trigger digest now").option("--key <key>", "Get specific digest by key").action(async (opts) => {
4641
+ program.command("digest").description("View or trigger daily digests").option("--trigger", "Trigger digest now").option("--key <key>", "Get specific digest by key").option("--json", "Output as JSON").action(async (opts) => {
4266
4642
  const { digestCommand: digestCommand2 } = await Promise.resolve().then(() => (init_digest(), digest_exports));
4267
4643
  await digestCommand2(opts);
4268
4644
  });
@@ -4311,7 +4687,7 @@ contactsCmd.command("show <contact-id>").option("--json", "Output as JSON").desc
4311
4687
  json: inheritOption(opts.json, parent.json)
4312
4688
  });
4313
4689
  });
4314
- contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requiredOption("--email <email>", "Contact email").option("--type <type>", "Contact type (individual, organization)", "individual").option("--category <category>", "Category (employee, contractor, board_member, investor, law_firm, valuation_firm, accounting_firm, officer, founder, member, other)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Add a new contact").action(async (opts, cmd) => {
4690
+ contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requiredOption("--email <email>", "Contact email").option("--type <type>", "Contact type (individual, organization)", "individual").option("--category <category>", "Category (employee, contractor, board_member, investor, law_firm, valuation_firm, accounting_firm, officer, founder, member, other)").option("--cap-table-access <level>", "Cap table access (none, summary, detailed)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Add a new contact").action(async (opts, cmd) => {
4315
4691
  const parent = cmd.parent.opts();
4316
4692
  const { contactsAddCommand: contactsAddCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
4317
4693
  await contactsAddCommand2({
@@ -4320,7 +4696,7 @@ contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requi
4320
4696
  json: inheritOption(opts.json, parent.json)
4321
4697
  });
4322
4698
  });
4323
- contactsCmd.command("edit <contact-id>").option("--name <name>", "Contact name").option("--email <email>", "Contact email").option("--category <category>", "Contact category").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Edit an existing contact").action(async (contactId, opts, cmd) => {
4699
+ contactsCmd.command("edit <contact-id>").option("--name <name>", "Contact name").option("--email <email>", "Contact email").option("--category <category>", "Contact category").option("--cap-table-access <level>", "Cap table access (none, summary, detailed)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Edit an existing contact").action(async (contactId, opts, cmd) => {
4324
4700
  const parent = cmd.parent.opts();
4325
4701
  const { contactsEditCommand: contactsEditCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
4326
4702
  await contactsEditCommand2(contactId, {
@@ -4353,6 +4729,15 @@ capTableCmd.command("409a").description("Current 409A valuation").action(async (
4353
4729
  const { fourOhNineACommand: fourOhNineACommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
4354
4730
  await fourOhNineACommand2(parent);
4355
4731
  });
4732
+ capTableCmd.command("create-instrument").requiredOption("--kind <kind>", "Instrument kind (common_equity, preferred_equity, membership_unit, option_grant, safe)").requiredOption("--symbol <symbol>", "Instrument symbol").option("--issuer-legal-entity-id <id>", "Issuer legal entity ID (auto-detected from the cap table if omitted)").option("--authorized-units <n>", "Authorized units", parseInt).option("--issue-price-cents <n>", "Issue price in cents", parseInt).option("--terms-json <json>", "JSON object of instrument terms").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the instrument").description("Create a cap table instrument").action(async (opts, cmd) => {
4733
+ const parent = cmd.parent.opts();
4734
+ const { createInstrumentCommand: createInstrumentCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
4735
+ await createInstrumentCommand2({
4736
+ ...opts,
4737
+ entityId: parent.entityId,
4738
+ json: inheritOption(opts.json, parent.json)
4739
+ });
4740
+ });
4356
4741
  capTableCmd.command("issue-equity").requiredOption("--grant-type <type>", "Grant type (common, preferred, membership_unit, stock_option, iso, nso, rsa)").requiredOption("--shares <n>", "Number of shares", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--email <email>", "Recipient email (auto-creates contact if needed)").option("--instrument-id <id>", "Instrument ID (auto-detected from cap table if omitted)").option("--meeting-id <id>", "Board meeting ID required when a board approval already exists or is being recorded").option("--resolution-id <id>", "Board resolution ID required when issuing under a board-governed entity").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the round").description("Issue an equity grant (creates a round, adds security, and issues it)").action(async (opts, cmd) => {
4357
4742
  const parent = cmd.parent.opts();
4358
4743
  const { issueEquityCommand: issueEquityCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
@@ -4407,7 +4792,7 @@ capTableCmd.command("add-security").requiredOption("--round-id <id>", "Round ID"
4407
4792
  json: inheritOption(opts.json, parent.json)
4408
4793
  });
4409
4794
  });
4410
- capTableCmd.command("issue-round").option("--json", "Output as JSON").option("--dry-run", "Show the request without issuing the round").requiredOption("--round-id <id>", "Round ID").description("Issue all securities and close a staged round").action(async (opts, cmd) => {
4795
+ capTableCmd.command("issue-round").option("--meeting-id <id>", "Board meeting ID required when issuing under a board-governed entity").option("--resolution-id <id>", "Board resolution ID required when issuing under a board-governed entity").option("--json", "Output as JSON").option("--dry-run", "Show the request without issuing the round").requiredOption("--round-id <id>", "Round ID").description("Issue all securities and close a staged round").action(async (opts, cmd) => {
4411
4796
  const parent = cmd.parent.opts();
4412
4797
  const { issueRoundCommand: issueRoundCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
4413
4798
  await issueRoundCommand2({
@@ -4445,36 +4830,60 @@ capTableCmd.command("approve-valuation <valuation-id>").option("--resolution-id
4445
4830
  json: inheritOption(opts.json, parent.json)
4446
4831
  });
4447
4832
  });
4448
- var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <id>", "Entity ID (overrides active entity)");
4449
- financeCmd.command("invoice").requiredOption("--customer <name>", "Customer name").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--due-date <date>", "Due date (ISO 8601)").option("--description <desc>", "Description", "Services rendered").description("Create an invoice").action(async (opts, cmd) => {
4833
+ var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON");
4834
+ financeCmd.command("invoice").requiredOption("--customer <name>", "Customer name").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--due-date <date>", "Due date (ISO 8601)").option("--description <desc>", "Description", "Services rendered").option("--json", "Output as JSON").description("Create an invoice").action(async (opts, cmd) => {
4450
4835
  const parent = cmd.parent.opts();
4451
4836
  const { financeInvoiceCommand: financeInvoiceCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4452
- await financeInvoiceCommand2({ ...opts, entityId: parent.entityId });
4837
+ await financeInvoiceCommand2({
4838
+ ...opts,
4839
+ entityId: parent.entityId,
4840
+ json: inheritOption(opts.json, parent.json)
4841
+ });
4453
4842
  });
4454
- financeCmd.command("payroll").requiredOption("--period-start <date>", "Pay period start").requiredOption("--period-end <date>", "Pay period end").description("Run payroll").action(async (opts, cmd) => {
4843
+ financeCmd.command("payroll").requiredOption("--period-start <date>", "Pay period start").requiredOption("--period-end <date>", "Pay period end").option("--json", "Output as JSON").description("Run payroll").action(async (opts, cmd) => {
4455
4844
  const parent = cmd.parent.opts();
4456
4845
  const { financePayrollCommand: financePayrollCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4457
- await financePayrollCommand2({ ...opts, entityId: parent.entityId });
4846
+ await financePayrollCommand2({
4847
+ ...opts,
4848
+ entityId: parent.entityId,
4849
+ json: inheritOption(opts.json, parent.json)
4850
+ });
4458
4851
  });
4459
- financeCmd.command("pay").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--method <method>", "Payment method", "ach").description("Submit a payment").action(async (opts, cmd) => {
4852
+ financeCmd.command("pay").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--method <method>", "Payment method", "ach").option("--json", "Output as JSON").description("Submit a payment").action(async (opts, cmd) => {
4460
4853
  const parent = cmd.parent.opts();
4461
4854
  const { financePayCommand: financePayCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4462
- await financePayCommand2({ ...opts, entityId: parent.entityId });
4855
+ await financePayCommand2({
4856
+ ...opts,
4857
+ entityId: parent.entityId,
4858
+ json: inheritOption(opts.json, parent.json)
4859
+ });
4463
4860
  });
4464
- financeCmd.command("open-account").option("--institution <name>", "Banking institution", "Mercury").description("Open a business bank account").action(async (opts, cmd) => {
4861
+ financeCmd.command("open-account").option("--institution <name>", "Banking institution", "Mercury").option("--json", "Output as JSON").description("Open a business bank account").action(async (opts, cmd) => {
4465
4862
  const parent = cmd.parent.opts();
4466
4863
  const { financeOpenAccountCommand: financeOpenAccountCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4467
- await financeOpenAccountCommand2({ ...opts, entityId: parent.entityId });
4864
+ await financeOpenAccountCommand2({
4865
+ ...opts,
4866
+ entityId: parent.entityId,
4867
+ json: inheritOption(opts.json, parent.json)
4868
+ });
4468
4869
  });
4469
- financeCmd.command("classify-contractor").requiredOption("--name <name>", "Contractor name").requiredOption("--state <code>", "US state code").requiredOption("--hours <n>", "Hours per week", parseInt).option("--exclusive", "Exclusive client", false).requiredOption("--duration <n>", "Duration in months", parseInt).option("--provides-tools", "Company provides tools", false).description("Analyze contractor classification risk").action(async (opts, cmd) => {
4870
+ financeCmd.command("classify-contractor").requiredOption("--name <name>", "Contractor name").requiredOption("--state <code>", "US state code").requiredOption("--hours <n>", "Hours per week", parseInt).option("--exclusive", "Exclusive client", false).requiredOption("--duration <n>", "Duration in months", parseInt).option("--provides-tools", "Company provides tools", false).option("--json", "Output as JSON").description("Analyze contractor classification risk").action(async (opts, cmd) => {
4470
4871
  const parent = cmd.parent.opts();
4471
4872
  const { financeClassifyContractorCommand: financeClassifyContractorCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4472
- await financeClassifyContractorCommand2({ ...opts, entityId: parent.entityId });
4873
+ await financeClassifyContractorCommand2({
4874
+ ...opts,
4875
+ entityId: parent.entityId,
4876
+ json: inheritOption(opts.json, parent.json)
4877
+ });
4473
4878
  });
4474
- financeCmd.command("reconcile").requiredOption("--start-date <date>", "Period start").requiredOption("--end-date <date>", "Period end").description("Reconcile ledger").action(async (opts, cmd) => {
4879
+ financeCmd.command("reconcile").requiredOption("--start-date <date>", "Period start").requiredOption("--end-date <date>", "Period end").option("--json", "Output as JSON").description("Reconcile ledger").action(async (opts, cmd) => {
4475
4880
  const parent = cmd.parent.opts();
4476
4881
  const { financeReconcileCommand: financeReconcileCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
4477
- await financeReconcileCommand2({ ...opts, entityId: parent.entityId });
4882
+ await financeReconcileCommand2({
4883
+ ...opts,
4884
+ entityId: parent.entityId,
4885
+ json: inheritOption(opts.json, parent.json)
4886
+ });
4478
4887
  });
4479
4888
  var governanceCmd = program.command("governance").description("Governance bodies, seats, meetings, resolutions").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
4480
4889
  const { governanceListCommand: governanceListCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
@@ -4790,23 +5199,35 @@ program.command("approvals").description("Approvals are managed through governan
4790
5199
  "Approvals are managed through governance meetings.\n Use: corp governance convene ... to schedule a board meeting\n Use: corp governance vote <meeting-id> <item-id> ... to cast votes"
4791
5200
  );
4792
5201
  });
4793
- var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--legal-name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Founder as 'name,email,role[,pct]' or key=value pairs like 'name=...,email=...,role=...,officer_title=cto,is_incorporator=true,address=street|city|state|zip' (repeatable)", (v, a) => [...a, v], []).option("--member-json <json>", "Founder JSON object (repeatable)", (v, a) => [...a, v], []).option("--members-file <path>", 'Path to a JSON array of founders or {"members": [...]}').option("--address <address>", "Company address as 'street,city,state,zip'").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)", "12-31").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the entity").action(async (opts) => {
5202
+ var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--legal-name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Founder as 'name,email,role[,pct[,address[,officer_title[,is_incorporator]]]]' with address as street|city|state|zip, or key=value pairs like 'name=...,email=...,role=...,officer_title=cto,is_incorporator=true,address=street|city|state|zip' (repeatable)", (v, a) => [...a, v], []).option("--member-json <json>", "Founder JSON object (repeatable)", (v, a) => [...a, v], []).option("--members-file <path>", 'Path to a JSON array of founders or {"members": [...]}').option("--address <address>", "Company address as 'street,city,state,zip'").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)", "12-31").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the entity").action(async (opts) => {
4794
5203
  if (opts.entityType && !opts.type) opts.type = opts.entityType;
4795
5204
  if (opts.legalName && !opts.name) opts.name = opts.legalName;
4796
5205
  const { formCommand: formCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
4797
5206
  await formCommand2(opts);
4798
5207
  });
4799
- formCmd.command("create").description("Create a pending entity (staged flow step 1)").requiredOption("--type <type>", "Entity type (llc, c_corp)").requiredOption("--name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the pending entity").action(async (opts) => {
5208
+ formCmd.command("create").description("Create a pending entity (staged flow step 1)").requiredOption("--type <type>", "Entity type (llc, c_corp)").requiredOption("--name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the pending entity").action(async (opts, cmd) => {
4800
5209
  const { formCreateCommand: formCreateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
4801
- await formCreateCommand2(opts);
5210
+ await formCreateCommand2({
5211
+ ...opts,
5212
+ json: inheritOption(opts.json, cmd.parent.opts().json),
5213
+ dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
5214
+ });
4802
5215
  });
4803
- formCmd.command("add-founder <entity-id>").description("Add a founder to a pending entity (staged flow step 2)").requiredOption("--name <name>", "Founder name").requiredOption("--email <email>", "Founder email").requiredOption("--role <role>", "Role: director|officer|manager|member|chair").requiredOption("--pct <pct>", "Ownership percentage").addOption(new Option("--officer-title <title>", "Officer title (corporations only)").choices(["ceo", "cfo", "cto", "coo", "secretary", "treasurer", "president", "vp", "other"])).option("--incorporator", "Mark as sole incorporator (corporations only)").option("--address <address>", "Founder address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without adding the founder").action(async (entityId, opts) => {
5216
+ formCmd.command("add-founder <entity-id>").description("Add a founder to a pending entity (staged flow step 2)").requiredOption("--name <name>", "Founder name").requiredOption("--email <email>", "Founder email").requiredOption("--role <role>", "Role: director|officer|manager|member|chair").requiredOption("--pct <pct>", "Ownership percentage").addOption(new Option("--officer-title <title>", "Officer title (corporations only)").choices(["ceo", "cfo", "cto", "coo", "secretary", "treasurer", "president", "vp", "other"])).option("--incorporator", "Mark as sole incorporator (corporations only)").option("--address <address>", "Founder address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without adding the founder").action(async (entityId, opts, cmd) => {
4804
5217
  const { formAddFounderCommand: formAddFounderCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
4805
- await formAddFounderCommand2(entityId, opts);
5218
+ await formAddFounderCommand2(entityId, {
5219
+ ...opts,
5220
+ json: inheritOption(opts.json, cmd.parent.opts().json),
5221
+ dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
5222
+ });
4806
5223
  });
4807
- formCmd.command("finalize <entity-id>").description("Finalize formation and generate documents + cap table (staged flow step 3)").option("--authorized-shares <count>", "Authorized shares for corporations").option("--par-value <value>", "Par value per share, e.g. 0.0001").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--incorporator-name <name>", "Incorporator legal name (overrides founder)").option("--incorporator-address <address>", "Incorporator mailing address (overrides founder)").option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing formation").action(async (entityId, opts) => {
5224
+ formCmd.command("finalize <entity-id>").description("Finalize formation and generate documents + cap table (staged flow step 3)").option("--authorized-shares <count>", "Authorized shares for corporations").option("--par-value <value>", "Par value per share, e.g. 0.0001").option("--board-size <count>", "Board size for corporations").option("--principal-name <name>", "Principal or manager name for LLCs").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--incorporator-name <name>", "Incorporator legal name (overrides founder)").option("--incorporator-address <address>", "Incorporator mailing address (overrides founder)").option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing formation").action(async (entityId, opts, cmd) => {
4808
5225
  const { formFinalizeCommand: formFinalizeCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
4809
- await formFinalizeCommand2(entityId, opts);
5226
+ await formFinalizeCommand2(entityId, {
5227
+ ...opts,
5228
+ json: inheritOption(opts.json, cmd.parent.opts().json),
5229
+ dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
5230
+ });
4810
5231
  });
4811
5232
  program.command("api-keys").description("List API keys").option("--json", "Output as JSON").action(async (opts) => {
4812
5233
  const { apiKeysCommand: apiKeysCommand2 } = await Promise.resolve().then(() => (init_api_keys(), api_keys_exports));
@@ -4824,5 +5245,5 @@ program.command("serve").description("Start the API server locally").option("--p
4824
5245
  const { serveCommand: serveCommand2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
4825
5246
  await serveCommand2(opts);
4826
5247
  });
4827
- program.parse();
5248
+ await program.parseAsync(process.argv);
4828
5249
  //# sourceMappingURL=index.js.map