- The clone exclusion is now '.runner*' (catches .runner_migrated /
.credentials_migrated, which GitHub writes on migrated runners and
which equally trip the already-configured refusal — hit live during
the 2026-07-27 org-group migration).
- The problem statement now states the verdict runs on ubuntu-latest,
scopes the switch to enterprise Linux-pool outages, and names the
residual dependency: node-compat/python-sdk/windows stay standard-
hosted, so a broader hosted-capacity failure still blocks the
verdict, with Windows the only leg lacking any in-house substitute.
Static gate green locally: 32 passed, 0 failed.
config.sh only registers; the runner stays offline until svc.sh
install/start. Both language sides updated so emergency capacity
actually comes online.
- serial-linux-selfhosted checks out fetch-depth 0: depth 2 misses
github.event.before on multi-commit or force pushes, failing the
archive verifier on a valid tree. Full fetch is cheap against the
VM's local mirror.
- Runbook (both languages): every remaining admin phrasing (problem
statement, switch heading, alternatives, consequences) now says
writer; and the 'composes with this mechanism' claim about a
master-ref-pinned runner group is replaced with the truth observed
live on 2026-07-27 — master-ref pinning blocks PR failover, and the
shipped posture is repository-scoped all-workflow group access.
Static gate green locally: 32 passed, 0 failed.
The standby lane itself is push-only, but under failover pull_request
jobs do reach these runners with the PR merge ref's workflow. The
workflow comment and the larger-runner note (both languages) now state
that plainly and name the actual boundary — repository membership
(private, forking disabled, Dependabot excluded) — matching the
runbook. Static gate green locally: 32 passed, 0 failed.
- Sweep every remaining 'admin-only' claim (workflow comments, runbook
lines 13/40, topology note, all zh pairs): the variable is
writer-manageable, and the boundary against untrusted code is
repository membership (private, forking disabled, Dependabot
excluded) — stated identically at every site instead of only in the
'who can flip' paragraph.
- Serial cross-platform reference note (both languages): master now
runs four references — the three hosted OS legs plus the self-hosted
standby drill, linked to the failover runbook.
Static gate green locally: 32 passed, 0 failed.
- serial-linux-selfhosted now fetches depth 2 and passes
DSH_ARCHIVE_BASE_REF=github.event.before, running the same
frozen-archive comparison as serial-linux instead of diffing the
new manifest against itself.
- Runbook (both languages): documents the deliberate dependabot
exception (queued-on-hosted during failover is expected, not a
failed switch); corrects the emergency-capacity bootstrap to
exclude .runner/.credentials when cloning a runner directory; and
replaces the 'admin-only' variable claim with the accurate
trust-model statement — repository variables are writer-manageable,
which in this private fork-disabled repo with an all-workflows
runner group is routing among members, not an escalation.
Static gate green locally: 32 passed, 0 failed.
- All four failover selectors (three workers + the verdict job) and the
paired env/cache expressions now exclude dependabot[bot]: under
failover, dependency-supplied code keeps queueing for the hosted pool
instead of executing on the persistent VM. A delayed Dependabot PR
during an outage is an acceptable cost; dependency code on the
privileged host is not.
- Runbook (both languages): records the shipped failover bounds
(coverage 8, snapshots 12, sized for six instances) and documents
that the verdict job follows the selector too — operators previously
had no explanation for a verdict queued after all workers passed.
- Local static gate green: 32 passed, 0 failed (translation pairing
519 pairs consistent).
The pairing gate requires link target #9 to be byte-identical between
the language sides; my earlier 'fix' pointed the zh side at the zh
runbook and broke the contract. Reverted to the shared target and
re-recorded the pairing hash.
The required windows job moves from windows-2025 to ubuntu-latest, running
checksum-verified Windows Node under Wine at Linux-job wall clock (2m46s
warm vs 7-9min); master's serial-windows native-kernel reference is
untouched, and a new master-only wine-apt-cache job seeds the apt cache
every pull request restores. The experiment workflow folds into ci.yml,
the Agent Note moves to implemented with measured results, and the two CI
topology notes update to the shipped facts.
The spare tier is retired. Steady-state pool load is one serial standby
job per master push, so six always-on instances already are the
failover capacity; pre-registered offline runners are a silently
expiring guarantee (GitHub garbage-collects them after 30 days
offline). Incident-time extra capacity is a one-minute org-token
registration, now documented in the runbook.
Head-to-head replay of the same ten historical examples, both arms in
one time window with identical prompts and pairwise blind judging:
prose quality and cost at parity (stylistic margins only); the shipped
briefing wins two objective outcomes — code-fence-only examples land
byte-identical to the human-reviewed updates with zero model tokens,
and the flagged first-occurrence move reproduces the human-reviewed
gloss relocation the section-only form leaves as a contract violation.
Chinese counterpart brought along via the briefed path and the pair
re-recorded.
The briefing now maps each update at the narrowest safely aligned
granularity, widening deterministically on mapping failure: a change
confined to the pair's byte-identical code fences is computed outright
(--apply splices it into the counterpart and validates the result
against the pairing gate's structural signature before writing);
otherwise changed Markdown units — headings, paragraphs, table rows,
list items, fences, block quotes, HTML blocks, thematic breaks, link
definitions, matched by container-scoped kind sequences — each carry
their last-confirmed source, current source, and current counterpart
text; units that do not align fall back to depth-matched heading
sections (depth only, so translated heading text still maps); and when
sections do not align either, or both sides drifted, the briefing says
so and withholds the mapping. Terminology rows now match the changed
spans only, English terms on word boundaries with plural inflections,
and Chinese-target briefings track each relevant term's document-wide
first occurrence — a moved occurrence pulls the vacated and receiving
spans into the briefing with an explanatory note.
The unit mapping, mechanical code splice, and first-occurrence tracking
adopt the planner design from the incremental prompt-pipeline PR (#684),
whose provider-backed bake-off independently validated the same scope
ladder; this PR carries those mechanics into the agent-facing briefing
path so both consumers of the consistency records behave alike. The
prior line-hunk section mapping and its heading-text alignment (which
could not map cross-language sections) are replaced wholesale.
Docs: SKILL.md update path, i18n README pair, development.md pair, and
the briefed-updates Agent Note pair brought along; the development.md
fence edit was applied with --apply itself, and the prose updates were
made through the new unit/section briefings.
The dsh-translate-docs skill now triages updates onto a briefing-driven
path — gen-translation-brief output as the translator's whole working
set, orchestrator-applied mechanical fence edits, scoped record/check —
while the whole-document path for new pairs is unchanged. The i18n
README documents the scoped gate forms and the briefing tool;
development.md lists the new command; the new bilingual Agent Note
records the decision and the ten-example benchmark behind it (briefed
path ~1/3 the tokens and wall clock of the corpus-loading path at equal
judged quality; whole-document re-translation rejected on preservation
collapse). Counterpart updates in this commit were produced with the
new briefed path; the new note's Chinese side is a whole-document
translation.
Every PR that changes product-user-visible GUI behavior now includes a
demonstration GIF with real provenance (that branch's built tree, real
key, real model rounds). Recording stays side-effect-free; the skill
gains a bounded final publication step: GIFs go on an append-only
orphan assets branch (one per PR series) and embed via the blob URL
with ?raw=true, never on the PR branch itself.
Folds in the operational lessons from the Code Mode UI series:
.playwright-mcp/ screenshot roots (now gitignored), per-PR staging and
precise server teardown, one-call DOM polling for transient states,
exact-text completion predicates, prompt engineering for UI states,
and the export-before-invoke GIF_SKILL_DIR encoder pitfall.
Agent Note: implemented/process/2026-07-26-gui-pr-gif-evidence-and-assets-branch (+ zh pair); the 2026-07-23 recording note now defers publication policy to it.
Responding to ds-review-bot round 2 on #662:
- LANG_ALIASES is a Map: an assistant-authored fence label like
constructor or __proto__ now misses (plain render) instead of resolving
an inherited object property and crashing shiki mid-conversation. Test
sweeps the inherited-key labels.
- The singleton is pre-warmed in a deferred task at plugin boot (the
~120-175ms engine+grammar construction long task moves off the first
finalized fence's render); the lazy path remains the correctness
fallback, and unref keeps non-browser imports from pinning the loop.
Agent Note updated (both languages).
A repo-wide Not Invented Here audit (ten parallel domain surveys covering
every package group, scripts/, native/, vendor/ edges, python/, test
infrastructure, and CI) asked of each hand-rolled surface whether a
maintained external package or Node builtin deletes it with a net win.
Policy: new implemented process note records that a dependency which
genuinely deletes owned code is a preferred simplification (bar: net
deletion, health, boundary fit, settled seams stay); root AGENTS.md
carries the one-line rule and dsh-find-simplifications now surveys for
hand-rolled-where-a-dependency-exists candidates.
Findings, all bilingual from birth:
- proposed/simplification: eventsource-parser for llm-deepseek SSE,
node:timers/promises for three hand-rolled sleeps, turndown (or
minimal 'entities') for tool-web HTML->markdown, gate-script
consolidation onto mdast/parseArgs/globSync
- proposed/testing: execa + parseArgs + loadEnvFile + vi.waitFor for
hand-rolled test subprocess plumbing
- proposed/process: pnpm/action-setup for symmetric CI caching
- proposed/feature: evaluate landstrip before building a Windows
sandbox launcher
- rejected/simplification: ~30 swap verdicts recorded (vscode-jsonrpc,
p-retry, Ajv, write-file-atomic, msw, hono, better-sqlite3, wireit,
landstrip-for-linux, YAML consolidation, ...) so the survey is not
re-litigated from scratch
Also drops the stale prompt/ entry from the AGENTS.md layout map
(workspace instructions live in packages/context/workspace-context).
One highlighter for the client: a synchronous fine-grained shiki core
(JS regex engine, no WASM) in ui-primitives with an explicit grammar
allowlist (typescript, shellscript, json — aliases resolve, unknown
languages take a geometry-identical plain arm). The shared CodeBlock
component owns both arms; markdown fences, the run_code expanded
program body (typescript), and the details panel Input (json) all
route through it. Token colors live in a new ui-theme shiki.css sheet
as --shiki-* custom properties (light/dark blocks), wired through the
shell's base.css chain — tokens-only styling holds; shiki's generated
span tree is the sanctioned innerHTML path (static output, no user
HTML). jsdom specs pin token spans, aliases, both fallbacks, and the
fence route; the built-bundle snapshot asserts the highlighted program
under the code row.
Review round on the pivoted design:
- node-24 (static) kept an unconditional hosted pnpm cache restore while the
coverage and consumers lanes skip it under failover. On the self-hosted VM
that restore downloads ~180 MB into /home/runner, a path pnpm never reads
there, adding latency and contention during an outage. Gate it with the same
`vars.DSH_CI_FAILOVER != 'selfhosted'` condition so all three lanes match.
- Runbook switch step 2 said "Re-run failed jobs", but the documented
indefinite-queue outage leaves jobs queued (not failed), which cannot be
re-run in place and do not retarget on variable change. Correct both language
sides to cancel the run and re-run all jobs, or push a new commit.
- The standby-lane comment still described the switch as a one-line runs-on
change; it is now setting the admin-only DSH_CI_FAILOVER variable.
The failover runbook landed as .agents/notes/implemented/process/ci-failover-runbook.md,
which fails three doc-sync gates: the classification/format gates require a
yyyy-mm-dd-topic.md filename and the implemented Agent Note skeleton
(Problem/Decision/Alternatives/Consequences), and the bilingual pairing gate
requires cross-note link targets to match between the two language sides.
Rename to 2026-07-26-ci-failover-runbook.md/.zh.md, reshape both sides into the
implemented skeleton (the runbook steps live in bespoke sections under Decision),
point the sibling topology note and the ci.yml comment at the dated filename, and
make both sides link the canonical .md per the bilingual convention. Re-recorded
the i18n pairing records.