@ted-galago/wave-cli 0.1.16 → 0.1.18

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.cjs CHANGED
@@ -181,6 +181,22 @@ function graphqlOperationName(command) {
181
181
  function toCamelCase(value) {
182
182
  return value.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
183
183
  }
184
+ function capitalizeFirst(value) {
185
+ return value.length === 0 ? value : value[0].toUpperCase() + value.slice(1);
186
+ }
187
+ var MUTATION_PARAMS_INPUT_TYPE_OVERRIDES = {
188
+ createOpenAiRealtimeClientSecret: "OpenAiRealtimeClientSecretInput",
189
+ createOpenAiRealtimeSession: "OpenAiRealtimeSessionInput",
190
+ createOpenAiTranscription: "OpenAiTranscriptionInput",
191
+ finalizeOpenAiTranscription: "OpenAiFinalizeTranscriptionInput"
192
+ };
193
+ function inferMutationParamsInputType(input) {
194
+ if (input.operationType !== "mutation") {
195
+ return null;
196
+ }
197
+ const graphqlField = toCamelCase(input.field);
198
+ return MUTATION_PARAMS_INPUT_TYPE_OVERRIDES[graphqlField] ?? `${capitalizeFirst(graphqlField)}ParamsInput`;
199
+ }
184
200
  function inferStatusFromGraphqlErrors(errors) {
185
201
  if (!Array.isArray(errors) || errors.length === 0) {
186
202
  return 400;
@@ -413,7 +429,7 @@ function buildFeedbackFindRequestBody(command, identity) {
413
429
  page: 1,
414
430
  per: 1
415
431
  },
416
- selectionSet: "{ data { id type attributes } count currentPage totalPages }"
432
+ selectionSet: "{ data { id type attributes { id name slug year quarter organizationId memberIds } } count currentPage totalPages }"
417
433
  });
418
434
  }
419
435
  async function requestGraphqlHttp(params) {
@@ -484,7 +500,13 @@ function graphqlTypeForValue(value) {
484
500
  }
485
501
  return "JSON";
486
502
  }
487
- function graphqlTypeForVariable(name, value) {
503
+ function graphqlTypeForVariable(input, name, value) {
504
+ if (name === "params") {
505
+ const paramsInputType = inferMutationParamsInputType(input);
506
+ if (paramsInputType) {
507
+ return paramsInputType;
508
+ }
509
+ }
488
510
  if (name === "id" || name.endsWith("Id")) {
489
511
  return "ID";
490
512
  }
@@ -528,7 +550,7 @@ function buildGraphqlBody(input) {
528
550
  const variableDecl = variableEntries.map(([name, value]) => {
529
551
  const overriddenType = graphqlVariableTypes[name];
530
552
  const hasOverriddenType = typeof overriddenType === "string" && overriddenType.trim().length > 0;
531
- const typeName = hasOverriddenType ? overriddenType.trim() : graphqlTypeForVariable(name, value);
553
+ const typeName = hasOverriddenType ? overriddenType.trim() : graphqlTypeForVariable(input, name, value);
532
554
  return `$${name}: ${hasOverriddenType ? typeName : withNonNull(typeName)}`;
533
555
  }).join(", ");
534
556
  const fieldArgs = variableEntries.map(([name]) => `${name}: $${name}`).join(", ");
@@ -823,8 +845,7 @@ var RESOURCE_QUERY_FIELDS = {
823
845
  "memberIds",
824
846
  "leadMemberId",
825
847
  "organizationId",
826
- "responsibilities",
827
- "keyMetric"
848
+ "responsibilities"
828
849
  ],
829
850
  member: [
830
851
  "slug",
@@ -1280,16 +1301,16 @@ function defaultQuerySelectionSet(field, isList) {
1280
1301
  const canonicalField = RESOURCE_FIELD_ALIASES[field] ?? field;
1281
1302
  const explicitFields = RESOURCE_QUERY_FIELDS[canonicalField];
1282
1303
  if (explicitFields) {
1304
+ const attributes = explicitFields.length > 0 ? `attributes { ${Array.from(/* @__PURE__ */ new Set(["id", ...explicitFields])).join(" ")} }` : "attributes";
1283
1305
  if (isList) {
1284
- return "{ data { id type attributes } count currentPage totalPages }";
1306
+ return `{ data { id type ${attributes} } count currentPage totalPages }`;
1285
1307
  }
1286
- const fields = Array.from(/* @__PURE__ */ new Set(["id", "type", ...explicitFields, "attributes"])).join(" ");
1287
- return `{ ${fields} }`;
1308
+ return `{ id type ${attributes} }`;
1288
1309
  }
1289
1310
  if (isList) {
1290
- return "{ data { id type attributes } count currentPage totalPages }";
1311
+ return "{ data { id type } count currentPage totalPages }";
1291
1312
  }
1292
- return "{ id type attributes }";
1313
+ return "{ id type }";
1293
1314
  }
1294
1315
  function isRecord(value) {
1295
1316
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -2594,7 +2615,10 @@ var idSchema3 = import_zod4.z.string().min(1);
2594
2615
  var projectCreateDataJsonHelp = buildDataJsonHelp("project", "create") ?? 'JSON object for project or {"project": {...}}';
2595
2616
  var projectUpdateDataJsonHelp = buildDataJsonHelp("project", "update") ?? 'JSON object for project or {"project": {...}}';
2596
2617
  var projectsIndexMinimalSelectionSet = "{ count currentPage totalPages data { id type attributes { name slug status priority } } }";
2597
- var projectShowFullSelectionSet = "{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type attributes viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type attributes filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type value memberId createdAt updatedAt commentType commentableId commentableType parentCommentId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }";
2618
+ var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId }";
2619
+ var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
2620
+ var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
2621
+ var projectShowFullSelectionSet = `{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type ${displayPreferenceAttributesSelectionSet} viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type ${filterPreferenceAttributesSelectionSet} filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { ${healthUpdateSummarySelectionSet} replies { ${healthUpdateSummarySelectionSet} replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }`;
2598
2622
  function asRecord2(value) {
2599
2623
  return value && typeof value === "object" ? value : null;
2600
2624
  }
@@ -3999,7 +4023,7 @@ function registerSystemToolCommands(program) {
3999
4023
  page: 1,
4000
4024
  per: 200
4001
4025
  },
4002
- selectionSet: "{ data { id type slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds attributes } count currentPage totalPages }",
4026
+ selectionSet: "{ data { id type slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds attributes { id slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds } } count currentPage totalPages }",
4003
4027
  transformData: (value) => {
4004
4028
  if (!value || typeof value !== "object") {
4005
4029
  return null;
@@ -4616,7 +4640,13 @@ function registerFoundationCommands(program) {
4616
4640
  var import_zod12 = require("zod");
4617
4641
  var idSchema11 = import_zod12.z.string().min(1);
4618
4642
  var jsonObjectSchema = import_zod12.z.record(import_zod12.z.string(), import_zod12.z.unknown());
4619
- var childListMinimalSelectionSet = "{ data { id type attributes } count currentPage totalPages }";
4643
+ function buildChildListSelectionSet(parentField, extraFields = []) {
4644
+ const fields = Array.from(
4645
+ /* @__PURE__ */ new Set(["id", "type", "name", "status", "priority", "rank", "dueDate", "memberId", parentField, ...extraFields])
4646
+ );
4647
+ const attributeFields = fields.filter((field) => field !== "type");
4648
+ return `{ data { ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } } count currentPage totalPages }`;
4649
+ }
4620
4650
  function parseJsonObject2(raw) {
4621
4651
  try {
4622
4652
  const parsed = JSON.parse(raw);
@@ -4821,7 +4851,7 @@ function registerChildEntityCommands(program) {
4821
4851
  createOperationName: "SubtasksCreate",
4822
4852
  updateOperationName: "SubtasksUpdate",
4823
4853
  destroyOperationName: "SubtasksDestroy",
4824
- listSelectionSet: childListMinimalSelectionSet,
4854
+ listSelectionSet: buildChildListSelectionSet("taskId"),
4825
4855
  listParentTypedField: "taskId",
4826
4856
  normalizeCreateBody: normalizeSubtaskCreateBody
4827
4857
  });
@@ -4840,7 +4870,7 @@ function registerChildEntityCommands(program) {
4840
4870
  createOperationName: "MilestonesCreate",
4841
4871
  updateOperationName: "MilestonesUpdate",
4842
4872
  destroyOperationName: "MilestonesDestroy",
4843
- listSelectionSet: childListMinimalSelectionSet
4873
+ listSelectionSet: buildChildListSelectionSet("rockId")
4844
4874
  });
4845
4875
  registerChildCommands(program, {
4846
4876
  command: "subitems",
@@ -4857,7 +4887,7 @@ function registerChildEntityCommands(program) {
4857
4887
  createOperationName: "SubitemsCreate",
4858
4888
  updateOperationName: "SubitemsUpdate",
4859
4889
  destroyOperationName: "SubitemsDestroy",
4860
- listSelectionSet: childListMinimalSelectionSet,
4890
+ listSelectionSet: buildChildListSelectionSet("listItemId"),
4861
4891
  listParentTypedField: "listItemId"
4862
4892
  });
4863
4893
  registerChildCommands(program, {
@@ -4875,7 +4905,7 @@ function registerChildEntityCommands(program) {
4875
4905
  createOperationName: "SubtodosCreate",
4876
4906
  updateOperationName: "SubtodosUpdate",
4877
4907
  destroyOperationName: "SubtodosDestroy",
4878
- listSelectionSet: childListMinimalSelectionSet,
4908
+ listSelectionSet: buildChildListSelectionSet("todoId"),
4879
4909
  listParentTypedField: "todoId"
4880
4910
  });
4881
4911
  registerChildCommands(program, {
@@ -4893,7 +4923,7 @@ function registerChildEntityCommands(program) {
4893
4923
  createOperationName: "SubissuesCreate",
4894
4924
  updateOperationName: "SubissuesUpdate",
4895
4925
  destroyOperationName: "SubissuesDestroy",
4896
- listSelectionSet: childListMinimalSelectionSet,
4926
+ listSelectionSet: buildChildListSelectionSet("issueId"),
4897
4927
  listParentTypedField: "issueId"
4898
4928
  });
4899
4929
  registerChildCommands(program, {
@@ -4911,7 +4941,7 @@ function registerChildEntityCommands(program) {
4911
4941
  createOperationName: "TalkingPointsCreate",
4912
4942
  updateOperationName: "TalkingPointsUpdate",
4913
4943
  destroyOperationName: "TalkingPointsDestroy",
4914
- listSelectionSet: childListMinimalSelectionSet,
4944
+ listSelectionSet: buildChildListSelectionSet("meetingId", ["description", "creatorId", "slug"]),
4915
4945
  listParentTypedField: "meetingId"
4916
4946
  });
4917
4947
  }
@@ -4920,6 +4950,7 @@ function registerChildEntityCommands(program) {
4920
4950
  var import_zod13 = require("zod");
4921
4951
  var idSchema12 = import_zod13.z.string().min(1);
4922
4952
  var nonEmptyString = import_zod13.z.string().min(1);
4953
+ var contentAttributesSelection = "attributes { id type name slug content firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId }";
4923
4954
  function assertUpdateFields(params) {
4924
4955
  if (!params.name && !params.content && !params.status) {
4925
4956
  throw new CliError({
@@ -4967,7 +4998,7 @@ function registerContentCommands(program) {
4967
4998
  per: opts.per
4968
4999
  }),
4969
5000
  isList: true,
4970
- selectionSet: "{ count currentPage totalPages data { id type attributes } }"
5001
+ selectionSet: `{ count currentPage totalPages data { id type ${contentAttributesSelection} } }`
4971
5002
  });
4972
5003
  });
4973
5004
  content.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
@@ -4984,7 +5015,7 @@ function registerContentCommands(program) {
4984
5015
  id
4985
5016
  }),
4986
5017
  isShow: true,
4987
- selectionSet: "{ id type name slug firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId attributes }"
5018
+ selectionSet: `{ id type resources { id resourceType slug url } ${contentAttributesSelection} }`
4988
5019
  });
4989
5020
  });
4990
5021
  content.command("update").requiredOption("--id <id>").option("--name <name>").option("--body <body>").option("--status <status>").action(async (opts, cmd) => {
@@ -6088,7 +6119,7 @@ function registerMutationCapabilityCommands(program) {
6088
6119
  var import_promises = require("fs/promises");
6089
6120
  var import_zod16 = require("zod");
6090
6121
  var sourceSchema = import_zod16.z.enum(["canonical_osmd", "agent_overlay", "agent_wiki"]);
6091
- var accessSchema = import_zod16.z.enum(["read_only", "read_write", "append_only"]);
6122
+ var accessSchema = import_zod16.z.enum(["read_only", "read_write", "append_only"]).catch("read_write");
6092
6123
  var ownerSchema = import_zod16.z.enum(["system", "atlas"]);
6093
6124
  var suggestedActionSchema = import_zod16.z.enum([
6094
6125
  "read",
@@ -6098,7 +6129,7 @@ var suggestedActionSchema = import_zod16.z.enum([
6098
6129
  "append",
6099
6130
  "forbidden",
6100
6131
  "invalid_parent"
6101
- ]);
6132
+ ]).catch("update");
6102
6133
  var agentMarkdownErrorCodeSchema = import_zod16.z.enum([
6103
6134
  "canonical_osmd_read_only",
6104
6135
  "agent_parent_not_found",
@@ -6109,9 +6140,13 @@ var agentMarkdownErrorCodeSchema = import_zod16.z.enum([
6109
6140
  "unsupported_agent_file",
6110
6141
  "invalid_agent_wiki_path"
6111
6142
  ]);
6143
+ var agentMarkdownErrorCodeFieldSchema = agentMarkdownErrorCodeSchema.nullable().catch(null);
6112
6144
  var nonEmptyString3 = import_zod16.z.string().min(1);
6113
6145
  var nonNegativeInt3 = import_zod16.z.coerce.number().int().min(0);
6114
- var agentOverlayFileSchema = import_zod16.z.enum(["notes.md", "log.md"]);
6146
+ var supportedAgentOverlayFile = "notes.md";
6147
+ var supportedWikiIndexFile = "index.md";
6148
+ var supportedWikiLogFile = "log.md";
6149
+ var agentOverlayFileSchema = import_zod16.z.enum([supportedAgentOverlayFile]);
6115
6150
  var agentMarkdownFileSchema = import_zod16.z.object({
6116
6151
  path: import_zod16.z.string(),
6117
6152
  source: sourceSchema,
@@ -6124,7 +6159,7 @@ var agentMarkdownFileSchema = import_zod16.z.object({
6124
6159
  parentRef: import_zod16.z.string().nullable().optional(),
6125
6160
  agentChildrenAllowed: import_zod16.z.boolean(),
6126
6161
  suggestedAction: suggestedActionSchema,
6127
- errorCode: agentMarkdownErrorCodeSchema.nullable().optional(),
6162
+ errorCode: agentMarkdownErrorCodeFieldSchema.optional(),
6128
6163
  content: import_zod16.z.string().nullable().optional(),
6129
6164
  url: import_zod16.z.string().nullable().optional()
6130
6165
  }).transform((value) => ({
@@ -6198,6 +6233,21 @@ var AGENT_JSON_KEY_ALIASES = {
6198
6233
  suggested_action: "suggestedAction",
6199
6234
  error_code: "errorCode"
6200
6235
  };
6236
+ function isSupportedAgentMarkdownFile(file) {
6237
+ if (file.source !== "agent_overlay") {
6238
+ return true;
6239
+ }
6240
+ return file.path === `.agent/${supportedAgentOverlayFile}` || file.path.endsWith(`/.agent/${supportedAgentOverlayFile}`);
6241
+ }
6242
+ function filterSupportedAgentMarkdownData(data) {
6243
+ if (isRecord5(data) && Array.isArray(data.files)) {
6244
+ return {
6245
+ ...data,
6246
+ files: data.files.filter(isSupportedAgentMarkdownFile)
6247
+ };
6248
+ }
6249
+ return data;
6250
+ }
6201
6251
  var contentStdinPromise = null;
6202
6252
  function isRecord5(value) {
6203
6253
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -6370,7 +6420,7 @@ async function runAgentMarkdownMutation(params) {
6370
6420
  envelope: buildSuccessEnvelope({
6371
6421
  command: params.command,
6372
6422
  status: mutationPayload.status,
6373
- data: parsedData.data,
6423
+ data: filterSupportedAgentMarkdownData(parsedData.data),
6374
6424
  requestId: result.envelope.meta.requestId
6375
6425
  })
6376
6426
  });
@@ -6381,24 +6431,50 @@ function normalizeAgentFilePath(file) {
6381
6431
  const parsed = agentOverlayFileSchema.safeParse(fileName);
6382
6432
  if (!parsed.success) {
6383
6433
  throw new CliError({
6384
- message: ".agent supports only notes.md and log.md in this CLI slice.",
6434
+ message: ".agent supports only notes.md in this CLI slice.",
6385
6435
  kind: "invalid_args",
6386
6436
  status: 400,
6387
6437
  exitCode: EXIT_CODES.invalidArgs,
6388
- details: { supportedFiles: ["notes.md", "log.md"] }
6438
+ details: { supportedFiles: [supportedAgentOverlayFile] }
6389
6439
  });
6390
6440
  }
6391
6441
  return `.agent/${parsed.data}`;
6392
6442
  }
6393
- function normalizeWikiPath(path) {
6443
+ function supportedWikiFilesMessage(files) {
6444
+ return `Agent Wiki file commands support only ${files.join(" and ")} in this CLI slice.`;
6445
+ }
6446
+ function normalizeWikiPath(path, options = {}) {
6447
+ const supportedFiles = options.supportedFiles ?? [supportedWikiIndexFile, supportedWikiLogFile];
6394
6448
  const trimmed = nonEmptyString3.parse(path).trim().replace(/^\/+/, "");
6395
6449
  if (trimmed.localeCompare("Agent Wiki", void 0, { sensitivity: "accent" }) === 0) {
6396
- return "Agent Wiki";
6450
+ if (options.allowRoot) {
6451
+ return "Agent Wiki";
6452
+ }
6453
+ throw new CliError({
6454
+ message: supportedWikiFilesMessage(supportedFiles),
6455
+ kind: "invalid_args",
6456
+ status: 400,
6457
+ exitCode: EXIT_CODES.invalidArgs,
6458
+ details: { supportedFiles }
6459
+ });
6397
6460
  }
6398
- if (trimmed.toLowerCase().startsWith("agent wiki/")) {
6399
- return `Agent Wiki/${trimmed.slice("Agent Wiki/".length)}`;
6461
+ const fileName = trimmed.toLowerCase().startsWith("agent wiki/") ? trimmed.slice("Agent Wiki/".length) : trimmed;
6462
+ if (!supportedFiles.includes(fileName)) {
6463
+ throw new CliError({
6464
+ message: supportedWikiFilesMessage(supportedFiles),
6465
+ kind: "invalid_args",
6466
+ status: 400,
6467
+ exitCode: EXIT_CODES.invalidArgs,
6468
+ details: { supportedFiles }
6469
+ });
6400
6470
  }
6401
- return `Agent Wiki/${trimmed}`;
6471
+ return `Agent Wiki/${fileName}`;
6472
+ }
6473
+ function normalizeWikiIndexPath(path) {
6474
+ return normalizeWikiPath(path, { supportedFiles: [supportedWikiIndexFile] });
6475
+ }
6476
+ function normalizeWikiLogPath(path = supportedWikiLogFile) {
6477
+ return normalizeWikiPath(path, { supportedFiles: [supportedWikiLogFile] });
6402
6478
  }
6403
6479
  function parseOptionalParentRef(value) {
6404
6480
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
@@ -6508,6 +6584,14 @@ function writePreflightError(status, action) {
6508
6584
  status: 403
6509
6585
  };
6510
6586
  }
6587
+ if (status.access === "append_only" && action !== "append") {
6588
+ return {
6589
+ code: "append_only_violation",
6590
+ message: `Agent markdown file is append-only and cannot be overwritten: ${status.path}`,
6591
+ suggestedAction: status.suggestedAction,
6592
+ status: 403
6593
+ };
6594
+ }
6511
6595
  if (action === "create") {
6512
6596
  if (status.exists) {
6513
6597
  return {
@@ -6519,7 +6603,7 @@ function writePreflightError(status, action) {
6519
6603
  }
6520
6604
  if (!status.canCreate) {
6521
6605
  return {
6522
- code: status.access === "append_only" ? "append_only_violation" : "agent_path_forbidden",
6606
+ code: "agent_path_forbidden",
6523
6607
  message: `Create is not allowed for ${status.path}.`,
6524
6608
  suggestedAction: status.suggestedAction,
6525
6609
  status: 403
@@ -6537,13 +6621,31 @@ function writePreflightError(status, action) {
6537
6621
  }
6538
6622
  if (!status.canUpdate) {
6539
6623
  return {
6540
- code: status.access === "append_only" ? "append_only_violation" : "agent_path_forbidden",
6624
+ code: "agent_path_forbidden",
6541
6625
  message: `Update is not allowed for ${status.path}.`,
6542
6626
  suggestedAction: status.suggestedAction,
6543
6627
  status: 403
6544
6628
  };
6545
6629
  }
6546
6630
  }
6631
+ if (action === "append") {
6632
+ if (!status.exists) {
6633
+ return {
6634
+ code: "agent_file_not_found",
6635
+ message: status.suggestedAction === "init" ? `Agent Wiki log is not initialized. Run wave osmd wiki init before append-log.` : `Agent markdown file does not exist: ${status.path}`,
6636
+ suggestedAction: status.suggestedAction,
6637
+ status: 404
6638
+ };
6639
+ }
6640
+ if (status.access !== "append_only" || !status.canAppend) {
6641
+ return {
6642
+ code: "append_only_violation",
6643
+ message: `Append is not allowed for ${status.path}.`,
6644
+ suggestedAction: status.suggestedAction,
6645
+ status: 403
6646
+ };
6647
+ }
6648
+ }
6547
6649
  return null;
6548
6650
  }
6549
6651
  function statusCodeForAgentError(code) {
@@ -6586,19 +6688,28 @@ async function runWriteFlow(params) {
6586
6688
  update: {
6587
6689
  operationName: "UpdateAgentMarkdownFile",
6588
6690
  field: "update_agent_markdown_file"
6691
+ },
6692
+ append: {
6693
+ operationName: "RecordAgentMarkdownLog",
6694
+ field: "record_agent_markdown_log"
6589
6695
  }
6590
6696
  }[params.action];
6697
+ const variables = params.action === "append" ? {
6698
+ organization_id: params.organizationId,
6699
+ path: status.data.path,
6700
+ content: params.content
6701
+ } : {
6702
+ organization_id: params.organizationId,
6703
+ path: status.data.path,
6704
+ parent_ref: status.data.parentRef ?? params.parentRef,
6705
+ content: params.content
6706
+ };
6591
6707
  return runAgentMarkdownMutation({
6592
6708
  command: params.command,
6593
6709
  operationName: mutation.operationName,
6594
6710
  runtimeOptions: params.runtimeOptions,
6595
6711
  field: mutation.field,
6596
- variables: {
6597
- organization_id: params.organizationId,
6598
- path: status.data.path,
6599
- parent_ref: status.data.parentRef ?? params.parentRef,
6600
- content: params.content
6601
- }
6712
+ variables
6602
6713
  });
6603
6714
  }
6604
6715
  function addContentOptions(command) {
@@ -6692,8 +6803,8 @@ function registerOsmdCommands(program) {
6692
6803
  })
6693
6804
  });
6694
6805
  });
6695
- const agent = osmd.command("agent").description(".agent overlay files writable by agents; supports notes.md and log.md");
6696
- agent.command("status <parent-ref> <file>").action(async (parentRef, file, _opts, cmd) => {
6806
+ const agent = osmd.command("agent").description(".agent overlay memory attached to canonical OSMD parents; supports notes.md");
6807
+ agent.command("status <parent-ref> <file>").description("Show .agent notes.md metadata without creating files").action(async (parentRef, file, _opts, cmd) => {
6697
6808
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6698
6809
  const result = await requestAgentMarkdownStatus({
6699
6810
  command: "osmd.agent.status",
@@ -6711,7 +6822,7 @@ function registerOsmdCommands(program) {
6711
6822
  })
6712
6823
  });
6713
6824
  });
6714
- agent.command("init <parent-ref>").action(async (parentRef, _opts, cmd) => {
6825
+ agent.command("init <parent-ref>").description("Idempotently initialize supported .agent files for a canonical OSMD parent").action(async (parentRef, _opts, cmd) => {
6715
6826
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6716
6827
  return runAgentMarkdownMutation({
6717
6828
  command: "osmd.agent.init",
@@ -6725,7 +6836,7 @@ function registerOsmdCommands(program) {
6725
6836
  }
6726
6837
  });
6727
6838
  });
6728
- agent.command("read <parent-ref> <file>").action(async (parentRef, file, _opts, cmd) => {
6839
+ agent.command("read <parent-ref> <file>").description("Read .agent notes.md without creating files").action(async (parentRef, file, _opts, cmd) => {
6729
6840
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6730
6841
  const result = await requestAgentMarkdownFile({
6731
6842
  command: "osmd.agent.read",
@@ -6743,7 +6854,9 @@ function registerOsmdCommands(program) {
6743
6854
  })
6744
6855
  });
6745
6856
  });
6746
- addContentOptions(agent.command("create <parent-ref> <file>")).action(
6857
+ addContentOptions(
6858
+ agent.command("create <parent-ref> <file>").description("Create .agent notes.md after status/permission preflight")
6859
+ ).action(
6747
6860
  async (parentRef, file, opts, cmd) => {
6748
6861
  const globals = cmd.optsWithGlobals();
6749
6862
  const content = await resolveContentInput(opts, globals);
@@ -6759,7 +6872,9 @@ function registerOsmdCommands(program) {
6759
6872
  });
6760
6873
  }
6761
6874
  );
6762
- addContentOptions(agent.command("update <parent-ref> <file>")).action(
6875
+ addContentOptions(
6876
+ agent.command("update <parent-ref> <file>").description("Update .agent notes.md after status/permission preflight")
6877
+ ).action(
6763
6878
  async (parentRef, file, opts, cmd) => {
6764
6879
  const globals = cmd.optsWithGlobals();
6765
6880
  const content = await resolveContentInput(opts, globals);
@@ -6775,8 +6890,21 @@ function registerOsmdCommands(program) {
6775
6890
  });
6776
6891
  }
6777
6892
  );
6778
- const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; first slice should use index.md and log.md");
6779
- wiki.command("status <path>").action(async (path, _opts, cmd) => {
6893
+ const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md and append-only log.md");
6894
+ wiki.command("init").description("Idempotently initialize Agent Wiki system files").action(async function() {
6895
+ const { organizationId, runtimeOptions } = await resolveOsmdContext(this);
6896
+ return runAgentMarkdownMutation({
6897
+ command: "osmd.wiki.init",
6898
+ operationName: "InitAgentMarkdown",
6899
+ runtimeOptions,
6900
+ field: "init_agent_markdown",
6901
+ variables: {
6902
+ organization_id: organizationId,
6903
+ path: "Agent Wiki"
6904
+ }
6905
+ });
6906
+ });
6907
+ wiki.command("status <path>").description("Show Agent Wiki index.md or log.md metadata without creating files").action(async (path, _opts, cmd) => {
6780
6908
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6781
6909
  const result = await requestAgentMarkdownStatus({
6782
6910
  command: "osmd.wiki.status",
@@ -6793,7 +6921,7 @@ function registerOsmdCommands(program) {
6793
6921
  })
6794
6922
  });
6795
6923
  });
6796
- wiki.command("read <path>").action(async (path, _opts, cmd) => {
6924
+ wiki.command("read <path>").description("Read Agent Wiki index.md or log.md without creating files").action(async (path, _opts, cmd) => {
6797
6925
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6798
6926
  const result = await requestAgentMarkdownFile({
6799
6927
  command: "osmd.wiki.read",
@@ -6810,13 +6938,13 @@ function registerOsmdCommands(program) {
6810
6938
  })
6811
6939
  });
6812
6940
  });
6813
- wiki.command("children [path]").action(async (path, _opts, cmd) => {
6941
+ wiki.command("children [path]").description("List Agent Wiki children through backend metadata").action(async (path, _opts, cmd) => {
6814
6942
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6815
6943
  const result = await requestAgentMarkdownChildren({
6816
6944
  command: "osmd.wiki.children",
6817
6945
  runtimeOptions,
6818
6946
  organizationId,
6819
- path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path) : "Agent Wiki",
6947
+ path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true }) : "Agent Wiki",
6820
6948
  source: "agent_wiki"
6821
6949
  });
6822
6950
  return printEnvelopeAndExit({
@@ -6828,7 +6956,9 @@ function registerOsmdCommands(program) {
6828
6956
  })
6829
6957
  });
6830
6958
  });
6831
- addContentOptions(wiki.command("create <path>")).action(async (path, opts, cmd) => {
6959
+ addContentOptions(
6960
+ wiki.command("create <path>").description("Create Agent Wiki index.md after status/permission preflight")
6961
+ ).action(async (path, opts, cmd) => {
6832
6962
  const globals = cmd.optsWithGlobals();
6833
6963
  const content = await resolveContentInput(opts, globals);
6834
6964
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
@@ -6837,11 +6967,13 @@ function registerOsmdCommands(program) {
6837
6967
  action: "create",
6838
6968
  runtimeOptions,
6839
6969
  organizationId,
6840
- path: normalizeWikiPath(path),
6970
+ path: normalizeWikiIndexPath(path),
6841
6971
  content
6842
6972
  });
6843
6973
  });
6844
- addContentOptions(wiki.command("update <path>")).action(async (path, opts, cmd) => {
6974
+ addContentOptions(
6975
+ wiki.command("update <path>").description("Update Agent Wiki index.md after status/permission preflight")
6976
+ ).action(async (path, opts, cmd) => {
6845
6977
  const globals = cmd.optsWithGlobals();
6846
6978
  const content = await resolveContentInput(opts, globals);
6847
6979
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
@@ -6850,7 +6982,22 @@ function registerOsmdCommands(program) {
6850
6982
  action: "update",
6851
6983
  runtimeOptions,
6852
6984
  organizationId,
6853
- path: normalizeWikiPath(path),
6985
+ path: normalizeWikiIndexPath(path),
6986
+ content
6987
+ });
6988
+ });
6989
+ addContentOptions(
6990
+ wiki.command("append-log [path]").description("Append to Agent Wiki log.md after status/permission preflight")
6991
+ ).action(async (path, opts, cmd) => {
6992
+ const globals = cmd.optsWithGlobals();
6993
+ const content = await resolveContentInput(opts, globals);
6994
+ const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6995
+ return runWriteFlow({
6996
+ command: "osmd.wiki.append-log",
6997
+ action: "append",
6998
+ runtimeOptions,
6999
+ organizationId,
7000
+ path: normalizeWikiLogPath(typeof path === "string" && path.trim() !== "" ? path : void 0),
6854
7001
  content
6855
7002
  });
6856
7003
  });
@@ -6900,23 +7047,21 @@ function buildCli(options) {
6900
7047
 
6901
7048
  // src/index.ts
6902
7049
  function printCliFailure(params) {
6903
- printEnvelopeAndExit({
6904
- envelope: {
6905
- ok: false,
6906
- command: "cli",
6907
- status: params.status,
6908
- data: null,
6909
- error: {
6910
- code: params.code,
6911
- message: params.message,
6912
- details: params.details ?? {}
6913
- },
6914
- meta: {
6915
- requestId: "local_error"
6916
- }
7050
+ printEnvelope({
7051
+ ok: false,
7052
+ command: "cli",
7053
+ status: params.status,
7054
+ data: null,
7055
+ error: {
7056
+ code: params.code,
7057
+ message: params.message,
7058
+ details: params.details ?? {}
6917
7059
  },
6918
- exitCode: params.exitCode
7060
+ meta: {
7061
+ requestId: "local_error"
7062
+ }
6919
7063
  });
7064
+ process.exitCode = params.exitCode;
6920
7065
  }
6921
7066
  async function main() {
6922
7067
  const program = buildCli();