Files
Ghazi 843654a5ed Release 0.8.11 (#174)
* fix(security): XSS in threads plugin + invalid JSON in init template (S-7, F9)

- threads plugin: stop interpolating raw authors.json text into a <script>
  body. Parse as JSON and re-serialise through scriptLiteral, which escapes
  </script, <!--, U+2028, and U+2029. Closes CWE-79 XSS in
  config.plugins.threads.authors for every page that loads the threads
  client. Add @docmd/utils as a runtime dependency.
- init: missing comma between two navigation entries produced invalid
  JSON in the generated docmd.config.json, breaking the demo template
  inside the Docker image on first run.

Adds scripts/probe-threads-xss.mjs — a regression probe that feeds
attacker payloads (</script><script>, U+2028, non-object values) and
asserts the output contains no breakout.

* fix(0.8.11): cross-locale link, TUI error summary, docusaurus frontmatter, deploy node bump

Targeted 0.8.11 backlog. Every fix here is non-breaking and verified
against the full brute + feature test suites (543/543, 143/143,
plus 5/5 in the threads XSS probe). Closes four open items from
battle-test-reports/unified-issues.md.

- M-5: cross-locale link to default locale prefix
  fr/index.md writing [English](/en/) produced a 404 because the
  default locale lives at root, not under its own prefix. Strip the
  default-locale prefix from absolute hrefs in the rendered markdown
  so cross-locale links point to the actual page. The strip runs
  before #167 relative-path rewrite so both passes see a clean path.
  Adds Test 3.5 in feature-integration.test.js with 6 assertions
  covering the fix and the no-regression for the online build (clean
  URLs without index.html suffix).

- N-12: end-of-build error summary
  Previously the user saw "Build complete" and only later discovered
  plugin failures when downstream tools choked on a bad artifact. Now
  every failed plugin (load error or runtime error) is listed by name
  + hook + reason in the TUI before the build aborts, so the operator
  can grep for any of them.

- T-Z14 / T-Z17: Docusaurus frontmatter translation
  Docusaurus-specific keys (id, sidebar_label) are now translated to
  docmd equivalents (drop id, sidebar_label -> nav_title) when running
  docmd migrate --docusaurus. Files that fail to parse keep their
  original content; a TUI line reports the count of files touched.

- N-5 / N-8: deploy Dockerfile node version
  Bump packages/deployer/src/providers/docker.ts from node:20-alpine
  to node:22-alpine. Matches the 0.9.0 floor decision in repo memory
  and keeps the deployed image on the previous LTS (Node 22 is in
  maintenance until April 2027).

Verified:
  - pnpm --filter @docmd/parser build: clean
  - pnpm --filter @docmd/core build: clean
  - node tests/runner.js --skip-setup: 543 passed, 0 failed
  - node tests/feature-integration.test.js: 143 passed (was 137)
  - node scripts/probe-threads-xss.mjs: all checks pass

* chore(release): bump version 0.8.10 -> 0.8.11

Mechanical version bump across all 27 published packages, the
monorepo root, the @docmd/api plugin registry, and the rust engine
Cargo manifest + lock. Drops the 12-line duplicate comment block in
parser/src/markdown-processor.ts (the code was correct; only the
comment describing it was redundant). No functional changes.

* fix(search): semantic search auto-detect + single source of truth (S-7 search)

Three changes to fix the first-build semantic search failure:

1. client.ts: auto-detect semantic at runtime
   The client now probes for .docmd-search/manifest.json via a HEAD
   request, regardless of what data-semantic says on the modal. This
   fixes the first-build case where deps were installed in onPostBuild
   (after generateScripts already rendered the page without the
   data-semantic attribute). The probe is a single round-trip per
   page load — zero perf cost.

2. search plugin: onConfigResolved + searchConfig
   Added init capability. onConfigResolved computes a single
   searchConfig object (semanticRequested, docmdSearchInstalled,
   peersInstalled, semanticUsable, missingPeers) and stamps it on
   config._searchConfig. Every other hook reads from this same
   object — no more duplicate resolution checks across getAssets
   and generateScripts.

3. maybeReportPeerStatus: idempotent TUI block
   Emits per-dep [ DONE ]/@huggingface/transformers lines on the
   first build (or when the dep status changes). Suppressed on
   subsequent rebuilds when the status is unchanged. Silent when
   semantic was not requested.

Verified: 543/543 tests pass. Minimal build with semantic:true
emits .docmd-search-client.js and builds the semantic index on
first run.

* fix(search): move missing-deps warning after install attempt

The per-dep TUI block was firing BEFORE ensureDocmdSearch tried to
install the deps, so on first build the user saw:
  [ SKIP ] @huggingface/transformers
  [ SKIP ] onnxruntime-node
  Falling back to keyword search...
  [ DONE ] docmd-search installed successfully
  [ DONE ] Semantic search index built

Now the warning only appears inside the !ready fallback path,
after ensureDocmdSearch has genuinely failed to install.,

* Update plugins.generated.json
2026-07-11 11:56:44 +05:30
..
2026-07-11 11:56:44 +05:30