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