@norskvideo/ctl-dev-kit 0.1.4 → 0.1.6

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.
package/build/flake.nix CHANGED
@@ -1,7 +1,8 @@
1
1
  # Product build + dev shell — single-sourced in @norskvideo/ctl-dev-kit and
2
2
  # copied verbatim into each split product repo (nix needs a flake.nix at the repo
3
3
  # root for `nix develop`; it can't pull one from an npm package at CI bootstrap).
4
- # The copy is drift-gated (Workstream I), same model as the fenced CLAUDE.md core.
4
+ # The copy is to be drift-gated (Workstream I; not yet enforced), same model as
5
+ # the fenced CLAUDE.md core.
5
6
  #
6
7
  # Three shells:
7
8
  # nix develop -> build tools (bun, cargo/rustc, git) + the pinned
@@ -2,11 +2,11 @@
2
2
  <!--
3
3
  This block is the SHARED conventions core, single-sourced in
4
4
  @norskvideo/ctl-dev-kit (conventions/CLAUDE.core.md). It is copied verbatim
5
- into each product repo's CLAUDE.md between these fenced markers, and a
6
- drift-check gate (Workstream I) fails CI if a copy diverges from the dev-kit's
7
- version. Do NOT hand-edit a copy edit the dev-kit source and re-sync. The
8
- per-product tail (this product's build, iterate loop, gotchas) lives OUTSIDE
9
- the markers and is yours to own.
5
+ into each product repo's CLAUDE.md between these fenced markers. A drift-check
6
+ gate is planned (Workstream I) to fail CI if a copy diverges from the dev-kit's
7
+ version until it lands, do NOT hand-edit a copy: edit the dev-kit source and
8
+ re-sync. The per-product tail (this product's build, iterate loop, gotchas)
9
+ lives OUTSIDE the markers and is yours to own.
10
10
 
11
11
  It is copied (not `@import`ed) on purpose: CLAUDE.md's value is being read
12
12
  verbatim by a human on GitHub with no tooling, and an @import shows a human a
@@ -0,0 +1,94 @@
1
+ // Workstream I drift gate. Fails a product repo whose forced copies of the
2
+ // shared conventions have diverged from this dev-kit's canonical source:
3
+ // - the fenced `ctl-shared-conventions v1` core inside its CLAUDE.md, and
4
+ // - its root flake.nix.
5
+ //
6
+ // Both are copied verbatim (not @import-ed / not a dep) so a human reads them on
7
+ // GitHub with no tooling — which is exactly where drift starts. The gate makes
8
+ // "single-sourced in @norskvideo/ctl-dev-kit" true: a product runs it in CI
9
+ // against the dev-kit version it has installed, so bumping the pinned dev-kit
10
+ // forces a re-sync. Canonical bytes are the files shipped alongside this script
11
+ // (conventions/CLAUDE.core.md + build/flake.nix), resolved package-relative so
12
+ // they work both workspace-symlinked and installed from the published tarball.
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+
16
+ export interface DriftReport {
17
+ ok: boolean;
18
+ problems: string[];
19
+ }
20
+
21
+ const BEGIN = "<!-- BEGIN ctl-shared-conventions v1 -->";
22
+ const END = "<!-- END ctl-shared-conventions v1 -->";
23
+
24
+ const RESYNC = "Edit the dev-kit source and re-sync — never hand-edit the copy.";
25
+
26
+ // First line that differs, so the failure names the drift instead of dumping the
27
+ // whole block. Compared line-wise; the byte check is the substring test above.
28
+ function firstDiffLine(actual: string, expected: string): string {
29
+ const a = actual.split("\n");
30
+ const e = expected.split("\n");
31
+ for (let i = 0; i < Math.max(a.length, e.length); i++) {
32
+ if (a[i] !== e[i]) {
33
+ return `line ${i + 1}: expected ${JSON.stringify(e[i] ?? "<missing>")}, found ${JSON.stringify(a[i] ?? "<missing>")}`;
34
+ }
35
+ }
36
+ return "content differs";
37
+ }
38
+
39
+ function coreProblem(claude: string, canonicalCore: string): string | undefined {
40
+ if (claude.includes(canonicalCore)) return undefined;
41
+
42
+ const begin = claude.indexOf(BEGIN);
43
+ const end = claude.indexOf(END);
44
+ if (begin === -1 || end === -1) {
45
+ return `CLAUDE.md is missing the '${BEGIN}' / '${END}' marker block. Copy conventions/CLAUDE.core.md from @norskvideo/ctl-dev-kit verbatim between the markers.`;
46
+ }
47
+ const region = claude.slice(begin, end + END.length);
48
+ return `CLAUDE.md fenced core has drifted from @norskvideo/ctl-dev-kit conventions/CLAUDE.core.md (${firstDiffLine(region, canonicalCore.trimEnd())}). ${RESYNC}`;
49
+ }
50
+
51
+ export function checkDrift(repoRoot: string, canonical: { core: string; flake: string }): DriftReport {
52
+ const problems: string[] = [];
53
+
54
+ const claudePath = join(repoRoot, "CLAUDE.md");
55
+ if (!existsSync(claudePath)) {
56
+ problems.push(`CLAUDE.md not found at repo root (${claudePath}). It must embed the ctl-shared-conventions core.`);
57
+ } else {
58
+ const problem = coreProblem(readFileSync(claudePath, "utf8"), canonical.core);
59
+ if (problem) problems.push(problem);
60
+ }
61
+
62
+ const flakePath = join(repoRoot, "flake.nix");
63
+ if (!existsSync(flakePath)) {
64
+ problems.push(
65
+ `flake.nix not found at repo root (${flakePath}). It is copied verbatim from @norskvideo/ctl-dev-kit build/flake.nix.`,
66
+ );
67
+ } else {
68
+ const flake = readFileSync(flakePath, "utf8");
69
+ if (flake !== canonical.flake) {
70
+ problems.push(
71
+ `flake.nix has drifted from @norskvideo/ctl-dev-kit build/flake.nix (${firstDiffLine(flake, canonical.flake)}). ${RESYNC}`,
72
+ );
73
+ }
74
+ }
75
+
76
+ return { ok: problems.length === 0, problems };
77
+ }
78
+
79
+ if (import.meta.main) {
80
+ const repoRoot = process.argv[2] ?? process.cwd();
81
+ const canonical = {
82
+ core: readFileSync(join(import.meta.dir, "CLAUDE.core.md"), "utf8"),
83
+ flake: readFileSync(join(import.meta.dir, "..", "build", "flake.nix"), "utf8"),
84
+ };
85
+ const report = checkDrift(repoRoot, canonical);
86
+ if (report.ok) {
87
+ console.log("drift-check: CLAUDE.md core + flake.nix match @norskvideo/ctl-dev-kit.");
88
+ process.exit(0);
89
+ }
90
+ console.error(
91
+ `drift-check FAILED (${report.problems.length} problem(s)):\n${report.problems.map((p) => ` - ${p}`).join("\n\n")}`,
92
+ );
93
+ process.exit(1);
94
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norskvideo/ctl-dev-kit",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json"