(sectionId, field, value, mark = "draft", author = "agent")
| 712 | } |
| 713 | |
| 714 | function upsertSectionContent(sectionId, field, value, mark = "draft", author = "agent") { |
| 715 | const section = findSectionOrThrow(sectionId); |
| 716 | const normalizedField = safeString(field).trim(); |
| 717 | if (!normalizedField) { |
| 718 | throw new CanvasError("invalid_field", "Field name is required."); |
| 719 | } |
| 720 | if (isUnsafeFieldName(normalizedField)) { |
| 721 | throw new CanvasError("invalid_field", `Field name "${normalizedField}" is not allowed.`); |
| 722 | } |
| 723 | const normalizedValue = safeString(value, ""); |
| 724 | validateFieldValue(section.id, normalizedField, normalizedValue, mark); |
| 725 | const current = safeString(section.content[normalizedField], ""); |
| 726 | section.content[normalizedField] = normalizedValue; |
| 727 | section.lastModified = nowIso(); |
| 728 | stateCache.lastUpdated = section.lastModified; |
| 729 | addChange({ |
| 730 | type: "file_modified", |
| 731 | summary: `Content updated for ${section.name}.${normalizedField} (${mark}).`, |
| 732 | timestamp: section.lastModified, |
| 733 | sectionId: section.id, |
| 734 | }); |
| 735 | if (author === "human") { |
| 736 | addNote(sectionId, `Updated field "${normalizedField}" (${mark}).`, "human"); |
| 737 | } |
| 738 | return { section, field: normalizedField, current, value: normalizedValue }; |
| 739 | } |
| 740 | |
| 741 | function isSamplePlaceholder(value) { |
| 742 | return /^\[sample:/i.test(safeString(value).trim()); |
no test coverage detected