@opvs-ai/cli 0.23.0 → 0.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.
Files changed (45) hide show
  1. package/README.md +73 -0
  2. package/claude-plugin/.claude-plugin/marketplace.json +14 -0
  3. package/claude-plugin/.claude-plugin/plugin.json +9 -0
  4. package/claude-plugin/.mcp.json +8 -0
  5. package/claude-plugin/README.md +24 -0
  6. package/claude-plugin/hooks/hooks.json +50 -0
  7. package/claude-plugin/skills/remember/SKILL.md +31 -0
  8. package/claude-plugin/skills/remember/scripts/remember.mjs +121 -0
  9. package/dist/.build-stamp.json +4 -4
  10. package/dist/commands/code-graph.d.ts +17 -0
  11. package/dist/commands/code-graph.js +64 -0
  12. package/dist/commands/code-graph.js.map +1 -0
  13. package/dist/commands/code.d.ts +13 -3
  14. package/dist/commands/code.js +191 -3
  15. package/dist/commands/code.js.map +1 -1
  16. package/dist/commands/memory-capture.d.ts +76 -0
  17. package/dist/commands/memory-capture.js +592 -0
  18. package/dist/commands/memory-capture.js.map +1 -0
  19. package/dist/commands/memory-hook.d.ts +1 -0
  20. package/dist/commands/memory-hook.js +35 -11
  21. package/dist/commands/memory-hook.js.map +1 -1
  22. package/dist/commands/memory-install.d.ts +17 -0
  23. package/dist/commands/memory-install.js +349 -0
  24. package/dist/commands/memory-install.js.map +1 -0
  25. package/dist/commands/memory-lessons.d.ts +8 -0
  26. package/dist/commands/memory-lessons.js +135 -0
  27. package/dist/commands/memory-lessons.js.map +1 -0
  28. package/dist/commands/memory.d.ts +1 -9
  29. package/dist/commands/memory.js +17 -85
  30. package/dist/commands/memory.js.map +1 -1
  31. package/dist/commands/orgChart.d.ts +3 -0
  32. package/dist/commands/orgChart.js +88 -0
  33. package/dist/commands/orgChart.js.map +1 -0
  34. package/dist/commands/tasks.js +45 -3
  35. package/dist/commands/tasks.js.map +1 -1
  36. package/dist/index.js +4 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/lib/redact.d.ts +16 -0
  39. package/dist/lib/redact.js +120 -0
  40. package/dist/lib/redact.js.map +1 -0
  41. package/memory-services.d.ts +9 -0
  42. package/memory-services.js +118 -0
  43. package/package.json +5 -1
  44. package/runtime-plugins/cline/opvs-memory.ts +99 -0
  45. package/runtime-plugins/opencode/opvs-memory.ts +94 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * opvs memory lessons — pull and contribute a skill's shared lessons (AS-590).
3
+ *
4
+ * Skills that are installed on a brand can contribute their own anonymized
5
+ * lessons and pull the ones other brands left behind. The CLI is the terminal
6
+ * face of `/api/v1/skill-lessons/{vendor}/{name}`; the route validates the
7
+ * `<vendor>/<name>` reference server-side, but we validate it here too so a
8
+ * typo never hits the wire.
9
+ *
10
+ * The provenance field is one-way: `source_engagement_hash` is `sha256("cli:" +
11
+ * workspace_slug + ":" + body)`. It must NEVER carry a brand id (AS-445 sealed
12
+ * anything credential-shaped at curation, but the CLI never gets to find out the
13
+ * hard way).
14
+ */
15
+ import { createHash } from "node:crypto";
16
+ import { readFileSync } from "node:fs";
17
+ import { createClient } from "@opvs-ai/core";
18
+ import { buildUrl, printJson } from "../lib/format.js";
19
+ const SEGMENT_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
20
+ const REF_RE = /^@?([a-z0-9][a-z0-9-]{0,63})\/([a-z0-9][a-z0-9-]{0,63})$/;
21
+ export function parseSkillRef(ref) {
22
+ const match = REF_RE.exec(ref);
23
+ if (!match)
24
+ return null;
25
+ if (!SEGMENT_RE.test(match[1]) || !SEGMENT_RE.test(match[2]))
26
+ return null;
27
+ return { vendor: match[1], name: match[2] };
28
+ }
29
+ /** sha256("cli:" + workspace_slug + ":" + body) — never a brand id (AS-590). */
30
+ export function lessonProvenanceHash(workspace, body) {
31
+ return createHash("sha256").update(`cli:${workspace ?? ""}:${body}`).digest("hex");
32
+ }
33
+ function readBody(body, bodyFile) {
34
+ if (body && bodyFile) {
35
+ throw new Error("provide exactly one of --body or --body-file");
36
+ }
37
+ if (bodyFile)
38
+ return readFileSync(bodyFile, "utf8");
39
+ if (!body)
40
+ throw new Error("--body or --body-file is required");
41
+ return body;
42
+ }
43
+ function fail(message) {
44
+ console.error(`Error: ${message}`);
45
+ process.exit(1);
46
+ }
47
+ function workspaceOf(command) {
48
+ let current = command;
49
+ while (current) {
50
+ const opts = current.opts();
51
+ if (opts.workspace)
52
+ return opts.workspace;
53
+ current = current.parent;
54
+ }
55
+ return undefined;
56
+ }
57
+ export function registerLessonCommands(memory) {
58
+ const lessons = memory.command("lessons").description("Pull and contribute a skill's shared lessons");
59
+ lessons
60
+ .command("get <vendor>/<name>")
61
+ .description("Pull a skill's shared lessons")
62
+ .option("--query <text>", "FTS search over body + tags")
63
+ .option("--limit <n>", "Max items", "25")
64
+ .option("--since <cursor>", "Forward cursor from a prior pull")
65
+ .action(async (ref, opts) => {
66
+ const parsed = parseSkillRef(ref);
67
+ if (!parsed) {
68
+ fail(`invalid vendor/name: ${ref} (use <vendor>/<name>, e.g. opvs-ai/opvs-vibe)`);
69
+ }
70
+ const wsSlug = workspaceOf(memory);
71
+ try {
72
+ const client = createClient(wsSlug);
73
+ const params = {};
74
+ if (opts.query)
75
+ params.query = opts.query;
76
+ if (opts.limit)
77
+ params.limit = opts.limit;
78
+ if (opts.since)
79
+ params.since = opts.since;
80
+ const url = buildUrl(`/api/v1/skill-lessons/${parsed.vendor}/${parsed.name}`, params);
81
+ const res = await client.get(url);
82
+ printJson(await res.json());
83
+ }
84
+ catch (err) {
85
+ const detail = err?.detail;
86
+ fail(detail || "Failed to pull skill lessons");
87
+ }
88
+ });
89
+ lessons
90
+ .command("add <vendor>/<name>")
91
+ .description("Contribute an anonymized lesson to a skill (→ pending)")
92
+ .requiredOption("--kind <kind>", "learning | pattern")
93
+ .option("--body <text>", "The lesson text (NO brand data)")
94
+ .option("-f, --body-file <path>", "Read the lesson text from a file")
95
+ .option("--tags <a,b>", "Comma-separated tags")
96
+ .action(async (ref, opts) => {
97
+ const parsed = parseSkillRef(ref);
98
+ if (!parsed) {
99
+ fail(`invalid vendor/name: ${ref} (use <vendor>/<name>, e.g. opvs-ai/opvs-vibe)`);
100
+ }
101
+ if (opts.kind !== "learning" && opts.kind !== "pattern") {
102
+ fail(`invalid --kind: ${opts.kind} (expected learning | pattern)`);
103
+ }
104
+ const wsSlug = workspaceOf(memory);
105
+ let body;
106
+ try {
107
+ body = readBody(opts.body, opts.bodyFile);
108
+ }
109
+ catch (err) {
110
+ fail(err instanceof Error ? err.message : "Failed to read lesson body");
111
+ }
112
+ const payload = {
113
+ kind: opts.kind,
114
+ body,
115
+ tags: opts.tags
116
+ ? opts.tags
117
+ .split(",")
118
+ .map((tag) => tag.trim())
119
+ .filter(Boolean)
120
+ : null,
121
+ source_engagement_hash: lessonProvenanceHash(wsSlug, body),
122
+ craft_id: null,
123
+ };
124
+ try {
125
+ const client = createClient(wsSlug);
126
+ const res = await client.post(`/api/v1/skill-lessons/${parsed.vendor}/${parsed.name}`, payload);
127
+ printJson(await res.json());
128
+ }
129
+ catch (err) {
130
+ const detail = err?.detail;
131
+ fail(detail || "Failed to contribute skill lesson");
132
+ }
133
+ });
134
+ }
135
+ //# sourceMappingURL=memory-lessons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-lessons.js","sourceRoot":"","sources":["../../src/commands/memory-lessons.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  * opvs memory — search typed repository memory and propose human curation.
3
3
  */
4
4
  import { Command } from "commander";
5
+ export { OPVS_MEMORY_REPOSITORY, parseServicePatterns, repositoryNameFromRemote, serviceForPath, } from "../../memory-services.js";
5
6
  interface MemoryEntry {
6
7
  id: string;
7
8
  card?: string | null;
@@ -10,15 +11,6 @@ interface MemoryEntry {
10
11
  pinned?: boolean;
11
12
  [key: string]: unknown;
12
13
  }
13
- interface ServicePattern {
14
- service: string;
15
- pattern: string;
16
- }
17
14
  /** Keep the API's relative order within the pinned and unpinned groups. */
18
15
  export declare function pinnedFirst(entries: MemoryEntry[]): MemoryEntry[];
19
- /** Read the service names and path patterns from the canonical registry. */
20
- export declare function parseServicePatterns(registry: string): ServicePattern[];
21
- /** Apply services.yaml's global "most specific wins" rule to a repository path. */
22
- export declare function serviceForPath(path: string, patterns: ServicePattern[]): string | undefined;
23
16
  export declare function registerMemoryCommands(program: Command): void;
24
- export {};
@@ -5,7 +5,12 @@ import { existsSync, readFileSync } from "node:fs";
5
5
  import { dirname, join, resolve } from "node:path";
6
6
  import { createClient } from "@opvs-ai/core";
7
7
  import { buildUrl, printJson } from "../lib/format.js";
8
+ import { registerCaptureHooks } from "./memory-capture.js";
8
9
  import { registerMemoryHooks } from "./memory-hook.js";
10
+ import { registerMemoryInstallCommands } from "./memory-install.js";
11
+ import { registerLessonCommands } from "./memory-lessons.js";
12
+ import { parseServicePatterns, serviceForPath } from "../../memory-services.js";
13
+ export { OPVS_MEMORY_REPOSITORY, parseServicePatterns, repositoryNameFromRemote, serviceForPath, } from "../../memory-services.js";
9
14
  const SEARCH_PATH = "/api/v1/memory/entries/search";
10
15
  /** Keep the API's relative order within the pinned and unpinned groups. */
11
16
  export function pinnedFirst(entries) {
@@ -14,87 +19,6 @@ export function pinnedFirst(entries) {
14
19
  .sort((a, b) => Number(Boolean(b.entry.pinned)) - Number(Boolean(a.entry.pinned)) || a.index - b.index)
15
20
  .map(({ entry }) => entry);
16
21
  }
17
- function unquote(value) {
18
- const trimmed = value.trim();
19
- if (trimmed.length >= 2 &&
20
- ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
21
- (trimmed.startsWith("'") && trimmed.endsWith("'")))) {
22
- return trimmed.slice(1, -1);
23
- }
24
- return trimmed;
25
- }
26
- /** Read the service names and path patterns from the canonical registry. */
27
- export function parseServicePatterns(registry) {
28
- const patterns = [];
29
- let service;
30
- let inCodePaths = false;
31
- for (const line of registry.split(/\r?\n/)) {
32
- const serviceMatch = line.match(/^ {2}- name:\s*(\S+)\s*$/);
33
- if (serviceMatch) {
34
- service = unquote(serviceMatch[1]);
35
- inCodePaths = false;
36
- continue;
37
- }
38
- if (!service)
39
- continue;
40
- const planningMatch = line.match(/^ {4}planning_dir:\s*(.+?)\s*$/);
41
- if (planningMatch) {
42
- const planningDir = unquote(planningMatch[1].replace(/\s+#.*$/, ""));
43
- if (planningDir !== "null")
44
- patterns.push({ service, pattern: planningDir });
45
- continue;
46
- }
47
- if (/^ {4}code_paths:\s*$/.test(line)) {
48
- inCodePaths = true;
49
- continue;
50
- }
51
- if (/^ {4}\S/.test(line)) {
52
- inCodePaths = false;
53
- continue;
54
- }
55
- if (inCodePaths) {
56
- const pathMatch = line.match(/^ {6}-\s+(.+?)\s*$/);
57
- if (pathMatch) {
58
- const pattern = unquote(pathMatch[1].replace(/\s+#.*$/, ""));
59
- if (pattern)
60
- patterns.push({ service, pattern });
61
- }
62
- }
63
- }
64
- return patterns;
65
- }
66
- function globRegex(pattern) {
67
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*+/g, ".*");
68
- return new RegExp(`^${escaped}${pattern.endsWith("/") ? "" : "$"}`);
69
- }
70
- function matchesPattern(path, pattern) {
71
- if (pattern.includes("*"))
72
- return globRegex(pattern).test(path);
73
- return pattern.endsWith("/") ? path.startsWith(pattern) : path === pattern;
74
- }
75
- function specificity(pattern) {
76
- const wildcard = pattern.indexOf("*");
77
- return [wildcard === -1 ? pattern.length : wildcard, pattern.length];
78
- }
79
- /** Apply services.yaml's global "most specific wins" rule to a repository path. */
80
- export function serviceForPath(path, patterns) {
81
- const normalized = path.replace(/\\/g, "/").replace(/^\.\//, "");
82
- let best;
83
- for (const candidate of patterns) {
84
- if (!matchesPattern(normalized, candidate.pattern))
85
- continue;
86
- if (!best) {
87
- best = candidate;
88
- continue;
89
- }
90
- const [candidatePrefix, candidateLength] = specificity(candidate.pattern);
91
- const [bestPrefix, bestLength] = specificity(best.pattern);
92
- if (candidatePrefix > bestPrefix || (candidatePrefix === bestPrefix && candidateLength > bestLength)) {
93
- best = candidate;
94
- }
95
- }
96
- return best?.service;
97
- }
98
22
  function findServicesRegistry(start) {
99
23
  let directory = resolve(start);
100
24
  while (true) {
@@ -126,9 +50,9 @@ async function searchEntries(client, params) {
126
50
  const response = await client.get(buildUrl(SEARCH_PATH, params));
127
51
  return (await response.json());
128
52
  }
129
- function contextResult(entries) {
53
+ function contextResult(entries, warnings) {
130
54
  const sorted = pinnedFirst(uniqueEntries(entries));
131
- return { total: sorted.length, items: sorted };
55
+ return { total: sorted.length, items: sorted, warnings };
132
56
  }
133
57
  function fail(error, fallback) {
134
58
  const detail = error?.detail;
@@ -138,6 +62,9 @@ function fail(error, fallback) {
138
62
  export function registerMemoryCommands(program) {
139
63
  const memory = program.command("memory").description("Search typed repository memory and request curation");
140
64
  registerMemoryHooks(memory);
65
+ registerCaptureHooks(memory);
66
+ registerMemoryInstallCommands(memory);
67
+ registerLessonCommands(memory);
141
68
  memory
142
69
  .command("search <query>")
143
70
  .description("Search typed memory, with pinned entries first")
@@ -178,7 +105,7 @@ export function registerMemoryCommands(program) {
178
105
  card: opts.card,
179
106
  pinned_first: "true",
180
107
  });
181
- printJson(contextResult(entriesFrom(result).filter((entry) => entry.card === opts.card)));
108
+ printJson(contextResult(entriesFrom(result).filter((entry) => entry.card === opts.card), Array.isArray(result.warnings) ? result.warnings : []));
182
109
  return;
183
110
  }
184
111
  const files = (opts.files ?? "")
@@ -189,9 +116,12 @@ export function registerMemoryCommands(program) {
189
116
  const patterns = parseServicePatterns(registry);
190
117
  const services = new Set(files.map((path) => serviceForPath(path, patterns)).filter(Boolean));
191
118
  const entries = [];
119
+ const warnings = [];
192
120
  for (const anchor of files) {
193
121
  const result = await searchEntries(client, { anchor, pinned_first: "true" });
194
122
  entries.push(...entriesFrom(result));
123
+ if (Array.isArray(result.warnings))
124
+ warnings.push(...result.warnings);
195
125
  }
196
126
  for (const service of services) {
197
127
  const result = await searchEntries(client, {
@@ -199,8 +129,10 @@ export function registerMemoryCommands(program) {
199
129
  pinned_first: "true",
200
130
  });
201
131
  entries.push(...entriesFrom(result));
132
+ if (Array.isArray(result.warnings))
133
+ warnings.push(...result.warnings);
202
134
  }
203
- printJson(contextResult(entries));
135
+ printJson(contextResult(entries, warnings));
204
136
  }
205
137
  catch (error) {
206
138
  fail(error, "Failed to load memory context");
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/commands/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/commands/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ /** Register commands for the brand's AI Office org chart. */
3
+ export declare function registerOrgChartCommands(program: Command): void;
@@ -0,0 +1,88 @@
1
+ import { createClient } from "@opvs-ai/core";
2
+ import { Option } from "commander";
3
+ import { buildUrl, printResponse } from "../lib/format.js";
4
+ function fail(err, fallback) {
5
+ const e = err;
6
+ const status = e.status ?? e.statusCode;
7
+ if (status === 404) {
8
+ console.error("Not found");
9
+ }
10
+ else if (status === 422) {
11
+ console.error(e.detail || e.message || fallback);
12
+ }
13
+ else {
14
+ console.error(`Error: ${e.detail || e.message || fallback}`);
15
+ }
16
+ return process.exit(1);
17
+ }
18
+ /** Repeatable commander argParser that turns `--manager <id>` into an array. */
19
+ const collectManagers = (value, acc) => {
20
+ acc.push(value);
21
+ return acc;
22
+ };
23
+ /** Register commands for the brand's AI Office org chart. */
24
+ export function registerOrgChartCommands(program) {
25
+ const orgChart = program
26
+ .command("org-chart")
27
+ .description("Read and write the brand's AI Office org chart");
28
+ orgChart
29
+ .command("show")
30
+ .description("Show the brand's AI Office org chart")
31
+ .addOption(new Option("--format <format>", "Output format (default text; json|yaml pass through)")
32
+ .choices(["text", "json", "yaml"])
33
+ .default("text"))
34
+ .action(async (opts) => {
35
+ const workspace = program.opts().workspace;
36
+ try {
37
+ // text → no hint, CLI parses the JSON and prints lines.
38
+ // json|yaml → pass the format to the server, print whatever comes back.
39
+ const requestFormat = opts.format === "text" ? undefined : opts.format;
40
+ const response = await createClient(workspace).get(buildUrl("/api/v1/org-chart", {}, requestFormat));
41
+ if (opts.format === "text") {
42
+ const data = (await response.json());
43
+ const namesByHire = new Map((data.nodes ?? []).map((n) => [n.hire_id, n.name]));
44
+ for (const node of data.nodes ?? []) {
45
+ const managerNames = node.manager_hire_ids.map((id) => namesByHire.get(id) ?? id);
46
+ const tail = managerNames.length ? managerNames.join(", ") : "nobody";
47
+ console.log(`${node.name} (${node.role}) → reports to: ${tail}`);
48
+ }
49
+ }
50
+ else {
51
+ await printResponse(response);
52
+ }
53
+ }
54
+ catch (err) {
55
+ fail(err, "Failed to fetch org chart");
56
+ }
57
+ });
58
+ orgChart
59
+ .command("set-manager <hire_id>")
60
+ .description("Replace the manager list for a hire (--none clears it)")
61
+ .option("--manager <hire_id>", "Manager hire id (repeatable)", collectManagers, [])
62
+ .option("--none", "Clear all managers")
63
+ .action(async (hireId, opts) => {
64
+ // Bare `set-manager <hire>` would silently send `manager_hire_ids: []`
65
+ // and clear the hire's managers — refuse it before any request.
66
+ if (!opts.none && opts.manager.length === 0) {
67
+ console.error("Error: give --manager <hire_id> (repeatable) or --none");
68
+ process.exit(1);
69
+ return;
70
+ }
71
+ // Both intents are about the same wire field — picking one silently would
72
+ // send a bundle the operator did not ask for.
73
+ if (opts.none && opts.manager.length > 0) {
74
+ console.error("Error: --none cannot be combined with --manager");
75
+ process.exit(1);
76
+ return;
77
+ }
78
+ const workspace = program.opts().workspace;
79
+ try {
80
+ const response = await createClient(workspace).put(`/api/v1/org-chart/agents/${encodeURIComponent(hireId)}/managers`, { manager_hire_ids: opts.none ? [] : opts.manager });
81
+ await printResponse(response);
82
+ }
83
+ catch (err) {
84
+ fail(err, "Failed to set managers");
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=orgChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgChart.js","sourceRoot":"","sources":["../../src/commands/orgChart.ts"],"names":[],"mappings":"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"}
@@ -479,6 +479,7 @@ export function registerTaskCommands(program) {
479
479
  .command("update <id>")
480
480
  .description("Update a task (status, priority, result)")
481
481
  .option("--status <status>", "Status: pending, assigned, in_progress, blocked, review, done, cancelled, failed (pending can only go to assigned/in_progress/cancelled)")
482
+ .option("--any-status", "Skip status compare-and-set and write regardless of the card's current status")
482
483
  .option("--priority <priority>", "Priority: low, medium, high, critical")
483
484
  .option("--title <title>", "New title")
484
485
  .option("-d, --description <desc>", "New description (markdown)")
@@ -504,6 +505,11 @@ export function registerTaskCommands(program) {
504
505
  // defect of exactly the shape AgentCLI LEARNINGS records for `--column`:
505
506
  // an existing capability read as missing, and callers built workarounds.
506
507
  .option("--depends-on <refs>", "Comma-separated tasks this card waits on, REPLACING the current set — short refs (OSB-108), 8+ hex UUID prefixes, or full UUIDs. Pass '' to clear every edge.")
508
+ // OD-500 — a dependency write, not a field on the card: it goes to the
509
+ // dependency route (which runs the cycle guard and the stack limits), never
510
+ // into the PATCH body. Sent with met_at, that route creates the edge or
511
+ // flips an existing one, so re-running it is harmless.
512
+ .option("--stack-on <parent>", "Stacked cards: make ONE dependency on <parent> that is met when the parent's PR is APPROVED (the planner writes its approved_head), not only when it merges. Creates the edge or flips an existing one. One per card; a stack is at most 3 cards tall.")
507
513
  .option("--mutex-group <lane>", "DAG lane, or 'none' to clear it. Two cards sharing a lane on one board never run concurrently.")
508
514
  .option("--claimable-by <class>", "Actor gate: worker | agent | human, or 'none' to CLEAR the card's own gate — it then inherits the board's, then the project's, default, and is claimable by anyone only when neither sets one.")
509
515
  // ── Build routing pins (OSB-198 item 8) ────────────────────────────────
@@ -644,9 +650,45 @@ export function registerTaskCommands(program) {
644
650
  body.custom_fields_merge = true;
645
651
  }
646
652
  Object.assign(body, buildDeliveryFields(opts, true));
647
- if (Object.keys(body).length === 0) {
648
- console.error("Nothing to update. Provide --status, --priority, --title, --description, --result, --result-file, --agent-result, --blocked-reason, --assign, --assign-user, --labels, --due, --instructions, --instructions-file, --context, --parent, --depends-on, --mutex-group, --claimable-by, --task-type, --model, --provider, --harness, --subscription, --pin-env, --estimate, --workflow-doc, --workflow-skill, --workflow-rule, --pr, --pr-url, --branch, --worktree, --deploy-needs, --field, or --custom-fields");
653
+ const stackOn = typeof opts.stackOn === "string" ? opts.stackOn.trim() : undefined;
654
+ if (stackOn === "") {
655
+ console.error("Error: --stack-on needs the parent card (short ref or UUID).");
649
656
  process.exit(1);
657
+ return;
658
+ }
659
+ if (Object.keys(body).length === 0 && !stackOn) {
660
+ console.error("Nothing to update. Provide --status, --priority, --title, --description, --result, --result-file, --agent-result, --blocked-reason, --assign, --assign-user, --labels, --due, --instructions, --instructions-file, --context, --parent, --depends-on, --stack-on, --mutex-group, --claimable-by, --task-type, --model, --provider, --harness, --subscription, --pin-env, --estimate, --workflow-doc, --workflow-skill, --workflow-rule, --pr, --pr-url, --branch, --worktree, --deploy-needs, --field, or --custom-fields");
661
+ process.exit(1);
662
+ }
663
+ // The stack edge goes FIRST: a refusal (422 — a second stacked edge, or
664
+ // a stack taller than 3) then leaves the card exactly as it was.
665
+ if (stackOn) {
666
+ const cardRes = await client.get(`/api/v1/board/tasks/${id}`);
667
+ const card = (await cardRes.json());
668
+ const linkRes = await client.post(`/api/v1/board/boards/${card.board_id}/tasks/${card.id}/dependencies`, { depends_on_task_id: stackOn, met_at: "approved" });
669
+ const link = await linkRes.json();
670
+ if (Object.keys(body).length === 0) {
671
+ if (opts.json) {
672
+ printJson(link);
673
+ }
674
+ else {
675
+ console.log(`${id} stacks on ${stackOn} (met_at=approved)`);
676
+ }
677
+ return;
678
+ }
679
+ }
680
+ // Keep the optimistic-concurrency precondition out of the printed
681
+ // changed-field list: it controls this write but is not persisted.
682
+ const changedFields = Object.keys(body);
683
+ if (opts.status && !opts.anyStatus) {
684
+ const currentRes = await client.get(`/api/v1/board/tasks/${id}`);
685
+ // createClient returns a Response or throws. The truthiness check
686
+ // also keeps lightweight injected clients that omit a response
687
+ // object from crashing before the PATCH.
688
+ if (currentRes) {
689
+ const current = await currentRes.json();
690
+ body.expected_status = current.status;
691
+ }
650
692
  }
651
693
  const res = await client.patch(`/api/v1/board/tasks/${id}`, body);
652
694
  const data = await res.json();
@@ -654,7 +696,7 @@ export function registerTaskCommands(program) {
654
696
  printJson(data);
655
697
  }
656
698
  else {
657
- printWriteSummary(data, Object.keys(body));
699
+ printWriteSummary(data, changedFields);
658
700
  }
659
701
  }
660
702
  catch (err) {