Skip to content

feat(webkit): derive the Claude bundle from cli-templates and fence the CLAUDE.md fragment - #968

Merged
robson-junior-azion merged 3 commits into
mainfrom
feat/claude-bundle-fence
Sep 16, 2026
Merged

robson-junior-azion merged 3 commits into
mainfrom
feat/claude-bundle-fence

Conversation

@isaque-bock-azion

Copy link
Copy Markdown
Contributor

Summary

  • Derive webkit init's Claude Code bundle from cli-templates/claude/{rules,skills,agents} (bundle.js#listBundle) instead of a hand-maintained list in plan.js that had already drifted — webkit-comments.md shipped on disk but was never copied.
  • Replace the single-line, append-once CLAUDE.md marker with a fenced block (<!-- @aziontech/webkit:start --> … <!-- @aziontech/webkit:end -->) that bundle.js#spliceFragment replaces in place on every init run, so template updates reach a project that already ran init. A pre-fence legacy marker is migrated automatically, and a fragment duplicated across more than one legacy marker (the real case in the docs repo) is repaired down to one fenced block.
  • Add an idempotent fence action (written | merged | skipped) to apply.js, wired into cli.js's dry-run printer.

How to test

  1. pnpm --filter @aziontech/webkit test:toolkit — new test/cli/bundle.test.mjs covers listBundle (equals a plain directory walk, includes webkit-comments.md and every skill's SKILL.md) and spliceFragment (empty file, existing content, legacy single marker, legacy duplicated marker, already-fenced replace, stray extra fenced block — each asserted idempotent); test/cli/plan.test.mjs updated for the derived bundle and the fence action.
  2. pnpm --filter @aziontech/webkit lint and pnpm --filter @aziontech/webkit format:check.
  3. pnpm --filter @aziontech/webkit run smoke:consume (or node packages/webkit/scripts/smoke-consume.mjs directly) — builds the real packages, packs them, scaffolds a Vite app, runs the packed webkit init, and builds it. Confirms the consumer's .claude/ gets all 44 templates (was 43) including webkit-comments.md, and CLAUDE.md gets exactly one fenced block.
  4. Manually: run init twice against a project whose CLAUDE.md already has the old single-line marker (optionally duplicated at two positions) and confirm it converges to one fenced block with the current fragment body, with surrounding user content preserved.

Notes

None. Exported surface for anything building on top of this (e.g. a future webkit sync): bundle.js exports CLAUDE_TEMPLATES, listBundle(templatesDir?), spliceFragment(source, body, { start?, end? }), FRAGMENT_START, FRAGMENT_END, LEGACY_MARKER; plan.js keeps re-exporting the legacy marker as CLAUDE_FRAGMENT_MARKER for backward compatibility; the fence action shape is { type: 'fence', path, start, end, content }.

…he CLAUDE.md fragment

The `webkit init` Claude bundle was a hand-maintained list in plan.js that had
already drifted from the templates on disk: `webkit-comments.md` shipped in
cli-templates/claude/rules/ but was never copied into a consumer's .claude/.
bundle.js now derives the bundle by walking rules/, skills/, and agents/ under
the templates directory, so every template ships automatically and can never
silently fall out of sync again.

The CLAUDE.md fragment was guarded by a single append-once marker line with no
closing fence, so it could only ever be written once — a project that already
ran `init` never received updated invariants/skills from a newer webkit
version, and a fragment that ended up duplicated (the docs repo has it at two
positions today) could never be repaired. The fragment is now wrapped in a
`<!-- @aziontech/webkit:start/end -->` fence that is replaced in place on every
`init` run. A pre-fence legacy marker is migrated into the fence automatically,
and a fragment duplicated across more than one legacy marker is collapsed back
down to a single fenced block.

apply.js gains a `fence` action type (written | merged | skipped) alongside the
existing append/copy/patch-entry actions, and cli.js's dry-run printer gets an
explicit case for it.
Comment thread packages/webkit/src/cli/bundle.js Fixed
… limit

apply.js and bundle.js carried comment blocks over the construction-standard
5-line limit and, in bundle.js, enough prose to trip comment-heavy-file. The
long rationale (why the bundle is derived, why the fragment is fenced, how
legacy-marker migration/repair works) already lives in docs/toolkit/cli.md —
trim the source comments to short, objective notes and point there instead of
restating it inline.
…ariable'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@robson-junior-azion

Copy link
Copy Markdown
Contributor

Fragile coupling worth flagging (non-blocking)

  • FRAGMENT_OWN_HEADING in bundle.js ('## @aziontech/webkit design system') is a string literal duplicated from cli-templates/claude/CLAUDE.fragment.md's actual heading, with nothing enforcing they stay in sync. It's correct today, but if the fragment's heading text is ever edited without updating this constant, isForeignHeading will misclassify the fragment's own heading as a "foreign" section boundary — silently truncating the legacy migration path (pre-fence CLAUDE.md files) mid-body. Blast radius is limited to that one-time migration, but it's the kind of thing that fails silently and only shows up when someone's project has an old marker. Consider deriving the check from the fragment's first line, or at least a test that fails if the two drift apart.

Latent risk in listBundle() (non-blocking, but worth a decision)

  • walkMarkdown recurses into every subdirectory under skills//, not just its SKILL.md. Per authoring-docs.md, skill folders may legitimately contain ungoverned references/.md files. Today none of the consumer skillskills/ have such subfolders, sobehavior is correct now — but the moment one is added (mirroring the internal .claude/skills/ pattern, e.g. component-scaffold's references), it will be silently swept into the bundle and shipped to every consumer, unless someone remembers to add it to the (currently empty) EXCLUDE set. That's the same "someone hahis PR set out to eliminate forthe rules list. Might be worth restricting the skills walk to skills//SKILL.md specifically rather

@robson-junior-azion
robson-junior-azion merged commit 444e357 into main Sep 16, 2026
23 checks passed
@robson-junior-azion
robson-junior-azion deleted the feat/claude-bundle-fence branch September 16, 2026 12:49
@github-actions github-actions Bot mentioned this pull request Sep 16, 2026
gabriel-lisboa-azion added a commit that referenced this pull request Sep 21, 2026
demo/vue-sample had drifted 540 ahead / 31 behind main while most of its
webkit work was reviewed and landed upstream (#941 command-menu, #942
GlobalHeader placements, #943 NavigationMenu, #952 Menu, #960 sidebar
collapse, #973 floating-panel placement, #975 paginator, #977 templates
exports, #921 amount ladder), after which main swept comments (#951) and
reworked the CLI onto a derived bundle (#968/#970).

Main is the source for everything the two share. Of the 28 conflicted
source files, 17 differed from main only in comments — their code was
byte-identical — and 6 more were genuinely newer on main, so all 23 take
main verbatim, including the use-placement TypeScript rewrite that
replaces the old index.js.

Three carve-outs keep demo work main does not have yet:

- sidebar: main's CSS-driven collapse is the base; the `side` axis is
  re-applied on top of it as data-[side=end] variants rather than the JS
  edge map it used to be, and the drag sign moves into the rail
  composable. The one test that asserted the removed inline transform now
  asserts the panel's published edge, since the direction is CSS the
  unstyled test env cannot see.
- theme: texts.data.js keeps demo's 13 extra text-wrap and 10 extra
  tracking declarations (PR #982, in flight). Both sides carry the same
  34 entries, so an entry count would not have caught the loss.
- doc-prose keeps its chrome-padding fix (PR #981, in flight).

catalog.json, authoring-baseline.json, the theme dist and the lockfile
are regenerated rather than hand-resolved; the 13 conflicted visual
baselines take main's and are regenerated from CI next.

Verified: every file main touched is byte-identical to main except the
22 accounted for above; 2364 browser tests, 179 toolkit tests, lint,
vue-tsc, 99.98% type coverage, both ratchets, the Storybook build and
the webkit-sample build all pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants