@flighthq/tool-capture 0.4.0-next.1585.bf131c8 → 0.4.0-next.1602.af48ed1

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.
@@ -1,5 +1,25 @@
1
1
  export declare const CAPTURE_BUILD_IDENTITY_FILE = "capture-build.json";
2
2
  export declare const MAX_CAPTURE_BUILD_DIRTY_PATHS = 50;
3
+ /**
4
+ * Paths whose dirtiness cannot reach a render, and are therefore not evidence about the build.
5
+ *
6
+ * ★ THE QUESTION THE DIRTY LIST ANSWERS IS "COULD WHAT I CAPTURED DIFFER FROM THE COMMITTED TREE". A
7
+ * file that no build step reads and no scene imports cannot change a pixel, so listing it does not
8
+ * answer that question — it just adds noise to the answer.
9
+ *
10
+ * ★ THESE TWO ARE THE REVIEW WORKFLOW'S OWN OUTPUT, WHICH MAKES THE NOISE SELF-INFLICTED AND RECURRING.
11
+ * Commissioning writes a request into `reference-image-requests/` and holding writes
12
+ * `scripts/reference-image-held.json`; both are then uncommitted, so the NEXT review of the same session
13
+ * reports "Built with uncommitted changes" and names files the reviewer just created by reviewing. A
14
+ * warning that fires because you used the tool teaches you to ignore the warning, which is the one
15
+ * outcome worse than not having it — and it fires on exactly the iterative loop the tool exists for.
16
+ *
17
+ * ★ ADDING TO THIS LIST IS A CLAIM, NOT A CONVENIENCE. The claim is that nothing under the prefix is read
18
+ * by a build step or a scene. `functional/baselines/` deliberately stays OUT: a changed baseline does not
19
+ * alter a render, but it does alter what a capture reports as changed, so its dirtiness is evidence about
20
+ * the run even though it is not evidence about the build.
21
+ */
22
+ export declare const CAPTURE_BUILD_DIRTY_EXEMPT_PREFIXES: readonly string[];
3
23
  export interface CaptureBuildIdentity {
4
24
  /** The commit checked out when the build began. */
5
25
  commit: string | null;
@@ -12,6 +32,8 @@ export declare const UNSTAMPED_CAPTURE_BUILD: CaptureBuildIdentity;
12
32
  export declare function createCaptureBuildIdentity(commit: string | null, allDirtyPaths: readonly string[]): CaptureBuildIdentity;
13
33
  /** Reads git once at build time and creates the record that is stamped into dist. */
14
34
  export declare function getCaptureBuildIdentity(repositoryRoot: string): CaptureBuildIdentity;
35
+ /** Whether a dirty path is one the build and the scenes provably never read. */
36
+ export declare function isCaptureBuildDirtyExempt(path: string): boolean;
15
37
  /** Paths from `git status --porcelain=v1 -z`; rename/copy pairs remain one readable entry. */
16
38
  export declare function parseGitStatusPaths(status: string): string[];
17
39
  /** Reads a build-owned stamp from the directory capture is actually serving. */
@@ -1 +1 @@
1
- {"version":3,"file":"captureBuildIdentity.d.ts","sourceRoot":"","sources":["../src/captureBuildIdentity.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAChE,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0FAA0F;IAC1F,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,gGAAgG;IAChG,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB,EAAE,oBAAmE,CAAC;AAE1G,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,oBAAoB,CAMtB;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,oBAAoB,CAepF;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAgB5D;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAqBvF"}
1
+ {"version":3,"file":"captureBuildIdentity.d.ts","sourceRoot":"","sources":["../src/captureBuildIdentity.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAChE,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAGhE,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0FAA0F;IAC1F,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,gGAAgG;IAChG,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB,EAAE,oBAAmE,CAAC;AAE1G,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,oBAAoB,CAOtB;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,oBAAoB,CAepF;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/D;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAgB5D;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAqBvF"}
@@ -7,12 +7,36 @@ import { existsSync, readFileSync } from 'node:fs';
7
7
  import { join } from 'node:path';
8
8
  export const CAPTURE_BUILD_IDENTITY_FILE = 'capture-build.json';
9
9
  export const MAX_CAPTURE_BUILD_DIRTY_PATHS = 50;
10
+ /**
11
+ * Paths whose dirtiness cannot reach a render, and are therefore not evidence about the build.
12
+ *
13
+ * ★ THE QUESTION THE DIRTY LIST ANSWERS IS "COULD WHAT I CAPTURED DIFFER FROM THE COMMITTED TREE". A
14
+ * file that no build step reads and no scene imports cannot change a pixel, so listing it does not
15
+ * answer that question — it just adds noise to the answer.
16
+ *
17
+ * ★ THESE TWO ARE THE REVIEW WORKFLOW'S OWN OUTPUT, WHICH MAKES THE NOISE SELF-INFLICTED AND RECURRING.
18
+ * Commissioning writes a request into `reference-image-requests/` and holding writes
19
+ * `scripts/reference-image-held.json`; both are then uncommitted, so the NEXT review of the same session
20
+ * reports "Built with uncommitted changes" and names files the reviewer just created by reviewing. A
21
+ * warning that fires because you used the tool teaches you to ignore the warning, which is the one
22
+ * outcome worse than not having it — and it fires on exactly the iterative loop the tool exists for.
23
+ *
24
+ * ★ ADDING TO THIS LIST IS A CLAIM, NOT A CONVENIENCE. The claim is that nothing under the prefix is read
25
+ * by a build step or a scene. `functional/baselines/` deliberately stays OUT: a changed baseline does not
26
+ * alter a render, but it does alter what a capture reports as changed, so its dirtiness is evidence about
27
+ * the run even though it is not evidence about the build.
28
+ */
29
+ export const CAPTURE_BUILD_DIRTY_EXEMPT_PREFIXES = [
30
+ 'reference-image-requests/',
31
+ 'scripts/reference-image-held.json',
32
+ ];
10
33
  export const UNSTAMPED_CAPTURE_BUILD = { commit: null, dirty: [], dirtyOmitted: 0 };
11
34
  export function createCaptureBuildIdentity(commit, allDirtyPaths) {
35
+ const relevant = allDirtyPaths.filter((path) => !isCaptureBuildDirtyExempt(path));
12
36
  return {
13
37
  commit,
14
- dirty: allDirtyPaths.slice(0, MAX_CAPTURE_BUILD_DIRTY_PATHS),
15
- dirtyOmitted: Math.max(0, allDirtyPaths.length - MAX_CAPTURE_BUILD_DIRTY_PATHS),
38
+ dirty: relevant.slice(0, MAX_CAPTURE_BUILD_DIRTY_PATHS),
39
+ dirtyOmitted: Math.max(0, relevant.length - MAX_CAPTURE_BUILD_DIRTY_PATHS),
16
40
  };
17
41
  }
18
42
  /** Reads git once at build time and creates the record that is stamped into dist. */
@@ -33,6 +57,13 @@ export function getCaptureBuildIdentity(repositoryRoot) {
33
57
  return UNSTAMPED_CAPTURE_BUILD;
34
58
  }
35
59
  }
60
+ /** Whether a dirty path is one the build and the scenes provably never read. */
61
+ export function isCaptureBuildDirtyExempt(path) {
62
+ // A rename record is `old -> new`; either side landing under an exempt prefix is still the same class
63
+ // of file, and the pair is only formatted for a human to read.
64
+ const candidates = path.includes(' -> ') ? path.split(' -> ') : [path];
65
+ return candidates.every((candidate) => CAPTURE_BUILD_DIRTY_EXEMPT_PREFIXES.some((prefix) => candidate.startsWith(prefix)));
66
+ }
36
67
  /** Paths from `git status --porcelain=v1 -z`; rename/copy pairs remain one readable entry. */
37
68
  export function parseGitStatusPaths(status) {
38
69
  const records = status.split('\0');
@@ -1 +1 @@
1
- {"version":3,"file":"captureBuildIdentity.js","sourceRoot":"","sources":["../src/captureBuildIdentity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"captureBuildIdentity.js","sourceRoot":"","sources":["../src/captureBuildIdentity.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/tool-capture",
3
- "version": "0.4.0-next.1585.bf131c8",
3
+ "version": "0.4.0-next.1602.af48ed1",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,11 +42,11 @@
42
42
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
43
43
  },
44
44
  "dependencies": {
45
- "@flighthq/capture": "0.4.0-next.1585.bf131c8",
46
- "@flighthq/effects-wgpu": "0.4.0-next.1585.bf131c8",
47
- "@flighthq/render-wgpu": "0.4.0-next.1585.bf131c8",
48
- "@flighthq/bitmap": "0.4.0-next.1585.bf131c8",
49
- "@flighthq/types": "0.4.0-next.1585.bf131c8",
45
+ "@flighthq/capture": "0.4.0-next.1602.af48ed1",
46
+ "@flighthq/effects-wgpu": "0.4.0-next.1602.af48ed1",
47
+ "@flighthq/render-wgpu": "0.4.0-next.1602.af48ed1",
48
+ "@flighthq/bitmap": "0.4.0-next.1602.af48ed1",
49
+ "@flighthq/types": "0.4.0-next.1602.af48ed1",
50
50
  "@playwright/test": "^1.50.0",
51
51
  "picocolors": "^1.1.1"
52
52
  },
@@ -9,6 +9,7 @@ import {
9
9
  CAPTURE_BUILD_IDENTITY_FILE,
10
10
  createCaptureBuildIdentity,
11
11
  getCaptureBuildIdentity,
12
+ isCaptureBuildDirtyExempt,
12
13
  parseGitStatusPaths,
13
14
  readCaptureBuildIdentity,
14
15
  } from './captureBuildIdentity';
@@ -22,6 +23,42 @@ describe('createCaptureBuildIdentity', () => {
22
23
  expect(build.dirty).toEqual(paths.slice(0, 50));
23
24
  expect(build.dirtyOmitted).toBe(5);
24
25
  });
26
+
27
+ // ★ THE REVIEW WORKFLOW'S OWN OUTPUT IS NOT EVIDENCE ABOUT THE BUILD. Commissioning writes a request
28
+ // file and holding writes the ledger; both are then uncommitted, so the next review in the same session
29
+ // warned "Built with uncommitted changes" and named files the reviewer had just created BY REVIEWING.
30
+ // A warning that fires because you used the tool is one people learn to ignore.
31
+ it('ignores the request queue and the hold ledger, which no build step reads', () => {
32
+ const build = createCaptureBuildIdentity('a'.repeat(40), [
33
+ 'reference-image-requests/09cb2e5b.json',
34
+ 'scripts/reference-image-held.json',
35
+ ]);
36
+
37
+ expect(build.dirty).toEqual([]);
38
+ expect(build.dirtyOmitted).toBe(0);
39
+ });
40
+
41
+ // The exemption must not swallow the signal it sits next to: a real source edit alongside a request file
42
+ // is still a dirty build, and the warning still has to say so.
43
+ it('still reports a source path dirtied in the same tree', () => {
44
+ const build = createCaptureBuildIdentity('a'.repeat(40), [
45
+ 'reference-image-requests/09cb2e5b.json',
46
+ 'functional/scenes/text-basic.ts',
47
+ ]);
48
+
49
+ expect(build.dirty).toEqual(['functional/scenes/text-basic.ts']);
50
+ });
51
+
52
+ // The omitted count is taken AFTER the exemption, or a queue of fifty stale requests would report fifty
53
+ // omissions and re-create the noise the exemption removes.
54
+ it('counts omissions after the exemption, not before', () => {
55
+ const requests = Array.from({ length: 60 }, (_, index) => `reference-image-requests/r${index}.json`);
56
+
57
+ const build = createCaptureBuildIdentity('a'.repeat(40), [...requests, 'packages/bitmap/src/bitmap.ts']);
58
+
59
+ expect(build.dirty).toEqual(['packages/bitmap/src/bitmap.ts']);
60
+ expect(build.dirtyOmitted).toBe(0);
61
+ });
25
62
  });
26
63
 
27
64
  describe('getCaptureBuildIdentity', () => {
@@ -51,6 +88,31 @@ describe('getCaptureBuildIdentity', () => {
51
88
  });
52
89
  });
53
90
 
91
+ describe('isCaptureBuildDirtyExempt', () => {
92
+ it('exempts a path under the request queue', () => {
93
+ expect(isCaptureBuildDirtyExempt('reference-image-requests/09cb2e5b.json')).toBe(true);
94
+ });
95
+
96
+ it('does not exempt a scene or a package source', () => {
97
+ expect(isCaptureBuildDirtyExempt('functional/scenes/text-basic.ts')).toBe(false);
98
+ expect(isCaptureBuildDirtyExempt('packages/bitmap/src/bitmap.ts')).toBe(false);
99
+ });
100
+
101
+ // ★ `functional/baselines/` IS DELIBERATELY NOT EXEMPT, and the distinction is the whole rule. A changed
102
+ // baseline alters no render, but it does alter what a capture reports as CHANGED — so its dirtiness is
103
+ // evidence about the run even though it is not evidence about the build.
104
+ it('does not exempt a committed baseline', () => {
105
+ expect(isCaptureBuildDirtyExempt('functional/baselines/text-basic.json')).toBe(false);
106
+ });
107
+
108
+ // A rename is one readable record with both sides; exempting it requires both sides to be exempt, so a
109
+ // file moved OUT of the queue into the tree still counts as dirty.
110
+ it('exempts a rename only when both sides are exempt', () => {
111
+ expect(isCaptureBuildDirtyExempt('reference-image-requests/a.json -> reference-image-requests/b.json')).toBe(true);
112
+ expect(isCaptureBuildDirtyExempt('reference-image-requests/a.json -> functional/scenes/a.ts')).toBe(false);
113
+ });
114
+ });
115
+
54
116
  describe('parseGitStatusPaths', () => {
55
117
  it('keeps porcelain paths literal and represents a rename as one dirty entry', () => {
56
118
  expect(parseGitStatusPaths(' M ordinary.ts\0?? path with spaces.ts\0R renamed.ts\0old.ts\0')).toEqual([