@mytegroupinc/myte-core 0.0.30 → 0.0.32

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
@@ -57,6 +57,9 @@ PRD document contract:
57
57
  - `myte-kanban` uploads send `{ ticket_markdown }`, where the leading JSON block contains metadata and the remaining markdown is the PRD body.
58
58
  - The backend stores the markdown as `prd_markdown`, mirrors it as PRD text for search/sync, generates a DOCX attachment from it, and marks `prd_format=markdown`.
59
59
  - The UI renders the PRD from stored PRD text/document content, not from `description`.
60
+ - Renderer-friendly PRDs should use one `# Title`, `##` sections, concise paragraphs, bullets, GitHub tables/checklists where useful, and fenced code blocks only for real code/config.
61
+ - Do not wrap the whole PRD in a ` ```markdown ` fence. Do not use raw HTML, inline style blocks, or decorative banners.
62
+ - 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.
60
63
 
61
64
  Feedback comment support:
62
65
 
package/cli.js CHANGED
@@ -287,6 +287,8 @@ function printHelp() {
287
287
  " - Never put the full PRD in description. The complete PRD must live in the markdown file body",
288
288
  " - Each item carries the full PRD markdown blob as prd_markdown/ticket_markdown",
289
289
  " - Backend stores that blob as the renderable PRD document source, mirrors it for PRD text search/sync, and generates a DOCX attachment",
290
+ " - Renderer-friendly PRDs use one # title, ## sections, bullets, GitHub tables/checklists where useful, and code fences only for real code/config",
291
+ " - Do not wrap the whole PRD in a ```markdown fence; generic .md/.docx/.pdf/.txt uploads are normal attachments unless created as PRDs",
290
292
  " - PRD DOCX content: the markdown body is stored verbatim",
291
293
  "",
292
294
  "update-team contract:",
@@ -3404,6 +3406,7 @@ function writeFeedbackSnapshot({ snapshot, wrapperRoot, outputDir }) {
3404
3406
  const feedbackId = stableItemId(item, ["feedback_id", "id"], `F${String(index + 1).padStart(3, "0")}`);
3405
3407
  const conversationTurns = normalizeFeedbackConversationTurns(item.conversation_turns);
3406
3408
  const prdText = String(item.prd_text || "").trim();
3409
+ const attachmentDocuments = Array.isArray(item.attachment_documents) ? item.attachment_documents : [];
3407
3410
 
3408
3411
  let contextSource = "description_only";
3409
3412
  let contextNote = "No separate PRD. Use feedback_text as the context for this feedback item.";
@@ -3414,8 +3417,10 @@ function writeFeedbackSnapshot({ snapshot, wrapperRoot, outputDir }) {
3414
3417
  const prdPath = path.join(prdSyncDir, prdFilename);
3415
3418
  writeTextFile(prdPath, ensureTrailingNewline(prdText));
3416
3419
  prdFile = toPosixRelativePath(targetRoot, prdPath);
3417
- contextSource = "prd_file";
3418
- contextNote = "Full PRD context is stored in the linked file.";
3420
+ contextSource = attachmentDocuments.length > 0 ? "attachment_file" : "prd_file";
3421
+ contextNote = attachmentDocuments.length > 0
3422
+ ? "Readable feedback attachment documents are stored in the linked file."
3423
+ : "Full PRD context is stored in the linked file.";
3419
3424
  prdFileCount += 1;
3420
3425
  } else if (item.has_prd_text) {
3421
3426
  contextSource = "prd_declared_but_unavailable";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mytegroupinc/myte-core",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "Myte CLI core implementation.",
5
5
  "type": "commonjs",
6
6
  "main": "cli.js",
@@ -90,24 +90,24 @@ function writePrd(workspace, title, index) {
90
90
  return filePath;
91
91
  }
92
92
 
93
- function loadFeedbackManifest(workspace) {
94
- const manifestPath = path.join(workspace, "MyteCommandCenter", "data", "feedback.yml");
95
- if (!fs.existsSync(manifestPath)) {
96
- return { items: [] };
97
- }
98
- const text = fs.readFileSync(manifestPath, "utf8");
99
- try {
100
- const parsed = JSON.parse(text);
101
- const items = []
102
- .concat(Array.isArray(parsed.items) ? parsed.items : [])
103
- .concat(Array.isArray(parsed.queue) ? parsed.queue : []);
104
- return { items };
105
- } catch (_err) {
106
- // Older local files may still be YAML-like. Keep a small fallback parser so
107
- // the harness can validate either shape without adding runtime deps.
108
- }
109
- const items = [];
110
- let current = null;
93
+ function loadFeedbackManifest(workspace) {
94
+ const manifestPath = path.join(workspace, "MyteCommandCenter", "data", "feedback.yml");
95
+ if (!fs.existsSync(manifestPath)) {
96
+ return { items: [] };
97
+ }
98
+ const text = fs.readFileSync(manifestPath, "utf8");
99
+ try {
100
+ const parsed = JSON.parse(text);
101
+ const items = []
102
+ .concat(Array.isArray(parsed.items) ? parsed.items : [])
103
+ .concat(Array.isArray(parsed.queue) ? parsed.queue : []);
104
+ return { items };
105
+ } catch (_err) {
106
+ // Older local files may still be YAML-like. Keep a small fallback parser so
107
+ // the harness can validate either shape without adding runtime deps.
108
+ }
109
+ const items = [];
110
+ let current = null;
111
111
  for (const line of text.split(/\r?\n/)) {
112
112
  const feedbackMatch = line.match(/^\s*-\s+feedback_id:\s*["']?([^"'\s]+)["']?\s*$/) || line.match(/^\s*feedback_id:\s*["']?([^"'\s]+)["']?\s*$/);
113
113
  if (feedbackMatch) {