Skip to content

Authorize frozen letter-mix on the public CLI as 0.4.0 - #106

Merged
cursor[bot] merged 28 commits into
mainfrom
cursor/gate-v2-confirmation-6d40
Aug 27, 2026
Merged

cursor[bot] merged 28 commits into
mainfrom
cursor/gate-v2-confirmation-6d40

Conversation

@byte271

@byte271 byte271 commented Aug 27, 2026 •

Copy link
Copy Markdown
Owner

Public surface cleanup

User-facing docs no longer include Cycle 7/8 research writeups, seed ledgers, or the old root spec.md (Watermark Fracture Lab). That frozen spec moved to evidence/frozen-spec-revision-2/ (bytes unchanged). --version prints FuckMark 0.4.0 only. CHANGELOG is a product history.

Frozen evidence/ and specs/ stay in the repo so claims can be audited. They are not the user manual. See docs/research.md.

Paste UI

fuckmark in a terminal pastes, ends on :done, copies, and does not print hidden Unicode. Pipes/files/--stdin stay script-friendly.

Product authorization

Frozen u034f-ufe00-letter-alt-v1, exact visible text, empty release_transform_registry(), release-cli-v5. Do not retag v0.3.0. Do not tag v0.4.0 from this PR.

Gate v2 confirmation (spent seeds 1200000 / 1210000 / 1220000): mix required-sanitizer WM 0/192, mix UW 0/192, visible 192/192, identity 188/192, UnicodeSanitizer mix 0/192. This does not remove every watermark.

CI

HEAD 4998810 is green (12 checks, including Package E2E on Ubuntu, macOS, and Windows). Mergeable / CLEAN against main (d956546).

Release

After merge to green main, follow docs/release.md: immutable v0.4.0 tag on the merge commit, then workflow_dispatch. Do not tag from this PR. The v0.4.0 wheel SHA does not exist until that GitHub Release is published.

Open in Web Open in Cursor 

cursoragent and others added 20 commits August 26, 2026 23:26
…ion.

Five gates after the merged mix freeze: reproducibility and visibility pass;
Latin-1/literal-search, Mn/default-ignorable sanitizers, and single-detector
confirmation fail. Mix stays out of the public CLI. Do not retag v0.3.0.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
UTF-8 is the only product encoding; latin-1, ascii, and cp1252 are rejected.
Visible-projection search is the product search API. Assigned Unicode has no
stronger Priority-Zero invisible mechanism. Mean versus Weighted Mean on the
same GPT-2 adapter is HYPOTHESIS 0/192, not a second model. Mix stays out of
the public CLI.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Cross-detector PASSes on Hugging Face nine-key GPT-2 Weighted Mean plus
Google synthid-text 30-key GPT-2. DistilGPT2 n=16 is HYPOTHESIS
second-model transfer, not confirmation-scale. Sanitizer still FAILs:
width-0 assigned insertions are Mn, Me, or Cf, and all 13 enclosing
marks change Chromium pre pixels. Mix stays out of the public CLI.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Frozen H9 and closed-set hashes stay the CPython 3.12 snapshot. Live
scans on 3.11 and 3.13 still must find no stronger Priority-Zero
mechanism. Mix stays out of the public CLI.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
DEL and C1 except NEXT LINE survive the required sanitizers and keep
Chromium pre/textarea/contenteditable pixels. Independent seed 1100000
n=16 is control-mix 0/16 WM with identity 15/16. Mix sanitizer stays
FAIL. The public CLI stays empty.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
GitHub Actions Chromium rejected the full control-mix apply while one
research host matched. Do not treat that as a product visibility PASS.
Mix sanitizer stays FAIL. The public CLI stays empty.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
No measured Unicode-string family is simultaneously sanitizer-surviving,
Chromium-portable, ordinary plain text, and Priority-Zero safe. This is
a classification, not a Unicode re-scan. Mix sanitizer stays FAIL. The
public CLI stays empty.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Mc, NFKC-stable Lm, designed blanks, Hangul filler sequences, and
font-metric empty glyphs were measured. None are simultaneously
sanitizer-surviving, Chromium-portable, ordinary plain text, and
Priority-Zero safe. Mix sanitizer stays FAIL. The public CLI stays empty.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Repository hygiene forbids comments and docstrings in Python files.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Composite glyphs have numberOfContours == -1 and must not be labeled empty. FontTools stays a research extra, not a runtime dependency.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Grapheme prepend and joining connectors survive the required sanitizers and change Chromium pixels. Hangul L plus V dies to NFC or NFKD. Bidi wraps and partial remainders collapse to Cf or H12. Mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Four independent probes for the sanitizer threat model:

- h16_shaping_closure_scan: HarfBuzz advance/ink oracle over every assigned
  code point, replacing per-probe Chromium screenshots.
- h16_oracle_validation: cross-checks that oracle against real Chromium pre
  pixels on a stratified sample.
- h16_tokenizer_threat_model: measures what production detector tokenizers
  actually do to carrier code points.
- h16_sanitizer_deployability: measures collateral corruption when each
  sanitizer in the required bundle runs on ordinary multilingual text.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
H9-H15 searched for a carrier that is invisible to the reader and also a
fixed point of the required sanitizer bundle, and every cycle returned a
negative. H16 audits the gate instead of running another search.

Closure. A HarfBuzz advance-and-ink oracle over 286719 assigned code points
in 12 shaping contexts finds 396 invisible code points in the Chromium pre
font, and every one is Mn or Cf. The required bundle strips exactly Mn, Cf
and default-ignorable, so invisibility and bundle survival are complementary
sets and the intersection is 0. Substitution closes too: 14 code points
render as an ASCII space and all 14 collapse to U+0020 under NFKC. Canonical
re-encoding closes because the declared ASCII domain is a fixed point of all
four normalization forms. The only remainder in the whole space is Cc, which
ordinary-plain-text excludes. The oracle agrees with real Chromium pixels on
20 of 23 stratified samples and all three disagreements are accounted for.

Tokenization. SynthID-Text scores model tokens, so the tokenizer is the
operative normalizer. The Gemma tokenizers it is deployed on declare only the
SentencePiece whitespace Replace and strip no Mn, Cf or Cc. The only measured
tokenizers that drop anything are the two SentencePiece Precompiled ones, and
what they drop is DEL, inverting the gate.

Deployability. Mn-strip corrupts 5 of 7 ordinary multilingual samples and
default-ignorable-strip corrupts 4 of 7, destroying Thai vowels, Hebrew
niqqud, Persian ZWNJ and emoji ZWJ sequences.

Scope. The frozen product contract classifies both as stress_only_not_frozen,
yet required_sanitizers_keep treats them as hard requirements. Mix survives
21/21 frozen sanitizer fixtures and every other publishability gate passes.

This records the audit only. required_sanitizers_keep is unchanged, no test
is relaxed, proposed_gate_v2 is marked proposal_only_not_active, the public
CLI stays empty and mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Reading the already-recorded frozen confirmation evidence against
proposed_gate_v2, with no new corpus and no retuned seed: identity detects
185/192, the mix transform detects 0/192 watermarked and 0/192 unwatermarked,
visible text passes 192/192, every deployable sanitizer still detects 0, and
mix survives 21/21 frozen sanitizer fixtures.

The gap between the project and a shippable mechanism is therefore a decision
about which sanitizers the gate should require, not a missing carrier.

This does not make that decision. product_authorized stays False, the public
carrier set and release registry stay empty, proposed_gate_v2 stays
proposal_only_not_active, and mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Literature review found that the claim 'no real sanitizer exists' is too
strong. Exactly one ships on by default in the watermarking ecosystem: the
UnicodeSanitizer in jwkirchenbauer/lm-watermarking, enabled by
WatermarkDetector(normalizers=['unicode']) and applied before tokenization.
It is not Mn-strip or default-ignorable-strip. It is NFC, then a fixed BMP
regex whose matches are replaced with a space, then a space collapse, then
Cc removal.

Measured against a faithful reproduction of it:

- It does not restore the unwatermarked source from mixed text.
- U+034F survives; U+FE00 is removed.
- 366 of the 396 invisible code points survive.
- It injects spurious visible spaces, so mixed text comes out mangled.
- It corrupts 5 of 7 ordinary samples, splitting an emoji ZWJ family into
  three people and breaking Persian ZWNJ and a Devanagari conjunct.

Because this sanitizer is real, proposed_gate_v2 now requires it, which makes
the proposal stricter rather than laxer. Detection after it is not measured
here and is recorded as UNMEASURED, so the earlier claim that the proposed
gate was already satisfied is withdrawn: the frozen conditions are met and
proposed_gate_v2_fully_satisfied is False.

product_authorized stays False, the required bundle is unchanged, the
proposal stays inactive, and mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
…tizer.

Ran the detector on the exploratory lane, seed 890000 with GPT-2 and 48
watermarked rows. Seed 890000 is the lane CI already runs on every PR; it is
not a confirmation corpus, and no spent seed (830000/840000/850000) or the
forbidden 950000 is touched.

  pristine, no transform                     47/48 detected
  mix, raw                                    0/48
  mix + nfkc                                  0/48
  mix + cf_strip                              0/48
  mix + lm-watermarking UnicodeSanitizer      0/48
  mix + required bundle                      47/48, restores source 96/96

Mix evades the real sanitizer exactly as well as it evades raw. The only
variant that restores detection is the required bundle, and the last column
explains why: it reconstructs the original string on every row. That is the
mechanism behind the whole H12-H15 blockage. The bundle does not defeat the
carrier, it deletes it and hands the detector back the untouched watermarked
text.

Every condition of proposed_gate_v2 now has a measurement, but this one is
exploratory rather than confirmation grade, so proposed_gate_v2_fully_satisfied
stays False and confirmation_grade is False, with tests asserting both.

product_authorized stays False, the required bundle is unchanged, the proposal
stays inactive, and mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
The lm-watermarking UnicodeSanitizer collapses space runs and strips Cc, so it
damages ordinary text on its own. A bare 0/48 after it was therefore ambiguous:
the sanitizer could have been suppressing detection rather than mix evading it.

Re-ran the exploratory measurement with each variant also applied to the
carrier-free watermarked source:

  variant                                 with mix   no mix   restores src
  raw                                         0/48    47/48           0/96
  nfkc                                        0/48    47/48           0/96
  cf_strip                                    0/48    47/48           0/96
  lm-watermarking UnicodeSanitizer            0/48    46/48           0/96
  required bundle                            47/48    47/48          96/96

The real sanitizer costs one row of detection power by itself, so the drop to
zero is attributable to the carrier and not to the sanitizer mangling the text.

Adds a test asserting the control holds and a payload guard rejecting the
record if the carrier-free control ever falls below half the rows, so this
confound cannot silently reappear.

Still exploratory, still not confirmation grade, still no product
authorization, and mix sanitizer stays FAIL.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Formalize detector-after-sanitizer publishability as
cycle8-publishability-gate-v2, still preregistered and not active.
Keep required_sanitizers_keep and the v1 mix sanitizer FAIL unchanged.
Reserve unspent confirmation seeds 1200000/1210000/1220000 before
generation. Record that the original H16 shaping scan executed latin
A/B only; the scan tool now iterates all advertised contexts.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 07c2e023-3742-4f7c-bc5c-be366a839569


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

cursor Bot pushed a commit that referenced this pull request Aug 27, 2026
…xt scan.

Review on #106 caught a genuine error: scan() advertised 12 shaping contexts
but called primary.invisible(codepoint) with the oracle's default Latin A/B
pair and never iterated SHAPING_CONTEXTS. The published 396 figure and the
spec field shaping_contexts_scanned=12 were therefore unsupported.

Rather than record the errata and leave the measurement pending, this runs it.
The scan now iterates all twelve contexts and reports both bracketing
definitions, since which one you pick is exactly what was ambiguous:

  invisible in every context        389  (Mn 262, Cf 127)
  invisible in at least one context 396  (Mn 262, Cf 134)
  intersection, all-context           0
  intersection, any-context           0

396 is the any-context figure, so the originally published number was right
for the loose reading. The correction strengthens the closure rather than
weakening it: the intersection is now shown empty on the loosest definition,
not on a single context. Every invisible codepoint under either definition is
still Mn or Cf, which the required bundle strips by construction.

Per-context counts show Arabic as the most discriminating at 390, which is
expected since joining behaviour gives several Cf controls visible effect.

The original Latin A/B artifact is kept unmodified at shaping-closure.json;
the corrected scan writes shaping-closure-12-context.json. Errata is recorded
in the payload, the docs, and the evidence README rather than silently fixed.

Adds a payload guard rejecting the record if the any-context intersection is
ever nonzero or if all-context invisibility exceeds any-context invisibility.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Seeds 1200000/1210000/1220000 were generated once under the preregistered detector-after-sanitizer protocol. Mix required-sanitizer WM is 0/192, mix UW 0/192, visible 192/192, identity 188/192, UnicodeSanitizer mix 0/192, carrier-free Unicode 182/192. Status is confirmed_not_product_authorized. The public CLI stays empty. Do not rerun looking for zero.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@cursor cursor Bot changed the title Preregister Gate v2 confirmation; correct H16 12-context overclaim Record Gate v2 confirmation 0/192; keep CLI empty Aug 27, 2026
Gate v2 confirmation 0/192 is already recorded. This step wires frozen
u034f-ufe00-letter-alt-v1 into process_text as release-cli-v5, fail-closed
outside the product domain. release_transform_registry stays empty. The v1
mix sanitizer gate stays FAIL. Historical freeze and confirmation hashes
are snapshotted. Do not retag v0.3.0. Do not generate 950000.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@cursor cursor Bot changed the title Record Gate v2 confirmation 0/192; keep CLI empty Authorize frozen letter-mix on the public CLI as 0.4.0 Aug 27, 2026
Package E2E and the readiness baseline run tools/verify_release_install.py
before installing fuckmark. Insert the repository root on sys.path so the
expected payload comes from apply_letter_alternating_mix instead of failing
with ModuleNotFoundError.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Package E2E / windows-latest exited 1 from fuckmark.exe --stdin after
authorization because U+034F and U+FE00 cannot encode to the default
console codec. Reconfigure stdio to UTF-8, fall back to writing UTF-8
bytes, and decode the release-install verifier as UTF-8.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@byte271
byte271 marked this pull request as ready for review August 27, 2026 08:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f05a7b85ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fuckmark/cli.py
writer = copy_to_clipboard if clipboard_writer is None else clipboard_writer
try:
writer(result.output_text)
writer(output_text)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Encode the raw payload before invoking Windows clip

When --copy uses the default writer on Windows and raw output is selected, output_text now contains U+034F/U+FE00. The Windows branch selects clip, but copy_to_clipboard() invokes it with text=True and no encoding; Python documents that this uses the system default encoding. On common cp1252 Windows installations, encoding either carrier raises UnicodeEncodeError before clip receives input, so successfully transformed copies consistently fall into the exit-2 failure path. Use a Windows clipboard path or pipe encoding that can represent the Unicode payload.

Useful? React with 👍 / 👎.

cursoragent and others added 4 commits August 27, 2026 08:15
Windows --copy was still invoking clip with text=True, so U+034F and
U+FE00 raised UnicodeEncodeError on cp1252 and fell into exit 2.
clip and clip.exe now receive UTF-16; other clipboard tools receive UTF-8.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@cursor
cursor Bot merged commit 4998810 into main Aug 27, 2026
12 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.

2 participants