# Safe-Docx TS OpenSpec Traceability Matrix

> Auto-generated by `packages/docx-mcp/scripts/validate_openspec_coverage.mjs`.
> Do not hand-edit this file.

This matrix maps OpenSpec `#### Scenario:` entries to Allure story mappings extracted from `*.test.ts` files.

## Change: `add-accept-tracked-changes`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| accept_changes produces clean document body with no revision markup | covered | `src/tools/add_accept_tracked_changes.test.ts` |  |
| accepted document opens cleanly in Microsoft Word | covered | `src/tools/add_accept_tracked_changes.test.ts` |  |
| original document is not mutated | covered | `src/tools/add_accept_tracked_changes.test.ts` |  |

## Change: `add-apply-plan-and-style-source`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| __proto__ in step fields is rejected | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| canonical names are advertised | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| error when both steps and plan_file_path supplied | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| legacy aliases are rejected inside apply_plan steps | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| legacy aliases are rejected inside plan operations | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| legacy aliases are unavailable | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| legacy aliases rejected during validation | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| partial apply failure stops on first error | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| plan steps loaded from file path | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| step normalization accepts merged format | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| step normalization accepts raw format | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| style_source_id clones formatting from specified paragraph | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| style_source_id falls back to anchor with warning | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| style_source_id omitted uses anchor formatting (backward compatible) | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| successful apply executes all steps | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| unsupported operation is rejected during validation | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |
| validation failure returns all errors without applying | covered | `src/tools/add_apply_plan_and_style_source.test.ts` |  |

## Change: `add-attach-pretty-json-helper`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| attachPrettyJson renders formatted JSON inline | covered | `src/testing/add_attach_pretty_json_helper.test.ts` |  |
| debug JSON final-step label remains neutral | covered | `src/testing/add_attach_pretty_json_helper.test.ts` |  |
| short HTML attachment auto-fits without vertical scrollbar | covered | `src/testing/add_attach_pretty_json_helper.test.ts` |  |
| tall HTML attachment uses single vertical scrollbar | covered | `src/testing/add_attach_pretty_json_helper.test.ts` |  |

## Change: `add-auto-normalization-on-open`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| _bk_* IDs stable across normalization | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| document is normalized on open by default | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| document tools accept file-first entry without pre-open | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| existing session reuse is non-blocking and warns via metadata | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| missing file_path is rejected | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| new session creation includes normalization | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| normalization stats in session metadata | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| reuse policy selects most-recently-used session | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |
| skip_normalization bypasses preprocessing | covered | `src/tools/add_auto_normalization_on_open.test.ts` |  |

## Change: `add-comment-delete-tool`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| comment not found returns error | covered | `src/tools/delete_comment.test.ts` |  |
| delete a non-leaf reply cascades to descendants | covered | `src/tools/delete_comment.test.ts` |  |
| delete a single leaf reply | covered | `src/tools/delete_comment.test.ts` |  |
| delete comment successfully | covered | `src/tools/delete_comment.test.ts` |  |
| delete comment with replies cascades | covered | `src/tools/delete_comment.test.ts` |  |
| delete_comment supports session-or-file resolution | covered | `src/tools/delete_comment.test.ts` |  |
| missing comment_id returns error | covered | `src/tools/delete_comment.test.ts` |  |
| missing session context returns error | covered | `src/tools/delete_comment.test.ts` |  |

## Change: `add-comment-read-tool`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| document with no comments returns empty array | covered | `src/tools/get_comments.test.ts` |  |
| get_comments does not mutate session state | covered | `src/tools/get_comments.test.ts` |  |
| get_comments returns comment metadata and text | covered | `src/tools/get_comments.test.ts` |  |
| get_comments supports session-or-file resolution | covered | `src/tools/get_comments.test.ts` |  |
| missing session context returns error | covered | `src/tools/get_comments.test.ts` |  |
| threaded replies are nested under parent comments | covered | `src/tools/get_comments.test.ts` |  |

## Change: `add-docx-to-odf-conversion`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| convert_to_odt defaults the output path to the source with .odt | covered | `src/tools/add_docx_to_odf_conversion.test.ts` |  |
| convert_to_odt refuses to clobber the source document | covered | `src/tools/add_docx_to_odf_conversion.test.ts` |  |
| convert_to_odt refuses to overwrite without allow_overwrite | covered | `src/tools/add_docx_to_odf_conversion.test.ts` |  |
| convert_to_odt returns ODF_UNAVAILABLE when the provider is missing | covered | `src/tools/add_docx_to_odf_conversion.test.ts` |  |
| convert_to_odt writes a valid .odt and reports lossiness | covered | `src/tools/add_docx_to_odf_conversion.test.ts` |  |

## Change: `add-extract-revisions-tool`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| changed paragraphs inside table cells are extracted | covered | `src/tools/extract_revisions.test.ts` |  |
| deleted-only paragraph has empty after text | covered | `src/tools/extract_revisions.test.ts` |  |
| extracting revisions from a document with insertions and deletions | covered | `src/tools/extract_revisions.test.ts` |  |
| extracting revisions from a document with no tracked changes | covered | `src/tools/extract_revisions.test.ts` |  |
| extracting revisions includes associated comments | covered | `src/tools/extract_revisions.test.ts` |  |
| inserted-only paragraph has empty before text | covered | `src/tools/extract_revisions.test.ts` |  |
| invalid limit is rejected | covered | `src/tools/extract_revisions.test.ts` |  |
| invalid offset is rejected | covered | `src/tools/extract_revisions.test.ts` |  |
| missing session context returns error | covered | `src/tools/extract_revisions.test.ts` |  |
| new edit invalidates extraction cache | covered | `src/tools/extract_revisions.test.ts` |  |
| offset beyond total returns empty page | covered | `src/tools/extract_revisions.test.ts` |  |
| paginating through revisions with offset and limit | covered | `src/tools/extract_revisions.test.ts` |  |
| property-only changes are included in extraction | covered | `src/tools/extract_revisions.test.ts` |  |
| real DOCX redline with tracked changes extracts correctly | covered | `src/tools/extract_revisions.test.ts` |  |
| repeated extraction at same revision uses cache | covered | `src/tools/extract_revisions.test.ts` |  |
| retrieving subsequent pages with offset | covered | `src/tools/extract_revisions.test.ts` |  |
| session document is unchanged after extraction | covered | `src/tools/extract_revisions.test.ts` |  |
| structurally-empty inserted paragraphs are filtered out | covered | `src/tools/extract_revisions.test.ts` |  |
| two-file comparison then extraction workflow | covered | `src/tools/extract_revisions.test.ts` |  |

## Change: `add-footnote-support`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| add footnote successfully | covered | `src/tools/add_footnote_support.test.ts` |  |
| delete footnote successfully | covered | `src/tools/add_footnote_support.test.ts` |  |
| empty document returns empty array | covered | `src/tools/add_footnote_support.test.ts` |  |
| error when after_text not found | covered | `src/tools/add_footnote_support.test.ts` |  |
| error when anchor paragraph not found | covered | `src/tools/add_footnote_support.test.ts` |  |
| error when deleting reserved type | covered | `src/tools/add_footnote_support.test.ts` |  |
| error when note not found | covered | `src/tools/add_footnote_support.test.ts` |  |
| markers absent from edit matching | covered | `src/tools/add_footnote_support.test.ts` |  |
| markers present in document view | covered | `src/tools/add_footnote_support.test.ts` |  |
| read all footnotes | covered | `src/tools/add_footnote_support.test.ts` |  |
| update footnote successfully | covered | `src/tools/add_footnote_support.test.ts` |  |

## Change: `add-html-export`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| default html output path derives from the source path | covered | `src/tools/export_html.test.ts` |  |
| html export rejects a Google Docs source | covered | `src/tools/export_html.test.ts` |  |
| html export writes a file and returns its path and content | covered | `src/tools/export_html.test.ts` |  |
| html overwrite of an existing output file is blocked by default | covered | `src/tools/export_html.test.ts` |  |
| include_markdown false omits the rendered html content | covered | `src/tools/export_html.test.ts` |  |

## Change: `add-markdown-export`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| allow_overwrite permits replacing an existing output file | covered | `src/tools/export.test.ts` |  |
| default output path derives from the source path | covered | `src/tools/export.test.ts` |  |
| explicit output_path is honored | covered | `src/tools/export.test.ts` |  |
| export rejects a Google Docs source | covered | `src/tools/export.test.ts` |  |
| export resolves a session from file_path | covered | `src/tools/export.test.ts` |  |
| include_markdown false omits the rendered content | covered | `src/tools/export.test.ts` |  |
| markdown export writes a file and returns its path and content | covered | `src/tools/export.test.ts` |  |
| overwrite of an existing output file is blocked by default | covered | `src/tools/export.test.ts` |  |
| unknown export format is rejected | covered | `src/tools/export.test.ts` |  |

## Change: `add-multi-agent-plan-merge-phase-1`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| init_plan returns revision-bound context | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| init_plan uses file-first session resolution | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans can return diagnostics without hard failure | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans fails by default when conflicts exist | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans reports base-revision conflict | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans reports duplicate step IDs | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans reports insert-slot collision | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans reports overlapping replace ranges | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans reports unknown-range conflict for same paragraph | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |
| merge_plans returns merged artifact when no conflicts | covered | `src/tools/add_multi_agent_plan_merge_phase_1.test.ts` |  |

## Change: `add-multi-platform-mcp-discovery`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| AI agent configures SafeDocX from install guide | covered | `src/add_multi_platform_mcp_discovery.test.ts` |  |
| Extension manifest is valid JSON with required fields | covered | `src/add_multi_platform_mcp_discovery.test.ts` |  |
| Gemini CLI discovers SafeDocX via extension manifest | covered | `src/add_multi_platform_mcp_discovery.test.ts` |  |
| Gemini model reads context file for tool guidance | covered | `src/add_multi_platform_mcp_discovery.test.ts` |  |

## Change: `add-odf-comments`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Missing or ambiguous `anchor_text` is rejected | covered | `src/tools/odf/odf_comments.test.ts` |  |
| Replies are unsupported for ODF | covered | `src/tools/odf/odf_comments.test.ts` |  |
| `add_comment` annotates a substring via `anchor_text` | covered | `src/tools/odf/odf_comments.test.ts` |  |
| `add_comment` annotates a whole ODF paragraph | covered | `src/tools/odf/odf_comments.test.ts` |  |
| `get_comments` returns ODF annotations | covered | `src/tools/odf/odf_comments.test.ts` |  |

## Change: `add-odf-compare`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| DOCX two-file compare is unchanged | covered | `src/tools/odf/odf_compare.test.ts` |  |
| Inserted and deleted paragraphs are counted | covered | `src/tools/odf/odf_compare.test.ts` |  |
| Output path may not overwrite a source | covered | `src/tools/odf/odf_compare.test.ts` |  |
| Still-unsupported tools remain guarded for ODF sessions | covered | `src/tools/odf/odf_compare.test.ts` |  |
| The redline reopens with the changes preserved | covered | `src/tools/odf/odf_compare.test.ts` |  |
| Two-file `.odt` compare produces a redline | covered | `src/tools/odf/odf_compare.test.ts` |  |

## Change: `add-odf-compare-session`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| An unedited session produces an empty redline | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| Comparison does not mutate the live session | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| Output path may not overwrite the session's original | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| Session edits produce a tracked-changes redline | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| Session-resolution metadata is attached | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| The session redline reopens with deleted content out-of-line | covered | `src/tools/odf/odf_compare_session.test.ts` |  |
| Two-file mode keeps precedence over a stray `file_path` | covered | `src/tools/odf/odf_compare_session.test.ts` |  |

## Change: `add-odf-core`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| File-first `.odt` auto-opens | covered | `src/tools/odf/odf_tools.test.ts` |  |
| Open a local `.odt` | covered | `src/tools/odf/odf_tools.test.ts` |  |
| Supported tools route to the ODF handler | covered | `src/tools/odf/odf_tools.test.ts` |  |
| Unsupported extensions still rejected | covered | `src/tools/odf/odf_tools.test.ts` |  |
| Unsupported tools are guarded for ODF | covered | `src/tools/odf/odf_tools.test.ts` |  |

## Change: `add-odf-grep-insert`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Still-unsupported tools remain guarded | covered | `src/tools/odf/odf_grep_insert.test.ts` |  |
| `grep` searches an ODF session | covered | `src/tools/odf/odf_grep_insert.test.ts` |  |
| `insert_paragraph` inserts into an ODF session | covered | `src/tools/odf/odf_grep_insert.test.ts` |  |

## Change: `add-odf-intra-paragraph-compare`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Two-file `.odt` compare reports inline granularity and meaningful modifications | covered | `src/tools/odf/odf_compare_inline.test.ts` |  |
| Whole-paragraph-only diffs still report zero modifications | covered | `src/tools/odf/odf_compare_inline.test.ts` |  |

## Change: `add-run-level-formatting-visibility`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| TOON output shows inline formatting tags at run boundaries by default | covered | `src/tools/add_run_level_formatting_visibility.test.ts` |  |
| show_formatting=false suppresses inline tags | covered | `src/tools/add_run_level_formatting_visibility.test.ts` |  |
| writable tag vocabulary matches replace_text new_string vocabulary | covered | `src/tools/add_run_level_formatting_visibility.test.ts` |  |

## Change: `add-safe-docx-batch-apply-and-strict-anchor-resolution`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| MCP catalog omits open_document | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |
| canonical names are advertised | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |
| document tools accept file-first entry without pre-open | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |
| legacy aliases are rejected inside plan operations | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |
| legacy aliases are unavailable | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |
| open_document call is rejected as unsupported | covered | `src/tools/add_safe_docx_batch_apply_and_strict_anchor_resolution.test.ts` |  |

## Change: `add-safe-docx-docx-helper-tools`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| add root comment to target range | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| add threaded reply linked to parent comment | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| auto-repair fixes known safe issues | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| comment parts are bootstrapped when missing | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| merge_runs consolidates adjacent format-identical runs | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| redline validation runs when original baseline is provided | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| replace_text can normalize fragmented runs before search | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| replace_text performs formatting-preserving replacement | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| simplify_redlines merges adjacent same-author tracked wrappers | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| simplify_redlines reports tracked-change author summary | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |
| validate packed or unpacked DOCX inputs | covered | `src/tools/add_safe_docx_docx_helper_tools.test.ts` |  |

## Change: `add-safe-docx-layout-format-controls`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| format paragraph spacing by paragraph ID | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| format table row height and cell padding | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| format_layout does not invoke external process tooling at runtime | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| invalid layout values are rejected with structured error | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| no spacer paragraphs are introduced | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| npx runtime remains Python-free | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |
| paragraph IDs remain stable after layout formatting | covered | `src/tools/add_safe_docx_layout_format_controls.test.ts` |  |

## Change: `add-safe-docx-ts-formatting-parity`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| field-aware visible text does not destroy fields | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| fingerprint ignores volatile attributes | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| formatting-based header detection | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| header semantics accepted via tags for backward compatibility | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| insert_paragraph preserves header semantics | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| pagination rules deterministic for zero offset | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| post-edit invariants prevent empty paragraph stubs | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| read_file JSON mode returns node metadata | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| read_file returns TOON schema with structure columns | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| replace_text preserves mixed-run formatting | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |
| stable style IDs within a session | covered | `src/add_safe_docx_ts_formatting_parity.test.ts` |  |

## Change: `add-table-context-to-document-view`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| JSON format includes table_context | covered | `src/tools/read_file_pagination.test.ts` |  |
| Simple format includes table markers | covered | `src/tools/read_file_pagination.test.ts` |  |
| Table markers do not inflate paragraph count | covered | `src/tools/read_file_pagination.test.ts` |  |
| Toon format includes table markers | covered | `src/tools/read_file_pagination.test.ts` |  |

## Change: `add-text-export`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| plaintext default output path swaps the extension for .txt | covered | `src/tools/export_plaintext.test.ts` |  |
| plaintext export does not return a markdown field | covered | `src/tools/export_plaintext.test.ts` |  |
| plaintext export strips inline formatting | covered | `src/tools/export_plaintext.test.ts` |  |
| plaintext export writes a .txt file and returns its content | covered | `src/tools/export_plaintext.test.ts` |  |
| plaintext overwrite is blocked by default | covered | `src/tools/export_plaintext.test.ts` |  |

## Change: `add-typescript-mcp-server`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Bookmark-based targeting | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Concurrent sessions | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Destructive tools annotated correctly | covered | `src/add_typescript_mcp_server.test.ts` |  |
| File not found error | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Format-preserving text replacement | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Invalid file type error | covered | `src/add_typescript_mcp_server.test.ts` |  |
| NPM package availability | covered | `src/add_typescript_mcp_server.test.ts` |  |
| No XML corruption | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Read-only tools annotated correctly | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Session creation | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Session expiration auto-reopens | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Windows compatibility | covered | `src/add_typescript_mcp_server.test.ts` |  |
| Zero-friction installation on Claude Desktop | covered | `src/add_typescript_mcp_server.test.ts` |  |
| download tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| get_file_status tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| grep tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| insert_paragraph tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| macOS compatibility | covered | `src/add_typescript_mcp_server.test.ts` |  |
| open_document tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| read_file tool | covered | `src/add_typescript_mcp_server.test.ts` |  |
| replace_text tool | covered | `src/add_typescript_mcp_server.test.ts` |  |

## Change: `document-paragraph-id-stability-and-fingerprint`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Identifiers are byte-identical across machines for identical stored bytes | covered | `src/tools/paragraph_id_stability.traceability.test.ts` |  |
| Inserting new paragraph does not renumber unrelated IDs | covered | `src/tools/paragraph_id_stability.traceability.test.ts` |  |
| Missing intrinsic IDs are backfilled once | covered | `src/tools/paragraph_id_stability.traceability.test.ts` |  |
| Re-opening unchanged document yields same IDs | covered | `src/tools/paragraph_id_stability.traceability.test.ts` |  |
| TOON format ignores include_fingerprint | covered | `src/tools/read_file_content_fingerprint.test.ts` |  |
| Two identical signature-block paragraphs remain uniquely addressable | covered | `src/tools/paragraph_id_stability.traceability.test.ts` |  |
| default JSON output omits fingerprint | covered | `src/tools/read_file_content_fingerprint.test.ts` |  |
| opt-in fingerprint adds field on JSON output | covered | `src/tools/read_file_content_fingerprint.test.ts` |  |
| same paragraph text produces same fingerprint across documents | covered | `src/tools/read_file_content_fingerprint.test.ts` |  |

## Change: `expose-comment-range-metadata`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| comment without range markers leaves range fields undefined | covered | `src/tools/get_comments_range_metadata.test.ts` |  |
| multi-paragraph range comment exposes start and end paragraph ids | covered | `src/tools/get_comments_range_metadata.test.ts` |  |
| single-paragraph range comment exposes range metadata | covered | `src/tools/get_comments_range_metadata.test.ts` |  |
| threaded replies pass range metadata through | covered | `src/tools/get_comments_range_metadata.test.ts` |  |

## Change: `update-safe-docx-save-defaults-and-stable-node-ids`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| Anchors unchanged after dual download | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Default download returns both variants | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Download response reports variant and cache details | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Explicit variant override returns subset | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Generating clean artifact does not invalidate redline anchors | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Inserting new paragraph does not renumber unrelated IDs | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Missing intrinsic IDs are backfilled once | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| New edit invalidates previous revision cache | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Open response advertises download defaults | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Re-opening unchanged document yields same IDs | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Repeat download reuses cached artifacts | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |
| Two identical signature-block paragraphs remain uniquely addressable | covered | `src/tools/update_safe_docx_save_defaults_and_stable_node_ids.test.ts` |  |

## Change: `update-safe-docx-sessionless-entry-and-session-controls`

| Scenario | Status | Allure Test Files | Notes |
|---|---|---|---|
| close all files requires explicit confirmation | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| close file by path | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| document tools accept file-first entry without pre-open | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| existing session reuse is non-blocking and warns via metadata | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| flexible-whitespace fallback ignores spacing variance | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| missing file_path is rejected | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| open_document remains callable with deprecation warning | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| quote-normalization scenarios are test-mapped in Allure coverage | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| quote-normalized fallback matches smart quotes and ASCII quotes | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| quote-optional fallback matches quoted and unquoted term references | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |
| reuse policy selects most-recently-used session | covered | `src/tools/update_safe_docx_sessionless_entry_and_session_controls.test.ts` |  |

Extra stories not found in spec:
- close file by path clears the session for that file

