Skip to content

fix: remove the consumer name that shipped in vendored bytecode - #129

Merged
baderdean merged 1 commit into
mainfrom
claude/boucle-bugs-cicd-nng1s1
Sep 14, 2026
Merged

baderdean merged 1 commit into
mainfrom
claude/boucle-bugs-cicd-nng1s1

Conversation

@baderdean

Copy link
Copy Markdown
Member

Follow-up to #128, which left .jcode/ out of the consumer-name cleanup. That exclusion was wrong, and the reason I gave for it was wrong twice over.

The reasoning I got wrong

I claimed .jcode/skills/ is "vendored upstream and re-synced by bin/update, so an edit there is churn the next sync reverts". bin/update's own comment settles it:

.jcode/ is synced as a whole — the engine owns it entirely (agents/, skills/, UPSTREAM-FIX-WORKFLOW.md, DESIGN-template.md, prompt-overlay.md)

The sync runs from this repo to consumers. This repo is the origin, not a vendored copy: an edit here is the fix, and it propagates on the next engine bump. The Makefile does exclude .jcode/ from shfmt, but that is about reformatting churn in vendored scripts — not a reason to leave content unreviewed.

What was actually in there

A consumer's project name, in an example command. .jcode/skills/ui-ux-pro-max/SKILL.md shipped:

python3 …/search.py "humanitarian NGO editorial brutalist dark" --design-system -p "<consumer project>"

Every agent that loads that skill reads it. It was the most explicit consumer name left in the repo, and #128 walked past it.

The same name in tracked bytecode. Four __pycache__ files were committed, and two carry that project name in bytecode compiled from a source version that no longer contains it:

.jcode/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-39.pyc
.jcode/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc
.jcode/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-39.pyc
.jcode/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc

A leak no text grep finds, shipped to every consumer by bin/update (SYNC_PATHS includes .jcode). The skill's .gitignore already listed __pycache__/ and *.pyca tracked file ignores .gitignore, which is how they survived it.

Byte-compiled output is regenerable, unreviewable, and outlives the source it was built from. Untracked and deleted.

The guard

A fourth test: no tracked compiled artifact. That was the vector, and unlike the name itself it is mechanically checkable.

Scope is now split rather than uniform:

check scope why
host allowlist engine surface, minus .jcode/skills/ those skills cite framework docs, vendor design systems, security references — some forty domains. A host there is a citation, not infrastructure; an allowlist would be forty entries long and would flag every reference a skill adds.
cross-project reference everything, .jcode/ included does not fire on citations
compiled artifact everything ditto

Two corrections to the guard, both caught by running it

  • <owner>/<project>#N is no longer matched. It cannot be told apart from citing a real upstream bug in a dependency, which is provenance a comment should carry — docker/Dockerfile.agents cites one in its base image, and widening the scope surfaced it as a false positive. Every consumer leak actually found was host-qualified.
  • The file scans itself, so the literal hostnames I wrote as examples in its own comments failed its own host check. Second time this has bitten (fix(dispatch,ci,diagrams): opt-in issue entry, stop polluting consumer CI on both forges, legible diagrams, no consumer names in the engine #128 hit it in CI with something.dev). There is now a note in the file: name domains by description, not by spelling them.

What it cannot catch, stated in the file rather than glossed

An arbitrary proper noun. No pattern separates a consumer's project name from any other capitalised phrase without the blocklist this design exists to avoid — a blocklist would have to spell out the identities the cleanup removes. What is checkable is the vector it travelled by.

Tests

make check green: 1117 tests, shellcheck + shfmt + check-lessons clean, bin/check-doc-sync clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HsXCEtWaFU9nWvKziiNqqy


Generated by Claude Code

I was wrong to leave .jcode/ out of the previous cleanup, and the reason I
gave was wrong twice over.

bin/update's own comment settles it: ".jcode/ is synced as a whole — the
engine owns it entirely (agents/, skills/, ...)". The sync runs FROM this
repo TO consumers, so this repo is the origin, not a vendored copy — an edit
here is the fix, and it propagates. The Makefile does exclude .jcode/ from
shfmt, but that is about reformatting churn in vendored scripts, not a reason
to leave content unreviewed.

What was actually in there:

  - .jcode/skills/ui-ux-pro-max/SKILL.md shipped an example command reading
    `--design-system -p "<consumer project>"` — a consumer's project name
    verbatim, in a command every agent loading that skill reads. The most
    explicit consumer name left in the repo, and I walked past it.
  - Four __pycache__ files were TRACKED, and two carried that same name in
    bytecode compiled from a source version that no longer contains it. A
    leak no text grep finds, shipped to every consumer on the next engine
    bump. The skill's .gitignore already listed __pycache__/ and *.pyc — a
    tracked file ignores .gitignore, which is how they survived.

The example is now a neutral project name; the bytecode is untracked and
deleted (regenerable, unreviewable, and it outlived the source it was built
from).

The guard grows a fourth test — no tracked compiled artifact — because that
was the vector, and its scope is now split rather than uniform:

  - The host allowlist stays on the engine's own surface. .jcode/skills/ is
    a library of design and review skills whose prose cites framework docs,
    vendor design systems and security references; a host there is a
    citation, so an allowlist would be forty domains long and would flag
    every reference a skill adds.
  - The cross-project reference and compiled-artifact checks apply to
    everything, .jcode/ included. Neither fires on a citation.

Two corrections to the guard itself, both caught by running it:

  - `<owner>/<project>#N` is no longer matched. It cannot be told apart from
    citing a real upstream bug in a dependency — docker/Dockerfile.agents
    cites one in its base image, which is provenance a comment SHOULD carry.
    Every consumer leak found was host-qualified.
  - The file scans itself, so the literal hostnames I wrote as examples in
    its own comments failed its own host check. Second time; there is now a
    note in the file saying to name domains by description, not by spelling
    them.

Stated in the file, not glossed: this guard cannot catch an arbitrary proper
noun. No pattern separates a consumer's project name from any other
capitalised phrase without the blocklist the design exists to avoid. What is
checkable is the vector, and that is the new test.

Tests: 1117 pass, doc-sync clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsXCEtWaFU9nWvKziiNqqy
@baderdean
baderdean marked this pull request as ready for review September 14, 2026 09:04
@baderdean
baderdean merged commit 4dccdbe into main Sep 14, 2026
15 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