agentleFS
yukiyokotaniyukiyokotani/office-open-xml-viewer/AGENTS.md

office-open-xml-viewer

AGENTS.md866 starsChanged 3 months agoMITView on GitHub

This file is the canonical workflow for AI coding agents working on this repository. Tool-specific files such as CLAUDE.md may add supplements, but they must not contradict this file. office-open-xml-viewer renders OOXML documents (docx, xlsx, pptx) to browser Canvas. The implementation is a Rust/WASM parser layer plus TypeScript Canvas renderers and viewers. Important directories: Use this flow for ordinary bug fixes and feature work: 1. Start from main and run git pull --ff-only. 2. If the checkout is dirty, preserve…

  • Installs packages
  • Commits and pushes

We split this AGENTS.md into the rules it gives an agent

69 rules. About 0 are common, 43 are distinctive, and 26 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈43

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 26

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Use this flow for ordinary bug fixes and feature work:

    line 25
  2. Distinctive:

    Start from main and run git pull --ff-only.

    line 27
  3. Very specific:

    If the checkout is dirty, preserve unrelated work before switching or pulling.

    line 28
  4. Very specific:

    Prefer git stash push -u -m <clear-message> for work that appears to belong to another session.

    line 29
  5. Very specific:

    Create a feature branch. Use codex/<topic> for Codex work when possible.

    line 31
  6. Very specific:

    When creating or entering a Codex/Claude worktree, make the root checkout's ignored spec/ directory available from that worktree as a local …

    line 33
  7. Very specific:

    If the worktree lives elsewhere, create spec as a symlink to the main local checkout's spec/ directory.

    line 41
  8. Distinctive:

    add a focused failing test,

    line 45
  9. Distinctive:

    Verify with the narrowest meaningful tests first, then broader checks when the touched surface warrants it.

    line 48
  10. Very specific:

    Commit only the intended source/docs/test files.

    line 50
  11. Distinctive:

    Never push directly to main.

    line 57
  12. Distinctive:

    Use PRs for integration into main.

    line 58
  13. Very specific:

    Do not squash merge. Use gh pr merge <number> --merge unless the user explicitly asks for another non-squash strategy.

    line 59
  14. Distinctive:

    Before git push, set git config http.postBuffer 524288000 if large pushes are expected.

    line 61
  15. Distinctive:

    Commit messages should match the repository style:

    line 63
  16. Distinctive:

    do not include local absolute paths, usernames, home directories, machine names, or other personal environment details.

    line 69
  17. Distinctive:

    do not quote or summarize the concrete contents of private or copyrighted samples.

    line 71
  18. Distinctive:

    keep local-only sample filenames and visual details out of public PR text unless the user explicitly approves publishing that information.

    line 76
  19. Distinctive:

    If Claude starts or delegates work to Codex, include both trailers in the resulting commit, including the model each agent actually used …

    line 83
  20. Distinctive:

    Prefer focused verification tied to the change.

    line 90
  21. Distinctive:

    If a check fails because ignored/generated WASM is stale, rebuild WASM before assuming the source change is broken.

    line 112
  22. Very specific:

    Before running parser-backed integration tests, Storybook, or VRT, rebuild generated WASM (pnpm build:wasm or the per-package command) …

    line 115
  23. Distinctive:

    Do not retain or add tests merely as a precaution, to preserve a test count, or to maintain a coverage percentage.

    line 126
  24. Distinctive:

    Delete implementation copies, tests that only verify their own mocks or fixtures, and assertions that merely restate type-system or …

    line 129
  25. Distinctive:

    Avoid asserting private fields, helper call order, source text, or exact internal object shape when an observable contract can express the …

    line 135
  26. Distinctive:

    Do not replace behavior tests with snapshots of implementation details.

    line 137
  27. Very specific:

    Before implementing OOXML behavior, consult the relevant documents under the local spec/ symlink.

    line 153
  28. Distinctive:

    Prefer ECMA-376 / ISO-29500 behavior over sample-specific tuning.

    line 160
  29. Distinctive:

    Do not add heuristics only to improve one VRT/sample number, such as arbitrary thresholds, empirical scaling constants, or special-casing a …

    line 161
  30. Very specific:

    When behavior differs from Word/Excel/PowerPoint, first check whether the parser discarded necessary information during parsing, …

    line 166
  31. Distinctive:

    If information is missing, extend the parser/model instead of guessing in the renderer.

    line 168
  32. Distinctive:

    If Office behavior is not fully specified and requires reverse engineering, explain that explicitly and ask for user approval before adding …

    line 170
  33. Distinctive:

    If a temporary heuristic is unavoidable, mark it clearly in code with the missing spec/implementation work and track it for removal.

    line 173
  34. Distinctive:

    When an investigation settles a rule, incorporate it and its essential rationale into the responsible source before declaring the work …

    line 188
  35. Distinctive:

    Create them in a task-owned temporary directory outside the checkout by default.

    line 193
  36. Distinctive:

    Before cleanup, inspect contents, tracked status, symlinks, and active-task ownership.

    line 200
  37. Distinctive:

    Treat one package's bug as a signal to inspect the sibling packages.

    line 210
  38. Very specific:

    If the concept is shared, fix the shared layer (packages/ooxml-common or packages/core) where possible.

    line 211
  39. Distinctive:

    Do not duplicate pure parsing predicates or common type definitions across packages unless the format truly diverges.

    line 213
  40. Distinctive:

    Avoid false abstraction. Renderer logic that is tightly coupled to a package's layout model may stay local.

    line 215
  41. Distinctive:

    Before declaring an OOXML feature or bug fix complete, perform an adversarial review of the final diff.

    line 222
  42. Distinctive:

    Specification fidelity: Verify the implementation against the applicable ECMA-376 / ISO-29500 rule and Microsoft extension notes.

    line 227
  43. Distinctive:

    No unexplained heuristics: Search for sample-specific branches, magic thresholds, empirical scale factors, path/name checks, and renderer …

    line 232
  44. Distinctive:

    Remove them or justify them under the OOXML Implementation Policy.

    line 234
  45. Distinctive:

    Bounded inference for implicit behavior: When Word, Excel, or PowerPoint behavior is not fully specified, base the inference on …

    line 236
  46. Distinctive:

    Regression evidence: Run focused behavioral tests plus the broadest proportionate cross-package checks.

    line 259
  47. Very specific:

    When using a Codex/Claude worktree, copy local private stories/samples from the main local checkout if needed.

    line 280
  48. Distinctive:

    Before using Storybook for parser-backed samples, rebuild WASM from the current worktree source:

    line 285
  49. Distinctive:

    Use those prefixes when fetching sample files.

    line 306
  50. Very specific:

    demo: every file under packages/<fmt>/public/demo/ (tracked).

    line 326
  51. Very specific:

    private: every file under packages/<fmt>/public/private/<fmt>/ (gitignored).

    line 328
  52. Very specific:

    Run pnpm vrt:fidelity alongside the self-VRT for every renderer change, so main always passes its own ratchet.

    line 390
  53. Distinctive:

    Only update references when the user explicitly asks:

    line 404
  54. Very specific:

    Do not automatically update files under packages/*/tests/visual/references/.

    line 410
  55. Very specific:

    use as Type assertions instead of postfix non-null assertions,

    line 428
  56. Very specific:

    use canvas for canvas-backed viewers (DocxViewer, PptxViewer),

    line 429
  57. Very specific:

    use container for container-backed viewers (XlsxViewer),

    line 430
  58. Distinctive:

    avoid documenting private/local-only sample paths as public API.

    line 431
  59. Distinctive:

    Keep announcements concise and user-facing:

    line 433
  60. Distinctive:

    write first for readers who do not know the implementation: lead with the visible outcome and group low-level fixes by the user problem …

    line 435
  61. Very specific:

    If a technical qualification is useful, put it in a final Technical note section after the outcome and migration guidance.

    line 440
  62. Very specific:

    keep version-sensitive bundle measurements on the stable /bundle-size page, not in release announcements.

    line 442
  63. Distinctive:

    do not link API reference details directly to release notes.

    line 444
  64. Very specific:

    When the user asks for a release, prepare a dedicated PR named release/<version> and do all release changes there.

    line 449
  65. Very specific:

    Update README screenshots in docs/images/{pptx,docx,xlsx}.png with pnpm screenshots:readme.

    line 454
  66. Very specific:

    Add a new top CHANGELOG.md section: ## 0.x.0 — YYYY-MM-DD.

    line 467
  67. Very specific:

    After bumping the root version, run pnpm sync:versions to synchronize packages/legacy-office/package.json (the public …

    line 475
  68. Very specific:

    Run cargo check -p ooxml-mcp-server after bumping the MCP server so Cargo.lock follows.

    line 482
  69. Distinctive:

    Create the GitHub Release with notes based on the changelog and a full changelog comparison link.

    line 488

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Agent Instructions

This file is the canonical workflow for AI coding agents working on this repository. Tool-specific files such as CLAUDE.md may add supplements, but they must not contradict this file.

Project

office-open-xml-viewer renders OOXML documents (docx, xlsx, pptx) to browser Canvas. The implementation is a Rust/WASM parser layer plus TypeScript Canvas renderers and viewers.

Important directories:

  • packages/core/ — shared rendering primitives and shared TypeScript helpers.
  • packages/ooxml-common/ — shared Rust parsing/model helpers.
  • packages/docx/ — DOCX parser, renderer, viewer, and tests.
  • packages/xlsx/ — XLSX parser, renderer, viewer, and tests.
  • packages/pptx/ — PPTX parser, renderer, viewer, and tests.
  • site/ — public site.
  • .storybook/ — unified Storybook config.

Standard Development Flow

Use this flow for ordinary bug fixes and feature work:

  1. Start from main and run git pull --ff-only.
  2. If the checkout is dirty, preserve unrelated work before switching or pulling. Prefer git stash push -u -m <clear-message> for work that appears to belong to another session.
  3. Create a feature branch. Use codex/<topic> for Codex work when possible; otherwise follow the repository's existing branch naming.
  4. When creating or entering a Codex/Claude worktree, make the root checkout's ignored spec/ directory available from that worktree as a local symlink. For the standard .claude/worktrees/<name> layout, run:

    ln -s ../../../spec spec

    If the worktree lives elsewhere, create spec as a symlink to the main local checkout's spec/ directory. Do not copy or commit the specification files.

  5. Work with TDD for bug fixes:
    • explore the failing sample or behavior,
    • add a focused failing test,
    • make it pass,
    • refactor only where it reduces real complexity.
  6. Verify with the narrowest meaningful tests first, then broader checks when the touched surface warrants it.
  7. Commit only the intended source/docs/test files. Do not commit private samples or generated local artifacts.
  8. Push the feature branch, create a PR, wait for checks when practical, and merge with a merge commit. Do not squash.

Git and PR Rules

  • Never push directly to main.
  • Use PRs for integration into main.
  • Do not squash merge. Use gh pr merge <number> --merge unless the user explicitly asks for another non-squash strategy.
  • Before git push, set git config http.postBuffer 524288000 if large pushes are expected.
  • Commit messages should match the repository style:
    • subject: fix(scope): ..., test(scope): ..., refactor(scope): ..., etc.
    • body: explain the root cause, the fix, and verification.
    • include specification sections or observed Office behavior when relevant.
  • PR titles, PR descriptions, commit messages, and public docs must be safe for an OSS repository:
    • do not include local absolute paths, usernames, home directories, machine names, or other personal environment details;
    • do not quote or summarize the concrete contents of private or copyrighted samples;
    • describe private-sample-driven work in terms of the implementation problem, the OOXML/Office behavior mismatch, the general class of affected documents, and the verification command or local-only comparison that was performed;
    • keep local-only sample filenames and visual details out of public PR text unless the user explicitly approves publishing that information.
  • Agent-authored commits should include a matching co-author trailer. Include the actual model used for that task; do not hard-code a model name across tasks. Examples:
    • Codex: Co-Authored-By: Codex <model-name> <noreply@openai.com>
    • Claude/Fable: Co-Authored-By: Claude <model-name> <noreply@anthropic.com>
  • If Claude starts or delegates work to Codex, include both trailers in the resulting commit, including the model each agent actually used for that task. This preserves the human-readable provenance of the orchestration layer and the implementation agent.

Verification

Prefer focused verification tied to the change. Common commands:

pnpm test
pnpm typecheck
pnpm build:wasm
pnpm storybook
pnpm build-storybook

For a narrow DOCX renderer fix, a good verification set is:

./node_modules/.bin/vitest run \
  packages/docx/src/cell-border-conflict.test.ts \
  packages/docx/src/cell-border-conflict-render.test.ts \
  packages/docx/src/column-widths.test.ts

./node_modules/.bin/tsc --build --pretty false
git diff --check

If a check fails because ignored/generated WASM is stale, rebuild WASM before assuming the source change is broken.

Before running parser-backed integration tests, Storybook, or VRT, rebuild generated WASM (pnpm build:wasm or the per-package command) whenever parser (Rust) source has changed or packages/*/src/wasm/ may be stale — stale generated WASM can both hide real parser defects and fabricate failures.

Test value and consolidation

For every test, answer: What realistic defect would go undetected if this test were deleted? Compare that protection with execution cost, flakiness, fixture complexity, and the maintenance burden of legitimate refactoring.

  • Do not retain or add tests merely as a precaution, to preserve a test count, or to maintain a coverage percentage. TDD means a focused regression for the actual defect; it does not require keeping every exploratory case.
  • Delete implementation copies, tests that only verify their own mocks or fixtures, and assertions that merely restate type-system or dependency guarantees. Exercise production behavior with an independent expectation.
  • Consolidate overlapping tests under the narrowest meaningful production boundary. Keep a distinct case only when it catches a distinct plausible failure: for example precedence, a real boundary, ownership, or a race.
  • Avoid asserting private fields, helper call order, source text, or exact internal object shape when an observable contract can express the guarantee. Do not replace behavior tests with snapshots of implementation details.
  • Reduce exploratory parameter matrices to representative cases and meaningful boundaries. Parameterizing the same redundant matrix does not reduce its execution cost or improve its value.
  • Shared-helper coverage does not prove each format is wired correctly. Keep focused DOCX/XLSX/PPTX integration cases where their production paths differ; do not repeat the helper's entire input matrix in every format.
  • In a test audit, identify the exact cases to remove or merge, the remaining test that supplies any claimed replacement, and the realistic protection lost. Distinguish unconditional deletion from removal that first requires a replacement. Do not report a static review as measured runtime savings.

OOXML Implementation Policy

Be specification-first.

  • Before implementing OOXML behavior, consult the relevant documents under the local spec/ symlink. Prefer ECMA-376 / ISO-29500 for normative behavior, and Microsoft extension notes such as [MS-DOCX], [MS-XLSX], [MS-PPTX], and [MS-ODRAWXML] when Office-specific behavior or extensions are involved.
  • Record the relevant specification section, schema element, or observed Office behavior beside the implementing source when it materially explains the implementation. A commit body alone is not a durable substitute.
  • Prefer ECMA-376 / ISO-29500 behavior over sample-specific tuning.
  • Do not add heuristics only to improve one VRT/sample number, such as arbitrary thresholds, empirical scaling constants, or special-casing a sample path.
  • A user report like "this line is too long" or "this object is missing" is a hint that an OOXML rule is missing or mis-modeled. Identify the related section and implement the rule for the whole class of documents.
  • When behavior differs from Word/Excel/PowerPoint, first check whether the parser discarded necessary information during parsing, inheritance, or style merging. If information is missing, extend the parser/model instead of guessing in the renderer.
  • If Office behavior is not fully specified and requires reverse engineering, explain that explicitly and ask for user approval before adding a compatibility heuristic.
  • If a temporary heuristic is unavoidable, mark it clearly in code with the missing spec/implementation work and track it for removal.

Source is the durable specification

Express every settled library behavior in production source. Put necessary decision rationale, tradeoffs, evidence boundaries, and intentionally unsupported behavior in concise comments next to the responsible implementation. Distinguish normative specification rules from observed Office behavior and library policy. For an observed rule, record the tested input classes and boundary/counterexample results needed to explain its scope, without private sample contents or paths.

  • Code and these adjacent comments must remain understandable without local experiment files, handoff notes, chat history, PR descriptions, or a separate design document. Tests verify the contract; they must not be its only record.
  • When an investigation settles a rule, incorporate it and its essential rationale into the responsible source before declaring the work complete or deleting the evidence. Do not copy an entire experiment log into comments.
  • Parameter sweeps, generated Office samples/PDFs/images, probe scripts, logs, comparison builds, and scratch notes are temporary investigation artifacts. Create them in a task-owned temporary directory outside the checkout by default. Remove owned artifacts once their conclusions are captured in source and focused regression coverage. Do not accumulate permanent output/ or outputs/ directories as an alternative specification store.
  • Unresolved observations are not established compatibility rules. Record any implemented limitation beside its gate; preserve only the evidence still needed by an active investigation, with an owner and a cleanup point.
  • Before cleanup, inspect contents, tracked status, symlinks, and active-task ownership. Do not delete another task's ongoing evidence, original private samples, specification documents, or maintained VRT references. Never follow scratch-directory symlinks into dependencies or other worktrees for deletion.

Cross-Package Integration

DOCX, XLSX, and PPTX share many ECMA-376 concepts: DrawingML images, srcRect, text runs, paragraph properties, themes, fills, effects, and shape presets.

  • Treat one package's bug as a signal to inspect the sibling packages.
  • If the concept is shared, fix the shared layer (packages/ooxml-common or packages/core) where possible.
  • Do not duplicate pure parsing predicates or common type definitions across packages unless the format truly diverges.
  • Avoid false abstraction. Renderer logic that is tightly coupled to a package's layout model may stay local.
  • Cross-package fixes may touch core / ooxml-common and multiple packages in one PR when that is the coherent unit of work.

Mandatory Adversarial Review

Before declaring an OOXML feature or bug fix complete, perform an adversarial review of the final diff. This review is required even when focused tests and VRT already pass. Record the conclusion and any material evidence in the task handoff or PR description; do not silently waive an unresolved item.

  • Specification fidelity: Verify the implementation against the applicable ECMA-376 / ISO-29500 rule and Microsoft extension notes. Distinguish normative behavior, documented Office extensions, and implementation policy such as resource governance. Do not claim specification support from sample output alone.
  • No unexplained heuristics: Search for sample-specific branches, magic thresholds, empirical scale factors, path/name checks, and renderer guesses. Remove them or justify them under the OOXML Implementation Policy. A passing VRT is not evidence that a heuristic is correct.
  • Bounded inference for implicit behavior: When Word, Excel, or PowerPoint behavior is not fully specified, base the inference on sufficiently varied, Office-produced tests that exercise boundaries and counterexamples—not one private sample. State the observed behavior, the tested range, and the limits of the compatibility claim. Keep the implementation scope no broader than the evidence supports, and obtain user approval before adding a compatibility heuristic.
  • Performance and resource safety: Review asymptotic work, allocation size, decoded and retained memory, cache ownership/eviction, concurrency, worker transfer cost, repeated parsing or decoding, hot paths, and failure cleanup. Reject unbounded fan-out or whole-document work when visible/page-local work is sufficient. Add budget, concurrency, cache, or stress tests where the risk is material.
  • Module boundaries and single responsibility: Confirm that shared OOXML concepts and pure rendering/resource primitives live in ooxml-common or core, while DOCX, XLSX, and PPTX keep only format-specific parsing, layout, orchestration, and painting. Check for duplicated policy, false abstractions, package cycles, and classes/functions that mix unrelated responsibilities.
  • Cross-format wiring: For every shared capability, explicitly inspect DOCX, XLSX, and PPTX integration points. Verify the relevant parser/model, public options, viewer, renderer, cache/loader, worker protocol, error propagation, documentation, and tests for each applicable format. If one format is intentionally excluded, document the format-level reason.
  • Regression evidence: Run focused behavioral tests plus the broadest proportionate cross-package checks. For renderer changes, use the previous renderer as the self-VRT oracle and keep Office-reference fidelity evaluation separate. Investigate every unexplained difference; do not weaken comparison thresholds merely to make the review pass.

Private Samples and Storybook

Private Office samples and local-only sample stories are gitignored and must not be committed.

Typical local-only paths:

  • packages/docx/public/private/docx/
  • packages/xlsx/public/private/xlsx/
  • packages/pptx/public/private/pptx/
  • packages/*/src/*privateDemo.stories.ts

Generated build output such as packages/*/src/wasm/ is also git-ignored and must not be committed; rebuild it instead of copying it between worktrees.

When using a Codex/Claude worktree, copy local private stories/samples from the main local checkout if needed. Avoid copying .DS_Store, temporary Office lock files, screenshots, VRT diffs, or private reference images unless the user explicitly asks.

Before using Storybook for parser-backed samples, rebuild WASM from the current worktree source:

pnpm build:wasm

or per package:

cd packages/docx/parser && wasm-pack build --target web --out-dir ../src/wasm && node ../../../scripts/append-wasm-reinit.mjs ../src/wasm/docx_parser.js
cd packages/xlsx/parser && wasm-pack build --target web --out-dir ../src/wasm && node ../../../scripts/append-wasm-reinit.mjs ../src/wasm/xlsx_parser.js
cd packages/pptx/parser && wasm-pack build --target web --out-dir ../src/wasm && node ../../../scripts/append-wasm-reinit.mjs ../src/wasm/pptx_parser.js

Storybook is unified at the repository root. Static prefixes are:

  • packages/docx/public/ → /docx/
  • packages/xlsx/public/ → /xlsx/
  • packages/pptx/public/ → /pptx/

Use those prefixes when fetching sample files.

In sandboxed agent environments, Storybook's port detection may fail with EPERM while probing 0.0.0.0. Running Storybook outside the sandbox for local verification is acceptable when the user asks to view it.

Visual Regression Tests

VRT is local-only because private samples are not redistributable.

Regression detection must compare the changed renderer with images produced by the previous renderer. It must not use Word/Excel/PowerPoint or PDF reference images as the regression oracle. Keep Office-reference fidelity evaluation as a separate run.

Self-VRT (previous-renderer regression)

There are two self-VRT corpora per package. Both render every file completely and compare exact decoded pixels with the previous renderer's images:

  • demo: every file under packages/<fmt>/public/demo/ (tracked). Captured by pnpm vrt:snapshot and checked by pnpm vrt.
  • private: every file under packages/<fmt>/public/private/<fmt>/ (gitignored). Captured by pnpm vrt:private:snapshot and checked by pnpm vrt:private.

pnpm vrt also runs the package's other visual specs (worker parity, overlays, acceptance checks). Specs that need a private sample load it from public/private/<fmt>/ and skip when it is absent.

Baselines are produced from a clean, detached worktree at the previous-renderer revision, normally the full SHA of the latest origin/main. Snapshot mode rejects a dirty tracked checkout and writes a manifest binding the baseline to VRT_BASELINE_REVISION, the SHA-256 of each input and the exact page/sheet/slide set. The candidate run verifies that manifest and reads the images from the baseline worktree named by VRT_BASELINE_CHECKOUT. Use distinct ports so a candidate server can never satisfy the baseline run:

base=$(git rev-parse origin/main)
git worktree add --detach /tmp/ooxml-vrt-baseline "$base"
cd /tmp/ooxml-vrt-baseline
pnpm install --frozen-lockfile && pnpm build:wasm
VRT_BASELINE_REVISION=$base VRT_PORT=5190 pnpm vrt:snapshot
VRT_BASELINE_REVISION=$base VRT_PORT=5190 pnpm vrt:private:snapshot

cd <candidate-worktree>
pnpm build:wasm
VRT_BASELINE_REVISION=$base VRT_BASELINE_CHECKOUT=/tmp/ooxml-vrt-baseline VRT_PORT=5191 pnpm vrt
VRT_BASELINE_REVISION=$base VRT_BASELINE_CHECKOUT=/tmp/ooxml-vrt-baseline VRT_PORT=5191 pnpm vrt:private

The root scripts run every package without stopping at the first failing one, and still exit non-zero if any package failed. Filter a single package with pnpm --filter @silurus/ooxml-<fmt> vrt (and the matching snapshot script).

A comparison run requires VRT_BASELINE_CHECKOUT and fails closed unless it names the root of a Git checkout whose HEAD is exactly VRT_BASELINE_REVISION and whose renderer is unmodified: no tracked change, and no untracked file outside dependencies and the private corpus. The checkout is re-verified before every item is read, so a baseline that changes mid-run fails. Snapshot manifests record the checkout's real path and each image's SHA-256; the comparison requires both to match, and rejects any symlink below the baseline checkout, so copied, replaced or redirected images are never accepted. The harness runs Git with every GIT_* variable removed. A missing or mismatched baseline fails the run; it is not a successful regression check. Remove the baseline worktree when done.

For the one-time bootstrap of a harness change against a baseline revision that predates it, copy only the allowlisted VRT harness files listed in tests/visual/private-corpus.mjs into the baseline worktree and set VRT_ALLOW_HARNESS_CHANGES=1 for both the snapshot and the comparison run; renderer/parser changes remain forbidden.

Fidelity scores

pnpm vrt:fidelity compares each tracked demo file with its committed images under packages/<fmt>/tests/visual/references/demo/ and applies the fidelity ratchet: a page, sheet or slide fails when its match-% drops more than RATCHET_DROP_PCT below the score recorded in scores.json beside the images. The demo references are adopted renderer outputs, not Office exports, so the ratchet detects drift from the adopted generation. Office PDFs remain the fidelity ground truth.

Run pnpm vrt:fidelity alongside the self-VRT for every renderer change, so main always passes its own ratchet. Record scores only from a clean checkout of committed renderer code: the latest origin/main to resynchronize, or the head of a renderer PR whose score drop has been adjudicated against the Office PDF (recorded in that same PR). Never record from uncommitted work:

UPDATE_SCORES=1 pnpm vrt:fidelity

This rewrites only scores.json, never the reference images. Commit the re-recorded scores as their own change that names the source revision. Never loosen RATCHET_DROP_PCT or FAIL_ABOVE_PCT to make a run pass.

Only update references when the user explicitly asks:

UPDATE_REFS=1 pnpm vrt:fidelity

Do not automatically update files under packages/*/tests/visual/references/.

An exact private self-VRT difference is a detected regression candidate, even when every changed document carries the setting being implemented. Enumerate every changed page, sheet, or slide and adjudicate each one against an Office-produced reference. A manual review counts only when it explicitly compares the candidate and previous renderers with that Office output, or when the user explicitly adjudicates the difference. Never approve a group of differences solely because the affected files share a feature flag or OOXML element. If neither an Office reference nor user adjudication is available, report that item as unadjudicated rather than calling the VRT successful.

Documentation and Public Examples

Public docs and commit messages should be written in English.

README, docs, and Storybook public-facing code examples should:

  • use as Type assertions instead of postfix non-null assertions,
  • use canvas for canvas-backed viewers (DocxViewer, PptxViewer),
  • use container for container-backed viewers (XlsxViewer),
  • avoid documenting private/local-only sample paths as public API.

Keep announcements concise and user-facing:

  • write first for readers who do not know the implementation: lead with the visible outcome and group low-level fixes by the user problem they solve;
  • state explicitly whether migration is required. When it is, give the minimum steps and name any changed default or behavior; when it is not, say so plainly;
  • omit implementation detail that does not change a user's decision or action. If a technical qualification is useful, put it in a final Technical note section after the outcome and migration guidance;
  • keep version-sensitive bundle measurements on the stable /bundle-size page, not in release announcements;
  • do not link API reference details directly to release notes. Use a stable reference page when more detail is necessary.

Release Workflow

When the user asks for a release, prepare a dedicated PR named release/<version> and do all release changes there.

Release checklist:

  1. Update README screenshots in docs/images/{pptx,docx,xlsx}.png with pnpm screenshots:readme.
  2. Review README against the current implementation:
    • ESM-only package format,
    • install/import examples,
    • feature support table,
    • bundle-size notes,
    • deprecated API or stale version references.
  3. Sync public API documentation:
    • site/src/lib/api-reference.ts,
    • site/src/components/Capabilities.astro when capabilities changed.
    • site/src/pages/bundle-size.astro with the latest production measurements. Measure with node scripts/measure-bundle-size.mjs after pnpm build:wasm && pnpm build.
  4. Add a new top CHANGELOG.md section: ## 0.x.0 — YYYY-MM-DD.
  5. Bump all versions consistently:

    • root package.json,
    • packages/{core,pptx,xlsx,docx,markdown,node,vscode-extension}/package.json,
    • site/package.json,
    • packages/mcp-server/Cargo.toml.

    After bumping the root version, run pnpm sync:versions to synchronize packages/legacy-office/package.json (the public @silurus/ooxml-legacy-office package), its exact @silurus/ooxml peer pin, and the compiled companion runtime version. Run pnpm install --lockfile-only and pnpm check:versions; CI and publishing reject any mismatch. Both npm packages publish from the same tag, viewer first; retries skip exact versions already present on npm.

  6. Run cargo check -p ooxml-mcp-server after bumping the MCP server so Cargo.lock follows.
  7. Open PR chore(release): 0.x.0.
  8. Merge with gh pr merge <number> --merge or another non-squash strategy.
  9. Pull main, create and push the annotated tag: git tag -a v0.x.0 -m "v0.x.0" and git push origin v0.x.0.
  10. Create the GitHub Release with notes based on the changelog and a full changelog comparison link.

Reference images under tests/visual/references/ are outside the release checklist unless the user explicitly asks to update them.

VS Code Extension Release

The VS Code extension version should match the npm library version. Pushing a v* tag triggers .github/workflows/publish-vscode-extension.yml to publish the extension. For manual packaging checks, use the workflow dispatch dry run.

Download now (ZIP)

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository2 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.