@mytegroupinc/myte-core 0.0.32 → 0.0.34

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/README.md CHANGED
@@ -12,21 +12,30 @@ This package exists so the public wrapper can stay small and versioned cleanly.
12
12
  ## Requirements
13
13
 
14
14
  - Node `18+`
15
- - `MYTE_API_KEY` for project-scoped commands
16
- - `MYTEAI_API_KEY` for `myte ai`
17
- - `git` only when using `query --with-diff`
15
+ - `MYTE_API_KEY` for project-scoped commands
16
+ - `MYTEAI_API_KEY` for `myte ai`
17
+ - `MYTEAI_API_KEY` for `mytecody`
18
+ - `git` only when using `query --with-diff`
18
19
  - No runtime npm dependencies. The CLI uses Node 18+ built-ins for env loading, argument parsing, HTTP, and local context serialization.
19
20
 
20
21
  ## Behavior Summary
21
22
 
22
23
  - Snapshot-style commands such as `bootstrap`, `sync-qaqc`, `feedback-sync`, and `suggestions sync` write local `MyteCommandCenter` data.
23
24
  - `feedback status|edit|assign|archive` writes reviewable local YAML artifacts; `feedback submit|revise|reviews|review` routes them through the backend owner-review membrane.
24
- - `feedback move|undo|prd-versions|prd-diff|history` calls the project-key Feedback API while leaving lifecycle rules and permissions server-side. `feedback move --feedback-ids` sends one batch move request.
25
+ - `feedback move|comment|undo|prd-versions|prd-diff|history` calls the project-key Feedback API while leaving lifecycle rules and permissions server-side. `feedback move --feedback-ids` sends one batch move request.
25
26
  - `feedback validate|apply` remains available for validation and owner-direct apply paths; live authorization, stale checks, and history stay server-side.
26
27
  - `query --with-diff` requires project repos to be configured for diff collection and fails fast when no matching local project repo can be resolved.
27
- - Public package documentation is intentionally minimal. Internal rollout and design notes are not part of the npm package contract.
28
-
29
- ## Agent Usage Contract
28
+ - Public package documentation is intentionally minimal. Internal rollout and design notes are not part of the npm package contract.
29
+ - `mytecody` is a model-agnostic MyteCody team launcher. It supports `doctor`,
30
+ `doctor --probe-gateway`, `update --dry-run`, and `update`. On first coding
31
+ run, it installs the branded MyteCody engine from the Myte release manifest
32
+ into a user-local Myte cache after signature/hash checks. Coding execution
33
+ requires that engine, a reachable Myte AI Cody gateway, and `MYTEAI_API_KEY`.
34
+ - The package does not bundle the large MyteCody engine binary. See
35
+ `THIRD_PARTY_NOTICES.md` and `TRADEMARKS.md` for Codex lineage and Myte brand
36
+ notices.
37
+
38
+ ## Agent Usage Contract
30
39
 
31
40
  Coding agents should treat `MYTE_API_KEY` as a project-scoped Project Assistant key:
32
41
 
@@ -42,7 +51,8 @@ Coding agents should treat `MYTE_API_KEY` as a project-scoped Project Assistant
42
51
  - Use `suggestions revise` only against an existing `suggestion_id`; do not send `change_type` on revisions because the backend keeps the thread's original type.
43
52
  - Use `suggestions review` for owner/elevated mission-review decisions: `approve`, `request_changes`, or `reject`.
44
53
  - Use `mission archive` for project-key lifecycle archival. Do not send `Archived` through `mission status`; restore archived missions from the web archived-board view.
45
- - Use `feedback move` only when a direct audited state move is intended and include a concrete `--reason`. Use `--feedback-ids` for batch active-state moves or authorized batch archive.
54
+ - Use `feedback move` only when a direct audited state move is intended and include a concrete `--reason`. Use `--feedback-ids` for batch active-state moves or authorized batch archive.
55
+ - Use `feedback comment --feedback-id <id> --body-file ./comment.md` for text-only feedback-specific implementation notes. Attachments remain web UI only for this project-key endpoint.
46
56
  - Do not use the project-key API/CLI to unarchive Feedback. Normal `feedback-sync` excludes archived Feedback; unarchive from the web archived Feedback view.
47
57
  - Use `update-team` when an agent needs to leave a project-level implementation note or verification comment.
48
58
 
@@ -61,11 +71,12 @@ PRD document contract:
61
71
  - Do not wrap the whole PRD in a ` ```markdown ` fence. Do not use raw HTML, inline style blocks, or decorative banners.
62
72
  - PRD identity is explicit: `myte create-prd` creates a PRD asset with PRD metadata. Generic uploaded `.md`, `.docx`, `.pdf`, and `.txt` files remain normal attachments unless explicitly created as PRDs.
63
73
 
64
- Feedback comment support:
65
-
66
- - `feedback-sync` includes existing feedback comment turns in local context.
67
- - Feedback-specific comment creation exists in the web backend at `/api/feedbacks/<feedback_id>/comments`, protected by JWT/project assignment.
68
- - There is no project-key CLI command for `myte feedback comment` yet. That requires a Project Assistant feedback-comment route plus npm command before agents should rely on it.
74
+ Feedback comment support:
75
+
76
+ - `feedback-sync` includes existing feedback comment turns in local context.
77
+ - Feedback-specific comment creation exists in the web backend at `/api/feedbacks/<feedback_id>/comments`, protected by JWT/project assignment.
78
+ - Project-key comment creation is available through `myte feedback comment --feedback-id <id> --body "..."` or `--body-file ./comment.md`.
79
+ - The project-key feedback comment endpoint is text-only in this slice and caps content at 500,000 characters. Use the web UI when comment attachments are required.
69
80
 
70
81
  ## Mission Action Map
71
82
 
@@ -147,9 +158,10 @@ Agent rule: never guess `suggestion_id`. If `mission-ops.yml` is missing or stal
147
158
  | `feedback submit` | Sends a local proposal artifact to the backend as a review request. | Does not mutate live feedback before approval. |
148
159
  | `feedback revise` | Resubmits the original submitter's request after `request_changes`. | Only valid for the original submitter and `needs_changes` requests. |
149
160
  | `feedback reviews` | Lists review requests or fetches one request by `--request-id`. | Read-only; response includes backend permissions. |
150
- | `feedback review` | Approves, rejects, requests changes, or cancels one review request, or a batch with `--request-ids`. | Backend restricts approval/review decisions to Project Owner or elevated delegate for Feedback scope; batch review uses one grouped notification path. |
151
- | `feedback move` | Moves a card or batch of cards across allowed board states directly with an audit event. | `--feedback-ids` sends one batch request. Blocked with `pending_feedback_review` while an active linked review request exists; governed states such as archive/reject/deploy/freeze remain backend-authorized. Project-key unarchive is not supported. |
152
- | `feedback undo` | Reverses an audited board event when there is no conflict. | Backend validates event ownership/project scope and conflict state. |
161
+ | `feedback review` | Approves, rejects, requests changes, or cancels one review request, or a batch with `--request-ids`. | Backend restricts approval/review decisions to Project Owner or elevated delegate for Feedback scope; batch review uses one grouped notification path. |
162
+ | `feedback move` | Moves a card or batch of cards across allowed board states directly with an audit event. | `--feedback-ids` sends one batch request. Blocked with `pending_feedback_review` while an active linked review request exists; governed states such as archive/reject/deploy/freeze remain backend-authorized. Project-key unarchive is not supported. |
163
+ | `feedback comment` | Creates a text-only comment on one Feedback item. | Backend checks project-key access, owner/assigned permission, idempotency, and the 500,000-character content cap. Attachments remain web UI only. |
164
+ | `feedback undo` | Reverses an audited board event when there is no conflict. | Backend validates event ownership/project scope and conflict state. |
153
165
  | `feedback prd-versions` | Lists retained PRD baselines/revisions for a feedback item. | Read-only; old S3 objects are retained by reference. |
154
166
  | `feedback prd-diff` | Fetches backend-generated text diff for PRD versions. | Read-only; backend controls version access. |
155
167
  | `feedback history` | Lists audited feedback board/refinement events. | Read-only; backend checks project access. |
@@ -205,9 +217,10 @@ Mutation routes:
205
217
  - `POST /api/project-assistant/feedback-review-requests/batch-review`
206
218
  - `POST /api/project-assistant/feedback-review-requests/<request_id>/request-changes`
207
219
  - `POST /api/project-assistant/feedback-review-requests/<request_id>/cancel`
208
- - `POST /api/project-assistant/feedback/<feedback_id>/board-move`
209
- - `POST /api/project-assistant/feedback/batch-board-move`
210
- - `POST /api/project-assistant/feedback/<feedback_id>/events/<event_id>/undo`
220
+ - `POST /api/project-assistant/feedback/<feedback_id>/board-move`
221
+ - `POST /api/project-assistant/feedback/batch-board-move`
222
+ - `POST /api/project-assistant/feedback/<feedback_id>/comments`
223
+ - `POST /api/project-assistant/feedback/<feedback_id>/events/<event_id>/undo`
211
224
  - `POST /api/project-assistant/suggestions`
212
225
  - `POST /api/project-assistant/suggestions/revise`
213
226
  - `POST /api/project-assistant/suggestions/review`
@@ -0,0 +1,21 @@
1
+ # Third-Party Notices
2
+
3
+ This package includes the Myte CLI launcher and MyteCody distribution client.
4
+
5
+ The branded MyteCody engine installed by the launcher is derived from the
6
+ OpenAI Codex open-source project. OpenAI Codex is licensed under the
7
+ Apache License, Version 2.0.
8
+
9
+ Source lineage tracked for this slice:
10
+
11
+ - Project: OpenAI Codex
12
+ - Version baseline: `0.139.0`
13
+ - License: Apache-2.0
14
+ - Upstream: https://github.com/openai/codex
15
+
16
+ The MyteCody engine artifact is distributed separately from this npm package
17
+ through a Myte release manifest. This package verifies the release artifact
18
+ before installing it into the user's Myte-owned local cache.
19
+
20
+ Myte names, marks, logos, terminal branding, and product design are not part of
21
+ the OpenAI Codex project and remain Myte-owned brand assets.
package/TRADEMARKS.md ADDED
@@ -0,0 +1,10 @@
1
+ # Trademarks
2
+
3
+ Myte, Myte AI, MyteCody, "MYTE CODY - Your Tech Your Way", logo assets, terminal
4
+ animation assets, and related product branding are Myte-owned marks and brand
5
+ assets.
6
+
7
+ OpenAI and Codex are trademarks or project names of their respective owners.
8
+ MyteCody uses a Codex-derived open-source engine under the applicable open
9
+ source license, but MyteCody is a Myte product surface and is not presented as
10
+ an official OpenAI product.
package/cli.js CHANGED
@@ -208,9 +208,10 @@ function printHelp() {
208
208
  " myte feedback reviews [--status open|terminal|all] [--request-id <id>] [--json]",
209
209
  " myte feedback review --request-id <id> --action approve|reject|request_changes|cancel [--reason \"...\"] [--json]",
210
210
  " myte feedback review --request-ids \"<id1,id2>\" --action approve|reject|request_changes|cancel [--reason \"...\"] [--json]",
211
- " myte feedback move --feedback-id <id> --to-state in_progress --from-state todo --reason \"...\" [--json]",
212
- " myte feedback move --feedback-ids \"<id1,id2>\" --to-state in_progress --reason \"...\" [--json]",
213
- " myte feedback undo --feedback-id <id> --event-id <id> --reason \"...\" [--json]",
211
+ " myte feedback move --feedback-id <id> --to-state in_progress --from-state todo --reason \"...\" [--json]",
212
+ " myte feedback move --feedback-ids \"<id1,id2>\" --to-state in_progress --reason \"...\" [--json]",
213
+ " myte feedback comment --feedback-id <id> --body \"...\" [--body-file ./comment.md] [--json]",
214
+ " myte feedback undo --feedback-id <id> --event-id <id> --reason \"...\" [--json]",
214
215
  " myte feedback prd-versions --feedback-id <id> [--json]",
215
216
  " myte feedback prd-diff --feedback-id <id> --version-id <id> [--compare-to <id>] [--json]",
216
217
  " myte feedback validate --file ./MyteCommandCenter/reviews/feedback/<id>-status.yml [--json]",
@@ -312,7 +313,7 @@ function printHelp() {
312
313
  " - Archived feedback is intentionally excluded from normal sync; returning it to active work is web UI only",
313
314
  " - Writes project feedback metadata and conversation turns into MyteCommandCenter/data/feedback.yml",
314
315
  " - Stores full PRD context in MyteCommandCenter/PRD/feedback-sync/*.md and points to those files from feedback.yml",
315
- " - Reads existing feedback comments; direct project-key creation of feedback-specific comments is not exposed yet",
316
+ " - Reads existing feedback comments and can create text-only feedback-specific comments through the project-key API",
316
317
  "",
317
318
  "feedback review contract:",
318
319
  " - Draft commands write review artifacts under MyteCommandCenter/reviews/feedback/*.yml for local IDE diff review",
@@ -321,8 +322,9 @@ function printHelp() {
321
322
  " - reviews/review expose owner/delegate approval, rejection, request-changes, and cancel decisions",
322
323
  " - review with --request-ids sends one batch review request; it does not loop single-review calls",
323
324
  " - live lifecycle moves return pending_feedback_review while an active linked review request exists",
324
- " - move/undo operate safe board states directly; governed states remain backend-authorized",
325
- " - move with --feedback-ids sends one batch board move request; it supports active-state moves and authorized archive",
325
+ " - move/undo operate safe board states directly; governed states remain backend-authorized",
326
+ " - move with --feedback-ids sends one batch board move request; it supports active-state moves and authorized archive",
327
+ " - comment creates text-only feedback-specific comments; attachments remain web UI only for this endpoint",
326
328
  " - project-key API/CLI cannot unarchive archived Feedback; use the web archived Feedback view",
327
329
  " - get/history read current feedback snapshots and audited event history through the project-key API",
328
330
  " - prd-versions/prd-diff expose retained PRD versions and backend-generated text diffs",
@@ -338,8 +340,9 @@ function printHelp() {
338
340
  " - revise: resubmit the original submitter's request after request_changes",
339
341
  " - reviews: list open/terminal/all requests or inspect one request",
340
342
  " - review: approve, reject, request_changes, or cancel; backend restricts this to owner/delegate capability",
341
- " - move: direct audited board movement for allowed states; governed transitions remain backend-authorized",
342
- " - undo: reverse an audited board event when conflict checks allow it",
343
+ " - move: direct audited board movement for allowed states; governed transitions remain backend-authorized",
344
+ " - comment: create a text-only comment on one Feedback item",
345
+ " - undo: reverse an audited board event when conflict checks allow it",
343
346
  " - prd-versions: list retained PRD baselines/revisions for a feedback item",
344
347
  " - prd-diff: fetch backend-generated text diff between PRD versions",
345
348
  " - history: list board/refinement events for audit review",
@@ -360,10 +363,11 @@ function printHelp() {
360
363
  " --stdin Read supported command content from stdin instead of inline text or a file path",
361
364
  " --title <text> Override PRD title for raw markdown uploads",
362
365
  " --description <text> Set feedback description/card summary for raw markdown uploads",
363
- " --content <text> Team update content for update-team",
364
- " --subject <text> Subject for update-owner or update-client",
366
+ " --content <text> Team update content for update-team",
367
+ " --body <text> Feedback comment body for feedback comment",
368
+ " --subject <text> Subject for update-owner or update-client",
365
369
  " --body-markdown <md> Markdown body for update-owner or update-client",
366
- " --body-file <path> Read update-owner or update-client markdown body from a file",
370
+ " --body-file <path> Read feedback comment, update-owner, or update-client markdown body from a file",
367
371
  " --target-contact-id Add one client contact ObjectId (repeatable)",
368
372
  " --target-contact-ids Comma-separated client contact ObjectIds",
369
373
  " --feedback-id <id> Feedback ObjectId for feedback review commands",
@@ -417,9 +421,10 @@ function printHelp() {
417
421
  " myte feedback status --feedback-id 507f1f77bcf86cd799439011 --status in_review --reason \"Ready for owner review\"",
418
422
  " myte feedback submit --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-edit.yml --json",
419
423
  " myte feedback reviews --status open --json",
420
- " myte feedback review --request-id 507f1f77bcf86cd799439022 --action approve --reason \"Looks correct\" --json",
421
- " myte feedback move --feedback-id 507f1f77bcf86cd799439011 --to-state in_progress --reason \"Started\" --json",
422
- " myte feedback validate --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
424
+ " myte feedback review --request-id 507f1f77bcf86cd799439022 --action approve --reason \"Looks correct\" --json",
425
+ " myte feedback move --feedback-id 507f1f77bcf86cd799439011 --to-state in_progress --reason \"Started\" --json",
426
+ " myte feedback comment --feedback-id 507f1f77bcf86cd799439011 --body \"Implementation notes are ready for review.\" --json",
427
+ " myte feedback validate --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
423
428
  " myte feedback apply --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
424
429
  " myte suggestions create --file ./suggestions/create.yml",
425
430
  " myte suggestions revise",
@@ -1970,7 +1975,7 @@ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId,
1970
1975
  return body.data || {};
1971
1976
  }
1972
1977
 
1973
- async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
1978
+ async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
1974
1979
  const fetchFn = await getFetch();
1975
1980
  const url = `${apiBase}/project-assistant/feedback/batch-board-move`;
1976
1981
  const { resp, body } = await fetchJsonWithTimeout(
@@ -1996,10 +2001,39 @@ async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload
1996
2001
  err.data = body?.data;
1997
2002
  throw err;
1998
2003
  }
1999
- return body.data || {};
2000
- }
2001
-
2002
- async function fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId }) {
2004
+ return body.data || {};
2005
+ }
2006
+
2007
+ async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
2008
+ const fetchFn = await getFetch();
2009
+ const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/comments`;
2010
+ const { resp, body } = await fetchJsonWithTimeout(
2011
+ fetchFn,
2012
+ url,
2013
+ {
2014
+ method: "POST",
2015
+ headers: {
2016
+ "Content-Type": "application/json",
2017
+ Authorization: `Bearer ${key}`,
2018
+ "X-Idempotency-Key": String(idempotencyKey || "").trim(),
2019
+ ...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
2020
+ },
2021
+ body: JSON.stringify(payload || {}),
2022
+ },
2023
+ timeoutMs
2024
+ );
2025
+
2026
+ if (!resp.ok || body.status !== "success") {
2027
+ const msg = body?.message || `Feedback comment failed (${resp.status})`;
2028
+ const err = new Error(msg);
2029
+ err.status = resp.status;
2030
+ err.data = body?.data;
2031
+ throw err;
2032
+ }
2033
+ return body.data || {};
2034
+ }
2035
+
2036
+ async function fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId }) {
2003
2037
  const fetchFn = await getFetch();
2004
2038
  const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/prd/versions`;
2005
2039
  const { resp, body } = await fetchJsonWithTimeout(
@@ -5088,13 +5122,33 @@ function resolveFeedbackRequestIdArg(args) {
5088
5122
  return firstNonEmptyString(args["request-id"], args.requestId, args.request_id, args._?.[1]);
5089
5123
  }
5090
5124
 
5091
- function resolveFeedbackEventIdArg(args) {
5092
- return firstNonEmptyString(args["event-id"], args.eventId, args.event_id, args._?.[1]);
5093
- }
5094
-
5095
- function resolveFeedbackVersionIdArg(args) {
5096
- return firstNonEmptyString(args["version-id"], args.versionId, args.version_id, args._?.[1]);
5097
- }
5125
+ function resolveFeedbackEventIdArg(args) {
5126
+ return firstNonEmptyString(args["event-id"], args.eventId, args.event_id, args._?.[1]);
5127
+ }
5128
+
5129
+ function resolveFeedbackVersionIdArg(args) {
5130
+ return firstNonEmptyString(args["version-id"], args.versionId, args.version_id, args._?.[1]);
5131
+ }
5132
+
5133
+ async function resolveFeedbackCommentContent(args, feedbackId) {
5134
+ const explicit = firstNonEmptyString(args.body, args.content, args["body-markdown"], args.bodyMarkdown, args.body_markdown);
5135
+ if (explicit) return explicit;
5136
+
5137
+ const bodyFile = firstNonEmptyString(args["body-file"], args.bodyFile, args.body_file);
5138
+ if (bodyFile) {
5139
+ const bodyPath = resolveInputFile(bodyFile, "Feedback comment body");
5140
+ return fs.readFileSync(bodyPath, "utf8");
5141
+ }
5142
+
5143
+ if (args.stdin) {
5144
+ return readStdinText();
5145
+ }
5146
+
5147
+ const positionals = Array.isArray(args._) ? args._.slice(1) : [];
5148
+ const feedbackIdFromPositional = positionals[0] && String(positionals[0]) === String(feedbackId);
5149
+ const textParts = feedbackIdFromPositional ? positionals.slice(1) : positionals;
5150
+ return textParts.join(" ");
5151
+ }
5098
5152
 
5099
5153
  function summarizeFeedbackReviewRequestPayload(data) {
5100
5154
  const request = data?.request || data || {};
@@ -5453,7 +5507,7 @@ async function runFeedbackReviewDecision(args) {
5453
5507
  if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
5454
5508
  }
5455
5509
 
5456
- async function runFeedbackMove(args) {
5510
+ async function runFeedbackMove(args) {
5457
5511
  const key = getProjectApiKey();
5458
5512
  if (!key) {
5459
5513
  console.error("Missing MYTE_API_KEY (project key) in environment/.env");
@@ -5559,9 +5613,85 @@ async function runFeedbackMove(args) {
5559
5613
  console.log(`State: ${data.feedback_state || toState}`);
5560
5614
  if (data.event?.event_id) console.log(`Event: ${data.event.event_id}`);
5561
5615
  if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
5562
- }
5563
-
5564
- async function runFeedbackUndo(args) {
5616
+ }
5617
+
5618
+ async function runFeedbackComment(args) {
5619
+ const key = getProjectApiKey();
5620
+ if (!key) {
5621
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
5622
+ process.exit(1);
5623
+ }
5624
+ const feedbackId = resolveFeedbackIdArg(args);
5625
+ if (!feedbackId) {
5626
+ console.error("Missing --feedback-id.");
5627
+ process.exit(1);
5628
+ }
5629
+
5630
+ const content = String(await resolveFeedbackCommentContent(args, feedbackId) || "").trim();
5631
+ if (!content) {
5632
+ console.error("Missing feedback comment body. Use --body, --body-file, --stdin, or positional text.");
5633
+ process.exit(1);
5634
+ }
5635
+
5636
+ const payload = { content };
5637
+ const timeoutMs = resolveTimeoutMs(args);
5638
+ const apiBase = resolveApiBase(args);
5639
+ const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
5640
+ if (clientSessionId) payload.client_session_id = clientSessionId;
5641
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
5642
+ args,
5643
+ operation: `feedback_comment_create:${feedbackId}`,
5644
+ payload,
5645
+ });
5646
+
5647
+ if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
5648
+ console.log(JSON.stringify(payload, null, 2));
5649
+ return;
5650
+ }
5651
+
5652
+ let data;
5653
+ try {
5654
+ data = await postFeedbackComment({
5655
+ apiBase,
5656
+ key,
5657
+ timeoutMs,
5658
+ feedbackId,
5659
+ payload,
5660
+ idempotencyKey,
5661
+ clientSessionId,
5662
+ });
5663
+ } catch (err) {
5664
+ if (args.json) {
5665
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
5666
+ } else {
5667
+ console.error("Feedback comment failed:", err?.message || err);
5668
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
5669
+ }
5670
+ process.exit(1);
5671
+ }
5672
+
5673
+ const postSync = await refreshFeedbackSnapshotAfterMutation(args, { apiBase, key, timeoutMs });
5674
+ if (args.json) {
5675
+ console.log(JSON.stringify({ ok: true, ...data, post_sync: postSync }, null, 2));
5676
+ return;
5677
+ }
5678
+
5679
+ if (data.comment_id) console.log(`Comment ID: ${data.comment_id}`);
5680
+ console.log(`Feedback: ${data.feedback_id || feedbackId}`);
5681
+ if (data.project_id) console.log(`Project ID: ${data.project_id}`);
5682
+ if (data.user_name) console.log(`Author: ${data.user_name}`);
5683
+ if (data.created_at) console.log(`Created At: ${data.created_at}`);
5684
+ if (data.content) {
5685
+ const body = String(data.content);
5686
+ const truncated = body.length > 2000 ? `${body.slice(0, 2000)}\n...[truncated]` : body;
5687
+ console.log("Content:");
5688
+ console.log(truncated);
5689
+ }
5690
+ if (postSync?.data_root) console.log(`Synced feedback: ${postSync.data_root}`);
5691
+ if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
5692
+ }
5693
+
5694
+ async function runFeedbackUndo(args) {
5565
5695
  const key = getProjectApiKey();
5566
5696
  if (!key) {
5567
5697
  console.error("Missing MYTE_API_KEY (project key) in environment/.env");
@@ -5756,11 +5886,15 @@ async function runFeedback(args) {
5756
5886
  await runFeedbackReviewDecision(args);
5757
5887
  return;
5758
5888
  }
5759
- if (subcommand === "move") {
5760
- await runFeedbackMove(args);
5761
- return;
5762
- }
5763
- if (subcommand === "undo") {
5889
+ if (subcommand === "move") {
5890
+ await runFeedbackMove(args);
5891
+ return;
5892
+ }
5893
+ if (subcommand === "comment" || subcommand === "comments") {
5894
+ await runFeedbackComment(args);
5895
+ return;
5896
+ }
5897
+ if (subcommand === "undo") {
5764
5898
  await runFeedbackUndo(args);
5765
5899
  return;
5766
5900
  }
@@ -5776,7 +5910,7 @@ async function runFeedback(args) {
5776
5910
  await runFeedbackGetOrHistory(args, subcommand);
5777
5911
  return;
5778
5912
  }
5779
- console.error("Unknown feedback command. Use status, edit, assign, archive, submit, revise, reviews, review, move, undo, prd-versions, prd-diff, get, history, validate, or apply.");
5913
+ console.error("Unknown feedback command. Use status, edit, assign, archive, submit, revise, reviews, review, move, comment, undo, prd-versions, prd-diff, get, history, validate, or apply.");
5780
5914
  process.exit(1);
5781
5915
  }
5782
5916
 
@@ -0,0 +1,11 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAi+YAnayqofu0kdLQlgO3
3
+ TWcyp6NC6U5O8/MPubmqv36Zg9yHca/PndK+yvIiFqi6ReYziM9x2xb7mPlfZ+ia
4
+ EBz7WPvd9OFUOxSngsHOAaM7jYwGzCdbJm+aJ/4NXw7kjv22Sj7FtOrJUFbA3ePW
5
+ WZIXiyl1MH144sHAG8hkPvTov/BIiEGh2G0IDUXH0n4Ksab+FQp/Z+MDRoxwhqEP
6
+ HlqJwhF6vQhfq1nFHFetaop8y0DoFe5AFXLOMdgPq90gYkVTe+9PFIx8ISi+0RyN
7
+ 6dS0sEb3Z0frLGyzDxgtJseGGCe5XWyxVfBCb/uztB395EtIB4ZWHi4Oyy9XcP3c
8
+ hPGJgJiX83tSgVO/bQzk43Yl/LIKBxh1mFa9zJACU7Gx0s4DvwBug5rZvpAUddgX
9
+ v7v/8kjN/YYLwSf+VsMZ+Vedy51dPkwyCVOUk8y1MW1vvwaLFYfqVAJ//FNjC+Jf
10
+ 51G2zxYxLXcDOFvvrra988Ng4ybfDMOy/qalWxHU0AOpAgMBAAE=
11
+ -----END PUBLIC KEY-----