playhead-cli 0.1.0
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/Dockerfile +24 -0
- package/LICENSE +21 -0
- package/README.md +184 -0
- package/action.yml +71 -0
- package/dist/audio/mux.d.ts +29 -0
- package/dist/audio/mux.d.ts.map +1 -0
- package/dist/audio/timing.d.ts +6 -0
- package/dist/audio/timing.d.ts.map +1 -0
- package/dist/audio/tts.d.ts +23 -0
- package/dist/audio/tts.d.ts.map +1 -0
- package/dist/authoring/author.d.ts +40 -0
- package/dist/authoring/author.d.ts.map +1 -0
- package/dist/authoring/catalog.d.ts +31 -0
- package/dist/authoring/catalog.d.ts.map +1 -0
- package/dist/authoring/explore.d.ts +30 -0
- package/dist/authoring/explore.d.ts.map +1 -0
- package/dist/authoring/serialize.d.ts +26 -0
- package/dist/authoring/serialize.d.ts.map +1 -0
- package/dist/authoring/validate.d.ts +31 -0
- package/dist/authoring/validate.d.ts.map +1 -0
- package/dist/beforeafter.d.ts +25 -0
- package/dist/beforeafter.d.ts.map +1 -0
- package/dist/bundle/hash.d.ts +3 -0
- package/dist/bundle/hash.d.ts.map +1 -0
- package/dist/bundle/reader.d.ts +6 -0
- package/dist/bundle/reader.d.ts.map +1 -0
- package/dist/bundle/types.d.ts +54 -0
- package/dist/bundle/types.d.ts.map +1 -0
- package/dist/bundle/writer.d.ts +35 -0
- package/dist/bundle/writer.d.ts.map +1 -0
- package/dist/capture/driver-api.d.ts +190 -0
- package/dist/capture/driver-api.d.ts.map +1 -0
- package/dist/capture/events.d.ts +78 -0
- package/dist/capture/events.d.ts.map +1 -0
- package/dist/capture/executor.d.ts +19 -0
- package/dist/capture/executor.d.ts.map +1 -0
- package/dist/capture/playwright-driver.d.ts +122 -0
- package/dist/capture/playwright-driver.d.ts.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +6648 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/compose/camera/interpolate.d.ts +9 -0
- package/dist/compose/camera/interpolate.d.ts.map +1 -0
- package/dist/compose/camera/planner.d.ts +19 -0
- package/dist/compose/camera/planner.d.ts.map +1 -0
- package/dist/compose/captions.d.ts +22 -0
- package/dist/compose/captions.d.ts.map +1 -0
- package/dist/compose/cursor/path.d.ts +17 -0
- package/dist/compose/cursor/path.d.ts.map +1 -0
- package/dist/compose/cursor/render.d.ts +10 -0
- package/dist/compose/cursor/render.d.ts.map +1 -0
- package/dist/compose/index.d.ts +25 -0
- package/dist/compose/index.d.ts.map +1 -0
- package/dist/compose/kinds.d.ts +27 -0
- package/dist/compose/kinds.d.ts.map +1 -0
- package/dist/compose/overlays/build.d.ts +7 -0
- package/dist/compose/overlays/build.d.ts.map +1 -0
- package/dist/compose/overlays/draw.d.ts +12 -0
- package/dist/compose/overlays/draw.d.ts.map +1 -0
- package/dist/compose/overlays/text.d.ts +18 -0
- package/dist/compose/overlays/text.d.ts.map +1 -0
- package/dist/compose/render/encoder.d.ts +13 -0
- package/dist/compose/render/encoder.d.ts.map +1 -0
- package/dist/compose/render/frameStore.d.ts +27 -0
- package/dist/compose/render/frameStore.d.ts.map +1 -0
- package/dist/compose/render/renderer.d.ts +5 -0
- package/dist/compose/render/renderer.d.ts.map +1 -0
- package/dist/compose/timeline/pacing.d.ts +36 -0
- package/dist/compose/timeline/pacing.d.ts.map +1 -0
- package/dist/compose/types.d.ts +236 -0
- package/dist/compose/types.d.ts.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4963 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/jira.d.ts +44 -0
- package/dist/integrations/jira.d.ts.map +1 -0
- package/dist/mcp/bin.d.ts +3 -0
- package/dist/mcp/bin.d.ts.map +1 -0
- package/dist/mcp/bin.js +5749 -0
- package/dist/mcp/bin.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/shared/easing.d.ts +9 -0
- package/dist/shared/easing.d.ts.map +1 -0
- package/dist/shared/exit.d.ts +32 -0
- package/dist/shared/exit.d.ts.map +1 -0
- package/dist/shared/ffmpeg.d.ts +19 -0
- package/dist/shared/ffmpeg.d.ts.map +1 -0
- package/dist/shared/geometry.d.ts +47 -0
- package/dist/shared/geometry.d.ts.map +1 -0
- package/dist/shared/log.d.ts +10 -0
- package/dist/shared/log.d.ts.map +1 -0
- package/dist/shared/version.d.ts +4 -0
- package/dist/shared/version.d.ts.map +1 -0
- package/dist/spec/locators.d.ts +62 -0
- package/dist/spec/locators.d.ts.map +1 -0
- package/dist/spec/parse.d.ts +16 -0
- package/dist/spec/parse.d.ts.map +1 -0
- package/dist/spec/schema.d.ts +365 -0
- package/dist/spec/schema.d.ts.map +1 -0
- package/dist/theme/index.d.ts +23 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/verify/checks.d.ts +27 -0
- package/dist/verify/checks.d.ts.map +1 -0
- package/dist/verify/contact-sheet.d.ts +7 -0
- package/dist/verify/contact-sheet.d.ts.map +1 -0
- package/dist/verify/media.d.ts +42 -0
- package/dist/verify/media.d.ts.map +1 -0
- package/dist/verify/report.d.ts +12 -0
- package/dist/verify/report.d.ts.map +1 -0
- package/dist/verify/runner.d.ts +13 -0
- package/dist/verify/runner.d.ts.map +1 -0
- package/dist/verify/types.d.ts +63 -0
- package/dist/verify/types.d.ts.map +1 -0
- package/dist/verify/vision.d.ts +19 -0
- package/dist/verify/vision.d.ts.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VerifyContext, CheckResult } from './types.js';
|
|
2
|
+
/** 1. Every target legibly in frame around its action beat. */
|
|
3
|
+
export declare function checkTargetInFrame(ctx: VerifyContext): Promise<CheckResult>;
|
|
4
|
+
/** 2. Rendered cursor sits on the target at each click beat. */
|
|
5
|
+
export declare function checkCursorOnTarget(ctx: VerifyContext): Promise<CheckResult>;
|
|
6
|
+
/** 3. Every action visibly changed the UI (dead-click detection). */
|
|
7
|
+
export declare function checkActionEffect(ctx: VerifyContext): Promise<CheckResult>;
|
|
8
|
+
/** 4. No unplanned frozen footage, no blank frames, in the delivered video. */
|
|
9
|
+
export declare function checkFrozenBlank(ctx: VerifyContext): Promise<CheckResult>;
|
|
10
|
+
/** 5. Captions legible: no truncation, font floor respected, inside safe bounds. */
|
|
11
|
+
export declare function checkCaptions(ctx: VerifyContext): Promise<CheckResult>;
|
|
12
|
+
/** 6. Pacing sanity: steps get readable screen time; total duration sane. */
|
|
13
|
+
export declare function checkPacing(ctx: VerifyContext): Promise<CheckResult>;
|
|
14
|
+
/** 7. The MP4 itself is intact and matches the manifest. */
|
|
15
|
+
/** 9. Narration audio: when the video was narrated, the track must exist, be audible, and span the video. */
|
|
16
|
+
export declare function checkAudio(ctx: VerifyContext): Promise<CheckResult>;
|
|
17
|
+
export declare function checkEncode(ctx: VerifyContext): Promise<CheckResult>;
|
|
18
|
+
/** 8. Masking held: masked regions are covered in footage, secrets absent from the log. */
|
|
19
|
+
export declare function checkMasks(ctx: VerifyContext): Promise<CheckResult>;
|
|
20
|
+
/**
|
|
21
|
+
* 10. The DELIVERED pixels match the plan: for sampled steps, the region of the output MP4
|
|
22
|
+
* where the subject should be must correlate with the same region of the source bundle frame.
|
|
23
|
+
* Every geometry check above re-runs the planner's math — this one closes the plan-vs-pixels
|
|
24
|
+
* hole: a renderer drawing the wrong frame or the wrong crop fails HERE.
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkOutputPixels(ctx: VerifyContext): Promise<CheckResult>;
|
|
27
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/verify/checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAmC5E,+DAA+D;AAC/D,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA4DjF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA4BlF;AAED,qEAAqE;AACrE,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAuFhF;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAwE/E;AAED,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5E;AAED,6EAA6E;AAC7E,wBAAsB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAc1E;AAED,4DAA4D;AAC5D,6GAA6G;AAC7G,wBAAsB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA8EzE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAsB1E;AAED,2FAA2F;AAC3F,wBAAsB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAgDzE;AAkBD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAwDhF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComposeManifest } from '../compose/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Contact sheet: one tile per step at its action beat (decoded from the OUTPUT video —
|
|
4
|
+
* what viewers actually see) plus first and last frames, annotated with captions.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderContactSheet(manifest: ComposeManifest, videoPath: string, outPath: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=contact-sheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-sheet.d.ts","sourceRoot":"","sources":["../../src/verify/contact-sheet.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAU3D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAiEjB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { BundleData } from '../bundle/types.js';
|
|
2
|
+
/** Extract grayscale frames from the output video at a fixed rate. */
|
|
3
|
+
export declare function extractGrayFrames(videoPath: string, fps: number, w: number, h: number): Promise<{
|
|
4
|
+
frames: Buffer[];
|
|
5
|
+
intervalMs: number;
|
|
6
|
+
}>;
|
|
7
|
+
/** Extract one PNG frame from the output video at a timestamp (ms). */
|
|
8
|
+
export declare function extractFrameAt(videoPath: string, tMs: number): Promise<Buffer>;
|
|
9
|
+
export interface ProbeInfo {
|
|
10
|
+
codec: string;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
durationSec: number;
|
|
14
|
+
fps: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function probeVideo(videoPath: string): Promise<ProbeInfo>;
|
|
17
|
+
export declare function meanAbsDiff(a: Buffer, b: Buffer): number;
|
|
18
|
+
export declare function variance(a: Buffer): number;
|
|
19
|
+
/** Decode a capture-bundle source frame to grayscale at reduced width. */
|
|
20
|
+
export declare function sourceFrameGray(bundle: BundleData, tMs: number, width: number): Promise<{
|
|
21
|
+
data: Buffer;
|
|
22
|
+
w: number;
|
|
23
|
+
h: number;
|
|
24
|
+
frameT: number;
|
|
25
|
+
}>;
|
|
26
|
+
/** Decode a region of a source frame (frame px) to grayscale raw. */
|
|
27
|
+
export declare function sourceRegionGray(bundle: BundleData, tMs: number, region: {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
w: number;
|
|
31
|
+
h: number;
|
|
32
|
+
}, preferAfter?: boolean, color?: boolean): Promise<Buffer | null>;
|
|
33
|
+
/** Crop a region from PNG bytes (or an image file), grayscale, resize to 48x48 raw. */
|
|
34
|
+
export declare function regionGray48(input: Buffer | string, rect: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
w: number;
|
|
38
|
+
h: number;
|
|
39
|
+
}): Promise<Buffer | null>;
|
|
40
|
+
/** Normalized cross-correlation of two equal-length gray buffers, in [-1, 1]. */
|
|
41
|
+
export declare function normalizedCorrelation(a: Buffer, b: Buffer): number;
|
|
42
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/verify/media.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,sEAAsE;AACtE,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBnD;AAED,uEAAuE;AACvE,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAcpF;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAuBtE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO1C;AAED,0EAA0E;AAC1E,wBAAsB,eAAe,CACnC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAQjE;AAED,qEAAqE;AACrE,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACtD,WAAW,UAAQ,EACnB,KAAK,UAAQ,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBxB;AAED,uFAAuF;AACvF,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAevI;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAuBlE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Verdict } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The canonical signable payload: everything that makes the verdict a CLAIM (result, artifact
|
|
4
|
+
* hashes, provenance, per-check outcomes), in a fixed key order. Paths are excluded — moving
|
|
5
|
+
* files doesn't change what was proven.
|
|
6
|
+
*/
|
|
7
|
+
export declare function signablePayload(v: Omit<Verdict, 'signature'>): string;
|
|
8
|
+
/** HMAC-SHA256 signature over the canonical payload; null when no key is configured. */
|
|
9
|
+
export declare function signVerdict(v: Omit<Verdict, 'signature'>, key?: string | undefined): string | null;
|
|
10
|
+
/** JUnit XML: one testsuite per verdict, one testcase per check — the shape every CI ingests. */
|
|
11
|
+
export declare function toJUnit(v: Verdict, suiteName?: string): string;
|
|
12
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/verify/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,MAAM,CAkBrE;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,GAAG,qBAAmC,GAAG,MAAM,GAAG,IAAI,CAGhH;AAED,iGAAiG;AACjG,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,SAAa,GAAG,MAAM,CAuBlE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BundleData } from '../bundle/types.js';
|
|
2
|
+
import type { ComposeManifest } from '../compose/types.js';
|
|
3
|
+
import type { Verdict } from './types.js';
|
|
4
|
+
/** Bumped whenever a check is added or its semantics change — part of provenance. */
|
|
5
|
+
export declare const CHECK_SUITE_VERSION = "playhead/checks@2";
|
|
6
|
+
export interface VerifyOptions {
|
|
7
|
+
outDir: string;
|
|
8
|
+
vision?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function verify(bundle: BundleData, manifest: ComposeManifest, videoPath: string, opts: VerifyOptions): Promise<Verdict>;
|
|
11
|
+
/** Re-load a compose manifest from disk (for `playhead verify <bundle> <mp4>`). */
|
|
12
|
+
export declare function loadComposeManifest(path: string): Promise<ComposeManifest>;
|
|
13
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/verify/runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAe,OAAO,EAAiB,MAAM,YAAY,CAAC;AAsBtE,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,MAAM,CAC1B,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,OAAO,CAAC,CAiElB;AAED,mFAAmF;AACnF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAMhF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { BundleData } from '../bundle/types.js';
|
|
2
|
+
import type { ComposeManifest } from '../compose/types.js';
|
|
3
|
+
export type CheckStatus = 'pass' | 'fail' | 'warn' | 'skip';
|
|
4
|
+
export interface CheckEvidence {
|
|
5
|
+
stepRef?: string;
|
|
6
|
+
t?: number;
|
|
7
|
+
note: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CheckResult {
|
|
10
|
+
id: string;
|
|
11
|
+
status: CheckStatus;
|
|
12
|
+
details: string;
|
|
13
|
+
evidence?: CheckEvidence[];
|
|
14
|
+
}
|
|
15
|
+
export interface VerifyContext {
|
|
16
|
+
bundle: BundleData;
|
|
17
|
+
manifest: ComposeManifest;
|
|
18
|
+
videoPath: string;
|
|
19
|
+
outDir: string;
|
|
20
|
+
}
|
|
21
|
+
/** Who/what/when produced this verdict — the difference between a claim and evidence. */
|
|
22
|
+
export interface VerdictProvenance {
|
|
23
|
+
playheadVersion: string;
|
|
24
|
+
/** Hash of the spec as executed (from the bundle). */
|
|
25
|
+
specHash: string;
|
|
26
|
+
appUrl: string;
|
|
27
|
+
capturedAt: string;
|
|
28
|
+
verifiedAt: string;
|
|
29
|
+
checkSuiteVersion: string;
|
|
30
|
+
host: string;
|
|
31
|
+
/** Present when this verdict covers a FAILED capture's partial bundle / failure clip. */
|
|
32
|
+
partial?: boolean;
|
|
33
|
+
failure?: {
|
|
34
|
+
stepRef: string;
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface Verdict {
|
|
39
|
+
schema: 'playhead/verdict@2';
|
|
40
|
+
verdict: 'publishable' | 'not-publishable';
|
|
41
|
+
video: {
|
|
42
|
+
path: string;
|
|
43
|
+
sha256: string;
|
|
44
|
+
};
|
|
45
|
+
bundleHashes: {
|
|
46
|
+
events: string;
|
|
47
|
+
framesIndex: string;
|
|
48
|
+
};
|
|
49
|
+
provenance: VerdictProvenance;
|
|
50
|
+
checks: CheckResult[];
|
|
51
|
+
contactSheet: string;
|
|
52
|
+
vision: {
|
|
53
|
+
model: string;
|
|
54
|
+
findings: {
|
|
55
|
+
severity: string;
|
|
56
|
+
note: string;
|
|
57
|
+
}[];
|
|
58
|
+
} | null;
|
|
59
|
+
/** HMAC-SHA256 over the canonical signable payload, keyed by PLAYHEAD_SIGNING_KEY.
|
|
60
|
+
* Null when no key is configured — an unsigned verdict is explicit, never implied. */
|
|
61
|
+
signature: string | null;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/verify/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAAC;IAC3C,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,YAAY,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,UAAU,EAAE,iBAAiB,CAAC;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACjF;2FACuF;IACvF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CheckResult } from './types.js';
|
|
2
|
+
import type { ComposeManifest } from '../compose/types.js';
|
|
3
|
+
export interface VisionReview {
|
|
4
|
+
model: string;
|
|
5
|
+
findings: {
|
|
6
|
+
severity: string;
|
|
7
|
+
note: string;
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Optional AI review: sends the contact sheet to Claude for a judgment call the
|
|
12
|
+
* deterministic checks can't make ("does this read as a coherent, professional
|
|
13
|
+
* walkthrough?"). Advisory only — findings become warn-level check entries.
|
|
14
|
+
*/
|
|
15
|
+
export declare function visionReview(contactSheetPath: string, manifest: ComposeManifest): Promise<{
|
|
16
|
+
check: CheckResult;
|
|
17
|
+
review: VisionReview | null;
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=vision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision.d.ts","sourceRoot":"","sources":["../../src/verify/vision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAK3D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,CAAC,CA0E9D"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "playhead-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Product video as a build artifact: spec + live product → finished, verified video.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"video",
|
|
9
|
+
"demo",
|
|
10
|
+
"walkthrough",
|
|
11
|
+
"playwright",
|
|
12
|
+
"screen-recording",
|
|
13
|
+
"verified",
|
|
14
|
+
"ci",
|
|
15
|
+
"documentation"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/Cypher-aman/playhead.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://playheadhq.com",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"playhead": "./dist/cli/index.js",
|
|
27
|
+
"playhead-mcp": "./dist/mcp/bin.js"
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"import": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"action.yml",
|
|
41
|
+
"Dockerfile",
|
|
42
|
+
"LICENSE"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"demo": "node demo/server.mjs",
|
|
50
|
+
"playhead": "tsx src/cli/index.ts",
|
|
51
|
+
"prepublishOnly": "npm run build && npm test"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@anthropic-ai/sdk": "^0.123.0",
|
|
55
|
+
"@expo-google-fonts/inter": "^0.4.2",
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
57
|
+
"@napi-rs/canvas": "^1.0.8",
|
|
58
|
+
"commander": "^15.0.0",
|
|
59
|
+
"ffmpeg-static": "^5.3.0",
|
|
60
|
+
"ffprobe-static": "^3.1.0",
|
|
61
|
+
"picocolors": "^1.1.1",
|
|
62
|
+
"playwright": "^1.62.1",
|
|
63
|
+
"sharp": "^0.35.4",
|
|
64
|
+
"yaml": "^2.9.0",
|
|
65
|
+
"zod": "^4.5.4"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@types/node": "^26.4.1",
|
|
69
|
+
"tsup": "^8.5.1",
|
|
70
|
+
"tsx": "^4.23.13",
|
|
71
|
+
"typescript": "^7.0.2",
|
|
72
|
+
"vitest": "^3.2.7"
|
|
73
|
+
}
|
|
74
|
+
}
|