Bump the renderer to 3f25999 and bind documents to published profile versions
governance / governance (pull_request) Successful in 16s
ci / vet-and-test (pull_request) Successful in 1m2s

Why: Agent-Document-Renderer main publishes company.default@1.1.0 with a
declarative TOC (spec 04, acceptance 10 §4 §7) and keeps 1.0.0 loadable by
version. The fixed defaultProfileVersion "1.0.0" no longer matched
LoadCompanyDefaultContext (1.1.0), so every delivery failed with a profile
mismatch. New documents must take the latest published version, while
documents that already bind a published version keep rendering with exactly
that version, because published rules are immutable and old versions remain
retrievable (spec 08).

Evidence: go vet ./... ok; go test -count=1 ./... ok (all packages);
go run ./internal/docgen/internal/genrendereridentity -check ok;
scripts/agent-exec validate --repo . ok; scripts/dm governance check --repo .
ok; gofmt -l clean; git diff --cached --check clean. New tests cover the
default binding (1.1.0, TOC present), pinned 1.0.0 (no TOC) and 1.1.0 for
both a request pin and a persisted-Markdown replay, and refusal of unknown
versions and other profile IDs before any profile load.

Impact: docgen resolves the profile version from the persisted Markdown
binding or the request, defaults new documents to
profiles.LatestCompanyDefaultVersion, and loads it through
LoadCompanyDefaultVersionContext. The legacy migration comparison records the
declared TOC as an intentional corporate-layout difference
(RDR-T10-CMP-002) and keeps it out of the body visible-text dimension.
RendererIdentity is regenerated for 3f259990b5d4.

Refs: unified renderer plan Task 13; renderer PR #7
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-10-18 06:24:36 +00:00
co-authored by Cursor
parent bf8b912147
commit c34279ad55
5 changed files with 300 additions and 28 deletions
+52 -2
View File
@@ -62,6 +62,7 @@ type docxNumbering struct {
type docxComparison struct {
Paragraphs []string `json:"paragraphs"`
TOC []string `json:"toc"`
PageSize map[string]string `json:"pageSize"`
Margins map[string]string `json:"margins"`
Headers int `json:"headers"`
@@ -95,7 +96,7 @@ func compareLegacyAndShared(title string, source []byte, canonical model.Canonic
if legacyErr != nil || sharedErr != nil {
detail := fmt.Sprintf("legacy=%v shared=%v", legacyErr, sharedErr)
for _, name := range []string{
"visible-text", "page-layout", "header-footer", "node-bookmarks", "safe-links", "security-objects", "word-semantics",
"visible-text", "table-of-contents", "page-layout", "header-footer", "node-bookmarks", "safe-links", "security-objects", "word-semantics",
"word-numbering", "word-task-state", "word-thematic-rule", "word-table-alignment",
} {
receipt.Dimensions = append(receipt.Dimensions, ComparisonDimension{Name: name, Status: "unassessed", Detail: detail})
@@ -115,6 +116,12 @@ func compareLegacyAndShared(title string, source []byte, canonical model.Canonic
} else {
receipt.Dimensions = append(receipt.Dimensions, compareExactDimension("visible-text", legacyParagraphs, sharedDOCX.Paragraphs, ""))
}
if len(legacyDOCX.TOC) == 0 && len(sharedDOCX.TOC) > 0 {
receipt.Dimensions = append(receipt.Dimensions, intentionalDimension("table-of-contents", legacyDOCX.TOC, sharedDOCX.TOC,
comparisonExceptionCorporate, "published organization default declares a table of contents"))
} else {
receipt.Dimensions = append(receipt.Dimensions, compareExactDimension("table-of-contents", legacyDOCX.TOC, sharedDOCX.TOC, ""))
}
if equalJSON(legacyDOCX.PageSize, sharedDOCX.PageSize) {
receipt.Dimensions = append(receipt.Dimensions, compareExactDimension("page-size", legacyDOCX.PageSize, sharedDOCX.PageSize, ""))
@@ -501,6 +508,11 @@ func inspectComparisonDOCX(raw []byte) (docxComparison, error) {
inParagraph, inText, inCell, inParagraphBorder := false, false, false, false
paragraphLevel, paragraphNumID, cellAlignment := 0, "", ""
paragraphRule := false
// A TOC is its field's paragraphs plus an immediately preceding caption
// paragraph excluded from the outline (outlineLvl 9).
inInstruction, paragraphTOC, paragraphCaption := false, false, false
fieldDepth, tocFieldDepth := 0, 0
var pendingCaption []string
var table [][]string
var row []string
for {
@@ -518,10 +530,27 @@ func inspectComparisonDOCX(raw []byte) (docxComparison, error) {
inParagraph = true
paragraph.Reset()
paragraphLevel, paragraphNumID, paragraphRule = 0, "", false
paragraphTOC, paragraphCaption = tocFieldDepth > 0, false
case "t":
if inParagraph {
inText = true
}
case "outlineLvl":
if inParagraph && xmlAttributeValue(value.Attr, "val") == "9" {
paragraphCaption = true
}
case "fldChar":
switch xmlAttributeValue(value.Attr, "fldCharType") {
case "begin":
fieldDepth++
case "end":
if fieldDepth == tocFieldDepth {
tocFieldDepth = 0
}
fieldDepth = max(fieldDepth-1, 0)
}
case "instrText":
inInstruction = true
case "numId":
if inParagraph {
paragraphNumID = xmlAttributeValue(value.Attr, "val")
@@ -559,15 +588,35 @@ func inspectComparisonDOCX(raw []byte) (docxComparison, error) {
if inText {
paragraph.Write(value)
}
if inInstruction && tocFieldDepth == 0 && fieldDepth > 0 {
if fields := strings.Fields(string(value)); len(fields) > 0 && strings.EqualFold(fields[0], "TOC") {
tocFieldDepth, paragraphTOC = fieldDepth, inParagraph
}
}
case xml.EndElement:
switch value.Name.Local {
case "t":
inText = false
case "instrText":
inInstruction = false
case "pBdr":
inParagraphBorder = false
case "p":
text := normalizeComparisonText(paragraph.String())
if text != "" {
if paragraphTOC {
result.TOC = append(result.TOC, pendingCaption...)
pendingCaption = nil
if text != "" {
result.TOC = append(result.TOC, text)
}
inParagraph = false
break
}
result.Paragraphs = append(result.Paragraphs, pendingCaption...)
pendingCaption = nil
if text != "" && paragraphCaption {
pendingCaption = []string{text}
} else if text != "" {
result.Paragraphs = append(result.Paragraphs, text)
}
if paragraphNumID != "" {
@@ -596,6 +645,7 @@ func inspectComparisonDOCX(raw []byte) (docxComparison, error) {
}
}
}
result.Paragraphs = append(result.Paragraphs, pendingCaption...)
if len(numbered) > 0 {
numbering, found := parts["word/numbering.xml"]
if !found {
+51 -19
View File
@@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"sort"
"strings"
"time"
@@ -26,7 +27,6 @@ const (
ManifestSchemaVersion = "backend-document-delivery/v1"
AdapterIdentity = RendererIdentity + "/word-adapter-v1"
defaultProfileID = "company.default"
defaultProfileVersion = "1.0.0"
defaultRenderCapacity = 4
)
@@ -194,18 +194,15 @@ func Prepare(ctx context.Context, request Request) (PreparedDocument, error) {
if err := validateWorkspaceRoute(request, parsed.Metadata); err != nil {
return PreparedDocument{}, err
}
if parsed.Metadata.ProfileID != defaultProfileID || parsed.Metadata.ProfileVersion != defaultProfileVersion {
return PreparedDocument{}, fmt.Errorf("%w: Markdown binds %s@%s, expected %s@%s", ErrProfileMismatch,
parsed.Metadata.ProfileID, parsed.Metadata.ProfileVersion, defaultProfileID, defaultProfileVersion)
if _, err := profileVersionFor(request, &parsed.Metadata); err != nil {
return PreparedDocument{}, err
}
} else {
if request.ProfileID != "" || request.ProfileVersion != "" {
if request.ProfileID != defaultProfileID || request.ProfileVersion != defaultProfileVersion {
return PreparedDocument{}, fmt.Errorf("%w: requested %s@%s, expected %s@%s", ErrProfileMismatch,
request.ProfileID, request.ProfileVersion, defaultProfileID, defaultProfileVersion)
}
profileVersion, err := profileVersionFor(request, nil)
if err != nil {
return PreparedDocument{}, err
}
source, err := workspaceMarkdown(request, defaultProfileID, defaultProfileVersion)
source, err := workspaceMarkdown(request, defaultProfileID, profileVersion)
if err != nil {
return PreparedDocument{}, err
}
@@ -231,14 +228,14 @@ func Prepare(ctx context.Context, request Request) (PreparedDocument, error) {
}
type generatorDependencies struct {
loadDefault func(context.Context) (profiles.Bundle, error)
loadProfile func(context.Context, string) (profiles.Bundle, error)
newRenderer func(*profile.AssetReader) render.Renderer
legacyBuild func(string, string) ([]byte, error)
}
func defaultGeneratorDependencies() generatorDependencies {
return generatorDependencies{
loadDefault: profiles.LoadCompanyDefaultContext,
loadProfile: profiles.LoadCompanyDefaultVersionContext,
newRenderer: func(assets *profile.AssetReader) render.Renderer { return word.NewAdapter(assets) },
legacyBuild: legacyBuild,
}
@@ -274,6 +271,7 @@ func generateWithOptions(ctx context.Context, request Request, options RenderOpt
return Delivery{}, fmt.Errorf("%w: Markdown is %d bytes, limit is %d", ErrResourceLimit, len(request.Markdown), limits.MaxMarkdownBytes)
}
var parsed markdownrenderer.Result
var boundMetadata *markdownrenderer.Metadata
materialized := bytes.HasPrefix(bytes.TrimSpace(request.Markdown), []byte("---"))
if materialized {
parsed, err = parseMarkdownContext(ctx, request.Markdown, false, limits)
@@ -283,17 +281,20 @@ func generateWithOptions(ctx context.Context, request Request, options RenderOpt
if err := validateWorkspaceRoute(request, parsed.Metadata); err != nil {
return Delivery{}, err
}
boundMetadata = &parsed.Metadata
}
bundle, err := dependencies.loadDefault(ctx)
boundVersion, err := profileVersionFor(request, boundMetadata)
if err != nil {
return Delivery{}, fmt.Errorf("docgen: load company default: %w", err)
return Delivery{}, err
}
bundle, err := dependencies.loadProfile(ctx, boundVersion)
if err != nil {
return Delivery{}, fmt.Errorf("docgen: load company default %s: %w", boundVersion, err)
}
profileID, profileVersion := bundle.Snapshot.ProfileIdentity()
if request.ProfileID != "" || request.ProfileVersion != "" {
if request.ProfileID != profileID || request.ProfileVersion != profileVersion {
return Delivery{}, fmt.Errorf("%w: requested %s@%s, available %s@%s", ErrProfileMismatch,
request.ProfileID, request.ProfileVersion, profileID, profileVersion)
}
if profileID != defaultProfileID || profileVersion != boundVersion {
return Delivery{}, fmt.Errorf("%w: loaded %s@%s, bound %s@%s", ErrProfileMismatch,
profileID, profileVersion, defaultProfileID, boundVersion)
}
if !materialized {
source, sourceErr := workspaceMarkdown(request, profileID, profileVersion)
@@ -481,6 +482,37 @@ func validateWorkspaceRoute(request Request, metadata markdownrenderer.Metadata)
return nil
}
// profileVersionFor returns the company-default version a document renders
// with. Published versions are immutable, so a version the persisted Markdown
// or the request already binds is kept; only a new, unbound document takes the
// latest published version. metadata is nil until Markdown is materialized.
func profileVersionFor(request Request, metadata *markdownrenderer.Metadata) (string, error) {
requested := request.ProfileID != "" || request.ProfileVersion != ""
if requested && !publishedProfileVersion(request.ProfileID, request.ProfileVersion) {
return "", fmt.Errorf("%w: requested %s@%s is not a published %s version", ErrProfileMismatch,
request.ProfileID, request.ProfileVersion, defaultProfileID)
}
if metadata == nil {
if requested {
return request.ProfileVersion, nil
}
return profiles.LatestCompanyDefaultVersion, nil
}
if !publishedProfileVersion(metadata.ProfileID, metadata.ProfileVersion) {
return "", fmt.Errorf("%w: Markdown binds %s@%s, which is not a published %s version", ErrProfileMismatch,
metadata.ProfileID, metadata.ProfileVersion, defaultProfileID)
}
if requested && request.ProfileVersion != metadata.ProfileVersion {
return "", fmt.Errorf("%w: requested %s@%s, Markdown binds %s@%s", ErrProfileMismatch,
request.ProfileID, request.ProfileVersion, metadata.ProfileID, metadata.ProfileVersion)
}
return metadata.ProfileVersion, nil
}
func publishedProfileVersion(profileID, profileVersion string) bool {
return profileID == defaultProfileID && slices.Contains(profiles.CompanyDefaultVersions(), profileVersion)
}
func validateWorkspaceMetadata(request Request, metadata markdownrenderer.Metadata, profileID, profileVersion string) error {
if err := validateWorkspaceRoute(request, metadata); err != nil {
return err
@@ -2,6 +2,6 @@
package docgen
const rendererRevision = "10950774736b64b5d8e544ce03d45ae5a6ceca7c"
const rendererRevision = "3f259990b5d43ec0d318f39d496816140ab559b5"
const RendererIdentity = "agent-document-renderer@" + rendererRevision
+195 -5
View File
@@ -160,7 +160,7 @@ func TestGeneratePersistsCanonicalMarkdownWithStableNodeParity(t *testing.T) {
if reparsed.Metadata.DocumentID != "workspace-minutes" || reparsed.Metadata.ProjectID != WorkspaceProjectID ||
reparsed.Metadata.DocumentType != "general" || reparsed.Metadata.Title != "研发周会纪要" ||
reparsed.Metadata.Language != "zh-CN" || reparsed.Metadata.ProfileID != "company.default" ||
reparsed.Metadata.ProfileVersion != "1.0.0" || reparsed.Metadata.Controlled {
reparsed.Metadata.ProfileVersion != profiles.LatestCompanyDefaultVersion || reparsed.Metadata.Controlled {
t.Fatalf("controlled metadata changed: %#v", reparsed.Metadata)
}
@@ -355,10 +355,10 @@ func TestPersistedControlledMetadataRoutesBeforeDefaultProfileLoad(t *testing.T)
request.Title = "Controlled"
loads := 0
deps := defaultGeneratorDependencies()
baseLoad := deps.loadDefault
deps.loadDefault = func(ctx context.Context) (profiles.Bundle, error) {
baseLoad := deps.loadProfile
deps.loadProfile = func(ctx context.Context, version string) (profiles.Bundle, error) {
loads++
return baseLoad(ctx)
return baseLoad(ctx, version)
}
_, err := generate(context.Background(), request, deps)
if !errors.Is(err, ErrRDMRequired) || loads != 0 {
@@ -367,7 +367,7 @@ func TestPersistedControlledMetadataRoutesBeforeDefaultProfileLoad(t *testing.T)
}
func TestRendererIdentityMatchesPublishedPin(t *testing.T) {
const want = "agent-document-renderer@10950774736b64b5d8e544ce03d45ae5a6ceca7c"
const want = "agent-document-renderer@3f259990b5d43ec0d318f39d496816140ab559b5"
if RendererIdentity != want {
t.Fatalf("RendererIdentity = %q, want %q", RendererIdentity, want)
}
@@ -456,6 +456,157 @@ func TestGenerateRejectsProfileAndAssetMismatch(t *testing.T) {
}
}
const tocFieldInstruction = `TOC \o "1-`
func TestGenerateBindsNewDocumentsToLatestPublishedProfile(t *testing.T) {
request := workspaceRequest([]byte(representativeMarkdown))
prepared, err := Prepare(context.Background(), request)
if err != nil {
t.Fatalf("Prepare: %v", err)
}
delivery, err := Generate(context.Background(), request)
if err != nil {
t.Fatalf("Generate: %v", err)
}
latest, err := profiles.LoadCompanyDefault()
if err != nil {
t.Fatal(err)
}
if _, version := latest.Snapshot.ProfileIdentity(); version != profiles.LatestCompanyDefaultVersion {
t.Fatalf("renderer latest company default = %s, want %s", version, profiles.LatestCompanyDefaultVersion)
}
for name, markdown := range map[string][]byte{"Prepare": prepared.Markdown.Bytes, "Generate": delivery.Markdown.Bytes} {
metadata := persistedMetadata(t, markdown)
if metadata.ProfileID != "company.default" || metadata.ProfileVersion != profiles.LatestCompanyDefaultVersion {
t.Fatalf("%s bound new document to %s@%s, want company.default@%s", name, metadata.ProfileID, metadata.ProfileVersion, profiles.LatestCompanyDefaultVersion)
}
}
if delivery.Profile.Version != profiles.LatestCompanyDefaultVersion || delivery.Profile.SnapshotHash != latest.Snapshot.SnapshotHash() {
t.Fatalf("delivery profile receipt = %#v, want latest snapshot %s", delivery.Profile, latest.Snapshot.SnapshotHash())
}
documentXML := docxPart(t, delivery.DOCX.Bytes, "word/document.xml")
if !strings.Contains(documentXML, tocFieldInstruction) || !strings.Contains(docxVisibleText(t, delivery.DOCX.Bytes), "目录") {
t.Fatal("new document rendered with the latest company default omitted its declared TOC")
}
}
func TestGenerateKeepsPinnedPublishedProfileVersion(t *testing.T) {
for _, test := range []struct {
version string
toc bool
}{
{version: "1.0.0", toc: false},
{version: "1.1.0", toc: true},
} {
t.Run(test.version, func(t *testing.T) {
pinned, err := profiles.LoadCompanyDefaultVersion(test.version)
if err != nil {
t.Fatal(err)
}
request := workspaceRequest([]byte(representativeMarkdown))
request.ProfileID, request.ProfileVersion = "company.default", test.version
prepared, err := Prepare(context.Background(), request)
if err != nil {
t.Fatalf("Prepare pinned %s: %v", test.version, err)
}
if metadata := persistedMetadata(t, prepared.Markdown.Bytes); metadata.ProfileVersion != test.version {
t.Fatalf("Prepare bound pinned request to %s, want %s", metadata.ProfileVersion, test.version)
}
first, err := Generate(context.Background(), request)
if err != nil {
t.Fatalf("Generate pinned %s: %v", test.version, err)
}
replay := workspaceRequest(first.Markdown.Bytes)
second, err := Generate(context.Background(), replay)
if err != nil {
t.Fatalf("Generate persisted %s Markdown: %v", test.version, err)
}
for name, delivery := range map[string]Delivery{"pinned request": first, "persisted replay": second} {
if delivery.Profile.ProfileID != "company.default" || delivery.Profile.Version != test.version ||
delivery.Profile.SnapshotHash != pinned.Snapshot.SnapshotHash() || delivery.Profile.ProfileSHA256 != pinned.Review.ProfileSHA256 {
t.Fatalf("%s profile receipt = %#v, want company.default@%s snapshot %s", name, delivery.Profile, test.version, pinned.Snapshot.SnapshotHash())
}
if metadata := persistedMetadata(t, delivery.Markdown.Bytes); metadata.ProfileVersion != test.version {
t.Fatalf("%s Markdown binds %s, want %s", name, metadata.ProfileVersion, test.version)
}
if got := strings.Contains(docxPart(t, delivery.DOCX.Bytes, "word/document.xml"), tocFieldInstruction); got != test.toc {
t.Fatalf("%s TOC present = %v, want %v for company.default@%s", name, got, test.toc, test.version)
}
}
if !bytes.Equal(first.DOCX.Bytes, second.DOCX.Bytes) {
t.Fatal("replaying persisted Markdown changed the pinned delivery bytes")
}
})
}
}
func TestProfileBindingRefusesUnpublishedVersionsBeforeLoad(t *testing.T) {
persisted, err := Generate(context.Background(), workspaceRequest([]byte(representativeMarkdown)))
if err != nil {
t.Fatal(err)
}
latestBinding := []byte("profileVersion: \"" + profiles.LatestCompanyDefaultVersion + "\"\n")
if !bytes.Contains(persisted.Markdown.Bytes, latestBinding) {
t.Fatalf("persisted Markdown does not carry %q", latestBinding)
}
pinnedOld := workspaceRequest(bytes.Replace(persisted.Markdown.Bytes, latestBinding, []byte("profileVersion: \"1.0.0\"\n"), 1))
pinnedOld.ProfileID, pinnedOld.ProfileVersion = "company.default", profiles.LatestCompanyDefaultVersion
tests := map[string]Request{}
for name, identity := range map[string][2]string{
"unknown version": {"company.default", "9.9.9"},
"other profile": {"company.other", "1.0.0"},
"missing version": {"company.default", ""},
"missing profile id": {"", "1.0.0"},
} {
request := workspaceRequest([]byte(representativeMarkdown))
request.ProfileID, request.ProfileVersion = identity[0], identity[1]
tests["requested "+name] = request
}
tests["persisted unknown version"] = workspaceRequest(bytes.Replace(persisted.Markdown.Bytes, latestBinding, []byte("profileVersion: \"9.9.9\"\n"), 1))
tests["persisted other profile"] = workspaceRequest(bytes.Replace(persisted.Markdown.Bytes,
[]byte("profileId: \"company.default\"\n"), []byte("profileId: \"company.other\"\n"), 1))
tests["request disagrees with persisted binding"] = pinnedOld
for name, request := range tests {
t.Run(name, func(t *testing.T) {
if _, err := Prepare(context.Background(), request); !errors.Is(err, ErrProfileMismatch) {
t.Fatalf("Prepare error = %v, want ErrProfileMismatch", err)
}
loads := 0
deps := defaultGeneratorDependencies()
baseLoad := deps.loadProfile
deps.loadProfile = func(ctx context.Context, version string) (profiles.Bundle, error) {
loads++
return baseLoad(ctx, version)
}
if _, err := generate(context.Background(), request, deps); !errors.Is(err, ErrProfileMismatch) || loads != 0 {
t.Fatalf("Generate error = %v profileLoads=%d, want ErrProfileMismatch before load", err, loads)
}
})
}
}
func TestGenerateRefusesLoadedProfileWithUnexpectedIdentity(t *testing.T) {
deps := defaultGeneratorDependencies()
deps.loadProfile = func(ctx context.Context, _ string) (profiles.Bundle, error) {
return profiles.LoadCompanyDefaultVersionContext(ctx, "1.0.0")
}
if _, err := generate(context.Background(), workspaceRequest([]byte(representativeMarkdown)), deps); !errors.Is(err, ErrProfileMismatch) {
t.Fatalf("Generate with a loader returning the wrong version error = %v, want ErrProfileMismatch", err)
}
}
func persistedMetadata(t *testing.T, markdown []byte) markdownrenderer.Metadata {
t.Helper()
parsed, err := markdownrenderer.Parse(markdown, markdownrenderer.Options{MaxBytes: 2 << 20, MaxNodes: 10_000, MaxDepth: 64})
if err != nil {
t.Fatalf("persisted Markdown is not parseable: %v", err)
}
return parsed.Metadata
}
func TestGenerateEnforcesLimitsAndCancellation(t *testing.T) {
request := workspaceRequest([]byte(representativeMarkdown))
request.Limits.MaxMarkdownBytes = 32
@@ -713,6 +864,45 @@ func TestRepresentativeLegacyComparisonRecordsOnlyIntentionalDifferences(t *test
t.Errorf("corporate layout exception %s detail = %q, want published organization default", dimension.Name, dimension.Detail)
}
}
if dimension := comparisonDimension(t, delivery.Comparison, "table-of-contents"); dimension.Status != "intentional" || dimension.ExceptionID != comparisonExceptionCorporate {
t.Errorf("declared TOC comparison = %#v, want intentional %s", dimension, comparisonExceptionCorporate)
}
if dimension := comparisonDimension(t, delivery.Comparison, "visible-text"); dimension.Status == "accidental" {
t.Errorf("declared TOC leaked into the body visible-text comparison: %#v", dimension)
}
request.ProfileID, request.ProfileVersion = "company.default", "1.0.0"
pinned, err := generateWithOptions(context.Background(), request, RenderOptions{MigrationComparison: true}, defaultGeneratorDependencies())
if err != nil {
t.Fatal(err)
}
if pinned.Comparison.Assessment != "assessed" || len(pinned.Comparison.AccidentalDifferences) != 0 {
t.Fatalf("pinned 1.0.0 comparison has accidental differences: %#v", pinned.Comparison.AccidentalDifferences)
}
if dimension := comparisonDimension(t, pinned.Comparison, "table-of-contents"); dimension.Status != "match" {
t.Errorf("pinned 1.0.0 TOC comparison = %#v, want match without a TOC", dimension)
}
}
func TestComparisonKeepsBodyTextLossAccidentalBesideDeclaredTOC(t *testing.T) {
const source = "# Report\n\n## Scope\n\nScope body.\n\n## Result\n\nResult body.\n"
request := workspaceRequest([]byte(source))
request.Title = "Report"
delivery, err := Generate(context.Background(), request)
if err != nil {
t.Fatal(err)
}
legacy, err := legacyBuild(request.Title, "# Report\n\n## Scope\n\nScope body.\n\n## Result\n\nDifferent body.\n")
if err != nil {
t.Fatal(err)
}
receipt := compareLegacyAndShared(request.Title, []byte(source), delivery.Document, legacy, delivery.DOCX.Bytes)
if dimension := comparisonDimension(t, receipt, "table-of-contents"); dimension.Status != "intentional" {
t.Fatalf("declared TOC comparison = %#v, want intentional", dimension)
}
if dimension := comparisonDimension(t, receipt, "visible-text"); dimension.Status != "accidental" {
t.Fatalf("body text loss beside a TOC = %#v, want accidental", dimension)
}
}
func TestComparisonDetectsCanonicalAndDOCXTableAlignmentLoss(t *testing.T) {