@mytegroupinc/myte-core 0.0.31 → 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 +3 -0
- package/cli.js +18 -16
- package/package.json +1 -1
- package/scripts/feedback-live-full-harness.js +18 -18
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:",
|
|
@@ -3401,25 +3403,25 @@ function writeFeedbackSnapshot({ snapshot, wrapperRoot, outputDir }) {
|
|
|
3401
3403
|
let prdFileCount = 0;
|
|
3402
3404
|
const materializedItems = items.map((rawItem, index) => {
|
|
3403
3405
|
const item = isPlainObject(rawItem) ? { ...rawItem } : {};
|
|
3404
|
-
const feedbackId = stableItemId(item, ["feedback_id", "id"], `F${String(index + 1).padStart(3, "0")}`);
|
|
3405
|
-
const conversationTurns = normalizeFeedbackConversationTurns(item.conversation_turns);
|
|
3406
|
-
const prdText = String(item.prd_text || "").trim();
|
|
3407
|
-
const attachmentDocuments = Array.isArray(item.attachment_documents) ? item.attachment_documents : [];
|
|
3408
|
-
|
|
3409
|
-
let contextSource = "description_only";
|
|
3410
|
-
let contextNote = "No separate PRD. Use feedback_text as the context for this feedback item.";
|
|
3411
|
-
let prdFile = null;
|
|
3406
|
+
const feedbackId = stableItemId(item, ["feedback_id", "id"], `F${String(index + 1).padStart(3, "0")}`);
|
|
3407
|
+
const conversationTurns = normalizeFeedbackConversationTurns(item.conversation_turns);
|
|
3408
|
+
const prdText = String(item.prd_text || "").trim();
|
|
3409
|
+
const attachmentDocuments = Array.isArray(item.attachment_documents) ? item.attachment_documents : [];
|
|
3410
|
+
|
|
3411
|
+
let contextSource = "description_only";
|
|
3412
|
+
let contextNote = "No separate PRD. Use feedback_text as the context for this feedback item.";
|
|
3413
|
+
let prdFile = null;
|
|
3412
3414
|
|
|
3413
3415
|
if (prdText) {
|
|
3414
3416
|
const prdFilename = `${sanitizeFileSegment(feedbackId, `feedback-${index + 1}`)}.md`;
|
|
3415
|
-
const prdPath = path.join(prdSyncDir, prdFilename);
|
|
3416
|
-
writeTextFile(prdPath, ensureTrailingNewline(prdText));
|
|
3417
|
-
prdFile = toPosixRelativePath(targetRoot, prdPath);
|
|
3418
|
-
contextSource = attachmentDocuments.length > 0 ? "attachment_file" : "prd_file";
|
|
3419
|
-
contextNote = attachmentDocuments.length > 0
|
|
3420
|
-
? "Readable feedback attachment documents are stored in the linked file."
|
|
3421
|
-
: "Full PRD context is stored in the linked file.";
|
|
3422
|
-
prdFileCount += 1;
|
|
3417
|
+
const prdPath = path.join(prdSyncDir, prdFilename);
|
|
3418
|
+
writeTextFile(prdPath, ensureTrailingNewline(prdText));
|
|
3419
|
+
prdFile = toPosixRelativePath(targetRoot, prdPath);
|
|
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.";
|
|
3424
|
+
prdFileCount += 1;
|
|
3423
3425
|
} else if (item.has_prd_text) {
|
|
3424
3426
|
contextSource = "prd_declared_but_unavailable";
|
|
3425
3427
|
contextNote = "A separate PRD exists for this feedback item, but readable PRD text was not included in this sync snapshot.";
|
package/package.json
CHANGED
|
@@ -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) {
|