- Node index: a Route pick the Finder refuses no longer falls back to
focus, which cleared the active Route.
- Schemas keep accepting retired meta.views (ignored) so existing
schema 1/2 files still validate, per the 2.x compatibility contract.
- Rail comfort check measures node label sizes directly, so the 12px
default-collapse rule covers all five diagram types.
- Rail choices live in memory first; blocked localStorage no longer
freezes collapse/expand/placement.
- Escape-collapsing the overlay rail returns focus to the reveal control.
- Oversized raster exports downscale below 1x instead of allocating a
canvas over the pixel cap.
- README and Gallery drop removed chapter-playback links and copy;
README demo captures and live-proof GIF re-recorded on the new shell.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
UI/UX only, re-cut from dev so no renderer or authoring-rule changes ride
along (those made diagrams noisier in real use and were dropped).
- Reader shell: system UI type, grouped toolbar that scrolls with the page,
refined style/export menus and navigation dock (Guide on "?", Map only
when zoomed), plain-language Path copy and compact picking panel.
- Summary rail with node index for every diagram: right by default,
collapsible, movable to the bottom, remembered per browser, and
collapsed when docking would shrink primary text below 12px.
- Raster exports reproduce the Viewer page without controls (title row,
canvas card, margins); background now covers non-zero viewBox origins.
- Canvas keeps dev's diagram colors and strokes; classic adds only a quiet
dot field and lifted nodes.
- Remove guided views and story playback (breaking): meta.views is no
longer accepted and fails with "remove unsupported property views".
- Skill: each diagram request goes into .archify/<type>-<slug>-<timestamp>/.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Drive the README parity checks from one per-language table so the
Japanese README is held to the same contract as the English and Chinese
ones: switcher completeness, brand mark and demo placement, the animated
proof, share-card and real-repository proofs, the Hermes Agent and DSH
installation rows, and the Star History ending. check-release-identity
now validates the Japanese version badge, a Japanese-language
development/stable marker, and the Raven manual-ZIP boundary.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YPwjsicFpC7T1Enc5fPo5s
A portrait diagram with conclusion cards could never reach a stable
layout: measure() derived the stage width from the current card height,
settle() narrowed the stage to remove the resulting overflow, the cards
rewrapped shorter at that width, and measure() widened again. The joint
layout wait then timed out and visual-check reported a Chrome runtime
failure instead of a layout verdict, so an author had nothing to repair.
Cap measure() at the widest reader the overflow settle has accepted for
the current viewport; a resize lifts the cap. Card height is monotonic in
reader width, so shrinking only converges.
While here, make the vertical overflow receipt actionable: visual-check
now measures the stacked page blocks (body padding, header, guided views,
diagram chrome, SVG, cards) and states the pixel budget and the concrete
target (maximum viewBox height at the minimum reader width, or why the
Reader cannot narrow a sub-1.55 ratio canvas) instead of "contain the
rendered layout within 1440x900".
Measure desktop readability against the declared wide Reader contract so
compiler-fit architectures are judged on the projected text size a reader
actually sees, and report edge and boundary labels as their own owners with
an executable reflow fix. The viewer exposes Archify.layoutStability so
visual-check waits once for reader layout, viewer chrome, and font settling
instead of four fixed waits, and slow Chrome startup is reported as an
environment failure rather than a candidate defect.
Renderer, viewer, and visual-check portion of tt-a1i/archify@d21948a7 and
@95170f3f (labs/first-draft-cost-20260918). Tests adapted to dev: fixtures
carry meta.output, the joint-wait contract exercises visual-check instead
of the deferred browser-check, and examples reference dev's shipped files.
Wrap each automatically routed connection and its crossover mask underlay
in one presentation-only group so the delivery checker finds adjacent
underlays in a single forward SVG scan, and reader states (focus, reach,
route journey, story beats, lens, motion) dim or emphasise the mask
together with its one semantic edge. Graph traversal and exports still
observe exactly one edge per relationship.
Renderer and viewer portion of tt-a1i/archify@31fa93c5
(labs/first-draft-cost-20260918), re-applied to the split viewer.css.
Mirrors the Raven path: WorkBuddy is installed by copying archify/ into
~/.workbuddy/skills/archify, so it is documented in README, the start
page, and the landing meta description, but is intentionally not added as
a generated agent-switcher command or a data-agent tab.
Updates the bilingual onboarding assertions to match the new agent list.
Closes#310, #277, #343.
preview.mjs (fix#310)
- Resolve the watched directory with fs.realpathSync.native() before
handing it to fs.watch. On Windows, 8.3 short names and junction
aliases crash libuv's ReadDirectoryChangesW with EINVAL; the native
realpath variant expands short names to their NT form and is a no-op
on POSIX, so it's safe on every supported platform.
- Export resolveWatchTarget() so it can be unit-tested directly.
- Fall back to path.resolve() on ENOENT/EACCES/EPERM so the polling
timer (already in place) still detects changes on read-only
checkouts.
export.js (fix#277)
- fitCanvasText() now checks document.fonts.check('700 16px
"JetBrains Mono"') before measuring. If the bundled face hasn't
decoded yet (offline load, strict CSP, slow data: URL decode), force
the same ui-monospace, SFMono-Regular, Menlo, Consolas fallback the
SVG layer already renders, so Canvas width and SVG layout stay in
lockstep and the share-card title stops silently overflowing.
- New fontsLoaded() helper guards with typeof document.fonts and
typeof fonts.check so the path returns true on engines without the
Font Loading API, preserving original behavior.
template.source.html / tokens.css / generate-viewer.mjs (fix#343)
- Extract the 2,958-line THEME VARIABLES block from
viewer/template.source.html into viewer/tokens.css, dedented to
column 0 so it can be edited like a real CSS file.
- Build script now treats fragments uniformly: JS fragments keep
indent:0 (byte-identical concatenation) and tokens.css gets
indent:4 so it sits inside the surrounding <style> block at the
correct depth. The inlined output is byte-identical to the previous
monolithic template apart from the new export.js additions.
- generate-viewer.mjs strips the trailing \n after an indented
marker so the seam doesn't introduce a blank line between the
inlined fragment and the surrounding CSS.
Tests
- archify/test/resolve-watch-target.test.mjs (new): happy path,
missing-target fallback, export shape.
- archify/test/offline-font-fallback.test.mjs (new): pins the
document.fonts.check usage, the monospace fallback stack, and the
safe-return path.
- archify/test/generate-viewer.test.mjs: extended the literal-
replacement-tokens test to include the new tokens.css marker with
its reindent contract, and added tokens.css to the "editing any
authoritative source requires explicit regeneration" loop.
Derived fixtures (gallery, packaged examples, archify.zip,
docs/assets/archify-live-proof.json, examples/checkout-platform-
delta.{html,receipt.json}, examples/web-app.html) were regenerated
to reflect the new template bytes.
Full suite: 1306/1306 pass, 0 failures, 48 skipped (Chrome-only).
* fix(packaging): accept Windows-style absolute output paths in build-zip.sh
On Git Bash, `scripts/build-zip.sh C:\path\out.zip` (or `C:/...`) exited
with ENOENT: the script treated any path not starting with `/` as relative
and prepended `$(pwd)/`, and MSYS then handed Node a mixed path such as
`D:\repo\C;C:\Program Files\Git\Users\...`. Skip the prefix for drive paths,
which Node resolves natively, and add a win32-only regression test.
The repository's own package-gate tests pass os.tmpdir() paths, so on a
clean Windows checkout two of them failed before building anything.
* fix(packaging): record Git index modes so archify.zip reproduces on Windows
scripts/write-deterministic-zip.mjs derived each entry's mode from
fs.stat(), but NTFS cannot store an executable bit: after the stager's
chmod(0o755), stat() still reports 0o666 on Windows, so
archify/bin/archify.mjs (index mode 100755) was written as 0644 and the
archive differed from the committed bytes in four central-directory
bytes while every payload matched.
The stager now records every staged file's Git index mode in a manifest
outside the staged tree (--mode-manifest), the writer requires that
manifest and fails closed when it disagrees with the staged files, and
build-zip.sh passes it between them. Linux bytes are unchanged; together
with the output-path fix in the previous commit, a Windows rebuild is now
byte-identical to archify.zip.
Refs #384
* fix(packaging): harden output-path and mode-manifest handling from review
- build-zip.sh also passes \\-prefixed absolute paths (UNC shares, the
device namespace) through untouched instead of prefixing the cwd.
- stage-clean-skill.mjs compares the manifest and destination by their
physical locations (existing ancestors resolved through symlinks),
refuses a manifest path that already exists, creates the manifest
exclusively, and removes it on failure only when this invocation
created it.
- Tests: the Windows path regression also builds through a \\.\ device
path; the stager suite covers an existing manifest path and a
symlinked-ancestor alias on both sides.
Addresses the CodeRabbit findings on #385.
Refs #384
* fix(viewer): embed the viewer font so delivered pages stay self-contained
A delivered page linked fonts.googleapis.com and fonts.gstatic.com, so every
viewer's browser reached a third party to render the artifact as designed.
The consequence is larger than the reported typography loss. The adaptive
reader measures real font metrics rather than assuming them, so the resolved
column width depends on that request succeeding: the same file resolves a
960px reader column with the face loaded and 987px without it, and the diagram
repaints at the matching scale. Both states report readability: pass, so
nothing flags it. The producer sees one page and the receiver sees another.
Embed the woff2 subsets Google Fonts serves for JetBrains Mono as data: URIs,
one @font-face per unicode range over the variable wght 400-800 axis. The
bytes are identical to what the linked stylesheet resolved to, so typography
and geometry are unchanged and now reproducible offline. No local() source is
declared first on purpose: resolving an installed copy of unknown version puts
the metrics, and so the column width, back at the mercy of the viewer's
machine. The template comment publishes a sha256 per subset and a test
enforces that those digests match what ships.
Add test/offline-self-containment.test.mjs. It selects artifacts by the
presence of Archify.readerLayout rather than a generator meta match, because
readerLayout is the code that measures font metrics: the compare artifact
carries no generator meta yet is delivered like any other page, while the
site pages declare one and link a stylesheet on purpose. Each artifact is
scanned both as-is and with entities decoded, since compare embeds each side
as an escaped srcdoc whose subresources would otherwise read as clean. Both
artifact cases assert the six faces are present, because reaching no third
party by dropping the typography satisfies the offline check and still hands
the receiver a different page.
JetBrains Mono is under the SIL Open Font License 1.1; the notice and full
license text ship at assets/JetBrainsMono-OFL.txt rather than in the template
comment, so a grep over a delivered page reports zero external hosts.
Closes#242
* fix(viewer): share offline font bytes across delivery and exports
* chore: retrigger stalled PR update processing
* build: preserve showcase quality for the checkout comparison
* fix(packaging): check embedded fonts across the staged payload
---------
Co-authored-by: sunsunsun <fromzerobegin@gmail.com>
Co-authored-by: tt-a1i <2801884530@qq.com>
Add `github-copilot` alongside `cursor`, `codex`, `claude-code`, and
`opencode` in the Start page agent switcher, README EN/ZH quick start
copy, and landing metadata. The skills CLI already resolves
`github-copilot` to `.agents/skills` (global `~/.copilot/skills`), so
the switcher generates the same
`npx skills add tt-a1i/archify --skill archify --agent github-copilot ...`
commands it does for the other targets, installing the identical
checked Skill and zero-dependency renderers with no vendor-specific
fork.
- scripts/start-template.html / docs/start.html: new GitHub Copilot
tab, KNOWN_AGENTS set, and updated panel copy.
- README.md, README_EN.md, README_ZH.md: updated agent list and
switcher coverage sentences.
- docs/index.html: updated meta description.
- CHANGELOG.md: Unreleased entry.
- Updated cursor-onboarding, start-page, and landing tests to cover
the new agent.