Skip to content

Releases: ImmersiveFusion/deepcube-docs

Docs hardening.

Choose a tag to compare

@dankoverride dankoverride released this 02 Oct 01:23
79573c1
The Steam notes served a directory listing, not a page (#120)

* fix(routing): the Steam notes served a directory listing, not a page

All eleven of them, and every one is in the sitemap.

https://docs.deepcube.ai/DC/3D/steam/1.9.0 returned 200 with the title "Files
within public/DC/3D/steam/1.9.0/". A file index, not a release note. The same
was true of every version page.

CAUSE, reproduced locally against the real server with the real artifact. serve
resolves a path segment containing dots as a filename: path.extname("1.9.0") is
".0", so it never looks for index.html inside the directory and renders a
listing instead. cleanUrls then 301s /1.9.0/index.html back to /1.9.0/, so the
two rules chase each other and the page is unreachable by any URL.

MkDocs was building all eleven correctly. This was purely the serving layer.

FIX. Renamed the notes to dotless -- 1.9.0.md becomes 1-9-0.md -- which serves
correctly; verified both forms side by side against serve before committing.
Redirects added in both maps so the published URLs keep resolving, and the
IAPM-era redirects are retargeted straight to the new paths rather than chained
through the old ones, which would have made them two hops.

Also turned off directoryListing. A docs site has nothing to gain from serving
a file index, and this failure is exactly why: a listing returns 200, so
anything checking only status codes sees a healthy page.

The routing suite already knew that shape. Its comment says a directory listing
returns 200 "which is how cleanUrls:false shipped past a suite that only
asserted status codes. Check the TITLE." It had no case on these paths, so the
same failure shipped again somewhere it was not looking. Added two, one dotted-
version page and the newest note.

Verified: strict build clean, redirect parity clean, meta descriptions clean,
routing suite green, and by hand -- /DC/3D/steam/1.9.0/ now 301s to
/DC/3D/steam/1-9-0/ which serves the page, and /IAPM/3D/steam/1.9.0/ reaches it
in one hop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* ci: fetch full history so the revision-date plugin can date renamed pages

The Steam rename failed CI. Not the routing change itself: mkdocs build
--strict aborted on eleven warnings from git-revision-date-localized, one per
renamed page.

actions/checkout defaults to a depth-1 clone. A file renamed in the commit under
test has no history at that depth, so the plugin cannot date it and warns, and
--strict turns a warning into a failed build. The plugin's own message names the
fix: "Try setting fetch-depth: 0 in your GitHub Action."

It passed locally because a developer clone has full history, which is exactly
the class of failure that only appears in CI.

Worth noting beyond this PR: the warning is about dates being WRONG, not only
missing. Every page carries a "last updated" stamp from this plugin, and on a
shallow clone that stamp is only as good as the history fetched. This makes
those dates correct rather than incidental.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

Pricing updates.

Choose a tag to compare

@dankoverride dankoverride released this 09 Sep 22:02
3498cf5
Take the prices off the Plans page and point at the storefront (#118)

* docs(plans): take the prices off the page and point at the storefront

Closes #105.

The page carried live commercial terms in a repository that accepts outside
pull requests: per-node prices, node minimums, a volume-discount table with
thresholds and savings percentages, a worked forty-node calculation, and the
annual prepayment discount. A docs PR should not be able to change what the
product costs.

It also duplicated a surface the repo already treats as canonical. Four retired
pages -- Toolkit, the ROI calculator, Offers and Discounts -- already redirect to
immersivefusion.com/pricing. Plans was simply never swept with them, and a
second copy of a price list is a copy that drifts.

Removed with them, per Friday on bus #2337: the Uptime SLA row and the matching
per-plan bullets. The figures did match the finance model, unlike the retired
SLA page's, but an uptime commitment on a public page is a contractual
instrument and nothing establishes it has been approved for publication. Same
reasoning that retired Resources/Legal/sla.md in #104.

Also from #2337: "Enterprise SLA, 50+ nodes" in the plan-choosing table became
"Largest deployments, 50+ nodes". Enterprise is not one of our tiers, and this
is the adjectival use that most likely manufactured the Starter/Professional/
Enterprise set in the first place.

What stays is what a docs page should answer: what each plan does. Throughput,
retention, AI budget, support channels, infrastructure, and which capabilities
each tier includes. Retitled from "Plans & Pricing" to "Plans", since it no
longer carries pricing, and the inbound link from the OpenTelemetry page is
updated to match.

Not verified, and left as found rather than re-asserted: the throughput,
retention and AI query figures. They come from the same finance model as the
uptime numbers and I have no confirmation they are approved for publication.
Flagged rather than silently blessed by touching the page around them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(plans): put the uptime figures back

I removed them against an explicit instruction. Friday's ruling on bus #2337
says, in the WHAT TO DO block:

  "Plans page: rename Free to Start (free). Uptime figures already match
   canon; leave them."

The same reply also said "I would not publish the canon numbers either", and
marked that sentence, in capitals, A FLAG NOT A RULING. It was written about the
legal SLA page in the context of PR #104 retiring it, not about this table.

I promoted the advisory aside over the instruction and removed rows Friday had
told me to keep. The figures match docs/finance/pricing.md line 48 and belong on
a plan comparison: uptime by tier is one of the first things a buyer compares,
and Fuse at 99.99% is a selling point rather than a liability.

Restored: the Uptime SLA row and the three per-plan bullets. The pricing
removals in this PR stand, since those rest on their own reasoning -- commercial
terms in a repository that accepts outside pull requests, duplicating a
storefront the repo already treats as canonical.

Friday's flag is still worth answering, and is worth answering properly rather
than by my unilateral deletion: whether an uptime commitment sourced from a
finance model has been approved for publication is a legal question. Raising it
separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(plans): say that changing tiers costs money

The Changing Plans section walked a user through four steps to switch tiers and
never mentioned a fee. The storefront states a one-time charge for a tier change,
with same-tier node adjustments free. Someone following this page would follow
the steps and be charged without warning.

Found while checking whether dropping the volume-discount tables from this PR
was safe. It was: the storefront carries the per-node prices, the discount above
minimum, the node minimums and the annual prepayment discount, and carries them
more completely than this page did -- it also has Tessa seat pricing and this
fee, neither of which was ever here. The docs copy was a stale subset, which is
the argument for pointing at one surface rather than maintaining two.

The amount is deliberately not repeated here. Naming a figure recreates exactly
the drift this PR removes; saying a fee exists and linking to where it is stated
does not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

Docs and preferences.

Choose a tag to compare

@dankoverride dankoverride released this 09 Sep 16:57
ba66801
Rewrite Preferences from the Unity source (#112)

* docs(3D): rewrite Preferences from the Unity source

The page described a settings dialog that does not exist. It listed audio
volumes, mouse sensitivity, invert-Y, sprint multiplier, VR comfort options,
locomotion type, connection timeouts and a server-region picker. None of those
are in the client, in any form. Twenty of roughly twenty-five rows were marked
"coming soon" or "not yet configurable", which read as a roadmap but described
settings with no counterpart in the code.

Rewritten against PreferencesConfigurationDescriptors on the Unity branch that
introduces them, which declares every preference with a key, label, description,
category, section, control kind, value type and bounds. All twenty-three are
documented here with the labels and descriptions the UI itself uses, so the page
and the dialog say the same words.

The real categories are World, Display, Effects, Assistant and Advanced. Most of
what a user actually tunes is grid behaviour, not engine settings: which blocks
are drawn, whether errored and lost blocks age out, phantom-node detection.

Three things the old page did not say and should have:

Tessa can change twelve of these herself. The descriptors mark them
AgentWritable, and it is deliberately a short list -- redaction, sign-in and the
frame budget are excluded. Marked with an icon and explained once.

Demo mode redacts hosts, URLs and database names. It was not mentioned at all,
and it is the setting to reach for before screen-sharing.

Blocks per frame is the first thing to lower when the client struggles on a busy
grid.

Removed with the rest, and worth naming: "Server Region - Preferred data center
region". That is the same claim retired from the Data Security page in #109.
There is one region, and no user-facing picker exists.

Corrected the reset paths. The product folder is DC, not "Immersive APM" --
ProjectSettings has companyName "Immersive Fusion" and productName "DC" -- which
resolves the SP-074 TODO that was waiting for the shipped app to create it. The
Linux path is dropped rather than guessed: Unity's persistentDataPath on Linux
is not the path that was published, and I could not verify the correct one.

The F10 access line is dropped rather than restated. The dialog is opened from
the scene, not from code, so nothing in source confirms it and I could not
verify it either way.

Not documented: the Graphics, Audio and Comfort categories exist in the
PreferenceCategory enum with no descriptors yet. Those are where volume and
comfort settings will land. Tracked separately rather than pre-announced here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(3D): preferences open on F9, and restore the access line

Founder-confirmed: F9 opens preferences, not F10. The Navigation controls
table said F10 and the Preferences page said "F10 -> Main Menu -> Preferences".

The Preferences rewrite dropped the access line rather than restate a path it
could not verify from source, since the dialog is wired in the scene. It is
back, as the single key it actually is.

Not touched, and worth recording why. The Navigation table also lists
"Console | F12 | Open the developer console". SP-067 finds the McMaster console
unreachable and retires it, which looked like a second stale row -- but F2 of
the same spike says the QFSW Quantum Console is a different system and stays.
Two consoles, one being removed and one remaining, so the F12 row may well be
correct and is left alone rather than removed on a misreading.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(3D): document the function keys, and where they do not work

Founder-confirmed, filling gaps the controls table never had. The help dialog
defines ten key containers; the docs covered six of them and had one wrong.

  F1   Help          was undocumented
  F6   Copy          was undocumented
  F9   Preferences   was documented as F10
  F10  Main menu     was undocumented as itself
  F12  Console       already correct

That explains the old "F10 -> Main Menu -> Preferences" phrasing: F10 does open
the main menu, and preferences used to be reached through it. F9 opens
preferences directly.

Also recorded, and not derivable from the source: F1 and F9 are grid-only. The
lobby and the login screen do not have them and neither dialog opens there. A
reader following the controls table from the login screen would otherwise
conclude the app was broken.

Still undocumented: the help dialog also defines KEY_P, and what it does is not
established. Left out rather than guessed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(3D): drop the UI panel keys that are not a thing

Founder-confirmed: C, L and T are not implemented and are not planned in the
form the table described. They claimed to toggle the AI assistant panel, the log
panel and trace details. None appears in the help dialog's key set, and the
client has no such bindings.

Removed with them: "Toggle Metrics", which had no key at all and a not-yet-
configurable marker. A row with no key, no implementation and no date is not
documentation.

That leaves the UI & Panels table with the two camera-view keys that are real,
M and N.

On KEY_P, which the help dialog defines and which prompted this: the only
first-party reference is PlayerControlsControl.cs line 12, and it is commented
out --

  //public KeyCode ToggleKey = KeyCode.P;

-- so P does nothing in the client while the help dialog still advertises it.
That is a product defect rather than a documentation gap, and it stays out of
the docs until the key does something. The Avatar input map does bind
<Keyboard>/p, but to SecondaryPointerButtonPress in the XR simulator, which is
not a user-facing shortcut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(3D): mark Grid map and Avatar as unfinished

Both descriptors carry ComingSoon = true, which the descriptor documents as a
setting that is present but not finished -- "a dropdown with no options is
normally a defect worth an error; on a setting nobody has finished, it is just
the truth."

The rewrite listed them as working settings with a default. A reader would open
the dialog, find an empty dropdown, and reasonably conclude the client was
broken.

Found while verifying a different claim. The page says Tessa can change twelve
of these, which I had taken from AgentWritable without checking that anything
consumes it. It does: AssistantBootstrapper registers GetPreferencesTool and
SetPreferenceTool as tools, and PreferenceToolGateway enforces AgentWritable on
write and rejects unknown keys. The claim holds.

What the same check turned up is that the gateway computes writability as
"AgentWritable && !ComingSoon", which is what surfaced these two. Neither is
agent-writable, so the robot markers are unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

Region and redundancy clarifications.

Choose a tag to compare

@dankoverride dankoverride released this 04 Sep 02:05
5c385df
Correct two unsupportable claims on the Data Security page (#109)

* docs(legal): correct two unsupportable claims on the Data Security page

Both were live on a legal page, which is where a buyer's counsel reads them.

DATA RESIDENCY. The table listed "European Union | Available (Enterprise)".
There is no EU infrastructure: a region inventory across IF.GitOps,
services.json and the architecture docs finds East US carrying effectively
everything, East US 2 carrying only the Azure OpenAI deployment, West US
appearing solely as a worked example in README and RUNBOOK under "Adding a
region", and zero references to any EU region token.

The claim was not fabricated so much as mis-tensed. We can provision in
additional regions where the required services and capacity exist; no customer
has asked, so none is deployed. "Available" said it was ready today.

Rewritten to state what is true now (stored and processed in the United
States, AI-assisted features in a separate US region) and to put other regions
where they belong: on request, subject to availability and capacity. The tier
gating is gone too; "Enterprise" is not one of our tiers.

MULTI-REGION DR. Removed "Multi-region deployment for redundancy and disaster
recovery" from Infrastructure Security. One region is deployed. Having a
documented procedure for adding a second is not operating across two, and
unlike the residency row this one is not rescued by being able to provision on
request: it is a present-tense claim about the running architecture.

Verified before pushing: mkdocs build --strict succeeds, redirect parity and
meta-description checks pass, and the built page shows the new wording with a
resolving contact link and no remaining instance of the removed claims.

Not changed: Data-Security/.pages keeps hide: true. Unhiding is craft and mine,
but not in the same change that corrects the claims on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(legal): restore multi-region as a capability rather than deleting it

The previous commit removed the multi-region bullet outright. That was
inconsistent with how the same commit handled the residency row: both were
present-tense claims about a state we are not in, and the residency one was
re-tensed to a capability while this one was deleted. Same defect, two
treatments.

The capability is real. What was not true is the tense: under a list headed
"DeepCube is hosted on enterprise-grade cloud infrastructure with:", the
original wording reads as describing the running deployment, so a reader
concludes failover exists today. It does not.

Restored as "Multi-region capable - additional regions can be provisioned for
redundancy or data residency, subject to service availability and capacity."
That claims what we can do without asserting what we currently run, and it
matches the residency wording in the same file.

Deleting it undersold a genuine capability, which is its own kind of
inaccuracy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

Release notes.

Choose a tag to compare

@dankoverride dankoverride released this 31 Aug 06:05
docs(release-notes): 1.18.8 ships, and Steam catches up on eight tags

1.18.0 was the last Steam post, so the Steam note rolls up 1.18.1 through
1.18.8: Tessa drives the Shoebox sandbox end to end, the chat window becomes a
window you can select from, resize, zoom and reopen, and phantoms and error
nodes now say what they are through motion rather than color alone.

Web and Studio get roll-up entries too. Web 3.177.5 is the honest-charts
release: all 32 Insights charts rebuilt against the current telemetry after the
old queries were found rendering plausible but wrong numbers, plus a node
metering fix that had been under-counting multi-grid accounts. Studio 1.4.3 is
the rename and nothing else user-facing.

What is deliberately absent:

- Replay and time travel. The reference docs still say time travel is disabled
  while replay is reworked, and a lot of this range is SP-061 replay work.
  Announcing it would contradict a page we publish.
- Direct3D 12. It did not ship; the switch is parked as PR 3695 because it did
  not move the frame rate and broke the build gate.

whats-new.md also gains June and July, which were never recorded, and retires
its oldest highlight block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Page descriptions and CI work.

Choose a tag to compare

@dankoverride dankoverride released this 31 Aug 02:18
feat(seo): derive a description for every page from its own opening

Closes the defect Dobri reported: every page on the site served the same
meta description, so a Slack unfurl of an installation guide and of the
release notes were indistinguishable. 11 pages were fixed by hand on
2026-08-30. This covers the other 108.

NOT BY HAND, AND THAT IS THE POINT. The Writing Standard (canon,
2026-07-31) already requires the first ~50 words of a page to stand alone as
a summary. Where a page complies, its opening paragraph IS its description;
the text existed and simply was not reaching the meta tag. Sampling eight
untouched pages, seven opened with a usable summary sentence. So the hook
derives rather than invents, and hand-authoring drops from 108 to 3.

hooks/meta_descriptions.py runs on_page_markdown and fills the gap only.
Explicit front matter always wins. It SKIPS rather than guesses when it
cannot produce something honest: an include directive, an admonition, a list
item, anything under 40 characters. A page falling back to a correct generic
string beats one carrying a derived sentence that misleads.

Trademark per Friday's ruling (#2223, clarified #2270): the mark once, on
first appearance, never on every appearance, because "DeepCube Web" and
"DeepCube Studio" are distinct product names and marking the family name
inside them asserts a claim that has not been filed. Written &trade; to
match the &copy; already in mkdocs.yml.

TWO BUGS FOUND AND FIXED BEFORE WIRING IT UP, both caught by reading the
generated output rather than trusting it:

1. Multi-line HTML comments were not tracked across lines, only skipped at
   the opener. Uninstallation/Windows and macOS open with an SP-074 note, so
   the hook would have published "Per R-DOCS-005, docs that quote a shipping
   string stay on the old" as those pages' descriptions. An internal rule ID
   and a rename instruction, to Google. Comment state is now tracked like
   fence state.

2. The character budget measured the SOURCE string. `&trade;` is 7 source
   characters and 1 glyph, so a 159-character source is 153 to a reader. The
   ~155 budget belongs to the rendered snippet, not the markup producing it.
   Now measured with html.unescape, marking happens before truncation, and
   truncation never severs an entity.

THE CHECK NOW ASSERTS THE REAL INVARIANT. The compare pass only inspected
pages that DECLARE a description, so it could not see a page that has none
and silently inherits. That is precisely what shipped. A third pass now
fails any page serving site_description. Of 309 rendered pages, 0 inherit.

The allow-list is two entries and both are named. The homepage legitimately
carries the descriptor. Data-Residency is an EMPTY PAGE: 16 bytes, a heading
and nothing else, published under the legal section, linked from nowhere,
and returning 200 with only site chrome. It has no description because it
has no content, and writing one would describe a page that says nothing.
Tracked as DOC-SP-079, with the CI comment saying to delete the line when
the page gets content or is unpublished. That is a tracked defect, not an
exemption.

Verified: mkdocs --strict green, 41 front-matter blocks parse, 14 compared
and 0 mismatched, 309 checked for silent fallback and 0 inheriting, no
&amp;trade; leaking as literal text, no internal markers in any rendered
description.

The hook produces __pycache__ at build time; .gitignore already covered it
at line 7, so nothing was needed there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Restamps and clean up.

Choose a tag to compare

@dankoverride dankoverride released this 30 Aug 01:32
1.28.10

docs(seo): apply Friday's meta-description rulings, and fix a descrip…

Studio instructions

Choose a tag to compare

@dankoverride dankoverride released this 27 Aug 16:46
Studio ships on macOS, and the install page says it does not

The page opened with "Alpha channel, Windows only" and told readers that only
Windows builds are available and that macOS would follow. The macOS half is
false. Verified against the artifacts rather than taken on report:

  200  release/alpha/DCS.latest.msi
  200  release/alpha/DCS.latest.dmg     <- ships today
  404  beta, both platforms
  404  stable, both platforms

So Studio is alpha-only, which the warning got right, and it is alpha on BOTH
platforms, which it got wrong. The download section offered only the .msi, so a
Mac reader landed on our own install page, read that their platform was not
supported, and left. The build was one link away the whole time.

The warning now says alpha-only across both platforms, the dmg has a download
button, and there is a macOS section.

The macOS steps are sourced, not adapted from the 3D page on the assumption
that the two are alike. The bundle name is DCS.app, read off the dmg pipeline
(IF.APM.App.Avalonia/pipelines/cd-dmg.yml, sourceAppBundleName, with its own
comment recording that Dotnet.Bundle produces it from CFBundleName). The
quarantine removal is the same step 3D's macOS page documents, because it is a
property of unsigned bundles rather than of that product.

Deliberately not copied from 3D: its ring language. 3D is macOS alpha only with
Windows on all three rings, Studio is alpha only on both, and both are correct
for their own product (Friday, bus #2183, founder-confirmed). Nothing here
implies Studio will follow 3D's shape.

Raised by Friday on bus #2182 as the one part of that ask that was not low
priority. The structure mirror in the rest of it is not in this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Site title.

Choose a tag to compare

@dankoverride dankoverride released this 27 Aug 16:07
Read site_name from mkdocs.yml in the routing tests

The rename broke the routing suite, which is the suite working correctly: it
asserts page TITLES rather than status codes, precisely because a directory
listing also returns 200 and that is how cleanUrls:false once shipped past a
status-only suite. It caught the change.

What it should not have done is need a hand edit. The three title cases pinned
the literal string Immersive Fusion Docs, so the brand lived in a test file as
well as in mkdocs.yml, and a rename had to remember to visit both. It did not.
Renaming the site broke CI before it broke anything a reader could see, which
is the good version of this failure, but the next one might not be.

Now read from mkdocs.yml at import. The assertion still does its real job,
which is proving the response is a rendered page and not a directory listing,
and a directory listing will not carry the site name whatever it is called.

This is the rule check-redirect-parity.py already states for the redirect maps,
that there is exactly one reader of mkdocs.yml because a second one that
normalizes differently is how they drift apart. Same reason here.

Verified: the module imports, SITE_NAME reads back as DeepCube Docs, and the
three cases resolve to it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Forward fixes.

Choose a tag to compare

@dankoverride dankoverride released this 27 Aug 15:44
1.28.7

Agree the two redirect maps, and fill the block that was waiting on a…