Releases: ssheleg/super-ux
Release list
v0.56.0 — super-ux
Sherlock external-v3, 41 findings across this member, each one a commit carrying
its own executable regression under test/audit_regressions/. The ones worth
naming here:
- Scenarios carry three axes, not one word.
evidence_kind,
decision_statusandvalidation_statusare separate: approval moves the
decision, and only a dated interview or observation moves validation. A founder
cannot promote a wished-for persona toobservedby approving it. - Competitor funnels are observed exposure, never a proven base. The reference
admitted a well-funded loss-maker looks profitable and then called common
patterns proven; it now says what it can see. Frequency is computed with a
denominator, duplicates collapsed — two funnels of one owner are ONE
observation — and adoption is decided by a local experiment. /ux-auditpreconditions are per scope. A standalone blog with a brand pack
and no scenarios runs the copy audit instead of being routed into writing
scenarios it has no use for. Evidence is typed by claim:file:linefor this
codebase, URL + timestamp + capture for anything outside it.- BP-212 no longer calls local payment testing impossible. Three environments:
a local sandbox tests the whole payment→webhook→entitlement→success path with
the provider's own forwarding, and a public HTTPS endpoint is what PRODUCTION
delivery needs.
Two documents now share the ground one filename used to: interactive-flow-prototypes.md
is the machine-checkable graph contract (IFP-01 … IFP-06), and
clickable-flow-prototypes.md is the operator-facing practice that arrived with the
context-ready handoff. prototyping.md owns the decision to reach for either.
ux-audit and ux-flows were split back under the house working limit —
audit-depth.md and prototyping.md — after the audit's own doctrine grew them
past it. CI now MEASURES that budget with a real tokenizer instead of estimating it.
v0.55.1 — super-ux
Family audit 2026-09-06, wave AUDIT-WAVE-0906. The operator's routing block
promises a spoken refusal for each chain — "no scenarios" / «без сценариев» for
the UX chain, "no brand" / «без бренда» (plus "draft it" / «черновиком» for
copywriting) for the copy chain — and no skill text in this pack carried any of
them. With the routing block installed the promise held one layer up; a
standalone install advertised no opt-out at all, so an operator who wanted the
route skipped had no phrase the skill had agreed to hear.
One sentence in each of the seven bodies now states it: the operator declines
the route by saying the phrase, and the skill proceeds without the chain while
saying so — never silently. Measured before and after with the house auditor:
every body stays inside its working limit, the tightest being ux-audit
~4626/4750 and ux-flows ~4529/4750 tokens.
No description: changed, by decision rather than accident. Descriptions
pair with the umbrella's trigger table, and a dropped advertised phrase refuses
the family pin. ux-flows's description stands at 965/1024 — 965 of the 970
working limit — and is recorded here untouched for exactly that reason:
git diff -U0 over the skills shows zero changed description: lines.
repo validator checks re-measured at 4623 by running the command
docs/brand/facts.md names — the count did not move with this change, and
that is a measurement, not a restatement.
v0.55.0 — super-ux
A repair for what the previous release shipped, and the gate that would have caught
it. 0.54.0 went out with its verification ledger's newest section naming v0.53.0.
This repository's own gate said nothing; the umbrella's cross-member ratchet caught it one
layer up — 3 member ledgers describe a version older than they ship, and the ratchet
stands at 2 — which is the right backstop and the wrong first line.
validate_ledger_names_its_version reads the newest ## … section, resolves the version
it names and compares it with package.json. A ledger whose newest section names an older
artifact is a release nobody re-confirmed against anything.
The first draft crashed instead of refusing. It called a fail() this module does not
have — the name belongs to a sibling repository's validator — so the plant raised
NameError and the run stopped. rc=1 either way, which is exactly why the plant looked
like it had worked. A guard that crashes has not refused anything: it stops the suite
before the rest of it can speak, and it reports a defect in itself as a defect in the
tree. Rewritten through check(), watched refusing its plant with no traceback.
Ledger section added for 0.54.0's own content, so the release it repairs is recorded
rather than skipped. repo validator checks recomputed 4621 → 4623 by running the command
docs/brand/facts.md names, not by adding two.
v0.54.0 — super-ux
Closes ssheleg/sshlg-skills#B-87 (board row), and widens two advertised triggers.
A method told the agent to click through a competitor funnel by hand, in sessions
where two browser tools are connected. FR-01 read "open a competitor's ad, click
through, and you are in it at step one" and named no tool for the click — while the
same repository's neighbours already name chrome-devtools for their own crawling and
claude-in-chrome is connected beside it. FR-01's whole output is a list of live
funnel URLs with the ad that led to each: a walk a browser tool performs and a person
performs slowly.
The answer is both, and the split is the useful part. The walk is mechanical until
it is not:
- a browser tool opens the ad's destination, follows the redirect chain and captures
four things a screenshot loses — the final URL after redirects, every step's URL in
order, the network requests on the paywall step (which processor, which price ids —
the one place a funnel states its own price without a human reading it), and the ad
that led there; - a human takes over at three points that are not incidental: consent walls, which
vary by geography and are the first thing an automated walk gets stuck in; sign-in
and paywall steps, where a tool cannot proceed without real credentials or a real
card — and where FR-06 already forbids going further; and ad libraries themselves,
which rate-limit and serve challenges to a driven browser.
So: the library is read by a person, the funnel is walked by a tool, and the walk stops
at the first wall that asks who you are. Silence here read as nobody thought about
it, which is worse than either answer — and the method is otherwise the most
operationally precise document in the pack.
Two advertised triggers corrected rather than added. copywriting advertised
"пост для твиттера", which demands a literal «для» an operator does not type; it now
reads "пост в твиттер". And "error text" / "текст ошибки" is named, closing a route
the umbrella measured reaching nothing. The description moves 634 → 662 of 1024, leaving
308 characters — well clear of the 60-character reserve the family's ratchet counts.
v0.53.0 — super-ux
Closes ssheleg/sshlg-skills#96.
A metric is built to end an argument about coverage. Then the rule that decides what a
document is ABOUT turns out to be one line of string handling, and the number reports work
that exists as work that is missing — and the number now generates work that is fictional.
Measured: a screen inventory decided a screen was documented when a scenario named its path
as the primary entry point, taking the first backticked path from Entry point: whole.
Two scenarios name their subject with a query string — /reset-password?token=… and
/account/billing/return?invoice=&status= — so both matched no route, and two screens
that had always been documented were published as having no scenario at all. The board row
that followed named nine screens needing scenarios: two needed nothing, and a third was one
component at two addresses, which the rule can only ever name one of. Three of nine rows
were fiction, in a number whose whole purpose was to stop people arguing about coverage from
memory.
ux-audit now carries three rules for any metric over these documents:
- the aboutness rule is a named, exported function with a table of synthetic inputs,
including the negative cases — query strings, fragments, several paths in one field,
prose with no backticks. It was untestable while it was an inline regex, which is exactly
why it was never tested; - a metric that cannot express a real state says so beside the number rather than
counting that state as a failure. One screen at two addresses is one screen, and the
matrix carries a derived alias routes line instead of silently ranking the second
address undocumented; - a deliberate, hard-won rule is a reason to test it, not to trust it. This one had
already replaced a looser rule twice, each time after a screen was reported covered on a
mention rather than on a subject — and a rule with that history is the last one anybody
re-reads.
v0.52.5 — super-ux
The committed social preview is now the umbrella's own render, byte for byte
(node test/site_test.js → PASS: site — 42 checks). Nothing about this pack changed;
the string it is rendered from did.
super-ux's role cell said "what the interface must do and how it sounds" in the
routing map — the block's first content and its highest-salience surface — while the
precedence table 362 lines below gave "how it sounds" to copywriting, and this pack's
own router text says the same split. A reader who stopped at the first table routed copy
work to /ux, on the one router pair the block works hardest elsewhere to separate. The
cell is now "what the interface must do", which is exactly what the precedence table
already said.
The umbrella carries the fixture that keeps it: no member's role may contain another
router's answer, with one declared exemption. Watched refusing the old string —
super-ux's role answers copywriting's question: "how it sounds".
Board: B-131.
Changelog
v0.52.4 — super-ux
SKILL-CARD.md carries the fields Anthropic's Skills-for-enterprise guidance asks every
organisation to keep — "written so somebody who did not build this can decide". It said
0.48.3 while this package shipped 0.52.3.
Nothing read it, so it could only drift. The version moves in package.json,
plugin.json and marketplace.json on every release; the card was in no list. Measured
2026-09-01 across the family: four of nine cards were behind — this one by four minor
releases, agent-stack by ten.
The check refuses a card whose Version row disagrees with package.json, and refuses a
card that states no version at all: one a reader cannot see go stale is worse than one
that lags visibly. Watched failing before it shipped. repo validator checks
4617 → 4619, recomputed by the command the fact itself cites rather than by hand.
And the same defect as the sibling, in the same kind of place. test/validate.py
carried an invalid escape sequence — a lone backslash-pipe in a non-raw docstring — which
Python already warns about and future versions will reject. It sat in a paragraph
explaining that "the escape-awareness is the whole check". Now raw, zero escape
warnings — as agent-stack's was an hour earlier, from a paragraph explaining how to
escape a pipe.
v0.52.3 — super-ux
validate_front_matter_is_yamlparses all 30 shipped front-matter blocks with PyYAML
(B-033): 7SKILL.md, 15 commands, 8.mdcmirrors.front_matter()reads a block line
by line and never asks what a YAML parser would, so a:inside an unquoted scalar turns
the whole block into an invalid mapping and ships anyway — green here, refused by every
installer that parses YAML, and the hub copy freezes on the previous version. The family
shipped exactly that twice in twelve days (sheleg-design1.37.4 and 1.58.0, both
mapping values are not allowed here), so the remedy is ported from the sibling that
paid for it rather than reinvented.- The two guards are the ones that history says matter. It fails closed when PyYAML
is missing, because a guard that discloses and passes when its tool is absent is the hole
the first fix left open; and it refuses an empty walk, because globs that all match
nothing is a moved directory rather than a clean tree. Both watched:yamlblocked at
import, and the three globs renamed. YAML_SELF_TESTis a permanent plant, not a one-off. This gate's whole claim is that
it sees whatfront_matter()cannot; a parser that stopped refusing that shape would leave
it green on a clean tree forever, so the shape is re-checked on every run.- PyYAML installed in both workflows:
setup-pythonputs a different interpreter on PATH
than the runner's system one, which is where PyYAML is preinstalled.
v0.52.2 — super-ux
- The eval suite has dated rows instead of a vacant table (SUX-04, family audit
2026-08-29). 28 blind trigger probes — one fresh subagent per query per model
(haiku,sonnet), each shown only the query and the 28 installed family skill
descriptions — scored 14/14 on both models (train 8/8, validation 6/6), with every
raw answer recorded. Three scenario runs in fresh scratch workspaces scored 12/12
expected-behavior lines, each re-verified by running the pack's own linters over
the agents' outputs (s01 design chain:ux_lint.py0 errors; s03 rewritten copy:
brand pack is clean).test/evals/RESULTS.mdcarries the per-query receipts,
the scenario evidence, and a Method section that states the limits — single
repetition per query against a README that asks for three, model aliases rather
than snapshot ids, and the one non-hermetic call the s02 audit itself disclosed. - Two changes shipped inside v0.52.1 without a line of record, and this is that
line. The 0.52.1 commit was cut by a concurrent session from this working tree
while this run's edits sat uncommitted in it, so they rode along:
compatibility:front matter in all seven skills (SUX-02) — per-skill rather
than one blanket string: the five UX skills name python3 3.9+ (stdlib only) for
the linter this pack seeds,ux-flowsnames its optional MCPs (Figma for
mockups, Refero/Mobbin/Lazyweb for reference screens) and what happens when they
are absent,ux-auditstates which half of the Figma check survives without the
MCP, and the two brand skills namedocs/brand/lint.py— and$schemain both
manifests (SUX-05), the two schemastore spellings that resolve (the family also
carries aclaude-code-plugin.jsonvariant, which 404s and was not copied);
claude plugin validate --strictpasses on both. Everycompatibilityvalue is
a one-line YAML plain scalar with no colon-space sequence, parsed with
yaml.safe_loadbefore it ever reached a commit — the family shipped that exact
defect twice this week (sheleg-design 1.37.4 and 1.58.0), and a planted
colon-space here was caught by the samemapping values are not allowed here.
Budgets measured: 153–358 chars against the standard's 500; the pinned house
auditor returns 0 GAP on all seven. The class — a repo gate that parses shipped
front matter as YAML — is filed asB-033rather than claimed, because this
run's check was manual.
v0.52.1 — super-ux
B-029's board row carried an unescaped|inside a backticked span
(`Kind: copy \| layout`), and markdown splits a table row on the pipe before any
inline parsing happens, so the code fence does not protect it. Every column after the
break shifted by one andStatusread as whatever landed in its place: aresolvedrow
that a machine reads as something else, in one of the two files this pipeline treats as
its record. Escaped.- Found by the family umbrella's validator on this repository's own v0.52.0 tag, while
bumping the pin — not by anything here.validate_ledger_table_shapenow asks the same
question of both ledgers, and it is escape-aware because the first version was not: it
counted\|as a separator and reported fourteen broken rows in files that had one,
which is a detector nobody would have kept. Watched on the exact defect, and its limit
measured and written down —backlog.mdcarries its header twice, so the guard catches
a header that vanished entirely while a partial loss falls to the ratchet, which moved
4488 to 4475 on that plant.