@friedbotstudio/create-baseline 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +5 -0
  2. package/bin/cli.js +8 -2
  3. package/obj/template/.claude/skills/audit-baseline/audit.sh +11 -5
  4. package/obj/template/.claude/skills/google-analytics/SKILL.md +129 -0
  5. package/obj/template/.claude/skills/google-analytics/references/audiences.md +389 -0
  6. package/obj/template/.claude/skills/google-analytics/references/bigquery.md +470 -0
  7. package/obj/template/.claude/skills/google-analytics/references/custom-dimensions.md +355 -0
  8. package/obj/template/.claude/skills/google-analytics/references/custom-events.md +383 -0
  9. package/obj/template/.claude/skills/google-analytics/references/data-management.md +416 -0
  10. package/obj/template/.claude/skills/google-analytics/references/debugview.md +364 -0
  11. package/obj/template/.claude/skills/google-analytics/references/events-fundamentals.md +398 -0
  12. package/obj/template/.claude/skills/google-analytics/references/gtag.md +502 -0
  13. package/obj/template/.claude/skills/google-analytics/references/gtm-integration.md +483 -0
  14. package/obj/template/.claude/skills/google-analytics/references/measurement-protocol.md +519 -0
  15. package/obj/template/.claude/skills/google-analytics/references/privacy.md +441 -0
  16. package/obj/template/.claude/skills/google-analytics/references/recommended-events.md +464 -0
  17. package/obj/template/.claude/skills/google-analytics/references/reporting.md +397 -0
  18. package/obj/template/.claude/skills/google-analytics/references/setup.md +344 -0
  19. package/obj/template/.claude/skills/google-analytics/references/user-tracking.md +417 -0
  20. package/obj/template/.claude/skills/optimize-seo/SKILL.md +313 -0
  21. package/obj/template/.claude/skills/optimize-seo/scripts/pagespeed.mjs +197 -0
  22. package/obj/template/.claude/skills/pagespeed-insights/LICENSE.md +37 -0
  23. package/obj/template/.claude/skills/pagespeed-insights/SKILL.md +446 -0
  24. package/obj/template/.claude/skills/pagespeed-insights/reference.md +50 -0
  25. package/obj/template/CLAUDE.md +3 -3
  26. package/obj/template/docs/init/seed.md +2 -2
  27. package/obj/template/manifest.json +27 -6
  28. package/package.json +7 -2
  29. package/src/CLAUDE.template.md +3 -3
  30. package/src/cli/install.js +14 -4
  31. package/src/seed.template.md +2 -2
  32. package/obj/template/.claude/hooks/lib/__pycache__/resume_writer.cpython-314.pyc +0 -0
@@ -267,15 +267,15 @@ The vendored `impeccable` skill stays untouched (Article IX). `design-ui` is the
267
267
 
268
268
  ## Article XI — Skill provenance and the baseline manifest
269
269
 
270
- Every skill at `.claude/skills/<slug>/SKILL.md` SHALL declare ownership in its YAML frontmatter as `owner: baseline` or `owner: user`. The build script `scripts/build-manifest.mjs` reads each `owner:` value and emits the canonical baseline-skill set into `obj/template/manifest.json` under `owners.skills` (a JSON object mapping slug → `"baseline"`). The CLI mirrors this manifest verbatim to `<target>/.claude/.baseline-manifest.json` on install. The audit at `.claude/skills/audit-baseline/audit.sh` consumes `manifest.owners.skills` as the canonical baseline-skill enumeration — the previous hard-coded `EXPECTED_SKILLS` set is removed.
270
+ A skill at `.claude/skills/<slug>/SKILL.md` is **baseline-owned** iff its YAML frontmatter declares `owner: baseline`. Every other skill on disk — those without an `owner:` field, or those declaring `owner: user` — is user/third-party and out-of-scope of baseline audit checks. Absence-of-`owner` is the deliberate default so a project with pre-existing skills can install the baseline without annotating any of its own files. The build script `scripts/build-manifest.mjs` reads each `owner:` value and emits the canonical baseline-skill set into `obj/template/manifest.json` under `owners.skills` (a JSON object mapping slug → `"baseline"`). The CLI mirrors this manifest verbatim to `<target>/.claude/.baseline-manifest.json` on install. The audit at `.claude/skills/audit-baseline/audit.sh` consumes `manifest.owners.skills` as the canonical baseline-skill enumeration — the previous hard-coded `EXPECTED_SKILLS` set is removed.
271
271
 
272
272
  You SHALL:
273
273
 
274
- 1. **Declare ownership.** Every new SKILL.md you author starts with `owner: baseline` (if it ships in the baseline) or `owner: user` (if it is project-local). The field appears in frontmatter directly after `name:`. Missing or invalid values fail the audit with `missing owner frontmatter` or `invalid owner=<value>`.
274
+ 1. **Declare baseline ownership only.** A SKILL.md that ships in the baseline SHALL declare `owner: baseline` in its frontmatter directly after `name:`. Authoring a user/third-party skill does NOT require any `owner:` annotation absence is the default. Explicit `owner: user` is permitted but never required. The only frontmatter-related FAIL the audit emits is `invalid owner=<value>` (a present-but-malformed `owner:` field, e.g. typo). Missing-`owner:` is silently skipped.
275
275
  2. **Trust the manifest.** The shipped `obj/template/manifest.json` (mirrored to `<target>/.claude/.baseline-manifest.json` on install) is the canonical record of baseline-owned skills and their content hashes. You SHALL NOT maintain a separate hard-coded list of baseline-skill slugs anywhere in the codebase.
276
276
  3. **Re-derive on drift.** The audit re-derives sha256 hashes from `manifest.files` for every path under `.claude/skills/<slug>/` whose slug appears in `owners.skills`, and compares against on-disk content. Mismatches surface as `hash mismatch at <path>`. A baseline-listed slug missing from disk surfaces as `baseline skill missing`. These are hard FAIL — drift detection has no opt-out.
277
277
  4. **Preserve constitutional citation.** This Article XI SHALL remain in CLAUDE.md AND in `src/CLAUDE.template.md` (byte-equal mirror). The genesis §17 in `docs/init/seed.md` SHALL remain present, with `src/seed.template.md` mirroring it. The audit verifies both citations and reports `CLAUDE.md missing Article XI citation` or `seed.md missing §17 citation` on absence.
278
- 5. **Exempt user skills from baseline checks.** User-owned skills (`owner: user`) are excluded from the baseline count, the names-match check, and the hash-drift check. Adding a local skill does not break the audit; it is the user's responsibility to maintain.
278
+ 5. **Out-of-scope skills don't break the audit.** Any skill on disk that doesn't declare `owner: baseline` is out-of-scope: excluded from the baseline count, the names-match check, and the hash-drift check. Installing the baseline into a project that already has its own skills is zero-friction — no per-file annotation required. Maintenance of those skills is the user's responsibility.
279
279
 
280
280
  Cryptographic supply-chain attestation, signed lock files, and per-skill aggregate merkle hashes are non-goals. The per-file `manifest.files` map already covers every file in every skill directory. A future `npx @friedbotstudio/create-baseline upgrade` subcommand will consume `manifest.owners.skills` + `manifest.files` to re-overlay baseline-owned files safely while leaving user-added or locally-customized files untouched — that subcommand is out of scope of this Article.
281
281
 
@@ -12,6 +12,15 @@ const NPMRC_TEMPLATE_PATH = join(PACKAGE_ROOT, 'src/.npmrc.template');
12
12
 
13
13
  export const NEVER_TOUCH = Object.freeze(['.claude/project.json']);
14
14
  export const SPECIAL_MERGE = Object.freeze(['.mcp.json']);
15
+ // Files present in the shipped template that must NOT be cp'd to target. These
16
+ // are reference artifacts the CLI consults from templateDir (or that ship for
17
+ // inspection-time provenance), never materialized at consumer project root.
18
+ // `manifest.json`: the shipped sha256 table. The CLI's runtime manifest lives
19
+ // at `target/.claude/.baseline-manifest.json` (written by writeBaselineManifest);
20
+ // `target/manifest.json` would be a confusing duplicate. Keep the file in the
21
+ // published tarball so anyone inspecting `node_modules/<pkg>/obj/template/` can
22
+ // see what shipped, but exclude it from the fresh/force install copy.
23
+ export const COPY_EXCLUDE = Object.freeze(['manifest.json']);
15
24
 
16
25
  async function listFiles(root, base = root, acc = []) {
17
26
  for (const entry of await readdir(root, { withFileTypes: true })) {
@@ -37,6 +46,7 @@ function makeFilter(opts) {
37
46
  return (src, _dest) => {
38
47
  const rel = relative(opts.templateRoot, src).split(sep).join('/');
39
48
  if (rel === '') return true;
49
+ if (COPY_EXCLUDE.includes(rel)) return false;
40
50
  if (NEVER_TOUCH.includes(rel) && opts.skipNeverTouch) return false;
41
51
  if (SPECIAL_MERGE.includes(rel) && opts.skipSpecialMerge) return false;
42
52
  return true;
@@ -76,18 +86,18 @@ async function materializeNpmrc(target) {
76
86
  await writeFile(dst, bytes);
77
87
  }
78
88
 
79
- export async function freshInstall(templateDir, target) {
89
+ export async function freshInstall(templateDir, target, opts = {}) {
80
90
  const filter = makeFilter({ templateRoot: templateDir, skipNeverTouch: false, skipSpecialMerge: true });
81
91
  await cp(templateDir, target, { recursive: true, force: false, filter });
82
92
  await applySpecialAndNeverTouch(templateDir, target);
83
- await materializeNpmrc(target);
93
+ if (opts.withNpmrc === true) await materializeNpmrc(target);
84
94
  await writeBaselineManifest(target);
85
95
  }
86
96
 
87
- export async function forceInstall(templateDir, target) {
97
+ export async function forceInstall(templateDir, target, opts = {}) {
88
98
  const filter = makeFilter({ templateRoot: templateDir, skipNeverTouch: true, skipSpecialMerge: true });
89
99
  await cp(templateDir, target, { recursive: true, force: true, filter });
90
100
  await applySpecialAndNeverTouch(templateDir, target);
91
- await materializeNpmrc(target);
101
+ if (opts.withNpmrc === true) await materializeNpmrc(target);
92
102
  await writeBaselineManifest(target);
93
103
  }
@@ -576,9 +576,9 @@ Until `/init-project` runs, this section stays empty. Once populated, every fiel
576
576
 
577
577
  ## §17 — Skill provenance and the baseline manifest
578
578
 
579
- Every skill at `.claude/skills/<slug>/SKILL.md` SHALL declare ownership in its YAML frontmatter as `owner: baseline` or `owner: user`. Baseline-owned skills are those that ship with the baseline; user-owned skills are those a project adds locally. The build script `scripts/build-manifest.mjs` reads each `owner:` value at release time and emits the canonical baseline-skill set into `obj/template/manifest.json` under `owners.skills` (a JSON object mapping slug → `"baseline"`). The CLI mirrors this manifest verbatim to `<target>/.claude/.baseline-manifest.json` on `freshInstall`/`forceInstall`/`merge`.
579
+ A skill at `.claude/skills/<slug>/SKILL.md` is **baseline-owned** iff its YAML frontmatter declares `owner: baseline`. Baseline-owned skills are those that ship with the baseline; every other skill on disk — those without an `owner:` field, or those declaring `owner: user` — is user/third-party and out-of-scope of baseline audit checks. Absence-of-`owner` is the deliberate default so a project that already has its own skills can install the baseline without annotating any of those files. The build script `scripts/build-manifest.mjs` reads each `owner:` value at release time and emits the canonical baseline-skill set into `obj/template/manifest.json` under `owners.skills` (a JSON object mapping slug → `"baseline"`). The CLI mirrors this manifest verbatim to `<target>/.claude/.baseline-manifest.json` on `freshInstall`/`forceInstall`/`merge`.
580
580
 
581
- The audit at `.claude/skills/audit-baseline/audit.sh` consumes `manifest.owners.skills` as the canonical baseline-skill enumeration (replacing the previous hard-coded `EXPECTED_SKILLS` set). For every baseline-owned skill, the audit re-derives sha256 hashes from `manifest.files` and compares against on-disk content; a mismatch is reported as `hash mismatch at <path>` against the named slug. A baseline skill present in the manifest but absent from disk is reported as `baseline skill missing`. A SKILL.md missing the `owner:` field, or carrying an invalid value, is reported as `missing owner frontmatter` or `invalid owner=<value>`. User-owned skills (`owner: user`) are excluded from the baseline count and the names-match check, so adding a local skill does not break the audit.
581
+ The audit at `.claude/skills/audit-baseline/audit.sh` consumes `manifest.owners.skills` as the canonical baseline-skill enumeration (replacing the previous hard-coded `EXPECTED_SKILLS` set). For every baseline-owned skill, the audit re-derives sha256 hashes from `manifest.files` and compares against on-disk content; a mismatch is reported as `hash mismatch at <path>` against the named slug. A baseline skill present in the manifest but absent from disk is reported as `baseline skill missing`. A SKILL.md whose `owner:` field is present but carries an invalid value (anything other than `baseline` or `user`) is reported as `invalid owner=<value>`. SKILL.md files without an `owner:` field are treated as user/third-party and silently skipped — they are excluded from the baseline count, the names-match check, and the hash-drift check, so installing the baseline into a project that already has its own skills never breaks the audit.
582
582
 
583
583
  The audit also verifies constitutional citation: CLAUDE.md SHALL contain the literal string "Article XI" and a reference to the manifest, and `docs/init/seed.md` SHALL contain "§17" and a manifest reference. Missing citations trigger FAIL with `CLAUDE.md missing Article XI citation` or `seed.md missing §17 citation`.
584
584