@elevasis/sdk 1.36.4 → 1.36.5

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/cli.cjs CHANGED
@@ -45808,7 +45808,7 @@ function wrapAction(commandName, fn) {
45808
45808
  // package.json
45809
45809
  var package_default = {
45810
45810
  name: "@elevasis/sdk",
45811
- version: "1.36.4",
45811
+ version: "1.36.5",
45812
45812
  description: "SDK for building Elevasis organization resources",
45813
45813
  type: "module",
45814
45814
  bin: {
@@ -47834,8 +47834,11 @@ Resolved client: ${client.name}`));
47834
47834
  }
47835
47835
 
47836
47836
  // src/cli/commands/project/projects.ts
47837
+ function printJson2(value) {
47838
+ console.log(JSON.stringify(value, null, 2));
47839
+ }
47837
47840
  function registerProjectList(program3) {
47838
- program3.command("project:list").description("List projects\n Example: elevasis-sdk project:list --search alpha").option("--kind <kind>", "Filter by kind: client_engagement | internal | research | other").option("--status <status>", "Filter by status: active | on_track | at_risk | blocked | completed | paused").option("--search <query>", "Search by project name or description").option("--client <id-or-name>", "Filter by client hub record (UUID or fuzzy name)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47841
+ program3.command("project:list").description("List projects\n Example: elevasis-sdk project:list --search alpha").option("--kind <kind>", "Filter by kind: client_engagement | internal | research | other").option("--status <status>", "Filter by status: active | on_track | at_risk | blocked | completed | paused").option("--search <query>", "Search by project name or description").option("--client <id-or-name>", "Filter by client hub record (UUID or fuzzy name)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
47839
47842
  wrapAction(
47840
47843
  "project:list",
47841
47844
  async (options) => {
@@ -47853,6 +47856,10 @@ function registerProjectList(program3) {
47853
47856
  const qs = params.toString();
47854
47857
  const endpoint = `/api/external/projects${qs ? `?${qs}` : ""}`;
47855
47858
  const result = await apiGet(endpoint, apiUrl);
47859
+ if (options.json) {
47860
+ printJson2(result);
47861
+ return;
47862
+ }
47856
47863
  if (options.pretty) {
47857
47864
  const projects = result.projects;
47858
47865
  if (projects.length === 0) {
@@ -47878,9 +47885,13 @@ Projects (${projects.length}):
47878
47885
  function registerProjectResolve(program3) {
47879
47886
  program3.command("project:resolve <query>").description(
47880
47887
  'Resolve a project ID from a name, UUID, or search query\n Example: elevasis-sdk project:resolve "Alpha"'
47881
- ).option("--api-url <url>", "API base URL").option("--pretty", "Render project details instead of only the resolved ID").action(
47888
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render project details instead of only the resolved ID").option("--json", "Output as JSON").action(
47882
47889
  wrapAction("project:resolve", async (query, options) => {
47883
47890
  const project = await resolveProject(query, options.apiUrl);
47891
+ if (options.json) {
47892
+ printJson2(project);
47893
+ return;
47894
+ }
47884
47895
  if (options.pretty) {
47885
47896
  console.log(source_default.cyan(`
47886
47897
  Resolved project: ${project.name}`));
@@ -47918,10 +47929,14 @@ ${renderProjectWorkBrief(brief)}
47918
47929
  );
47919
47930
  }
47920
47931
  function registerProjectGet(program3) {
47921
- program3.command("project:get <id>").description("Get a project by ID\n Example: elevasis-sdk project:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47932
+ program3.command("project:get <id>").description("Get a project by ID\n Example: elevasis-sdk project:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
47922
47933
  wrapAction("project:get", async (id, options) => {
47923
47934
  const apiUrl = resolveApiUrl(options.apiUrl);
47924
47935
  const result = await apiGet(`/api/external/projects/${id}`, apiUrl);
47936
+ if (options.json) {
47937
+ printJson2(result);
47938
+ return;
47939
+ }
47925
47940
  if (options.pretty) {
47926
47941
  const p = result.project;
47927
47942
  console.log(source_default.cyan(`
@@ -47938,7 +47953,7 @@ Project: ${p.name}`));
47938
47953
  );
47939
47954
  }
47940
47955
  function registerProjectCreate(program3) {
47941
- program3.command("project:create").description('Create a new project\n Example: elevasis-sdk project:create --name "My Project" --kind internal').requiredOption("--name <name>", "Project name").requiredOption("--kind <kind>", "Project kind: client_engagement | internal | research | other").option("--status <status>", "Project status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "Project description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47956
+ program3.command("project:create").description('Create a new project\n Example: elevasis-sdk project:create --name "My Project" --kind internal').requiredOption("--name <name>", "Project name").requiredOption("--kind <kind>", "Project kind: client_engagement | internal | research | other").option("--status <status>", "Project status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "Project description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
47942
47957
  wrapAction(
47943
47958
  "project:create",
47944
47959
  async (options) => {
@@ -47962,6 +47977,10 @@ function registerProjectCreate(program3) {
47962
47977
  if (options.contractValue !== void 0) body.contract_value = options.contractValue;
47963
47978
  if (options.metadata) body.metadata = JSON.parse(options.metadata);
47964
47979
  const result = await apiPost("/api/external/projects", body, apiUrl);
47980
+ if (options.json) {
47981
+ printJson2(result);
47982
+ return;
47983
+ }
47965
47984
  if (options.pretty) {
47966
47985
  const p = result.project;
47967
47986
  console.log(source_default.green(`
@@ -47978,7 +47997,7 @@ Project created: ${p.name}`));
47978
47997
  );
47979
47998
  }
47980
47999
  function registerProjectUpdate(program3) {
47981
- program3.command("project:update <id>").description("Update a project\n Example: elevasis-sdk project:update <uuid> --status completed").option("--name <name>", "New project name").option("--status <status>", "New status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "New description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--clear-client", "Remove the client hub link (sets client_id to null)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--actual-end-date <date>", "Actual end date (ISO 8601)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48000
+ program3.command("project:update <id>").description("Update a project\n Example: elevasis-sdk project:update <uuid> --status completed").option("--name <name>", "New project name").option("--status <status>", "New status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "New description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--clear-client", "Remove the client hub link (sets client_id to null)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--actual-end-date <date>", "Actual end date (ISO 8601)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
47982
48001
  wrapAction(
47983
48002
  "project:update",
47984
48003
  async (id, options) => {
@@ -48021,6 +48040,10 @@ function registerProjectUpdate(program3) {
48021
48040
  }
48022
48041
  const apiUrl = resolveApiUrl(options.apiUrl);
48023
48042
  const result = await apiPatch(`/api/external/projects/${id}`, body, apiUrl);
48043
+ if (options.json) {
48044
+ printJson2(result);
48045
+ return;
48046
+ }
48024
48047
  if (options.pretty) {
48025
48048
  const p = result.project;
48026
48049
  console.log(source_default.green(`
@@ -48035,10 +48058,14 @@ Project updated: ${p.name}`));
48035
48058
  );
48036
48059
  }
48037
48060
  function registerProjectDelete(program3) {
48038
- program3.command("project:delete <id>").description("Delete a project\n Example: elevasis-sdk project:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48061
+ program3.command("project:delete <id>").description("Delete a project\n Example: elevasis-sdk project:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48039
48062
  wrapAction("project:delete", async (id, options) => {
48040
48063
  const apiUrl = resolveApiUrl(options.apiUrl);
48041
48064
  const result = await apiDelete(`/api/external/projects/${id}`, apiUrl);
48065
+ if (options.json) {
48066
+ printJson2(result);
48067
+ return;
48068
+ }
48042
48069
  if (options.pretty) {
48043
48070
  console.log(source_default.green(`
48044
48071
  Project ${id} deleted.`));
@@ -48054,6 +48081,9 @@ Project ${id} deleted.`));
48054
48081
  var import_node_fs3 = require("node:fs");
48055
48082
  init_source();
48056
48083
  init_config();
48084
+ function printJson3(value) {
48085
+ console.log(JSON.stringify(value, null, 2));
48086
+ }
48057
48087
  function parseChecklistOption(options) {
48058
48088
  if (options.checklist !== void 0 && options.checklistFile !== void 0) {
48059
48089
  process.stderr.write(
@@ -48074,10 +48104,14 @@ function parseChecklistOption(options) {
48074
48104
  }
48075
48105
  }
48076
48106
  function registerMilestoneList(program3) {
48077
- program3.command("project:milestone:list").description("List milestones for a project\n Example: elevasis-sdk project:milestone:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48107
+ program3.command("project:milestone:list").description("List milestones for a project\n Example: elevasis-sdk project:milestone:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48078
48108
  wrapAction("project:milestone:list", async (options) => {
48079
48109
  const apiUrl = resolveApiUrl(options.apiUrl);
48080
48110
  const result = await apiGet(`/api/external/projects/${options.project}/milestones`, apiUrl);
48111
+ if (options.json) {
48112
+ printJson3(result);
48113
+ return;
48114
+ }
48081
48115
  if (options.pretty) {
48082
48116
  const milestones = result.milestones;
48083
48117
  if (milestones.length === 0) {
@@ -48102,7 +48136,7 @@ Milestones (${milestones.length}):
48102
48136
  function registerMilestoneCreate(program3) {
48103
48137
  program3.command("project:milestone:create").description(
48104
48138
  'Create a milestone\n Example: elevasis-sdk project:milestone:create --project <uuid> --name "Phase 1"'
48105
- ).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--name <name>", "Milestone name").option("--status <status>", "Status: upcoming | in_progress | completed | overdue | blocked").option("--due-date <date>", "Due date (ISO 8601, e.g. 2026-06-01)").option("--description <description>", "Milestone description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48139
+ ).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--name <name>", "Milestone name").option("--status <status>", "Status: upcoming | in_progress | completed | overdue | blocked").option("--due-date <date>", "Due date (ISO 8601, e.g. 2026-06-01)").option("--description <description>", "Milestone description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48106
48140
  wrapAction(
48107
48141
  "project:milestone:create",
48108
48142
  async (options) => {
@@ -48116,6 +48150,10 @@ function registerMilestoneCreate(program3) {
48116
48150
  body,
48117
48151
  apiUrl
48118
48152
  );
48153
+ if (options.json) {
48154
+ printJson3(result);
48155
+ return;
48156
+ }
48119
48157
  if (options.pretty) {
48120
48158
  const m = result.milestone;
48121
48159
  console.log(source_default.green(`
@@ -48135,7 +48173,7 @@ function registerMilestoneUpdate(program3) {
48135
48173
  program3.command("project:milestone:update <id>").description("Update a milestone\n Example: elevasis-sdk project:milestone:update <uuid> --status completed").option("--name <name>", "New milestone name").option("--status <status>", "New status: upcoming | in_progress | completed | overdue | blocked").option("--description <description>", "New description").option("--due-date <date>", "New due date (ISO 8601)").option("--checklist <json>", `Replace checklist (full array): '[{"id":"1","label":"Step","completed":false}]'`).option(
48136
48174
  "--checklist-file <path>",
48137
48175
  "Read replacement checklist from a JSON file. Relative paths resolve against the project root."
48138
- ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48176
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48139
48177
  wrapAction(
48140
48178
  "project:milestone:update",
48141
48179
  async (id, options) => {
@@ -48157,6 +48195,10 @@ function registerMilestoneUpdate(program3) {
48157
48195
  }
48158
48196
  const apiUrl = resolveApiUrl(options.apiUrl);
48159
48197
  const result = await apiPatch(`/api/external/milestones/${id}`, body, apiUrl);
48198
+ if (options.json) {
48199
+ printJson3(result);
48200
+ return;
48201
+ }
48160
48202
  if (options.pretty) {
48161
48203
  const m = result.milestone;
48162
48204
  console.log(source_default.green(`
@@ -48171,10 +48213,14 @@ Milestone updated: ${m.name}`));
48171
48213
  );
48172
48214
  }
48173
48215
  function registerMilestoneDelete(program3) {
48174
- program3.command("project:milestone:delete <id>").description("Delete a milestone\n Example: elevasis-sdk project:milestone:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48216
+ program3.command("project:milestone:delete <id>").description("Delete a milestone\n Example: elevasis-sdk project:milestone:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48175
48217
  wrapAction("project:milestone:delete", async (id, options) => {
48176
48218
  const apiUrl = resolveApiUrl(options.apiUrl);
48177
48219
  const result = await apiDelete(`/api/external/milestones/${id}`, apiUrl);
48220
+ if (options.json) {
48221
+ printJson3(result);
48222
+ return;
48223
+ }
48178
48224
  if (options.pretty) {
48179
48225
  console.log(source_default.green(`
48180
48226
  Milestone ${id} deleted.`));
@@ -48190,6 +48236,9 @@ Milestone ${id} deleted.`));
48190
48236
  var import_node_fs4 = require("node:fs");
48191
48237
  init_source();
48192
48238
  init_config();
48239
+ function printJson4(value) {
48240
+ console.log(JSON.stringify(value, null, 2));
48241
+ }
48193
48242
  function parseChecklistOption2(options) {
48194
48243
  if (options.checklist !== void 0 && options.checklistFile !== void 0) {
48195
48244
  process.stderr.write(
@@ -48215,7 +48264,7 @@ function registerTaskList(program3) {
48215
48264
  ).requiredOption("--project <project-id>", "Project ID (UUID)").option(
48216
48265
  "--status <status>",
48217
48266
  "Filter by status: planned | in_progress | blocked | completed | cancelled | submitted | approved | rejected | revision_requested"
48218
- ).option("--milestone <milestone-id>", "Filter by milestone ID (UUID)").option("--parent <parent-task-id>", "Filter by parent task ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48267
+ ).option("--milestone <milestone-id>", "Filter by milestone ID (UUID)").option("--parent <parent-task-id>", "Filter by parent task ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48219
48268
  wrapAction(
48220
48269
  "project:task:list",
48221
48270
  async (options) => {
@@ -48227,6 +48276,10 @@ function registerTaskList(program3) {
48227
48276
  const qs = params.toString();
48228
48277
  const endpoint = `/api/external/projects/${options.project}/tasks${qs ? `?${qs}` : ""}`;
48229
48278
  const result = await apiGet(endpoint, apiUrl);
48279
+ if (options.json) {
48280
+ printJson4(result);
48281
+ return;
48282
+ }
48230
48283
  if (options.pretty) {
48231
48284
  const tasks = result.tasks;
48232
48285
  if (tasks.length === 0) {
@@ -48250,10 +48303,14 @@ Tasks (${tasks.length}):
48250
48303
  );
48251
48304
  }
48252
48305
  function registerTaskGet(program3) {
48253
- program3.command("project:task:get <id>").description("Get a task by ID\n Example: elevasis-sdk project:task:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48306
+ program3.command("project:task:get <id>").description("Get a task by ID\n Example: elevasis-sdk project:task:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48254
48307
  wrapAction("project:task:get", async (id, options) => {
48255
48308
  const apiUrl = resolveApiUrl(options.apiUrl);
48256
48309
  const result = await apiGet(`/api/external/project-tasks/${id}`, apiUrl);
48310
+ if (options.json) {
48311
+ printJson4(result);
48312
+ return;
48313
+ }
48257
48314
  if (options.pretty) {
48258
48315
  const t = result.task;
48259
48316
  console.log(source_default.cyan(`
@@ -48279,7 +48336,7 @@ function registerTaskCreate(program3) {
48279
48336
  ).option("--milestone <milestone-id>", "Milestone ID (UUID)").option("--parent <parent-task-id>", "Parent task ID (UUID) for subtasks").option("--description <description>", "Task description").option("--checklist <json>", `Checklist items as JSON array: '[{"id":"1","label":"Step","completed":false}]'`).option(
48280
48337
  "--checklist-file <path>",
48281
48338
  "Read checklist items from a JSON file. Relative paths resolve against the project root."
48282
- ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48339
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48283
48340
  wrapAction(
48284
48341
  "project:task:create",
48285
48342
  async (options) => {
@@ -48303,6 +48360,10 @@ function registerTaskCreate(program3) {
48303
48360
  )
48304
48361
  );
48305
48362
  }
48363
+ if (options.json) {
48364
+ printJson4(result);
48365
+ return;
48366
+ }
48306
48367
  if (options.pretty) {
48307
48368
  const t = result.task;
48308
48369
  console.log(source_default.green(`
@@ -48324,7 +48385,7 @@ function registerTaskUpdate(program3) {
48324
48385
  ).option("--milestone <milestone-id>", "New milestone ID (UUID)").option("--description <description>", "New description").option("--checklist <json>", `Replace checklist (full array): '[{"id":"1","label":"Step","completed":false}]'`).option(
48325
48386
  "--checklist-file <path>",
48326
48387
  "Read replacement checklist from a JSON file. Relative paths resolve against the project root."
48327
- ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48388
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48328
48389
  wrapAction(
48329
48390
  "project:task:update",
48330
48391
  async (id, options) => {
@@ -48346,6 +48407,10 @@ function registerTaskUpdate(program3) {
48346
48407
  }
48347
48408
  const apiUrl = resolveApiUrl(options.apiUrl);
48348
48409
  const result = await apiPatch(`/api/external/project-tasks/${id}`, body, apiUrl);
48410
+ if (options.json) {
48411
+ printJson4(result);
48412
+ return;
48413
+ }
48349
48414
  if (options.pretty) {
48350
48415
  const t = result.task;
48351
48416
  console.log(source_default.green(`
@@ -48360,10 +48425,14 @@ Task updated: ${t.name}`));
48360
48425
  );
48361
48426
  }
48362
48427
  function registerTaskDelete(program3) {
48363
- program3.command("project:task:delete <id>").description("Delete a task\n Example: elevasis-sdk project:task:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48428
+ program3.command("project:task:delete <id>").description("Delete a task\n Example: elevasis-sdk project:task:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48364
48429
  wrapAction("project:task:delete", async (id, options) => {
48365
48430
  const apiUrl = resolveApiUrl(options.apiUrl);
48366
48431
  const result = await apiDelete(`/api/external/project-tasks/${id}`, apiUrl);
48432
+ if (options.json) {
48433
+ printJson4(result);
48434
+ return;
48435
+ }
48367
48436
  if (options.pretty) {
48368
48437
  console.log(source_default.green(`
48369
48438
  Task ${id} deleted.`));
@@ -48377,12 +48446,16 @@ Task ${id} deleted.`));
48377
48446
  function registerTaskResume(program3) {
48378
48447
  program3.command("project:task:resume <id>").description(
48379
48448
  "Fetch the resume_context JSONB for a task (used by /work resume)\n Example: elevasis-sdk project:task:resume <uuid>"
48380
- ).option("--api-url <url>", "API base URL").option("--pretty", "Render a human-readable resume briefing instead of raw JSON").action(
48449
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render a human-readable resume briefing instead of raw JSON").option("--json", "Output as JSON").action(
48381
48450
  wrapAction("project:task:resume", async (id, options) => {
48382
48451
  const apiUrl = resolveApiUrl(options.apiUrl);
48383
48452
  const result = await apiGet(`/api/external/project-tasks/${id}`, apiUrl);
48384
48453
  const task = result.task;
48385
48454
  const ctx = task.resume_context ?? {};
48455
+ if (options.json) {
48456
+ printJson4(ctx);
48457
+ return;
48458
+ }
48386
48459
  if (options.pretty) {
48387
48460
  console.log(source_default.cyan(`
48388
48461
  Resume briefing for task: ${task.name}`));
@@ -48426,7 +48499,7 @@ function registerTaskSave(program3) {
48426
48499
  program3.command("project:task:save <id>").description(
48427
48500
  `Merge fields into resume_context for a task (used by /work save)
48428
48501
  Example: elevasis-sdk project:task:save <uuid> --current-state "Implemented X" --files-modified '["src/foo.ts"]'`
48429
- ).requiredOption("--current-state <text>", "Current state description").option("--files-modified <json>", "JSON array of modified file paths").option("--next-steps <text>", "Next steps description").option("--key-docs <json>", "JSON array of key doc paths").option("--tools <json>", "JSON array of tool names used").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48502
+ ).requiredOption("--current-state <text>", "Current state description").option("--files-modified <json>", "JSON array of modified file paths").option("--next-steps <text>", "Next steps description").option("--key-docs <json>", "JSON array of key doc paths").option("--tools <json>", "JSON array of tool names used").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48430
48503
  wrapAction(
48431
48504
  "project:task:save",
48432
48505
  async (id, options) => {
@@ -48468,6 +48541,10 @@ function registerTaskSave(program3) {
48468
48541
  }
48469
48542
  const apiUrl = resolveApiUrl(options.apiUrl);
48470
48543
  const result = await apiPatch(`/api/external/project-tasks/${id}/resume-context`, body, apiUrl);
48544
+ if (options.json) {
48545
+ printJson4(result);
48546
+ return;
48547
+ }
48471
48548
  if (options.pretty) {
48472
48549
  console.log(source_default.green(`
48473
48550
  Resume context saved for task ${id}`));
@@ -48646,12 +48723,19 @@ var NoteIdParamsSchema = external_exports.object({ id: UuidSchema });
48646
48723
 
48647
48724
  // src/cli/commands/project/notes.ts
48648
48725
  init_config();
48726
+ function printJson5(value) {
48727
+ console.log(JSON.stringify(value, null, 2));
48728
+ }
48649
48729
  var NOTE_TYPE_HELP = NoteTypeSchema.options.join(" | ");
48650
48730
  function registerNoteList(program3) {
48651
- program3.command("project:note:list").description("List notes for a project\n Example: elevasis-sdk project:note:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48731
+ program3.command("project:note:list").description("List notes for a project\n Example: elevasis-sdk project:note:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48652
48732
  wrapAction("project:note:list", async (options) => {
48653
48733
  const apiUrl = resolveApiUrl(options.apiUrl);
48654
48734
  const result = await apiGet(`/api/external/projects/${options.project}/notes`, apiUrl);
48735
+ if (options.json) {
48736
+ printJson5(result);
48737
+ return;
48738
+ }
48655
48739
  if (options.pretty) {
48656
48740
  const notes = result.notes;
48657
48741
  if (notes.length === 0) {
@@ -48676,7 +48760,7 @@ Notes (${notes.length}):
48676
48760
  function registerNoteCreate(program3) {
48677
48761
  program3.command("project:note:create").description(
48678
48762
  'Create a note\n Example: elevasis-sdk project:note:create --project <uuid> --content "Status update"'
48679
- ).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--content <content>", "Note content").option("--task <task-id>", "Attach to a task (UUID)").option("--milestone <milestone-id>", "Attach to a milestone (UUID)").option("--type <type>", `Note type: ${NOTE_TYPE_HELP}`).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48763
+ ).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--content <content>", "Note content").option("--task <task-id>", "Attach to a task (UUID)").option("--milestone <milestone-id>", "Attach to a milestone (UUID)").option("--type <type>", `Note type: ${NOTE_TYPE_HELP}`).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48680
48764
  wrapAction(
48681
48765
  "project:note:create",
48682
48766
  async (options) => {
@@ -48689,6 +48773,10 @@ function registerNoteCreate(program3) {
48689
48773
  if (options.type) body.type = options.type;
48690
48774
  const apiUrl = resolveApiUrl(options.apiUrl);
48691
48775
  const result = await apiPost("/api/external/project-notes", body, apiUrl);
48776
+ if (options.json) {
48777
+ printJson5(result);
48778
+ return;
48779
+ }
48692
48780
  if (options.pretty) {
48693
48781
  const n = result.note;
48694
48782
  console.log(source_default.green(`
@@ -48704,7 +48792,7 @@ Note created`));
48704
48792
  );
48705
48793
  }
48706
48794
  function registerNoteUpdate(program3) {
48707
- program3.command("project:note:update <id>").description('Update a note\n Example: elevasis-sdk project:note:update <uuid> --content "Updated content"').requiredOption("--content <content>", "New note content").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48795
+ program3.command("project:note:update <id>").description('Update a note\n Example: elevasis-sdk project:note:update <uuid> --content "Updated content"').requiredOption("--content <content>", "New note content").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48708
48796
  wrapAction("project:note:update", async (id, options) => {
48709
48797
  const apiUrl = resolveApiUrl(options.apiUrl);
48710
48798
  const result = await apiPatch(
@@ -48712,6 +48800,10 @@ function registerNoteUpdate(program3) {
48712
48800
  { content: options.content },
48713
48801
  apiUrl
48714
48802
  );
48803
+ if (options.json) {
48804
+ printJson5(result);
48805
+ return;
48806
+ }
48715
48807
  if (options.pretty) {
48716
48808
  console.log(source_default.green(`
48717
48809
  Note ${id} updated.`));
@@ -48723,10 +48815,14 @@ Note ${id} updated.`));
48723
48815
  );
48724
48816
  }
48725
48817
  function registerNoteDelete(program3) {
48726
- program3.command("project:note:delete <id>").description("Delete a note\n Example: elevasis-sdk project:note:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
48818
+ program3.command("project:note:delete <id>").description("Delete a note\n Example: elevasis-sdk project:note:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option("--json", "Output as JSON").action(
48727
48819
  wrapAction("project:note:delete", async (id, options) => {
48728
48820
  const apiUrl = resolveApiUrl(options.apiUrl);
48729
48821
  const result = await apiDelete(`/api/external/project-notes/${id}`, apiUrl);
48822
+ if (options.json) {
48823
+ printJson5(result);
48824
+ return;
48825
+ }
48730
48826
  if (options.pretty) {
48731
48827
  console.log(source_default.green(`
48732
48828
  Note ${id} deleted.`));
@@ -51055,7 +51151,7 @@ function endpointWithQuery2(endpoint, params) {
51055
51151
  const query = params.toString();
51056
51152
  return query ? `${endpoint}?${query}` : endpoint;
51057
51153
  }
51058
- function printJson2(value) {
51154
+ function printJson6(value) {
51059
51155
  console.log(JSON.stringify(value, null, 2));
51060
51156
  }
51061
51157
  function dealEmail(deal) {
@@ -51086,7 +51182,7 @@ function registerAcquisitionDealList(program3) {
51086
51182
  appendQuery2(params, "offset", options.offset);
51087
51183
  const result = await apiGet(endpointWithQuery2("/api/external/deals", params), apiUrl);
51088
51184
  if (!options.pretty) {
51089
- printJson2(result);
51185
+ printJson6(result);
51090
51186
  return;
51091
51187
  }
51092
51188
  if (result.data.length === 0) {
@@ -51114,7 +51210,7 @@ function registerAcquisitionDealGet(program3) {
51114
51210
  const apiUrl = resolveApiUrl(options.apiUrl);
51115
51211
  const result = await apiGet("/api/external/deals/" + id, apiUrl);
51116
51212
  if (!options.pretty) {
51117
- printJson2(result);
51213
+ printJson6(result);
51118
51214
  return;
51119
51215
  }
51120
51216
  console.log(source_default.cyan(`
@@ -51136,7 +51232,7 @@ function registerAcquisitionDealStatus(program3) {
51136
51232
  const apiUrl = resolveApiUrl(options.apiUrl);
51137
51233
  const result = await apiGet("/api/external/deals/summary", apiUrl);
51138
51234
  if (!options.pretty) {
51139
- printJson2(result);
51235
+ printJson6(result);
51140
51236
  return;
51141
51237
  }
51142
51238
  console.log(source_default.cyan("\nAcquisition deal status"));
@@ -51166,7 +51262,7 @@ function endpointWithQuery3(endpoint, params) {
51166
51262
  const query = params.toString();
51167
51263
  return query ? `${endpoint}?${query}` : endpoint;
51168
51264
  }
51169
- function printJson3(value) {
51265
+ function printJson7(value) {
51170
51266
  console.log(JSON.stringify(value, null, 2));
51171
51267
  }
51172
51268
  function renderListSummary(list) {
@@ -51194,7 +51290,7 @@ function registerAcquisitionListList(program3) {
51194
51290
  apiUrl
51195
51291
  );
51196
51292
  if (!options.pretty) {
51197
- printJson3(result);
51293
+ printJson7(result);
51198
51294
  return;
51199
51295
  }
51200
51296
  if (result.length === 0) {
@@ -51225,7 +51321,7 @@ function registerAcquisitionListGet(program3) {
51225
51321
  apiUrl
51226
51322
  );
51227
51323
  if (!options.pretty) {
51228
- printJson3(result);
51324
+ printJson7(result);
51229
51325
  return;
51230
51326
  }
51231
51327
  console.log(source_default.cyan(`
@@ -51247,7 +51343,7 @@ function registerAcquisitionListStatus(program3) {
51247
51343
  const apiUrl = resolveApiUrl(options.apiUrl);
51248
51344
  const result = await apiGet("/api/external/acquisition/lists/status", apiUrl);
51249
51345
  if (!options.pretty) {
51250
- printJson3(result);
51346
+ printJson7(result);
51251
51347
  return;
51252
51348
  }
51253
51349
  console.log(source_default.cyan("\nAcquisition list status"));
@@ -51412,7 +51508,7 @@ function registerClientCommands(program3) {
51412
51508
  // src/cli/commands/queue/queue.ts
51413
51509
  init_source();
51414
51510
  init_config();
51415
- function printJson4(value) {
51511
+ function printJson8(value) {
51416
51512
  console.log(JSON.stringify(value, null, 2));
51417
51513
  }
51418
51514
  function appendQuery4(params, key, value) {
@@ -51453,7 +51549,7 @@ function registerQueueList(program3) {
51453
51549
  apiUrl
51454
51550
  );
51455
51551
  if (!options.pretty) {
51456
- printJson4(result);
51552
+ printJson8(result);
51457
51553
  return;
51458
51554
  }
51459
51555
  if (result.tasks.length === 0) {
@@ -51481,7 +51577,7 @@ function registerQueueGet(program3) {
51481
51577
  const apiUrl = resolveApiUrl(options.apiUrl);
51482
51578
  const result = await apiGet(`/api/external/command-queue/${id}`, apiUrl);
51483
51579
  if (!options.pretty) {
51484
- printJson4(result);
51580
+ printJson8(result);
51485
51581
  return;
51486
51582
  }
51487
51583
  const task = result.task;
@@ -51514,7 +51610,7 @@ function registerQueueSelect(program3) {
51514
51610
  apiUrl
51515
51611
  );
51516
51612
  if (!options.pretty) {
51517
- printJson4(result);
51613
+ printJson8(result);
51518
51614
  return;
51519
51615
  }
51520
51616
  console.log(source_default.green(`
@@ -51535,7 +51631,7 @@ function registerQueueExpire(program3) {
51535
51631
  apiUrl
51536
51632
  );
51537
51633
  if (!options.pretty) {
51538
- printJson4(result);
51634
+ printJson8(result);
51539
51635
  return;
51540
51636
  }
51541
51637
  console.log(source_default.green(`
@@ -51561,7 +51657,7 @@ function registerQueueStatus(program3) {
51561
51657
  apiUrl
51562
51658
  );
51563
51659
  if (!options.pretty) {
51564
- printJson4(result);
51660
+ printJson8(result);
51565
51661
  return;
51566
51662
  }
51567
51663
  console.log(source_default.cyan("\nQueue status"));
@@ -51599,7 +51695,7 @@ function registerQueueCommands(program3) {
51599
51695
  // src/cli/commands/schedule/schedule.ts
51600
51696
  init_source();
51601
51697
  init_config();
51602
- function printJson5(value) {
51698
+ function printJson9(value) {
51603
51699
  console.log(JSON.stringify(value, null, 2));
51604
51700
  }
51605
51701
  function appendQuery5(params, key, value) {
@@ -51641,7 +51737,7 @@ function registerScheduleList(program3) {
51641
51737
  apiUrl
51642
51738
  );
51643
51739
  if (!options.pretty) {
51644
- printJson5(result);
51740
+ printJson9(result);
51645
51741
  return;
51646
51742
  }
51647
51743
  if (result.schedules.length === 0) {
@@ -51668,7 +51764,7 @@ function registerScheduleGet(program3) {
51668
51764
  apiUrl
51669
51765
  );
51670
51766
  if (!options.pretty) {
51671
- printJson5(result);
51767
+ printJson9(result);
51672
51768
  return;
51673
51769
  }
51674
51770
  console.log(source_default.cyan(`
@@ -51718,7 +51814,7 @@ function registerScheduleCreate(program3) {
51718
51814
  apiUrl
51719
51815
  );
51720
51816
  if (!options.pretty) {
51721
- printJson5(result);
51817
+ printJson9(result);
51722
51818
  return;
51723
51819
  }
51724
51820
  console.log(source_default.green(`
@@ -51770,7 +51866,7 @@ function registerScheduleUpdate(program3) {
51770
51866
  apiUrl
51771
51867
  );
51772
51868
  if (!options.pretty) {
51773
- printJson5(result);
51869
+ printJson9(result);
51774
51870
  return;
51775
51871
  }
51776
51872
  console.log(source_default.green(`
@@ -51793,7 +51889,7 @@ function registerScheduleStatusMutation(program3, commandName, description) {
51793
51889
  apiUrl
51794
51890
  );
51795
51891
  if (!options.pretty) {
51796
- printJson5(result);
51892
+ printJson9(result);
51797
51893
  return;
51798
51894
  }
51799
51895
  const verb = commandName === "pause" ? "paused" : commandName === "resume" ? "resumed" : "cancelled";
@@ -51910,7 +52006,7 @@ init_config();
51910
52006
  function getResourceType2(resource) {
51911
52007
  return resource.type ?? resource.resourceType;
51912
52008
  }
51913
- function printJson6(value) {
52009
+ function printJson10(value) {
51914
52010
  console.log(JSON.stringify(value, null, 2));
51915
52011
  }
51916
52012
  function registerAgentList(program3) {
@@ -51920,7 +52016,7 @@ function registerAgentList(program3) {
51920
52016
  const result = await apiGet("/api/external/resources", apiUrl);
51921
52017
  const agents = result.resources.filter((resource) => getResourceType2(resource) === "agent");
51922
52018
  if (options.json) {
51923
- printJson6({ agents, total: agents.length });
52019
+ printJson10({ agents, total: agents.length });
51924
52020
  return;
51925
52021
  }
51926
52022
  if (agents.length === 0) {
@@ -51948,7 +52044,7 @@ function registerAgentGet(program3) {
51948
52044
  const apiUrl = resolveApiUrl(options.apiUrl);
51949
52045
  const definition = await apiGet(`/api/external/resources/${id}/definition`, apiUrl);
51950
52046
  if (options.json) {
51951
- printJson6(definition);
52047
+ printJson10(definition);
51952
52048
  return;
51953
52049
  }
51954
52050
  const config3 = definition.config ?? {};
@@ -51982,7 +52078,7 @@ function registerAgentCommands(program3) {
51982
52078
  var import_node_fs10 = require("node:fs");
51983
52079
  init_source();
51984
52080
  init_config();
51985
- function printJson7(value) {
52081
+ function printJson11(value) {
51986
52082
  console.log(JSON.stringify(value, null, 2));
51987
52083
  }
51988
52084
  function appendQuery6(params, key, value) {
@@ -52090,7 +52186,7 @@ function registerSessionCreate(program3) {
52090
52186
  if (options.metadata) body.metadata = parseJson(options.metadata, "--metadata");
52091
52187
  const session = await apiPost("/api/external/sessions", body, apiUrl);
52092
52188
  if (options.json) {
52093
- printJson7(session);
52189
+ printJson11(session);
52094
52190
  return;
52095
52191
  }
52096
52192
  console.log(source_default.green(`Created session ${session.sessionId}.`));
@@ -52110,7 +52206,7 @@ function registerSessionList(program3) {
52110
52206
  appendQuery6(params, "limit", options.limit);
52111
52207
  const result = await apiGet(endpointWithQuery6("/api/external/sessions", params), apiUrl);
52112
52208
  if (options.json) {
52113
- printJson7(result);
52209
+ printJson11(result);
52114
52210
  return;
52115
52211
  }
52116
52212
  if (result.sessions.length === 0) {
@@ -52136,7 +52232,7 @@ function registerSessionGet(program3) {
52136
52232
  const apiUrl = resolveApiUrl(options.apiUrl);
52137
52233
  const session = await apiGet(`/api/external/sessions/${id}`, apiUrl);
52138
52234
  if (options.json) {
52139
- printJson7(session);
52235
+ printJson11(session);
52140
52236
  return;
52141
52237
  }
52142
52238
  console.log(source_default.cyan(`Session: ${session.title ?? session.sessionId}`));
@@ -52158,7 +52254,7 @@ function registerSessionTurn(program3) {
52158
52254
  const input = resolveTurnInput(options);
52159
52255
  const result = await apiPost(`/api/external/sessions/${id}/turns`, { input }, apiUrl);
52160
52256
  if (options.json) {
52161
- printJson7(result);
52257
+ printJson11(result);
52162
52258
  return;
52163
52259
  }
52164
52260
  console.log(source_default.green(`Turn ${result.turnNumber} complete.`));
@@ -52190,7 +52286,7 @@ function registerSessionMessages(program3) {
52190
52286
  const apiUrl = resolveApiUrl(options.apiUrl);
52191
52287
  const result = await fetchSessionMessages(id, apiUrl, options);
52192
52288
  if (options.json) {
52193
- printJson7(result);
52289
+ printJson11(result);
52194
52290
  return;
52195
52291
  }
52196
52292
  const total = result.total === void 0 ? result.messages.length : result.total;
@@ -52216,7 +52312,7 @@ function registerSessionEnd(program3) {
52216
52312
  apiUrl
52217
52313
  );
52218
52314
  if (options.json) {
52219
- printJson7(result);
52315
+ printJson11(result);
52220
52316
  return;
52221
52317
  }
52222
52318
  console.log(source_default.green(`Ended session ${result.sessionId ?? id}.`));
@@ -52237,7 +52333,7 @@ function registerSessionCommands(program3) {
52237
52333
  // src/cli/commands/grant/grant.ts
52238
52334
  init_source();
52239
52335
  init_config();
52240
- function printJson8(value) {
52336
+ function printJson12(value) {
52241
52337
  console.log(JSON.stringify(value, null, 2));
52242
52338
  }
52243
52339
  function appendQuery7(params, key, value) {
@@ -52312,7 +52408,7 @@ function registerGrantList(program3) {
52312
52408
  apiUrl
52313
52409
  );
52314
52410
  if (options.json) {
52315
- printJson8(result);
52411
+ printJson12(result);
52316
52412
  return;
52317
52413
  }
52318
52414
  if (result.grants.length === 0) {
@@ -52360,7 +52456,7 @@ function registerGrantCreate(program3) {
52360
52456
  const apiUrl = resolveApiUrl(options.apiUrl);
52361
52457
  const result = await apiPost("/api/external/agent-access-grants", body, apiUrl);
52362
52458
  if (options.json) {
52363
- printJson8(result.grant);
52459
+ printJson12(result.grant);
52364
52460
  return;
52365
52461
  }
52366
52462
  console.log(source_default.green(`Created agent access grant ${result.grant.slug}.`));
@@ -52403,7 +52499,7 @@ function registerGrantUpdate(program3) {
52403
52499
  apiUrl
52404
52500
  );
52405
52501
  if (options.json) {
52406
- printJson8(result.grant);
52502
+ printJson12(result.grant);
52407
52503
  return;
52408
52504
  }
52409
52505
  console.log(source_default.green(`Updated agent access grant ${result.grant.slug}.`));
@@ -52422,7 +52518,7 @@ function registerGrantDisable(program3) {
52422
52518
  apiUrl
52423
52519
  );
52424
52520
  if (options.json) {
52425
- printJson8(result.grant);
52521
+ printJson12(result.grant);
52426
52522
  return;
52427
52523
  }
52428
52524
  console.log(source_default.green(`Disabled agent access grant ${result.grant.slug}.`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "1.36.4",
3
+ "version": "1.36.5",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,9 +58,9 @@
58
58
  "tsup": "^8.0.0",
59
59
  "typescript": "5.9.2",
60
60
  "zod": "^4.1.0",
61
- "@repo/core": "0.50.0",
62
- "@repo/eslint-config": "0.0.0",
63
- "@repo/typescript-config": "0.0.0"
61
+ "@repo/core": "0.51.0",
62
+ "@repo/typescript-config": "0.0.0",
63
+ "@repo/eslint-config": "0.0.0"
64
64
  },
65
65
  "scripts": {
66
66
  "lint": "eslint src --max-warnings 0",
@@ -256,6 +256,28 @@ Organization scoping is handled server-side via `ELEVASIS_PLATFORM_KEY`. No org
256
256
 
257
257
  ---
258
258
 
259
+ ## Output Flags
260
+
261
+ All `project:*` commands support three output modes via flags:
262
+
263
+ | Flag | Behavior | Use when |
264
+ | ----------- | -------------------------- | --------------------------------------------------- |
265
+ | _(no flag)_ | Raw JSON (legacy default) | Existing scripts that parse default stdout |
266
+ | `--json` | Clean JSON via `printJson` | Agent automation — the preferred machine-parse flag |
267
+ | `--pretty` | Human-readable text | Interactive / debugging output |
268
+
269
+ **Canonical machine-parse recipe:**
270
+
271
+ ```bash
272
+ pnpm -s elevasis-sdk project:task:list --project <uuid> --json
273
+ ```
274
+
275
+ The `-s` / `--silent` flag suppresses the pnpm lifecycle preamble (`> project@... elevasis-sdk ...`) so stdout is pure JSON with no wrapper noise. Use `--json` and `-s` together for all agent automation.
276
+
277
+ **Defensive parse fallback** (if any wrapper noise remains): slice from the first `{` or `[` to the last `}` or `]` before calling `JSON.parse`.
278
+
279
+ ---
280
+
259
281
  ## Database Schema
260
282
 
261
283
  ### Tables
@@ -0,0 +1,33 @@
1
+ # Session UX fixes + project CLI `--json`
2
+
3
+ ## Why this note exists
4
+
5
+ This train bumps both `@elevasis/ui` and `@elevasis/sdk` with several tenant-facing changes beyond the shared `SessionConversationView` adoption (see the companion `2026-06-14-shared-session-conversation-view.md` note):
6
+
7
+ - **Lazy agent-session creation** (`@elevasis/ui`) — the Agent Sessions surface and the public agent-chat surface no longer create a `sessions` row on open/mount. The row is created on the first message-send ("create-on-first-turn"), so opened-then-abandoned chats no longer leave phantom "0 turns" rows.
8
+ - **Agent Sessions list refresh-after-delete fix** (`@elevasis/ui`) — a query-key factory bug (`sessionsKeys.sessions` appended a literal `undefined`) broke partial-match invalidation, so delete/create/archive left the list stale until a manual reload. Fixed; the list now refreshes automatically.
9
+ - **Project milestone progress badge fix** (`@elevasis/ui`) — the `/projects` milestone header badge counted the milestone's own (empty) checklist, showing `0/0 COMPLETE`. It now counts completed child tasks, with a checklist fallback for task-free milestones.
10
+ - **`project:*` CLI `--json` flag** (`@elevasis/sdk`) — every `project:*` command (project/task/milestone/note) now accepts `--json` for clean machine-parseable output, matching `grant:*`/`session:*`. The `/project` skill SKILL.md gains an Output Flags reference and the canonical `pnpm -s elevasis-sdk … --json` parse recipe (auto-propagated as a managed `.claude` write).
11
+
12
+ ## Applies to
13
+
14
+ - All template-derived projects that expose the agent-sessions page (`ui/src/features/operations/sessions/`) or the public agent-chat surface.
15
+ - All projects that drive work via the `elevasis-sdk project:*` CLI or surface the `/projects` delivery page.
16
+
17
+ ## Required actions
18
+
19
+ - Bump `@elevasis/ui` to `^2.55.0` and `@elevasis/sdk` to `^1.36.5` (or later) and install. The ship train's `external-sync` stage does this automatically via the package-cascade baselines — manual `pnpm update` is not required.
20
+ - No source changes are required to receive the lazy-session, delete-refresh, or milestone-badge fixes — they ship inside `@elevasis/ui`.
21
+ - Agents may now invoke `pnpm -s elevasis-sdk project:<cmd> … --json` for clean JSON; the propagated `/project` SKILL.md Output Flags table documents the parse recipe.
22
+
23
+ ## Verification
24
+
25
+ - `pnpm -C ui check-types` passes against `@elevasis/ui@^2.55.0`.
26
+ - Open an agent-session chat without sending → no new `sessions` row appears in the list; send one message → exactly one row with `1 turn`.
27
+ - Delete a session → the list refreshes without a manual reload.
28
+ - `pnpm -s elevasis-sdk project:task:list --project <id> --json` exits 0 with parseable JSON and no `unknown option` error.
29
+
30
+ ## Not handled by /git-sync
31
+
32
+ - `/git-sync` surfaces this note and pulls the propagated `/project` SKILL.md baseline, but it does not run the `@elevasis/ui` / `@elevasis/sdk` install for you when reconciling manually outside the ship train.
33
+ - The lazy-session change does NOT retroactively clean up pre-existing "0 turns" rows; those are left in place by design.
@@ -0,0 +1,26 @@
1
+ # Shared Session ConversationView
2
+
3
+ ## Why this note exists
4
+
5
+ `@elevasis/ui` now ships a shared `SessionConversationView` component (WebSocket-backed session-detail chat body). The template's session-detail page previously filled the `renderConversationView` slot with a local stub (`ui/src/features/assistant/components/ConversationView.tsx`) that returned `null`, so the agent-sessions chat page (`/operations/sessions/$sessionId`) rendered blank and the `DISCONNECTED` badge never cleared. The template `SessionChatPage` now renders the shared component directly, so derived projects get a working session chat with no local implementation.
6
+
7
+ ## Applies to
8
+
9
+ - All template-derived projects that expose the agent-sessions page (`ui/src/features/operations/sessions/SessionChatPage.tsx`).
10
+ - Any project still carrying the `null`-returning `ConversationView` stub in `ui/src/features/assistant/components/`.
11
+
12
+ ## Required actions
13
+
14
+ - Bump `@elevasis/ui` to `^2.55.0` (or later) in `ui/package.json` and install. (The ship train's `external-sync` stage does this automatically via the package-cascade baseline; manual `pnpm update` is not required.)
15
+ - Adopt the new `SessionChatPage` slot wiring: render `<SessionConversationView apiUrl={API_URL} sessionId={...} ... />` from `@elevasis/ui/features/operations`, reading `API_URL` from `@/lib/constants/api`, instead of the local `ConversationView` stub.
16
+ - The local `ConversationView` stub is now unused by the session page. It remains a generic placeholder for an AI-assistant feature; keep it only if you are building such a feature, otherwise it can be removed.
17
+
18
+ ## Verification
19
+
20
+ - `pnpm -C ui check-types` passes against `@elevasis/ui@^2.55.0`.
21
+ - The session-detail chat page renders history + live messages and the `DISCONNECTED` badge clears (connects) once `apiUrl` is wired.
22
+
23
+ ## Not handled by /git-sync
24
+
25
+ - `/git-sync` surfaces this note and pulls the template `SessionChatPage` baseline, but it does not delete the now-unused local `ConversationView` stub. Remove it manually if you do not intend to build an assistant feature.
26
+ - `/git-sync` does not run the `@elevasis/ui` install for you; run the install after the baseline bump if you are reconciling manually outside the ship train.