@thecorporation/cli 26.3.23 → 26.3.24

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
@@ -3077,8 +3077,15 @@ async function digestCommand(opts) {
3077
3077
  printJson(result);
3078
3078
  } else {
3079
3079
  const digests = await client.listDigests();
3080
- if (digests.length === 0) console.log("No digest history found.");
3081
- else printJson(digests);
3080
+ if (digests.length === 0) {
3081
+ if (opts.json) {
3082
+ printJson([]);
3083
+ } else {
3084
+ console.log("No digest history found.");
3085
+ }
3086
+ } else {
3087
+ printJson(digests);
3088
+ }
3082
3089
  }
3083
3090
  } catch (err) {
3084
3091
  printError2(`Failed: ${err}`);
@@ -3128,6 +3135,12 @@ __export(claim_exports, {
3128
3135
  async function claimCommand(code) {
3129
3136
  const cfg = loadConfig();
3130
3137
  const apiUrl = (cfg.api_url || "https://api.thecorporation.ai").replace(/\/+$/, "");
3138
+ if (apiUrl.startsWith("process://")) {
3139
+ printError2(
3140
+ "Claim codes require a remote API server.\n Run: npx corp config set api_url https://api.thecorporation.ai --force\n Or use: npx corp setup"
3141
+ );
3142
+ process.exit(1);
3143
+ }
3131
3144
  try {
3132
3145
  const resp = await fetch(`${apiUrl}/v1/workspaces/claim`, {
3133
3146
  method: "POST",
@@ -4125,6 +4138,16 @@ async function issueEquityCommand(opts) {
4125
4138
  grant_type: opts.grantType
4126
4139
  };
4127
4140
  if (opts.email) securityData.email = opts.email;
4141
+ const existingHolders = capTable.holders ?? [];
4142
+ const matchingHolder = existingHolders.find((h) => {
4143
+ const nameMatch = String(h.name ?? "").toLowerCase() === opts.recipient.toLowerCase();
4144
+ const emailMatch = opts.email && String(h.email ?? "").toLowerCase() === opts.email.toLowerCase();
4145
+ return nameMatch || emailMatch;
4146
+ });
4147
+ if (matchingHolder) {
4148
+ const holderId = matchingHolder.holder_id ?? matchingHolder.contact_id ?? matchingHolder.id;
4149
+ if (holderId) securityData.holder_id = holderId;
4150
+ }
4128
4151
  await client.addRoundSecurity(roundId, securityData);
4129
4152
  const issuePayload = { entity_id: eid };
4130
4153
  if (meetingId) issuePayload.meeting_id = meetingId;
@@ -4613,6 +4636,10 @@ async function dilutionPreviewCommand(opts) {
4613
4636
  printJson(result);
4614
4637
  return;
4615
4638
  }
4639
+ if (result.round_status === "closed" || result.round_status === "issued") {
4640
+ console.log(chalk7.yellow("Note: This round is already closed. Dilution preview reflects the finalized state, not a scenario model."));
4641
+ console.log(chalk7.dim(" For scenario modeling, create a new round with: corp cap-table start-round --name '...' --issuer-legal-entity-id '...'"));
4642
+ }
4616
4643
  printJson(result);
4617
4644
  } catch (err) {
4618
4645
  printError2(`Failed to preview dilution: ${err}`);
@@ -4626,14 +4653,42 @@ async function controlMapCommand(opts) {
4626
4653
  try {
4627
4654
  const eid = await resolver.resolveEntity(opts.entityId);
4628
4655
  const rootEntityId = opts.rootEntityId ? await resolver.resolveEntity(opts.rootEntityId) : eid;
4629
- const result = await client.getControlMap(eid, rootEntityId);
4656
+ let result;
4657
+ try {
4658
+ result = await client.getControlMap(eid, rootEntityId);
4659
+ } catch (firstErr) {
4660
+ const msg = String(firstErr);
4661
+ if (msg.includes("404") && !opts.rootEntityId) {
4662
+ try {
4663
+ const capTable = await client.getCapTable(eid);
4664
+ const issuerLegalEntityId = capTable.issuer_legal_entity_id;
4665
+ if (issuerLegalEntityId && issuerLegalEntityId !== eid) {
4666
+ result = await client.getControlMap(eid, issuerLegalEntityId);
4667
+ } else {
4668
+ throw firstErr;
4669
+ }
4670
+ } catch {
4671
+ throw firstErr;
4672
+ }
4673
+ } else {
4674
+ throw firstErr;
4675
+ }
4676
+ }
4630
4677
  if (opts.json) {
4631
4678
  printJson(result);
4632
4679
  return;
4633
4680
  }
4634
4681
  printJson(result);
4635
4682
  } catch (err) {
4636
- printError2(`Failed to fetch control map: ${err}`);
4683
+ const msg = String(err);
4684
+ if (msg.includes("404") && (msg.includes("root_entity_id") || msg.includes("not found"))) {
4685
+ printError2(
4686
+ `Control map: entity not found. Ensure the entity is active and has a cap table.
4687
+ Try: corp cap-table control-map --root-entity-id <legal-entity-id>`
4688
+ );
4689
+ } else {
4690
+ printError2(`Failed to fetch control map: ${err}`);
4691
+ }
4637
4692
  process.exit(1);
4638
4693
  }
4639
4694
  }
@@ -5521,12 +5576,22 @@ async function writtenConsentCommand(opts) {
5521
5576
  const result = await client.writtenConsent(payload);
5522
5577
  await resolver.stabilizeRecord("meeting", result, eid);
5523
5578
  resolver.rememberFromRecord("meeting", result, eid);
5524
- const meetingId = result.meeting_id ?? "OK";
5579
+ const meetingId = String(result.meeting_id ?? "");
5580
+ if (meetingId) {
5581
+ try {
5582
+ const seats = await client.getGovernanceSeats(resolvedBodyId, eid);
5583
+ const seatIds = seats.map((s2) => String(s2.seat_id ?? s2.id ?? "")).filter((id) => id.length > 0);
5584
+ if (seatIds.length > 0) {
5585
+ await client.conveneMeeting(meetingId, eid, { present_seat_ids: seatIds });
5586
+ }
5587
+ } catch {
5588
+ }
5589
+ }
5525
5590
  if (opts.json) {
5526
5591
  printJson(result);
5527
5592
  return;
5528
5593
  }
5529
- printSuccess(`Written consent created: ${meetingId}`);
5594
+ printSuccess(`Written consent created: ${meetingId || "OK"}`);
5530
5595
  printReferenceSummary("meeting", result, { showReuseHint: true });
5531
5596
  console.log(chalk8.dim("\n Next steps:"));
5532
5597
  console.log(chalk8.dim(` corp governance agenda-items @last:meeting`));
@@ -5895,7 +5960,17 @@ async function documentsSigningLinkCommand(docId, opts) {
5895
5960
  const resolver = new ReferenceResolver(client, cfg);
5896
5961
  try {
5897
5962
  const eid = await resolver.resolveEntity(opts.entityId);
5898
- const resolvedDocumentId = await resolver.resolveDocument(eid, docId);
5963
+ let resolvedDocumentId;
5964
+ try {
5965
+ resolvedDocumentId = await resolver.resolveDocument(eid, docId);
5966
+ } catch {
5967
+ printError2(
5968
+ `Could not resolve '${docId}' as a document. If you just generated a contract, use the document_id from the generate output, not @last (which may reference the contract_id).
5969
+ List documents with: corp documents`
5970
+ );
5971
+ process.exit(1);
5972
+ return;
5973
+ }
5899
5974
  const result = await client.getSigningLink(resolvedDocumentId, eid);
5900
5975
  const shareUrl = formatSigningLink(resolvedDocumentId, result);
5901
5976
  if (process.stdout.isTTY) {
@@ -5940,13 +6015,33 @@ async function documentsGenerateCommand(opts) {
5940
6015
  });
5941
6016
  await resolver.stabilizeRecord("document", result, eid);
5942
6017
  resolver.rememberFromRecord("document", result, eid);
6018
+ if (result.document_id) {
6019
+ resolver.remember("document", String(result.document_id), eid);
6020
+ }
5943
6021
  printWriteResult(result, `Contract generated: ${result.contract_id ?? "OK"}`, {
5944
6022
  jsonOnly: opts.json,
5945
6023
  referenceKind: "document",
5946
6024
  showReuseHint: true
5947
6025
  });
5948
6026
  } catch (err) {
5949
- printError2(`Failed to generate contract: ${err}`);
6027
+ const msg = String(err);
6028
+ if (opts.template === "employment_offer" && (msg.includes("department") || msg.includes("required"))) {
6029
+ printError2(
6030
+ `Failed to generate employment_offer: ${msg}
6031
+ Hint: employment_offer requires additional parameters. Use --param for each:
6032
+ --param department=Engineering --param dispute_resolution_terms=arbitration
6033
+ --param equity_grant_type=stock_option --param equity_shares=10000
6034
+ Or pass --base-salary 150000`
6035
+ );
6036
+ } else if (opts.template === "safe_agreement" && (msg.includes("purchase_amount") || msg.includes("required"))) {
6037
+ printError2(
6038
+ `Failed to generate safe_agreement: ${msg}
6039
+ Hint: safe_agreement requires purchase_amount. Use:
6040
+ --param purchase_amount=50000000`
6041
+ );
6042
+ } else {
6043
+ printError2(`Failed to generate contract: ${err}`);
6044
+ }
5950
6045
  process.exit(1);
5951
6046
  }
5952
6047
  }
@@ -6283,7 +6378,15 @@ async function agentsCreateCommand(opts) {
6283
6378
  showReuseHint: true
6284
6379
  });
6285
6380
  } catch (err) {
6286
- printError2(`Failed to create agent: ${err}`);
6381
+ const msg = String(err);
6382
+ if (msg.includes("409") || msg.includes("conflict") || msg.includes("already exists")) {
6383
+ printError2(
6384
+ `Agent name '${opts.name}' is already in use (deleted agents still reserve their name).
6385
+ Choose a different name, e.g.: corp agents create --name '...-v2' --prompt '...'`
6386
+ );
6387
+ } else {
6388
+ printError2(`Failed to create agent: ${err}`);
6389
+ }
6287
6390
  process.exit(1);
6288
6391
  }
6289
6392
  }
@@ -6309,7 +6412,16 @@ async function agentsResumeCommand(agentId, opts) {
6309
6412
  const result = await client.updateAgent(resolvedAgentId, { status: "active" });
6310
6413
  printWriteResult(result, `Agent ${resolvedAgentId} resumed.`, opts.json);
6311
6414
  } catch (err) {
6312
- printError2(`Failed to resume agent: ${err}`);
6415
+ const msg = String(err);
6416
+ if (msg.includes("409") || msg.includes("disabled") || msg.includes("deleted")) {
6417
+ printError2(
6418
+ `Cannot resume agent ${agentId}: the agent may be disabled or deleted.
6419
+ Disabled/deleted agents cannot be resumed. Create a new agent instead:
6420
+ corp agents create --name '...' --prompt '...'`
6421
+ );
6422
+ } else {
6423
+ printError2(`Failed to resume agent: ${err}`);
6424
+ }
6313
6425
  process.exit(1);
6314
6426
  }
6315
6427
  }
@@ -6372,7 +6484,15 @@ async function agentsMessageCommand(agentId, opts) {
6372
6484
  const result = await client.sendAgentMessage(resolvedAgentId, body);
6373
6485
  printWriteResult(result, `Message sent. Execution: ${result.execution_id ?? "OK"}`, opts.json);
6374
6486
  } catch (err) {
6375
- printError2(`Failed to send message: ${err}`);
6487
+ const msg = String(err);
6488
+ if (msg.includes("409")) {
6489
+ printError2(
6490
+ `Cannot message agent: the agent must be active or paused (not disabled/deleted).
6491
+ Check agent status: corp agents show ` + agentId + "\n Resume a paused agent: corp agents resume " + agentId
6492
+ );
6493
+ } else {
6494
+ printError2(`Failed to send message: ${err}`);
6495
+ }
6376
6496
  process.exit(1);
6377
6497
  }
6378
6498
  }
@@ -7297,18 +7417,33 @@ async function formCommand(opts) {
7297
7417
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
7298
7418
  const resolver = new ReferenceResolver(client, cfg);
7299
7419
  try {
7420
+ if (opts.type && !SUPPORTED_ENTITY_TYPES.includes(opts.type)) {
7421
+ printError2(`Unsupported entity type '${opts.type}'. Supported types: ${SUPPORTED_ENTITY_TYPES.join(", ")}`);
7422
+ process.exit(1);
7423
+ }
7424
+ if (opts.name != null && !opts.name.trim()) {
7425
+ printError2("--name cannot be empty or whitespace");
7426
+ process.exit(1);
7427
+ }
7300
7428
  let serverCfg = {};
7301
7429
  try {
7302
7430
  serverCfg = await client.getConfig();
7303
7431
  } catch {
7304
7432
  }
7305
- const scripted = Boolean(
7433
+ const hasMembers = Boolean(
7306
7434
  opts.member && opts.member.length > 0 || opts.memberJson && opts.memberJson.length > 0 || opts.membersFile
7307
7435
  );
7436
+ const scripted = hasMembers || opts.json || opts.dryRun || !process.stdout.isTTY;
7437
+ if (scripted && !hasMembers) {
7438
+ printError2("At least one --member, --member-json, or --members-file is required in non-interactive mode.");
7439
+ process.exit(1);
7440
+ }
7308
7441
  const { entityType, name, jurisdiction, companyAddress, fiscalYearEnd, sCorpElection } = await phaseEntityDetails(opts, serverCfg, scripted);
7309
7442
  const founders = await phasePeople(opts, entityType, scripted);
7310
7443
  const { transferRestrictions, rofr } = await phaseStock(opts, entityType, founders, scripted);
7311
- printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr);
7444
+ if (!opts.quiet) {
7445
+ printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr);
7446
+ }
7312
7447
  const shouldProceed = scripted ? true : await confirm6({ message: "Proceed with formation?", default: true });
7313
7448
  if (!shouldProceed) {
7314
7449
  console.log(chalk13.yellow("Formation cancelled."));
@@ -7354,6 +7489,11 @@ async function formCommand(opts) {
7354
7489
  saveConfig(cfg);
7355
7490
  console.log(chalk13.dim(` Active entity set to ${result.entity_id}`));
7356
7491
  }
7492
+ if (opts.quiet) {
7493
+ const id = result.entity_id ?? result.formation_id;
7494
+ if (id) console.log(String(id));
7495
+ return;
7496
+ }
7357
7497
  if (opts.json) {
7358
7498
  printJson(result);
7359
7499
  return;
@@ -7387,7 +7527,17 @@ async function formCommand(opts) {
7387
7527
  }
7388
7528
  } catch (err) {
7389
7529
  if (err instanceof Error && err.message.includes("exit")) throw err;
7390
- printError2(`Failed to create formation: ${err}`);
7530
+ const msg = String(err);
7531
+ if (msg.includes("officers_list") || msg.includes("officer")) {
7532
+ printError2(
7533
+ `Formation failed: ${msg}
7534
+ Hint: C-Corp directors need an officer_title. Use --member with officer_title field, e.g.:
7535
+ --member 'name=Alice,email=a@co.com,role=director,officer_title=ceo,pct=100'
7536
+ Or use --member-json with {"officer_title": "ceo"}`
7537
+ );
7538
+ } else {
7539
+ printError2(`Failed to create formation: ${err}`);
7540
+ }
7391
7541
  process.exit(1);
7392
7542
  }
7393
7543
  }
@@ -7447,6 +7597,11 @@ async function formCreateCommand(opts) {
7447
7597
  setActiveEntityId(cfg, String(result.entity_id));
7448
7598
  saveConfig(cfg);
7449
7599
  }
7600
+ if (opts.quiet) {
7601
+ const id = result.entity_id;
7602
+ if (id) console.log(String(id));
7603
+ return;
7604
+ }
7450
7605
  if (opts.json) {
7451
7606
  printJson(result);
7452
7607
  return;
@@ -7573,7 +7728,16 @@ async function formFinalizeCommand(entityId, opts) {
7573
7728
  Next: ${result.next_action}`));
7574
7729
  }
7575
7730
  } catch (err) {
7576
- printError2(`Failed to finalize formation: ${err}`);
7731
+ const msg = String(err);
7732
+ if (msg.includes("officers_list") || msg.includes("officer")) {
7733
+ printError2(
7734
+ `Finalization failed: ${msg}
7735
+ Hint: C-Corp entities require at least one founder with an officer_title.
7736
+ Add a founder with: corp form add-founder @last:entity --name '...' --email '...' --role director --pct 100 --officer-title ceo`
7737
+ );
7738
+ } else {
7739
+ printError2(`Failed to finalize formation: ${err}`);
7740
+ }
7577
7741
  process.exit(1);
7578
7742
  }
7579
7743
  }
@@ -7625,6 +7789,7 @@ async function formActivateCommand(entityId, opts) {
7625
7789
  process.exit(1);
7626
7790
  }
7627
7791
  }
7792
+ var SUPPORTED_ENTITY_TYPES;
7628
7793
  var init_form = __esm({
7629
7794
  "src/commands/form.ts"() {
7630
7795
  "use strict";
@@ -7633,6 +7798,7 @@ var init_form = __esm({
7633
7798
  init_output();
7634
7799
  init_references();
7635
7800
  init_formation_automation();
7801
+ SUPPORTED_ENTITY_TYPES = ["llc", "c_corp", "s_corp", "corporation"];
7636
7802
  }
7637
7803
  });
7638
7804
 
@@ -7750,14 +7916,26 @@ function scenarioConfig(name, scenario) {
7750
7916
  email: "alice@example.com",
7751
7917
  role: "member",
7752
7918
  investor_type: "natural_person",
7753
- ownership_pct: 60
7919
+ ownership_pct: 60,
7920
+ address: {
7921
+ street: "251 Little Falls Dr",
7922
+ city: "Wilmington",
7923
+ state: "DE",
7924
+ zip: "19808"
7925
+ }
7754
7926
  },
7755
7927
  {
7756
7928
  name: "Bob Martinez",
7757
7929
  email: "bob@example.com",
7758
7930
  role: "member",
7759
7931
  investor_type: "natural_person",
7760
- ownership_pct: 40
7932
+ ownership_pct: 40,
7933
+ address: {
7934
+ street: "251 Little Falls Dr",
7935
+ city: "Wilmington",
7936
+ state: "DE",
7937
+ zip: "19808"
7938
+ }
7761
7939
  }
7762
7940
  ],
7763
7941
  fiscal_year_end: "12-31",
@@ -7779,14 +7957,26 @@ function scenarioConfig(name, scenario) {
7779
7957
  email: "rosa@example.com",
7780
7958
  role: "manager",
7781
7959
  investor_type: "natural_person",
7782
- ownership_pct: 55
7960
+ ownership_pct: 55,
7961
+ address: {
7962
+ street: "18 Market St",
7963
+ city: "Wilmington",
7964
+ state: "DE",
7965
+ zip: "19801"
7966
+ }
7783
7967
  },
7784
7968
  {
7785
7969
  name: "Noah Patel",
7786
7970
  email: "noah@example.com",
7787
7971
  role: "member",
7788
7972
  investor_type: "natural_person",
7789
- ownership_pct: 45
7973
+ ownership_pct: 45,
7974
+ address: {
7975
+ street: "18 Market St",
7976
+ city: "Wilmington",
7977
+ state: "DE",
7978
+ zip: "19801"
7979
+ }
7790
7980
  }
7791
7981
  ],
7792
7982
  fiscal_year_end: "12-31",
@@ -7815,7 +8005,13 @@ function scenarioConfig(name, scenario) {
7815
8005
  investor_type: "natural_person",
7816
8006
  shares_purchased: 6e6,
7817
8007
  officer_title: "ceo",
7818
- is_incorporator: true
8008
+ is_incorporator: true,
8009
+ address: {
8010
+ street: "251 Little Falls Dr",
8011
+ city: "Wilmington",
8012
+ state: "DE",
8013
+ zip: "19808"
8014
+ }
7819
8015
  },
7820
8016
  {
7821
8017
  name: "Bob Martinez",
@@ -7823,7 +8019,13 @@ function scenarioConfig(name, scenario) {
7823
8019
  role: "director",
7824
8020
  investor_type: "natural_person",
7825
8021
  shares_purchased: 4e6,
7826
- officer_title: "cto"
8022
+ officer_title: "cto",
8023
+ address: {
8024
+ street: "251 Little Falls Dr",
8025
+ city: "Wilmington",
8026
+ state: "DE",
8027
+ zip: "19808"
8028
+ }
7827
8029
  }
7828
8030
  ],
7829
8031
  fiscal_year_end: "12-31",
@@ -8134,8 +8336,11 @@ var FINALIZE_ITEM_STATUS_CHOICES = [
8134
8336
  "withdrawn"
8135
8337
  ];
8136
8338
  var program = new Command();
8137
- program.name("corp").description("corp \u2014 Corporate governance from the terminal").version(pkg.version);
8339
+ program.name("corp").description("corp \u2014 Corporate governance from the terminal").version(pkg.version).enablePositionalOptions();
8138
8340
  program.option("-q, --quiet", "Only output the resource ID (for scripting)");
8341
+ program.action(() => {
8342
+ program.outputHelp();
8343
+ });
8139
8344
  program.command("setup").description("Interactive setup wizard").action(async () => {
8140
8345
  const { setupCommand: setupCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
8141
8346
  await setupCommand2();
@@ -8181,7 +8386,7 @@ program.command("obligations").description("List obligations with urgency tiers"
8181
8386
  const { obligationsCommand: obligationsCommand2 } = await Promise.resolve().then(() => (init_obligations(), obligations_exports));
8182
8387
  await obligationsCommand2(opts);
8183
8388
  });
8184
- 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) => {
8389
+ program.command("digest").description("View or trigger daily digests").option("--trigger", "Trigger digest now").option("--key <key>", "Get specific digest by key").option("--entity-id <ref>", "Entity reference (ID, short ID, @last, or unique name)").option("--json", "Output as JSON").action(async (opts) => {
8185
8390
  const { digestCommand: digestCommand2 } = await Promise.resolve().then(() => (init_digest(), digest_exports));
8186
8391
  await digestCommand2(opts);
8187
8392
  });
@@ -8469,12 +8674,17 @@ financeCmd.command("invoices").option("--json", "Output as JSON").description("L
8469
8674
  json: inheritOption(opts.json, parent.json)
8470
8675
  });
8471
8676
  });
8472
- financeCmd.command("invoice").requiredOption("--customer <name>", "Customer name").requiredOption("--amount-cents <n>", "Amount in cents (e.g. 500000 = $5,000.00)", parseInt).option("--amount <n>", "", 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) => {
8677
+ financeCmd.command("invoice").requiredOption("--customer <name>", "Customer name").option("--amount-cents <n>", "Amount in cents (e.g. 500000 = $5,000.00)", parseInt).option("--amount <n>", "Amount in dollars (converted to 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) => {
8473
8678
  const parent = cmd.parent.opts();
8679
+ const amountCents = opts.amountCents ?? (opts.amount != null ? opts.amount * 100 : void 0);
8680
+ if (amountCents == null) {
8681
+ cmd.error("required option '--amount-cents <n>' or '--amount <n>' not specified");
8682
+ return;
8683
+ }
8474
8684
  const { financeInvoiceCommand: financeInvoiceCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
8475
8685
  await financeInvoiceCommand2({
8476
8686
  ...opts,
8477
- amountCents: opts.amountCents ?? opts.amount,
8687
+ amountCents,
8478
8688
  entityId: parent.entityId,
8479
8689
  json: inheritOption(opts.json, parent.json)
8480
8690
  });
@@ -8506,12 +8716,17 @@ financeCmd.command("payments").option("--json", "Output as JSON").description("L
8506
8716
  json: inheritOption(opts.json, parent.json)
8507
8717
  });
8508
8718
  });
8509
- financeCmd.command("pay").requiredOption("--amount-cents <n>", "Amount in cents (e.g. 500000 = $5,000.00)", parseInt).option("--amount <n>", "", 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) => {
8719
+ financeCmd.command("pay").option("--amount-cents <n>", "Amount in cents (e.g. 500000 = $5,000.00)", parseInt).option("--amount <n>", "Amount in dollars (converted to 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) => {
8510
8720
  const parent = cmd.parent.opts();
8721
+ const amountCents = opts.amountCents ?? (opts.amount != null ? opts.amount * 100 : void 0);
8722
+ if (amountCents == null) {
8723
+ cmd.error("required option '--amount-cents <n>' or '--amount <n>' not specified");
8724
+ return;
8725
+ }
8511
8726
  const { financePayCommand: financePayCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
8512
8727
  await financePayCommand2({
8513
8728
  ...opts,
8514
- amountCents: opts.amountCents ?? opts.amount,
8729
+ amountCents,
8515
8730
  entityId: parent.entityId,
8516
8731
  json: inheritOption(opts.json, parent.json)
8517
8732
  });
@@ -8570,7 +8785,7 @@ financeCmd.command("reconciliations").option("--json", "Output as JSON").descrip
8570
8785
  json: inheritOption(opts.json, parent.json)
8571
8786
  });
8572
8787
  });
8573
- 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) => {
8788
+ financeCmd.command("reconcile").requiredOption("--start-date <date>", "Period start (required, ISO 8601)").requiredOption("--end-date <date>", "Period end (required, ISO 8601)").option("--json", "Output as JSON").description("Reconcile ledger (requires --start-date and --end-date)").action(async (opts, cmd) => {
8574
8789
  const parent = cmd.parent.opts();
8575
8790
  const { financeReconcileCommand: financeReconcileCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
8576
8791
  await financeReconcileCommand2({
@@ -8872,11 +9087,16 @@ taxCmd.command("deadlines").option("--json", "Output as JSON").description("List
8872
9087
  json: inheritOption(opts.json, parent.json)
8873
9088
  });
8874
9089
  });
8875
- taxCmd.command("deadline").requiredOption("--type <type>", "Deadline type").requiredOption("--due-date <date>", "Due date (ISO 8601)").requiredOption("--description <desc>", "Description").option("--recurrence <recurrence>", "Recurrence (e.g. annual; 'yearly' is normalized)").option("--json", "Output as JSON").description("Track a compliance deadline").action(async (opts, cmd) => {
9090
+ taxCmd.command("deadline").requiredOption("--type <type>", "Deadline type").requiredOption("--due-date <date>", "Due date (ISO 8601)").requiredOption("--description <desc>", "Description").option("--recurrence <recurrence>", "Recurrence (e.g. annual; 'yearly' is normalized). Required for annual_report type.").option("--json", "Output as JSON").description("Track a compliance deadline").action(async (opts, cmd) => {
8876
9091
  const parent = cmd.parent.opts();
9092
+ let recurrence = opts.recurrence;
9093
+ if (!recurrence && opts.type === "annual_report") {
9094
+ recurrence = "annual";
9095
+ }
8877
9096
  const { taxDeadlineCommand: taxDeadlineCommand2 } = await Promise.resolve().then(() => (init_tax(), tax_exports));
8878
9097
  await taxDeadlineCommand2({
8879
9098
  ...opts,
9099
+ recurrence,
8880
9100
  entityId: parent.entityId,
8881
9101
  json: inheritOption(opts.json, parent.json)
8882
9102
  });
@@ -8983,12 +9203,17 @@ workItemsCmd.command("show <item-ref>").option("--json", "Output as JSON").descr
8983
9203
  json: inheritOption(opts.json, parent.json)
8984
9204
  });
8985
9205
  });
8986
- workItemsCmd.command("create").requiredOption("--title <title>", "Work item title").requiredOption("--category <category>", "Work item category").option("--description <desc>", "Description").option("--deadline <date>", "Deadline (YYYY-MM-DD)").option("--asap", "Mark as ASAP priority").option("--created-by <name>", "Creator identifier").option("--json", "Output as JSON").description("Create a new work item").action(async (opts, cmd) => {
9206
+ workItemsCmd.command("create").requiredOption("--title <title>", "Work item title").option("--category <category>", "Work item category").option("--description <desc>", "Description").option("--deadline <date>", "Deadline (YYYY-MM-DD)").option("--asap", "Mark as ASAP priority").option("--created-by <name>", "Creator identifier").option("--json", "Output as JSON").description("Create a new work item").action(async (opts, cmd) => {
8987
9207
  const parent = cmd.parent.opts();
9208
+ const resolvedCategory = inheritOption(opts.category, parent.category);
9209
+ if (!resolvedCategory) {
9210
+ cmd.error("required option '--category <category>' not specified");
9211
+ return;
9212
+ }
8988
9213
  const { workItemsCreateCommand: workItemsCreateCommand2 } = await Promise.resolve().then(() => (init_work_items(), work_items_exports));
8989
9214
  await workItemsCreateCommand2({
8990
9215
  ...opts,
8991
- category: inheritOption(opts.category, parent.category),
9216
+ category: resolvedCategory,
8992
9217
  entityId: parent.entityId,
8993
9218
  json: inheritOption(opts.json, parent.json)
8994
9219
  });
@@ -9119,22 +9344,44 @@ program.command("approvals").description("Approvals are managed through governan
9119
9344
  const { approvalsListCommand: approvalsListCommand2 } = await Promise.resolve().then(() => (init_approvals(), approvals_exports));
9120
9345
  await approvalsListCommand2({});
9121
9346
  });
9122
- var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--type <type>", "Entity type (llc, c_corp)").option("--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) => {
9347
+ var formCmd = program.command("form").enablePositionalOptions().passThroughOptions().description("Form a new entity with founders and cap table").option("--type <type>", "Entity type (llc, c_corp)").option("--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, cmd) => {
9123
9348
  const { formCommand: formCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
9124
- await formCommand2(opts);
9349
+ await formCommand2({ ...opts, quiet: program.opts().quiet });
9125
9350
  });
9126
- 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) => {
9351
+ formCmd.command("create").description("Create a pending entity (staged flow step 1)").option("--type <type>", "Entity type (llc, c_corp)").option("--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) => {
9127
9352
  const parent = cmd.parent.opts();
9353
+ const resolvedType = inheritOption(opts.type, parent.type);
9354
+ const resolvedName = inheritOption(opts.name, parent.name);
9355
+ if (!resolvedType) {
9356
+ cmd.error("required option '--type <type>' not specified");
9357
+ return;
9358
+ }
9359
+ const SUPPORTED_ENTITY_TYPES2 = ["llc", "c_corp", "s_corp", "corporation"];
9360
+ if (!SUPPORTED_ENTITY_TYPES2.includes(resolvedType)) {
9361
+ cmd.error(`unsupported entity type '${resolvedType}'. Supported types: ${SUPPORTED_ENTITY_TYPES2.join(", ")}`);
9362
+ return;
9363
+ }
9364
+ if (!resolvedName) {
9365
+ cmd.error("required option '--name <name>' not specified");
9366
+ return;
9367
+ }
9368
+ if (!resolvedName.trim()) {
9369
+ cmd.error("--name cannot be empty or whitespace");
9370
+ return;
9371
+ }
9128
9372
  const { formCreateCommand: formCreateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
9129
9373
  await formCreateCommand2({
9130
9374
  ...opts,
9375
+ type: resolvedType,
9376
+ name: resolvedName,
9131
9377
  jurisdiction: inheritOption(opts.jurisdiction, parent.jurisdiction),
9132
9378
  fiscalYearEnd: inheritOption(opts.fiscalYearEnd, parent.fiscalYearEnd),
9133
9379
  sCorp: inheritOption(opts.sCorp, parent.sCorp),
9134
9380
  transferRestrictions: inheritOption(opts.transferRestrictions, parent.transferRestrictions),
9135
9381
  rofr: inheritOption(opts.rofr, parent.rofr),
9136
9382
  json: inheritOption(opts.json, parent.json),
9137
- dryRun: inheritOption(opts.dryRun, parent.dryRun)
9383
+ dryRun: inheritOption(opts.dryRun, parent.dryRun),
9384
+ quiet: program.opts().quiet
9138
9385
  });
9139
9386
  });
9140
9387
  formCmd.command("add-founder <entity-ref>").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) => {