Skip to content

Word task pane: a spike that boots, and reads its own limits correctly - #87

Merged
peopleworks merged 2 commits into
mainfrom
word-addin-spike
Sep 7, 2026
Merged

peopleworks merged 2 commits into
mainfrom
word-addin-spike

Conversation

@peopleworks

Copy link
Copy Markdown
Owner

Draft on purpose — it has not been loaded inside Word by anybody yet. That is the one question left, and sideloading answers it in a few minutes.

What it proves

Blazor WebAssembly boots in a 340px task pane and the engine runs there. Verified by driving the published page at pane width: 92 words of AI-flavoured text scores 90/100, lists 23 named signals, and says

No verdict at this length. This text is 92 words. The boundary was measured only on texts of 649 words and longer, so no verdict is given — the score is neither evidence that a machine wrote this nor evidence that a person did. Everything below is unaffected.

That is the whole product working in a pane, including the part that refuses to answer.

A third host, not a second product

Every rule, every component and the engine arrive through SignsOfAI.UI. HostCapabilities gets the third entry its own opening comment was written for:

"the day a third host appears… the components do not need revisiting"

It needed a new runtime key rather than reusing the browser's, because "runs 100% in your browser" is false inside Word the same way it was false inside a WPF window.

Why this host is worth more than the others

A task pane is a browser. The engine runs on the machine and the document is never uploaded. Every add-in in this category posts your document to an API; this one has no endpoint to post to.

The manifest asks for ReadDocument, not ReadWriteDocument — so Word itself enforces that this add-in only reads, rather than asking anyone to trust a sentence on a website.

What the spike found by running

  • The published page must reference _framework/blazor.webassembly#[.{fingerprint}].js. Without the placeholder the file name only exists during development and the pane never starts.
  • The shared stylesheet assumes a page with room. In a pane, anything with a minimum width pushes content off the right edge where there is no way to scroll to it.

Not proved, because it needs Word

  • That Word accepts the manifest and shows the ribbon button.
  • That Word.run returns the body of a real document. The call is written and has only ever run against nothing.

src/SignsOfAI.Word/README.md has the sideload steps. The shared-folder catalogue walkthrough from PowerPointWebViewer still applies — we solved that once already.

Named rather than forgotten

PowerPoint is a separate question

Not a second <Host> entry. A deck rarely clears 649 words, so it would mostly withhold the verdict — correctly. Its honest pitch is the character scan and the named tells, which hold at any length: "does this deck carry a humanizer's fingerprints", not "is this AI".

432 tests.

🤖 Generated with Claude Code

https://claude.ai/code/session_015PEbbiYSNPw7jE3LrPNhyF

peopleworks and others added 2 commits September 7, 2026 18:38
The most requested idea, and the cheapest thing that answers the expensive
question: does the engine run inside Word at all.

It does. Blazor WebAssembly boots in a 340px task pane, the shared components
render in one narrow column, and the analysis runs there. Verified by driving
the published page in a browser at pane width: 92 words of AI-flavoured text
scores 90/100, lists 23 named signals, and says

  No verdict at this length. This text is 92 words. The boundary was measured
  only on texts of 649 words and longer, so no verdict is given.

which is the whole product working, including the part that refuses to answer.

This is a third host, not a second product. Every rule, every component and the
engine arrive through SignsOfAI.UI, and `HostCapabilities` gets the third entry
its own opening comment was written for — "the day a third host appears, the
components do not need revisiting". It needed a new runtime key rather than
reusing the browser's, because "runs 100% in your browser" is false inside Word
the same way it was false inside a WPF window.

Why this host is worth more than the others: a task pane IS a browser, so the
engine runs on the machine and the document is never uploaded. Every add-in in
this category posts your document to an API. The manifest asks for ReadDocument
rather than ReadWriteDocument, so Word enforces that this one only reads instead
of asking anyone to trust a sentence on a website.

Two things the spike found by running, which is what a spike is for:

  - The published page must reference the fingerprint placeholder. Without it
    the file name only exists during development and the pane never starts.
  - The shared stylesheet assumes a page with room. In a pane, anything with a
    minimum width pushes content off the right edge, where nobody can scroll.

Not proved, because it needs Word itself: that Word accepts the manifest, and
that Word.run returns the body of a real document. That call is written and has
only ever run against nothing. Sideloading takes a few minutes and the README
says how — the shared-folder catalogue walkthrough from PowerPointWebViewer
still applies, since we solved it there.

Deliberately left for later, and named rather than forgotten: boot.js — the 503
retry from #73 and #74 — lives in SignsOfAI.Web/wwwroot and is not used here. A
pane that hangs inside Word is worse than a tab that hangs, so it should move
into the shared library before this ships. The Pages workflow does not publish
/word/ yet either.

PowerPoint is a separate question, not a second Host entry. A deck rarely clears
649 words, so it would mostly withhold the verdict — correctly. Its honest pitch
is the character scan and the named tells, which hold at any length: "does this
deck carry a humanizer's fingerprints", not "is this AI".

432 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015PEbbiYSNPw7jE3LrPNhyF
Sideloading the add-in answered the spike's first question and exposed the gap
the spike had named. Word accepts the manifest and puts "Read the signs" on the
Home tab; the pane opens. What it then showed was the web app's navigation and
"Sorry, the content you are looking for does not exist", with Word warning that
the add-in may not load properly.

None of that was the add-in. SourceLocation points at
peopleworks.github.io/SignsofAI/word/index.html, deploy-pages.yml published only
SignsOfAI.Web, and so that URL answered 404 — verified directly. Pages served its
SPA fallback, the web app's Blazor router has no route for /word/index.html, and
said so correctly. Word's warning was the 404. It was not, as it looked from the
outside, anything to do with the machine it ran on.

The workflow now publishes this project into /word/ with its own rewritten base
href, and fails the deploy when that entry point is missing. A task pane is
loaded by URL from inside Word, where a 404 surfaces as "this add-in may not load
properly" rather than as a missing page — which is a long way from the failure,
so it is worth failing here instead of finding out in Word a second time.

The whole deploy was simulated locally before pushing: publish both, rewrite both
base hrefs, copy the pane under /word/, serve the result, and load
/SignsofAI/word/index.html. It boots there, with the pane's own base href, and
renders its own page rather than the web app's.

Measured while there: first load is 3.4 MB compressed, of which 2 MB is ICU data.
That cannot go away via InvariantGlobalization — it would silently change how
Spanish is handled — so trimming ICU to the locales this needs is the next look.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015PEbbiYSNPw7jE3LrPNhyF
@peopleworks

Copy link
Copy Markdown
Owner Author

The first sideload: it loads, and it found the gap this PR had named

Pedro sideloaded it into Word on the web. Two results, and the second is not what it looked like.

Word accepts the manifest. The ribbon shows a Signs of AI group with a Read the signs button, and the pane opens over HTTPS. That is the spike's first unknown, answered.

The pane showed the wrong page, plus Word's "This add-in may not load properly". It looked like a flaky local environment. It was not:

GET https://peopleworks.github.io/SignsofAI/word/index.html  →  404

SourceLocation points there, deploy-pages.yml published only SignsOfAI.Web, so Pages answered with its SPA fallback — the web app's index.html — whose Blazor router has no route for /word/index.html and correctly rendered Not found. Word's warning was the 404.

This is exactly the gap the PR description listed as "the Pages workflow does not publish /word/ yet", reaching a user before it reached a fix.

Fixed

deploy-pages.yml now publishes this project into /word/ with its own rewritten <base href>, and fails the deploy when that entry point is missing. A task pane is loaded by URL from inside Word, where a 404 surfaces as an add-in error rather than a missing page — a long way from the cause, so it is worth failing at the deploy instead of in Word a second time.

Verified by simulating the whole deploy locally — publish both apps, rewrite both base hrefs, copy the pane under /word/, serve it, load /SignsofAI/word/index.html. It boots there and renders its own page:

banner: Signs of AI Writing · EN | ES
This pane is open outside Word, so there is no document to read.
footer: built with .NET 10 and Blazor WebAssembly · runs inside Word, on this machine

Still untested

That Word.run returns the body of a real document. The call is written and has only ever run against nothing, because the page containing it never loaded. Worth re-sideloading once this merges and Pages deploys.

The test document in the screenshots is 357 words, which is below the 649-word floor — so the expected result is a score with no verdict, and the named signals underneath.

Measured while in there

First load is 3.4 MB compressed, 2 MB of which is ICU data. That cannot be dropped with InvariantGlobalization — it would silently change how Spanish is handled — so trimming ICU to the locales this needs is the next look.

@peopleworks
peopleworks marked this pull request as ready for review September 7, 2026 22:58
@peopleworks

Copy link
Copy Markdown
Owner Author

Out of draft. The reason it was one — "nobody has loaded this in Word" — no longer holds: Word accepts the manifest, puts Read the signs on the Home tab, and opens the pane. The 404 that made it show the wrong page is fixed and verified by simulating the whole deploy locally.

The last unknown, Word.run returning a real document's body, can only be tested after this merges, because the page containing that call has to be deployed for Word to load it. That is the chicken-and-egg this PR resolves.

Risk, since merging this deploys

Only one file touches production: deploy-pages.yml. Everything else is a new project nothing depends on, plus two additive locale keys and one HostCapabilities entry.

If publishing the pane fails, or its entry point is missing, the job fails and no deploy happens — the live site keeps serving what it serves today. There is no path where this half-deploys.

After merging

  1. Wait for the Pages deploy (it runs on push to main).
  2. Confirm the URL is real: https://peopleworks.github.io/SignsofAI/word/index.html should be 200, not 404.
  3. Re-sideload the manifest in Word and press Read the signs.

With the 357-word test document, the correct result is a score with no verdict — the boundary was measured on texts of 649 words and longer — and the named signals listed underneath. If the verdict is withheld and the signals appear, Word.run works and the spike is finished.

@peopleworks
peopleworks merged commit db617c7 into main Sep 7, 2026
4 checks passed
peopleworks added a commit that referenced this pull request Sep 8, 2026
The Word add-in's section and screenshot, which #87 merged without
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant