@fairmint/captable-ai 0.1.10 → 0.1.12
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 +181 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -599,6 +599,22 @@ var COMMAND_REGISTRY = [
|
|
|
599
599
|
}
|
|
600
600
|
]
|
|
601
601
|
},
|
|
602
|
+
{
|
|
603
|
+
name: "objects review-non-cash",
|
|
604
|
+
group: "captable",
|
|
605
|
+
description: "List unmarked convertible issuances whose stored evidence suggests possible non-cash consideration.",
|
|
606
|
+
usage: "captable-ai objects review-non-cash [--status draft|committed] [--json]",
|
|
607
|
+
requiresAuth: true,
|
|
608
|
+
requiresPortal: true,
|
|
609
|
+
flags: [
|
|
610
|
+
{
|
|
611
|
+
name: "status",
|
|
612
|
+
description: "Review only latest draft or committed objects.",
|
|
613
|
+
type: "string",
|
|
614
|
+
enum: ["draft", "committed"]
|
|
615
|
+
}
|
|
616
|
+
]
|
|
617
|
+
},
|
|
602
618
|
{
|
|
603
619
|
name: "objects get",
|
|
604
620
|
group: "captable",
|
|
@@ -16575,7 +16591,10 @@ var warrantResolutionItemSchema = external_exports.object({
|
|
|
16575
16591
|
amount: external_exports.string(),
|
|
16576
16592
|
currency: external_exports.string()
|
|
16577
16593
|
}).nullable(),
|
|
16578
|
-
relatedSecurityId: external_exports.string().nullable()
|
|
16594
|
+
relatedSecurityId: external_exports.string().nullable(),
|
|
16595
|
+
// Present only on warrants whose deferred percentage exercise could not be replayed. They
|
|
16596
|
+
// are listed but excluded from the counts below, since they contribute no diluted shares.
|
|
16597
|
+
replayFailed: external_exports.boolean().optional()
|
|
16579
16598
|
});
|
|
16580
16599
|
var warrantsSnapshotSchema = external_exports.object({
|
|
16581
16600
|
numberOfSecurities: external_exports.number().int().nonnegative(),
|
|
@@ -17029,6 +17048,27 @@ Human table sorts lowest extraction confidence first. Conf markers:
|
|
|
17029
17048
|
|
|
17030
17049
|
Global:
|
|
17031
17050
|
--json Machine-readable JSON output (API order, not confidence-sorted)`;
|
|
17051
|
+
var HELP_OBJECTS_REVIEW_NON_CASH = `objects review-non-cash \u2014 Review possible unclassified non-cash convertibles
|
|
17052
|
+
|
|
17053
|
+
Builds a read-only, portal-wide review queue from unmarked convertible issuances
|
|
17054
|
+
whose stored consideration text, comments, or source-document name mentions
|
|
17055
|
+
services or other possible non-cash consideration. Matches are evidence for human
|
|
17056
|
+
review only: this command never classifies, patches, or commits an OCF object.
|
|
17057
|
+
|
|
17058
|
+
Usage:
|
|
17059
|
+
captable-ai objects review-non-cash [--status draft|committed] [--json]
|
|
17060
|
+
|
|
17061
|
+
Options:
|
|
17062
|
+
--status STATUS Review only latest draft or committed objects
|
|
17063
|
+
|
|
17064
|
+
Workflow:
|
|
17065
|
+
1. Run with --status committed --json and review each source agreement.
|
|
17066
|
+
2. For confirmed wholly non-cash issuances, patch only consideration_text with
|
|
17067
|
+
NON_CASH: <document-verbatim description> using the reported object version.
|
|
17068
|
+
3. Dry-run and commit exactly the reviewed object IDs together.
|
|
17069
|
+
|
|
17070
|
+
Global:
|
|
17071
|
+
--json Machine-readable output including evidence and object version`;
|
|
17032
17072
|
var HELP_OBJECTS_GET = `objects get \u2014 Show one OCF object
|
|
17033
17073
|
|
|
17034
17074
|
After the OCF payload, prints a one-line vesting summary when the object (or
|
|
@@ -17146,6 +17186,8 @@ var HELP_OBJECTS_GROUP = `objects \u2014 OCF objects
|
|
|
17146
17186
|
|
|
17147
17187
|
${HELP_OBJECTS_LIST}
|
|
17148
17188
|
|
|
17189
|
+
${HELP_OBJECTS_REVIEW_NON_CASH}
|
|
17190
|
+
|
|
17149
17191
|
${HELP_OBJECTS_GET}
|
|
17150
17192
|
|
|
17151
17193
|
${HELP_OBJECTS_DUMP}
|
|
@@ -20167,6 +20209,136 @@ Reverted ${res.data.revertedCount} draft object(s).
|
|
|
20167
20209
|
`);
|
|
20168
20210
|
}
|
|
20169
20211
|
|
|
20212
|
+
// src/commands/objects-review-non-cash.ts
|
|
20213
|
+
var NON_CASH_PREFIX = "NON_CASH:";
|
|
20214
|
+
var POSSIBLE_NON_CASH_TERMS = /\b(?:non[- ]cash|services?|consulting|advisory|advisor|intellectual property|ip assignment|debt forgiveness|in[- ]kind)\b/i;
|
|
20215
|
+
function stringValue(value) {
|
|
20216
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
20217
|
+
}
|
|
20218
|
+
function collectCommentText(value) {
|
|
20219
|
+
if (typeof value === "string") return value.trim() ? [value.trim()] : [];
|
|
20220
|
+
if (!Array.isArray(value)) return [];
|
|
20221
|
+
return value.flatMap((comment) => {
|
|
20222
|
+
if (typeof comment === "string") return comment.trim() ? [comment.trim()] : [];
|
|
20223
|
+
if (!comment || typeof comment !== "object") return [];
|
|
20224
|
+
const text = Reflect.get(comment, "text") ?? Reflect.get(comment, "comment");
|
|
20225
|
+
return typeof text === "string" && text.trim() ? [text.trim()] : [];
|
|
20226
|
+
});
|
|
20227
|
+
}
|
|
20228
|
+
function hasValidNonCashMarker(considerationText) {
|
|
20229
|
+
if (typeof considerationText !== "string") return false;
|
|
20230
|
+
const trimmed = considerationText.trimStart();
|
|
20231
|
+
if (!trimmed.startsWith(NON_CASH_PREFIX)) return false;
|
|
20232
|
+
return trimmed.slice(NON_CASH_PREFIX.length).trim().length > 0;
|
|
20233
|
+
}
|
|
20234
|
+
function findNonCashReviewCandidates(objects, documents) {
|
|
20235
|
+
const documentsById = new Map(documents.map((document) => [document.id, document]));
|
|
20236
|
+
const candidates = [];
|
|
20237
|
+
for (const object2 of objects) {
|
|
20238
|
+
if (object2.subtype !== "TX_CONVERTIBLE_ISSUANCE") continue;
|
|
20239
|
+
if (hasValidNonCashMarker(object2.ocf.consideration_text)) continue;
|
|
20240
|
+
const evidence = [];
|
|
20241
|
+
const considerationText = stringValue(object2.ocf.consideration_text);
|
|
20242
|
+
if (considerationText && (considerationText.startsWith(NON_CASH_PREFIX) || POSSIBLE_NON_CASH_TERMS.test(considerationText))) {
|
|
20243
|
+
evidence.push({ field: "consideration_text", text: considerationText });
|
|
20244
|
+
}
|
|
20245
|
+
for (const comment of collectCommentText(object2.ocf.comments)) {
|
|
20246
|
+
if (POSSIBLE_NON_CASH_TERMS.test(comment)) {
|
|
20247
|
+
evidence.push({ field: "comments", text: comment });
|
|
20248
|
+
}
|
|
20249
|
+
}
|
|
20250
|
+
const document = object2.documentId ? documentsById.get(object2.documentId) : void 0;
|
|
20251
|
+
if (document && POSSIBLE_NON_CASH_TERMS.test(document.name)) {
|
|
20252
|
+
evidence.push({ field: "document", text: document.name });
|
|
20253
|
+
}
|
|
20254
|
+
if (evidence.length === 0) continue;
|
|
20255
|
+
candidates.push({
|
|
20256
|
+
objectId: object2.id,
|
|
20257
|
+
version: object2.version,
|
|
20258
|
+
status: object2.status,
|
|
20259
|
+
securityId: stringValue(object2.ocf.security_id),
|
|
20260
|
+
customId: stringValue(object2.ocf.custom_id),
|
|
20261
|
+
investmentAmount: object2.ocf.investment_amount ?? null,
|
|
20262
|
+
considerationText,
|
|
20263
|
+
documentId: object2.documentId ?? null,
|
|
20264
|
+
documentName: document?.name ?? null,
|
|
20265
|
+
evidence
|
|
20266
|
+
});
|
|
20267
|
+
}
|
|
20268
|
+
return candidates.sort((left, right) => left.objectId.localeCompare(right.objectId));
|
|
20269
|
+
}
|
|
20270
|
+
async function runObjectsReviewNonCash(args, rawArgv) {
|
|
20271
|
+
if (argvRequestsHelp(rawArgv)) {
|
|
20272
|
+
process.stdout.write(`${HELP_OBJECTS_REVIEW_NON_CASH}
|
|
20273
|
+
`);
|
|
20274
|
+
process.exit(0);
|
|
20275
|
+
}
|
|
20276
|
+
validateFlags(args, { flags: ["status"] });
|
|
20277
|
+
if (args.positional.length > 0) {
|
|
20278
|
+
exitWithError(
|
|
20279
|
+
`Unexpected argument: ${args.positional[0]}. This command takes no positional arguments.`,
|
|
20280
|
+
"UNEXPECTED_ARGUMENT",
|
|
20281
|
+
void 0,
|
|
20282
|
+
EXIT.USAGE
|
|
20283
|
+
);
|
|
20284
|
+
}
|
|
20285
|
+
const status = getFlagValue(args, "status");
|
|
20286
|
+
if (status !== void 0 && status !== "draft" && status !== "committed") {
|
|
20287
|
+
exitWithError(
|
|
20288
|
+
`--status must be one of: draft, committed (got: "${status}")`,
|
|
20289
|
+
"VALIDATION_FAILED",
|
|
20290
|
+
void 0,
|
|
20291
|
+
EXIT.VALIDATION
|
|
20292
|
+
);
|
|
20293
|
+
}
|
|
20294
|
+
const portalId = await getActivePortalId();
|
|
20295
|
+
const page = await fetchAllObjectPages(portalId, {
|
|
20296
|
+
subtype: "TX_CONVERTIBLE_ISSUANCE",
|
|
20297
|
+
status
|
|
20298
|
+
});
|
|
20299
|
+
const candidates = findNonCashReviewCandidates(page.data.objects, page.data.documents);
|
|
20300
|
+
if (isJsonMode()) {
|
|
20301
|
+
printJson({
|
|
20302
|
+
data: {
|
|
20303
|
+
candidates,
|
|
20304
|
+
reviewedCount: page.data.objects.length
|
|
20305
|
+
},
|
|
20306
|
+
meta: {
|
|
20307
|
+
candidateCount: candidates.length,
|
|
20308
|
+
classification: "human_review_required"
|
|
20309
|
+
}
|
|
20310
|
+
});
|
|
20311
|
+
return;
|
|
20312
|
+
}
|
|
20313
|
+
printLine(
|
|
20314
|
+
`
|
|
20315
|
+
Possible unclassified non-cash convertible consideration (${candidates.length} found):
|
|
20316
|
+
`
|
|
20317
|
+
);
|
|
20318
|
+
printTable(
|
|
20319
|
+
candidates.map((candidate) => ({
|
|
20320
|
+
id: candidate.objectId,
|
|
20321
|
+
version: candidate.version,
|
|
20322
|
+
security: candidate.customId ?? candidate.securityId ?? "",
|
|
20323
|
+
amount: candidate.investmentAmount && typeof candidate.investmentAmount === "object" ? Reflect.get(candidate.investmentAmount, "amount") ?? "" : "",
|
|
20324
|
+
document: candidate.documentName ?? candidate.documentId ?? "",
|
|
20325
|
+
evidence: candidate.evidence.map((item) => item.field).join(", ")
|
|
20326
|
+
})),
|
|
20327
|
+
[
|
|
20328
|
+
{ key: "id", label: "Object ID", width: 38 },
|
|
20329
|
+
{ key: "version", label: "Version", width: 8 },
|
|
20330
|
+
{ key: "security", label: "Security", width: 18 },
|
|
20331
|
+
{ key: "amount", label: "Amount", width: 12 },
|
|
20332
|
+
{ key: "document", label: "Document", width: 24 },
|
|
20333
|
+
{ key: "evidence", label: "Evidence", width: 28 }
|
|
20334
|
+
]
|
|
20335
|
+
);
|
|
20336
|
+
printLine(
|
|
20337
|
+
"\nReview the source agreement before patching. This command never classifies or writes objects."
|
|
20338
|
+
);
|
|
20339
|
+
printLine();
|
|
20340
|
+
}
|
|
20341
|
+
|
|
20170
20342
|
// src/commands/objects-update.ts
|
|
20171
20343
|
import { readFileSync as readFileSync2 } from "fs";
|
|
20172
20344
|
async function readStdin2() {
|
|
@@ -21257,6 +21429,7 @@ Cap Table (read):
|
|
|
21257
21429
|
Review: --stakeholder, --document, --max-confidence N (requires --all)
|
|
21258
21430
|
Pagination: --limit (1-250), --cursor, --all
|
|
21259
21431
|
Dates: --from / --to as YYYY-MM-DD
|
|
21432
|
+
objects review-non-cash Find unmarked convertibles that need consideration review
|
|
21260
21433
|
objects get <id> Show a single OCF object (vesting summary when present)
|
|
21261
21434
|
objects dump Engine-shaped ocf.json (default --status committed; --output path)
|
|
21262
21435
|
schemas list List OCF object types
|
|
@@ -21554,6 +21727,12 @@ async function main() {
|
|
|
21554
21727
|
case "patch":
|
|
21555
21728
|
await runObjectsPatch(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
|
|
21556
21729
|
break;
|
|
21730
|
+
case "review-non-cash":
|
|
21731
|
+
await runObjectsReviewNonCash(
|
|
21732
|
+
parseArgs(positionalArgs.slice(2)),
|
|
21733
|
+
positionalArgs.slice(2)
|
|
21734
|
+
);
|
|
21735
|
+
break;
|
|
21557
21736
|
case "revert":
|
|
21558
21737
|
await runObjectsRevert(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
|
|
21559
21738
|
break;
|
|
@@ -21565,7 +21744,7 @@ async function main() {
|
|
|
21565
21744
|
break;
|
|
21566
21745
|
default:
|
|
21567
21746
|
exitWithError(
|
|
21568
|
-
`Unknown objects command: ${sub ?? "(none)"}. Try: objects list | get | dump | update | patch | revert | versions | delete`,
|
|
21747
|
+
`Unknown objects command: ${sub ?? "(none)"}. Try: objects list | review-non-cash | get | dump | update | patch | revert | versions | delete`,
|
|
21569
21748
|
"UNKNOWN_COMMAND",
|
|
21570
21749
|
void 0,
|
|
21571
21750
|
EXIT.USAGE
|
package/package.json
CHANGED