Skip to content

Site positioning pass, JSON 0 fix, highlighting, comment-safe fmt, std/git docs - #33

Merged
csfh merged 7 commits into
mainfrom
site/positioning-pass
Oct 9, 2026
Merged

csfh merged 7 commits into
mainfrom
site/positioning-pass

Conversation

@csfh

@csfh csfh commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Summary

Seven commits, one per track, so each can be reviewed (and bisected) on its own. Merge with rebase to keep them.

  • ea8fada site: sharper homepage positioning (definition, highlights, runnable examples with output), per-page canonical/og/twitter tags, social card, favicon, install page fix (no xo doctor, Windows caveat), std/store reference, test:samples verifier.
  • 9c09889 syntax: highlights.scm generator emits operators before leaders and adds statement-scoped captures for ~, ^, &, so leaders stop rendering as gray operators. New test.
  • 261e71c grammar: regenerated tree-sitter package and synced site wasm (query and wasm must ship together).
  • 0ba9a63 json: std/json stringify no longer maps integer 0 to null. The bool/null mapping stays lossy and is now documented; a tagged JSON value is tracked in the roadmap.
  • 025fd58 fmt: xo fmt keeps comments and blank lines instead of deleting them. If a comment cannot be placed, formatting fails and the file is left unchanged. Covered by a 606-file corpus test (same AST, same comments, idempotent).
  • a4e3a30 www: rebuilt the Try page wasm with the new formatter.
  • f8d6149 git: std/git docs now match behavior and the module is marked Partial (pack verification and oid enumeration are gaps).

Known gaps (partial, not done)

  • JSON true/false/null are still indistinguishable from 1/0 at runtime.
  • std/git pack verification and oid enumeration are not implemented.
  • fmt comments inside multi-line expressions are rejected rather than moved.

Verification

  • cargo test -p echo_parser/ast/lexer/wasm/xo/syntax pass; fmt corpus passes.
  • Website prose, std-ref, docs and sitemap verifiers pass on every commit (checked in a throwaway worktree).
  • e26 failures seen locally were environmental (TLS fixtures need gitignored .pem files); CI is the authority here.

🤖 Generated with Claude Code

csfh and others added 7 commits October 8, 2026 23:19
Homepage
- Value-led definition and lead, plus a four-item highlights section
  (glyph leaders, errors as values, one LLVM pipeline, standard library).
- Hero sample and three programs are shown beside their real `xo run`
  output. `npm run test:samples` fails if a snippet drifts from its file
  under examples/ and, when xo is built, if the output changes.
- Install is the primary CTA; Book joins the nav and "Echo 2026" is
  labeled "Spec" (paths unchanged).

Metadata
- Per-page canonical, og:*, and twitter:* tags from applyStaticPage, a
  favicon link, and a 1200x630 social card (public/og.png, source in
  scripts/og-image.html). URLs use the trailing-slash form Cloudflare
  Pages actually serves; the sitemap now matches.
- verify-static-dist checks og.png and each page head.

Install page
- Drop the dead `xo doctor` line (xo only has `xo cache doctor`) and add
  the Windows caveat from the README.

Docs
- Add a std/store reference page (every example checked with `xo check`;
  behavior verified by running it) and an examples/misc/result_match.echo
  program for the "errors are values" claim.
- Correct the roadmap row that still called `xo get` unimplemented.
- Update www/SITE.md to match the new copy and verification.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Consumers resolve two captures on one range by taking the last one, but
emit_highlights_scm listed the generic operator block last. The loop
leader `*`, and `%` `:` `!` `<` `>` `+` `-` `/`, therefore rendered as
operators at the start of a statement.

- Emit the operator block before every leader capture.
- Add statement-scoped captures for the `~` bind, `^` return, and `&`
  effect-block leaders, which are anonymous dual-use glyphs.
- Test that every statement-scoped leader capture follows the operator
  list and that the three new captures exist.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The committed grammar had drifted from its generator: it lacked the `&`
effect-block statement and still modeled `~` and `^` as named
leader_tilde / leader_caret tokens. Regenerated with the documented
procedure (docs/tree-sitter.md):

  xo tools grammar tree-sitter -o grammars/tree-sitter-echo
  tree-sitter generate && tree-sitter build --wasm
  npm run sync:tree-sitter

The query and the wasm must ship together: the new highlights.scm names
tokens (`<<`, `>>`, `&`) that the old wasm does not have. Both files are
served with max-age=0, must-revalidate, so they update together.

Generated output only. External hosts that pin this directory (Zed) see
the node changes when they bump their rev.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
echo_to_json mapped the integer 0 to JSON null, so `{"n":0}` came back as
`{"n":null}`. Echo values are untagged integers at runtime, so JSON
true/false/null, 1, and 0 cannot be told apart. Decision (user, this
session): keep the lossy mapping and fix the integer case.

- stringify(0) emits 0 and stringify(1) emits 1.
- true parses to 1 and false/null parse to 0, now documented rather than
  implied. `true` does not round-trip, and a top-level 0/false/null
  document still fails to parse because 0 also signals failure.
- Runtime tests and e26 run/json/003 pin the mapping.
- Record the open design (a tagged JSON value) in docs/stdlib.md and
  docs/roadmap.md, and update the std/json reference page and example.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`xo fmt --write` rewrote files in place from an AST that carries no
trivia, so every `;` comment was deleted: 264 of the 606 parseable .echo
files in the repo lost comments.

- The lexer records comment spans (`Lexed::comments`); the formatter
  places them, so a `;` inside a string is never mistaken for one.
- `format_file_with_comments` keeps own-line comments at the next item's
  indent, same-line comments on their line (including a block header such
  as `? x { ; why`), and one blank line wherever the source had one or
  more. Runs collapse, none is added, none starts or ends a block.
- Comments are placed between statements, between match arms, before a
  closing `}`, and inside empty blocks.
- A comment inside an expression has no safe place: it is an error
  (`fmt-comment-in-expression`) and nothing is written. A final guard
  (`fmt-comment-unplaced`) turns any other unplaced comment into an error
  instead of a silent drop.
- `echo_parser::format_source` stays the single entry point, so xo, the
  LSP, and echo_wasm all get the fix. `xo fmt` now says the file was left
  unchanged on failure.
- Rules recorded in docs/pipeline.md, docs/testing.md, and /docs/toolchain.

Tests: unit tests for each rule, a wasm test for the Try page, and
crates/echo_parser/tests/fmt_corpus.rs, which formats every .echo under
examples/, echo26/, and std/ and requires the same AST, every comment, and
idempotence. 96 of 132 examples now pass `xo fmt --check`.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…matter

scripts/build-wasm.sh. The Format button on /try calls echo_wasm's
format, so the committed wasm kept deleting comments until rebuilt.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Verified against a real 7-object pack from `git pack-objects` plus
hand-built receive-pack and upload-pack bodies, and a copy of the pack
with its object data destroyed.

- pack_valid and index_pack check only the 12-byte header. A pack with
  corrupted object data and an intact header still reports valid.
- index_pack().checksum is the stored trailer in hex, not recomputed, and
  index_pack().objects is always empty (gix-pack walks the entries but the
  oids are discarded).
- receive_pack_split returns four fields (commands, pack, ref_name,
  new_oid); the old runtime comment listed two.

Changes
- Add the std/git reference page; every example passes `xo check`.
- Correct the runtime doc comments and pin both gaps with runtime tests.
- Add e26 run/git/001 for the behavior that needs no pack bytes.
- docs/stdlib.md: Done -> Partial, with the gaps; add a roadmap row.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying echo with  Cloudflare Pages  Cloudflare Pages

Latest commit: f8d6149
Status: ✅  Deploy successful!
Preview URL: https://4136501b.echo-1eh.pages.dev
Branch Preview URL: https://site-positioning-pass.echo-1eh.pages.dev

View logs

@csfh
csfh merged commit a4c79e2 into main Oct 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant