<feed xmlns='http://www.w3.org/2005/Atom'>
<title>shiftplanner/src, branch main</title>
<subtitle>Shift scheduling for small teams, running entirely in the browser</subtitle>
<id>https://newos.webx11.duckdns.org/shiftplanner/atom?h=main</id>
<link rel='self' href='https://newos.webx11.duckdns.org/shiftplanner/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/shiftplanner/'/>
<updated>2026-11-09T14:36:11+00:00</updated>
<entry>
<title>fix(products): ship the reviewed 1.0.1 builds — the 1.0.0 pdf2txt never ran</title>
<updated>2026-11-09T14:36:11+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-11-09T14:36:11+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/shiftplanner/commit/?id=a3732122a461c9aa654401f6e2c54f168eedaad5'/>
<id>urn:sha1:a3732122a461c9aa654401f6e2c54f168eedaad5</id>
<content type='text'>
A review of all three products in Chromium found defects that only execution exposes.

pdf2txt 1.0.0 DID NOT RUN. Both the packaged file and the live demo contained a duplicated
const declaration inside fetchModels, so the inline script threw a SyntaxError at parse time and
no handler was ever bound: no extraction, no translation, no config. Proven by extracting both
inline scripts from the committed file and from spaces/chatstudio/pdf2txt.html and running
node --check (SyntaxError: Identifier 'config' has already been declared). The two published
versions of this product were dead on arrival.

pdf2txt 1.0.1 also stops writing the API key and the whole extracted document to localStorage
(sessionStorage for the key, nothing for the text), keeps paragraphs (hasEOL), splits chunks on
word boundaries, reports a non-JSON 200 or a missing response field instead of writing "undefined"
into the editor, re-enables Translate after a run, resets stopRequested, stops a workflow on a
failed step, warns on a PDF with no text layer, recognises .PDF, fixes an unterminated mobile
media query, stops the Fullscreen button covering line 1, and makes the drop zone and all 39
controls reachable and named.

shiftplanner 1.0.1 fixes seven demonstrated defects: the settings modal recursed until the stack
overflowed, "+ Worker" prefilled the last edited worker id and overwrote that person, date maths
was off by one west of UTC (local-noon Date formatted with toISOString), same-day and overnight
shift overlaps were never flagged, the generator sliders never reached state.settings, CSV export
could execute a formula and broke on a quote, and the header never wrapped (390 px viewport gave a
1139 px document). Plus four data-integrity guards: unparseable saved plans are copied to a
recovery key instead of silently overwritten, wrong-typed fields are normalised, unknown top-level
fields survive a save, and a storage event syncs another tab.

chat-widget 1.0.1 closes a critical attribute-injection XSS. escapeHtml() round-tripped through
textContent, which does not escape a double quote, so a reply containing
https://x.test/"onclick="alert(1)// produced a real &lt;a onclick=...&gt; and fired alert(1) when
clicked. Proven both ways: the 1.0.0 file fired a dialog, the fixed one renders only
href/target/rel and stays silent. The launcher also covered the Send button at 390 px, so the
widget could not be used on a phone at all.

Also in this commit:
- Landing pages and demos are generated (build-product-pages.py). The "Try the demo" button used
  to point at spaces/chatstudio/pdf2txt.html (the dead copy above) and at a v2.1 shiftplanner with
  no AI panel: a demo that was a different build than the ZIP. Demos are now built into
  /demos/&lt;slug&gt;/ from products/&lt;slug&gt;/, with the ../vendor/ prefix rewritten, and the publish
  wrapper regenerates them before every publish.
- publish-public-repo.py refuses to publish a subtree with uncommitted changes. It reads git, so
  it silently republished the old tip while rc was 0 for every slug.
</content>
</entry>
<entry>
<title>feat(shiftplanner): canonical v2.1 tree, four earlier copies archived</title>
<updated>2026-11-09T14:02:14+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-11-09T14:02:14+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/shiftplanner/commit/?id=ff6155599ccc6b594dd91d0afab32515b5d98f51'/>
<id>urn:sha1:ff6155599ccc6b594dd91d0afab32515b5d98f51</id>
<content type='text'>
Canonical: downloads/shiftplanner-v12-ai.html (md5 37207b22, 136212 B, 2789 lines) — a strict
functional superset of both other v2.x copies, adds the AI panel. The two v1.3 copies keep
drag-and-drop and the richer Ollama wiring; archived with md5s in docs/CANONICAL.md.
</content>
</entry>
</feed>
