@llamaventures/cli 1.23.1 → 1.25.0

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/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ this project adheres to [Semantic Versioning](https://semver.org).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.25.0] - 2026-08-05
10
+
11
+ ### Added
12
+ - Add preview-first, revision-fenced `llama admin workflow remediate` for the
13
+ two allowlisted Workflow V2 false-green intake checks in Llama Command 3.26.0.
14
+
15
+ ## [1.24.0] - 2026-08-05
16
+
17
+ ### Added
18
+ - Add `llama admin workflow audit --deal <uuid> | --all` for the read-only
19
+ Workflow V2 production integrity auditor in Llama Command 3.25.0.
20
+
9
21
  ## [1.23.1] - 2026-08-05
10
22
 
11
23
  ### Added
package/README.md CHANGED
@@ -113,6 +113,26 @@ llama mentions
113
113
  llama agent-onboard # server-owned agent workflow contract
114
114
  ```
115
115
 
116
+ System admins can run the read-only production integrity auditor against one
117
+ Workflow V2 deal or every persisted V2 snapshot:
118
+
119
+ ```bash
120
+ llama admin workflow audit --deal <dealId>
121
+ llama admin workflow audit --all
122
+ ```
123
+
124
+ For the two supported false-green intake checks, remediation is preview-first
125
+ and one deal at a time. Apply requires the exact revision returned by preview:
126
+
127
+ ```bash
128
+ llama admin workflow remediate --deal <dealId> --guard intake.reason_why
129
+ llama admin workflow remediate --deal <dealId> --guard intake.reason_why \
130
+ --apply --expected-revision <revision> --reason "Confirmed missing canonical evidence"
131
+ ```
132
+
133
+ The server can only invalidate a system-generated green. It cannot advance a
134
+ deal, satisfy a check, change status/ownership, or override a human resolution.
135
+
116
136
  Status vocabulary — `Interested`: tracked before any contact ·
117
137
  `Outreached`: contacted, no response yet · `Sourced`: real relationship
118
138
  signal exists. `sourceDirection` is separate: `Inbound` came to the firm,
package/README.zh-CN.md CHANGED
@@ -135,6 +135,25 @@ llama mentions
135
135
  llama agent-onboard # 服务端下发的 agent 工作契约
136
136
  ```
137
137
 
138
+ 系统管理员可以只读审计一个 Workflow V2 deal,或审计全部已持久化的 V2 快照:
139
+
140
+ ```bash
141
+ llama admin workflow audit --deal <dealId>
142
+ llama admin workflow audit --all
143
+ ```
144
+
145
+ 对当前支持的两个 intake 假绿检查,修复必须先 preview,并且一次只处理一个 deal。
146
+ Apply 必须携带 preview 返回的精确 revision:
147
+
148
+ ```bash
149
+ llama admin workflow remediate --deal <dealId> --guard intake.reason_why
150
+ llama admin workflow remediate --deal <dealId> --guard intake.reason_why \
151
+ --apply --expected-revision <revision> --reason "已确认 canonical 证据缺失"
152
+ ```
153
+
154
+ 服务端只能把系统生成的绿灯改回未满足;不能推进 deal、把检查改成已满足、修改
155
+ status/owner,也不能覆盖人工 resolution。
156
+
138
157
  Status 语义——`Interested`:接触前先记录关注 · `Outreached`:已联系、
139
158
  尚无回应 · `Sourced`:已有真实关系信号。`sourceDirection` 是独立维度:
140
159
  `Inbound` 流入,`Outbound` 我们主动。
package/bin/llama.mjs CHANGED
@@ -36,6 +36,11 @@ import { LLAMA_CLI_CLIENT_ID, pkceLoopbackFlow, revokeToken as revokeOAuthToken
36
36
  import { deleteBundle, detectBackend, readBundle, writeBundle } from "../lib/oauth-storage.mjs";
37
37
  import { maybeNudgeUpdate, getUpdateNudge } from "../lib/version-check.mjs";
38
38
  import { getBuildInfo } from "../lib/build-info.mjs";
39
+ import { workflowAuditPath } from "../lib/workflow-audit.mjs";
40
+ import {
41
+ WORKFLOW_REMEDIATION_PATH,
42
+ workflowRemediationBody,
43
+ } from "../lib/workflow-remediation.mjs";
39
44
 
40
45
  const requireFromHere = createRequire(import.meta.url);
41
46
  const { version: PKG_VERSION } = requireFromHere("../package.json");
@@ -603,6 +608,9 @@ Deal page HTML (hand-authored sandboxed pages on /deals/<id>/browse/<slug>):
603
608
  update_deal_browse_html tool and the MCP html_upload_file tool.
604
609
 
605
610
  Admin (system admin only — server returns 403 for non-admin tokens):
611
+ llama admin workflow audit --deal <uuid> | --all
612
+ llama admin workflow remediate --deal <uuid> --guard intake.reason_why[,intake.founder_identity]
613
+ [--apply --expected-revision <n> --reason "..."]
606
614
  llama admin auth-events [--kind X] [--actor email] [--subject email] [--since 24h|7d|30d|<ISO>] [--limit 100]
607
615
  llama admin deal-events [--kind X] [--actor email] [--deal <uuid>] [--since 24h] [--limit 100]
608
616
  llama admin agent-events [--kind tool_call|loop_stalled|max_turns_reached] [--agent-kind deal|secretary|main|inbox]
@@ -2403,12 +2411,37 @@ Routing — is this the right command?
2403
2411
  // - agent-events : every AI tool call / loop_stalled / max_turns (AI ops)
2404
2412
  if (area === "admin") {
2405
2413
  const sub = action;
2406
- const valid = ["auth-events", "deal-events", "agent-events"];
2414
+ const valid = ["workflow", "auth-events", "deal-events", "agent-events"];
2407
2415
  if (!valid.includes(sub)) {
2408
2416
  throw new Error(
2409
2417
  `Unknown admin sub-command "${sub || ""}". Use: ${valid.join(", ")}`
2410
2418
  );
2411
2419
  }
2420
+ if (sub === "workflow") {
2421
+ if (!["audit", "remediate"].includes(rest[0])) {
2422
+ throw new Error("Usage: llama admin workflow audit|remediate ...");
2423
+ }
2424
+ if (rest[0] === "audit") {
2425
+ const { flags } = parseFlags(rest.slice(1), ["deal", "all"]);
2426
+ // @core-api-operation GET /api/admin/workflow-audit
2427
+ print(await request("GET", workflowAuditPath(flags)));
2428
+ return;
2429
+ }
2430
+ const { flags } = parseFlags(rest.slice(1), [
2431
+ "deal",
2432
+ "guard",
2433
+ "apply",
2434
+ "expected-revision",
2435
+ "reason",
2436
+ ]);
2437
+ const body = workflowRemediationBody(
2438
+ flags,
2439
+ flags.apply === true ? `cli-workflow-remediation-${randomUUID()}` : undefined,
2440
+ );
2441
+ // @core-api-operation POST /api/admin/workflow-remediation
2442
+ print(await request("POST", WORKFLOW_REMEDIATION_PATH, body));
2443
+ return;
2444
+ }
2412
2445
  const { flags } = parseFlags(rest);
2413
2446
  const params = new URLSearchParams();
2414
2447
  // Common filters across all three.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "format": "llama.core-api-contract.v1",
3
3
  "name": "llama-core-api",
4
- "apiVersion": "3.23.0",
4
+ "apiVersion": "3.26.0",
5
5
  "openapiVersion": "3.0.3",
6
- "sha256": "b959a28605693097ba8d8d9345729070d54fcce08f004abcfe9b8c2fd2dabc6d",
7
- "pathCount": 233,
8
- "operationCount": 304
6
+ "sha256": "1ab4db8774b6dc0d94d6d6b4dd79f8272c6a405a3474710ac4162cc8a0dc6981",
7
+ "pathCount": 236,
8
+ "operationCount": 307
9
9
  }
@@ -14,6 +14,14 @@
14
14
  "method": "GET",
15
15
  "path": "/api/admin/deal-events"
16
16
  },
17
+ {
18
+ "method": "GET",
19
+ "path": "/api/admin/workflow-audit"
20
+ },
21
+ {
22
+ "method": "POST",
23
+ "path": "/api/admin/workflow-remediation"
24
+ },
17
25
  {
18
26
  "method": "GET",
19
27
  "path": "/api/agent/activity"
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "format": "llama.cli-build.v1",
3
3
  "packageName": "@llamaventures/cli",
4
- "packageVersion": "1.23.1",
5
- "sourceSha": "8d5824095c03137b224bdbff50bc6be144d37486",
4
+ "packageVersion": "1.25.0",
5
+ "sourceSha": "4b70d873886c521d02cc7c75659425ed6e2989f6",
6
6
  "sourceKind": "github",
7
7
  "sourceDirty": false,
8
8
  "coreApiContract": {
9
9
  "format": "llama.core-api-contract.v1",
10
10
  "name": "llama-core-api",
11
- "apiVersion": "3.23.0",
11
+ "apiVersion": "3.26.0",
12
12
  "openapiVersion": "3.0.3",
13
- "sha256": "b959a28605693097ba8d8d9345729070d54fcce08f004abcfe9b8c2fd2dabc6d"
13
+ "sha256": "1ab4db8774b6dc0d94d6d6b4dd79f8272c6a405a3474710ac4162cc8a0dc6981"
14
14
  }
15
15
  }
@@ -0,0 +1,13 @@
1
+ export function workflowAuditPath(flags) {
2
+ const deal = typeof flags.deal === "string" && flags.deal.trim()
3
+ ? flags.deal.trim()
4
+ : null;
5
+ const all = flags.all === true;
6
+ if ((!deal && !all) || (deal && all)) {
7
+ throw new Error("Usage: llama admin workflow audit --deal <uuid> | --all");
8
+ }
9
+ const params = new URLSearchParams();
10
+ if (deal) params.set("deal", deal);
11
+ if (all) params.set("all", "true");
12
+ return `/api/admin/workflow-audit?${params.toString()}`;
13
+ }
@@ -0,0 +1,45 @@
1
+ export const WORKFLOW_REMEDIATION_PATH = "/api/admin/workflow-remediation";
2
+ export const WORKFLOW_REMEDIATION_GUARDS = [
3
+ "intake.founder_identity",
4
+ "intake.reason_why",
5
+ ];
6
+
7
+ export function workflowRemediationBody(flags, requestId) {
8
+ const dealId = typeof flags.deal === "string" ? flags.deal.trim() : "";
9
+ const rawGuards = typeof flags.guard === "string" ? flags.guard : "";
10
+ const guardKeys = [...new Set(
11
+ rawGuards.split(",").map((value) => value.trim()).filter(Boolean),
12
+ )];
13
+ if (!dealId || guardKeys.length < 1 || guardKeys.length > 2 ||
14
+ guardKeys.some((key) => !WORKFLOW_REMEDIATION_GUARDS.includes(key))) {
15
+ throw new Error(
16
+ "Usage: llama admin workflow remediate --deal <uuid> " +
17
+ "--guard intake.reason_why[,intake.founder_identity] " +
18
+ "[--apply --expected-revision <n> --reason \"...\"]",
19
+ );
20
+ }
21
+
22
+ if (flags.apply !== true) {
23
+ if (flags["expected-revision"] !== undefined || flags.reason !== undefined) {
24
+ throw new Error("--expected-revision and --reason require --apply");
25
+ }
26
+ return { action: "preview", dealId, guardKeys };
27
+ }
28
+
29
+ const expectedRevision = Number(flags["expected-revision"]);
30
+ const reason = typeof flags.reason === "string" ? flags.reason.trim() : "";
31
+ if (!Number.isInteger(expectedRevision) || expectedRevision < 0 || !reason) {
32
+ throw new Error("--apply requires --expected-revision <n> from preview and --reason \"...\"");
33
+ }
34
+ if (typeof requestId !== "string" || !requestId) {
35
+ throw new Error("workflow remediation apply requires a request ID");
36
+ }
37
+ return {
38
+ action: "apply",
39
+ dealId,
40
+ guardKeys,
41
+ expectedRevision,
42
+ requestId,
43
+ reason,
44
+ };
45
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@llamaventures/cli",
3
- "version": "1.23.1",
3
+ "version": "1.25.0",
4
4
  "description": "CLI + MCP server for the Llama Ventures investment workbench (command.llamaventures.vc).",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "npm run test:agent-routing && npm run test:contract",
8
8
  "test:agent-routing": "node scripts/verify-agent-routing.mjs",
9
- "test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/investment-workflow-contract.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs && node scripts/verify-core-api-contract.mjs",
9
+ "test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/investment-workflow-contract.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs scripts/workflow-audit.test.mjs scripts/workflow-remediation.test.mjs && node scripts/verify-core-api-contract.mjs",
10
10
  "verify:artifact": "node scripts/verify-release-artifact.mjs",
11
11
  "verify:release": "npm test && npm run verify:artifact && node scripts/verify-tarball-clean.mjs",
12
12
  "prepack": "node scripts/prepare-build-manifest.mjs",