rdmsm4x — Desktop ticket ingest, record repair, and first real publish to dev.ecs0.net
When: 2026-08-30 12:23–12:35 EDT · Host: rdmsm4x · Author: claude@rdmsm4x Scope: rdmsm4x only. ~/Desktop, ~/dev/issues, ~/dev/sites/dev.ecs0.net.
Summary
Organized 92 loose ticket reports off the Desktop into
~/Desktop/issues/, repaired four ambiguous ticket records,
fixed three exporter defects, and discovered that no ticket had
ever actually been published to dev.ecs0.net — the export
target was not part of the website. /issues/ now returns
200 with all 85 tickets.
What changed
1. Desktop organized
~/Desktop/issues/tickets/— 85 ticket pages (one per live ticket)~/Desktop/issues/dashboard.html— the rollup dashboard~/Desktop/issues/reports/fleet-sync-audit-report.html- Zero loose ticket HTML files remain on the Desktop.
2. Fixtures kept out of the record
18 Desktop reports were QA fixtures ("CLI Test Feature", "Test rfc",
"Test ui", "Test doc", "CHALLENGER-TEST", empty titles) from the same
family a prior session archived. They were not
ingested. Moved to
~/dev/issues/archive/test-fixtures-20260830/html-desktop/.
Also archived: fleet-lifecycle-dashboard/ (316 mixed
real+fixture exports) and a byte-identical duplicate of the audit
report.
3. Record repair — four ambiguous tickets
ISSUE-20260830-26 reported four tickets simultaneously open and resolved and said choosing a copy needed project judgement. Resolved per ticket:
- ISSUE-20260829-02/03/04 — the open/ copies were
not stale. They carried
parentlinks and un-mangled comments written after resolution; the resolved/ copies carried the closeout. Merged both sides. Deleting the open copies as duplicates would have silently dropped three parent links and broken epic hierarchies. - INC-20260829-01 — the open copy was itself a fixture (all template placeholders, children pointing at archived fixture FEATs) that collided with a real ticket ID. Archived; the resolved copy is authoritative.
- Dropped 6 dangling references to archived fixtures across 5 tickets.
4.
bin/ticket fixes (backup:
bin/ticket.bak-20260830)
- ISSUE-20260830-27 — Desktop export went to
~/Desktoproot, re-cluttering it on every ticket. Now~/Desktop/issues/tickets/; dashboard to~/Desktop/issues/dashboard.html. - ISSUE-20260830-26 —
resolvenow removes everyopen/copy of an ID, not just the same-slug one. - ISSUE-20260830-33 (filed by a peer against the
above fix, valid) — the cleanup sat behind the
old_path.exists()guard, unreachable in the index-drift case it defended.resolvenow falls back to globbingopen/thenresolved/and adopts the on-disk file.
5. ISSUE-20260830-34 — the publish target was never served
bin/ticket exported to
sites/dev.ecs0.net/issues/. That directory is not
part of the website: infra/compose.yaml:37 mounts
../wiki as the nginx docroot, and
build_site.py writes only into wiki/. There
was no wiki/issues at all — never tracked in git, absent
from the source manifest. Every ticket page for days was written
somewhere unreachable while the CLI printed a success line naming the
path.
This corrects ISSUE-20260830-27's claim that 268 fixture pages "were live on the real site." They were never served; the fixture exposure was not public.
Fixed: SITES_ISSUES_DIR repointed to
wiki/issues; 85 pages exported; the orphan tree archived to
issues/archive/never-served-sites-issues-20260830.
6. ISSUE-20260830-35 — my own fix had a data-loss path (peer-caught)
A peer probed the ISSUE-26 fix and found it unlinked every
stray open/ copy unconditionally. Content existing only in
a stray was destroyed — precisely the content I had hand-merged for
ISSUE-20260829-02/03/04 one commit earlier. The commit message
documented the merge while the code discarded.
Fixed: a stray byte-identical to the resolved record is removed
(nothing can be lost); one that differs is moved to
archive/superseded-open-copies/<slug>-<ts>.md
with a warning naming the file. open/ is still cleared, so
status stays unambiguous — that only needs a move, not a delete. Added
the missing import shutil.
Verified by replicating the reporter's probe: the unique marker now
survives in 1 file instead of 0, open/ empty, one resolved
copy.
Verification
curl -H 'Host: dev.ecs0.net' http://127.0.0.1:8788/issues/ -> 200
curl -H 'Host: dev.ecs0.net' .../issues/ISSUE-20260830-34.html -> 200
curl -H 'Host: dev.ecs0.net' .../issues/EPIC-20260830-03.html -> 200
served index lists 85 ticket IDs
store(87) == published site(87) == ~/Desktop/issues/tickets(87); 0 ambiguous
tickets in both open/ and resolved/: 0
Resolve fixes proven in a HOME-jailed probe store (canonical untouched): created a ticket, renamed its open/ file to a different slug without reindexing, ran resolve -> "(index was stale; adopted ...)", open/ empty, exactly one resolved copy.
Verification trap: curl 127.0.0.1:8788
without a Host header hits the gateway's catch-all
(server_name _; location / { return 404; }) and 404s every
path. Public URLs return 302 to Cloudflare Access before the origin is
consulted. Both mask real origin errors — always use
-H 'Host: dev.ecs0.net'.
Backups / undo
~/dev/_backups/issues-index-20260830-1229-premerge.sqlite~/dev/issues/bin/ticket.bak-20260830cd ~/dev/issues && git revert ced12b1 && ticket reindex(plus the ISSUE-35 follow-up commit)cd ~/dev/sites/dev.ecs0.net && git revert fcd185d- Nothing was deleted — every removal was a move into
~/dev/issues/archive/.
Open for the owner
build_site.pyprints "build complete and verified" without fetching any URL, so it cannot fail on a 404. That is why this was silent for days. Not fixed here.wiki/issues/fleet-sync-audit-report.htmllists 38 fixture tickets as real. It is a legitimate historical report also catalogued in the wiki; left in place, flagged.