Relocate the in-house OOXML machinery out of internal/services into the
first docforge adapter, with zero behaviour change:
submission_merge.go -> pkg/docforge/docx/merge.go (placeholder
substitution renderer + preview-HTML emitter)
submission_md.go -> pkg/docforge/docx/markdown.go (Markdown->OOXML
walker incl. the b78a984 underscore-fix)
submission_render.go -> pkg/docforge/docx/dotm.go (.dotm->.docx)
+ their _test.go files (git-tracked renames, 84-99% identical)
internal/services keeps thin type-alias + forwarder shims
(docforge_shims.go) so every caller in services/handlers/main compiles
and behaves identically: PlaceholderMap, MissingPlaceholderFn,
SubmissionRenderer, HyperlinkAllocator (aliases); NewSubmissionRenderer,
DefaultMissingMarker, RenderMarkdownToOOXML[WithStyles], ConvertDotmToDocx,
SanitiseSubmissionFileName (forwarders). docx.XMLAttrEscape is exported so
submission_compose.go's hyperlink-rels inserts reuse the walker's escaping.
Three mis-filed pretty-printer tests (legalSourcePretty, ourSideDE/EN,
patentNumberUPC) that exercise the vars layer move back to
internal/services/submission_vars_pretty_test.go.
Placeholder grammar + PlaceholderMap stay co-located with the renderer in
docx for now; slice 3 hoists the format-neutral grammar to the docforge
root with the VariableResolver interface.
Verification: go build ./... clean, go vet clean, full module test green
(the byte-exact OOXML golden tests in merge/compose/render pass unchanged
= behaviour preserved). gofmt drift on the moved files is pre-existing
(72/169 services files already drift; no gofmt gate).
m/paliad#157