Skip to content

Releases: AnastasiyaW/crossweft

crossweft 0.2.10

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 28 Oct 11:08

Release commit (pin this in CI): 13bbefd0a7bbde9cc3165d74f568b6e9d1be2858

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@13bbefd0a7bbde9cc3165d74f568b6e9d1be2858"  # v0.2.10
  • ui_actions: a new guard that follows every UI control (a button's
    data-action, a keyboard callback) through the hand-written tables that
    dispatch it -- maps, registries, prefix rules -- to its handler and, with
    "routes": true, to a route a link declares. A control nobody handles, a
    handler no control sends to, and a key bound twice are problems
    (ui:<id>:dead|unrouted|orphan|conflict; an allow that excuses nothing
    is stale-allow). A UI request path ending in / is one request, not
    every route below it. crossweft actions [--json]
    prints each control's chain. The polyglot-shop example gains an admin page
    and smoke/click_smoke.py, which presses every mapped button in Chromium and
    waits for its request (with a self-test that must turn red on a handler that
    throws).
  • The crossweft skill explains the ui: problems and crossweft actions;
    after upgrading, re-run crossweft agents.

crossweft 0.2.9

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 24 Oct 00:18

Release commit (pin this in CI): f127e9d7ac5d249e36f736d6157f07e8f60e1b73

python -m pip install "git+https://github.com/happyin-app/crossweft.git@f127e9d7ac5d249e36f736d6157f07e8f60e1b73"  # v0.2.9
  • crossweft validators --incremental for the stop hook: a self-test or normal run
    that passed last time is reused while everything it observed is unchanged -- the
    bytes of the files it read, the directories it listed, the paths it checked, the
    environment variables it read, the output of the read-only git commands it ran,
    the validator itself and the runtime. The runner learns this by tracing each run
    (Python audit hooks, also in Python child processes). A run that starts any other
    program, forks, uses a socket, a database driver or ctypes, or has a child that
    did not report, is never reused; failures are never kept; a kept run expires after
    24 hours. The report marks reused rows, says why a kept run ran again (the first
    input that changed), and names every run that could not be kept, with the reason. Validators see CROSSWEFT_VALIDATORS_INCREMENTAL=1. CI runs plain
    crossweft validators.
  • gone on a legacy link maps a retired route the server still answers on purpose
    ({"status": 410, "replaced_by": "<current link>"}): it no longer needs a finding as
    route:unmapped, removing the tombstone is route:gone-unserved, and a client
    literal that still names it is route:gone-called.

crossweft 0.2.8

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 15 Oct 14:01

Release commit (pin this in CI): d00defb4675665e938d2d25866a4bdd2c7098e33

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@d00defb4675665e938d2d25866a4bdd2c7098e33"  # v0.2.8
  • The README, docs/agents.md and docs/enforcing-across-repos.md named 0.2.6 in their
    install, clone and CI examples while the package was 0.2.7, so a reader installed the
    previous release. They now name this release, and this repository's own map compares
    each of those install, clone, CI and pre-commit examples, the README status line and the
    Codex plugin manifest with the package version, so these examples can no longer drift
    from the release.

crossweft 0.2.7

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 12 Oct 21:10

Release commit (pin this in CI): 417190c90915c0f895ea2944eca780bd626509c5

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@417190c90915c0f895ea2944eca780bd626509c5"  # v0.2.7
  • Built-in hazard rules, opt-in with "hazards": {"include": [globs]} in
    crossweft.json (optional exclude, rules): script lines that run without
    an error and still break what another program reads. cmd-digit-redirect
    (echo x=%V%>>file loses a one-digit value to a stream handle),
    empty-to-zero ([int]$parts[1], int(x or 0) turn a missing status into 0),
    toolchain-env-name (set RC=%ERRORLEVEL% before cmake/cl/msbuild/make) and
    glob-length-guard (case ??..?* reject branch refuses exactly-N input).
    Hits are hazards problems keyed by a digest of the line, excusable by a
    finding; an include glob that names no file is fatal. Planted unsafe and
    safe cases run in crossweft self-test; see docs/model-reference.md.

crossweft 0.2.6

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 11 Oct 19:51

Crossweft: guards the seams between languages

What it is

When a product is written in several languages, the costliest bugs live between files. A Go server and a TypeScript client both hold the same API version, the same DTO fields, the same env var names. An agent changes one side, the tests stay green, and the install breaks on a customer's machine.

Crossweft keeps a map of these seams next to the code and checks that both sides agree.

How it works

  1. The map. seams/model lists the components, the links between them and, for every value written by hand on both sides, a guard that reads both files.
  2. After every edit. If the agent touches a file that sits on a seam, Crossweft names the file on the other side and the guard that watches it.
  3. Before finishing. crossweft check runs. If a seam disagrees, the hook sends the agent back with what to fix, so "Done" means both sides agree.

It works as a Claude Code plugin (hooks and a skill), a Codex skill, an MCP server for other agents, and a GitHub Action for CI. Python 3.9+, standard library only.

Try it on the demo:

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@v0.2.6"
git clone --branch v0.2.6 --depth 1 https://github.com/AnastasiyaW/crossweft
cd crossweft/examples/polyglot-shop && crossweft check

The story behind it: https://happyin.work/blog/crossweft-seams/ · project page: https://happyin.work/crossweft/

In this release

  • README: a GitHub Action section with a workflow example and the inputs table.
  • action.yml: a description that says what the check catches.

Release commit (pin this in CI): 8db353a01130c13718ff8eef589dfb9197f11d4d

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@8db353a01130c13718ff8eef589dfb9197f11d4d"  # v0.2.6

crossweft 0.2.5

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 11 Oct 19:33

Crossweft: guards the seams between languages

What it is

When a product is written in several languages, the costliest bugs live between files. A Go server and a TypeScript client both hold the same API version, the same DTO fields, the same env var names. An agent changes one side, the tests stay green, and the install breaks on a customer's machine.

Crossweft keeps a map of these seams next to the code and checks that both sides agree.

How it works

  1. The map. seams/model lists the components, the links between them and, for every value written by hand on both sides, a guard that reads both files.
  2. After every edit. If the agent touches a file that sits on a seam, Crossweft names the file on the other side and the guard that watches it.
  3. Before finishing. crossweft check runs. If a seam disagrees, the hook sends the agent back with what to fix, so "Done" means both sides agree.

It works as a Claude Code plugin (hooks and a skill), a Codex skill, an MCP server for other agents, and a GitHub Action for CI. Python 3.9+, standard library only.

Try it on the demo:

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@v0.2.5"
git clone --branch v0.2.5 --depth 1 https://github.com/AnastasiyaW/crossweft
cd crossweft/examples/polyglot-shop && crossweft check

The story behind it: https://happyin.work/blog/crossweft-seams/ · project page: https://happyin.work/crossweft/

In this release

  • A working contact address for questions and adoption help in the README ("Tell us what broke"); the skill and the issue-form contact link point there.

Release commit (pin this in CI): 8bd4f376833f6dae34186069e2db8519e5948353

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@8bd4f376833f6dae34186069e2db8519e5948353"  # v0.2.5

crossweft 0.2.4

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 11 Oct 17:50

Release commit (pin this in CI): b19e96ae0c7349149edc18ded2e504202cd592e1

python -m pip install "git+https://github.com/AnastasiyaW/crossweft.git@b19e96ae0c7349149edc18ded2e504202cd592e1"  # v0.2.4
  • The repository moved to github.com/AnastasiyaW/crossweft; GitHub redirects
    the old address. Install commands, plugin manifests, the marketplace entry
    and the docs name the new one.
  • Feedback: issue forms for a problem, an idea and an agent report; the skill
    tells an agent, when crossweft itself gets something wrong, to draft a short
    report for its user (no private code) and let the user decide whether to
    send it; the README says where to write.
  • README: header and how-it-works images, a release badge that follows the
    latest release, and a link to the project page.
  • action.yml: a Marketplace-ready name (Crossweft seam check) and colour.

crossweft 0.2.3

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 11 Oct 02:03

Release commit (pin this in CI): d8a57c9f7710be6dfcebbb9b9ca733e2bdfdd342

python -m pip install "git+https://github.com/happyin-app/crossweft.git@d8a57c9f7710be6dfcebbb9b9ca733e2bdfdd342"  # v0.2.3
  • validators.exclude in crossweft.json: {"validate_x.py": "<reason>"} for a
    validate_*.py that is not a suite validator, such as a commit-time gate that
    judges one staged change. It is not run, and the report lists it with its
    reason. An entry that names no file, has no reason, or is also given a
    timeout is an error; excluding every file still fails with "nothing ran".

crossweft 0.2.2

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 11 Oct 01:15

Release commit (pin this in CI): 9cd31dd333dd04fc65b9d47540893fd3d98a9ee6

python -m pip install "git+https://github.com/happyin-app/crossweft.git@9cd31dd333dd04fc65b9d47540893fd3d98a9ee6"  # v0.2.2
  • check --incremental: --changed against the last commit at which the check
    passed in this work tree, plus the paths that were uncommitted then (they
    rerun, so reverting an uncommitted file cannot bring back unchecked bytes);
    the full check when there is no such commit, another crossweft version or
    build recorded it (the record keeps a digest of the engine code), or the map,
    config or a joint plugin changed. HEAD and the uncommitted paths are read
    before the check runs, so a commit landing meanwhile is never recorded. A pass moves the
    commit forward. The record lives in the git directory (per worktree, never
    committed). Exclusive with --changed; refused with --format sarif.
  • The stop hook runs check --incremental. Measured on a 1,140-file map with
    13 joint kinds: full check 385 s; a stop after editing one source file 38 s.
  • joints.sources in crossweft.json: the plugin files and the helpers they
    import, for a joints.dir that also holds unrelated code. --changed then
    falls back to the full check only when one of those files changes (before:
    any change under joints.dir). A plugin that imports a helper from its
    directory, or reads a file from it while imported or checked, that neither
    sources nor the kind's inputs cover is an error
    (joints:unlisted-read:<kind>:<path>), so the list cannot go stale silently.
    Globs match the way --changed matches them, part by part.

crossweft 0.2.1

Choose a tag to compare

@AnastasiyaW AnastasiyaW released this 10 Oct 20:33

Release commit (pin this in CI; a tag can be moved, a commit cannot): 6001e167056261058564d8f6993026521eb669f5

python -m pip install "git+https://github.com/happyin-app/crossweft.git@6001e167056261058564d8f6993026521eb669f5"  # v0.2.1
  • New transform go-http-status: a Go net/http status constant name
    (StatusTooManyRequests) becomes its number (429), so the statuses a Go
    handler writes can be compared with the numeric statuses a client in another
    language accepts. The table is Go's net/http/status.go; an unknown name stays
    as it is and never matches a number, so a guard reading it fails instead of
    passing.
  • A join point takes within (one capture group), like a set side: the point
    reads only those regions, e.g. the default block of a file that also documents
    an alternative value. Every match inside the regions still counts, so a drifted
    copy inside cannot hide. The regex runs on the whole file (not on a slice)
    and only matches lying wholly inside a region count, so ^, $,
    lookbehind and lookahead see the real text; a
    within that finds no region fails as anchor:join:<id>:within:<path>.
  • engine.Checker.route_registrations(text, function_prefixes, unscannable=None):
    the go-chi route enumerator check uses, as a side-effect-free classmethod,
    so a joint-kind plugin that needs the server's routes reuses it instead of
    keeping a second scanner. Registrations it cannot name go to the optional
    callback.
  • Docs: install by the release commit in CI (tag in a comment). A tag can be
    moved and would change what CI runs.