doc-detective-common 4.32.0 → 4.34.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/dist/index.cjs CHANGED
@@ -30469,9 +30469,10 @@ var schemas_default = {
30469
30469
  anyOf: [
30470
30470
  {
30471
30471
  title: "Screenshot (simple)",
30472
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
30472
30473
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
30473
30474
  type: "string",
30474
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30475
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30475
30476
  transform: [
30476
30477
  "trim"
30477
30478
  ]
@@ -30705,9 +30706,10 @@ var schemas_default = {
30705
30706
  },
30706
30707
  path: {
30707
30708
  title: "Screenshot (simple)",
30709
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
30708
30710
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
30709
30711
  type: "string",
30710
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30712
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30711
30713
  transform: [
30712
30714
  "trim"
30713
30715
  ]
@@ -30965,9 +30967,10 @@ var schemas_default = {
30965
30967
  schemas: {
30966
30968
  path: {
30967
30969
  title: "Screenshot (simple)",
30970
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
30968
30971
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
30969
30972
  type: "string",
30970
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30973
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
30971
30974
  transform: [
30972
30975
  "trim"
30973
30976
  ]
@@ -31201,9 +31204,10 @@ var schemas_default = {
31201
31204
  },
31202
31205
  path: {
31203
31206
  title: "Screenshot (simple)",
31207
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
31204
31208
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
31205
31209
  type: "string",
31206
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
31210
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
31207
31211
  transform: [
31208
31212
  "trim"
31209
31213
  ]
@@ -31677,9 +31681,10 @@ var schemas_default = {
31677
31681
  },
31678
31682
  path: {
31679
31683
  title: "Screenshot (simple)",
31684
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
31680
31685
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
31681
31686
  type: "string",
31682
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
31687
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
31683
31688
  transform: [
31684
31689
  "trim"
31685
31690
  ]
@@ -32061,6 +32066,7 @@ var schemas_default = {
32061
32066
  "image.png",
32062
32067
  "static/images/image.png",
32063
32068
  "/User/manny/projects/doc-detective/static/images/image.png",
32069
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
32064
32070
  "https://example.com/static/images/image.png",
32065
32071
  {
32066
32072
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -34495,10 +34501,11 @@ var schemas_default = {
34495
34501
  },
34496
34502
  overwrite: {
34497
34503
  type: "string",
34498
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
34504
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
34499
34505
  enum: [
34500
34506
  "true",
34501
- "false"
34507
+ "false",
34508
+ "aboveVariation"
34502
34509
  ]
34503
34510
  },
34504
34511
  name: {
@@ -34556,6 +34563,88 @@ var schemas_default = {
34556
34563
  }
34557
34564
  }
34558
34565
  ]
34566
+ },
34567
+ verify: {
34568
+ title: "Recording verify guards",
34569
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
34570
+ type: "object",
34571
+ additionalProperties: false,
34572
+ properties: {
34573
+ minDuration: {
34574
+ type: "number",
34575
+ description: "Fail if the video is shorter than this many seconds.",
34576
+ minimum: 0
34577
+ },
34578
+ maxDuration: {
34579
+ type: "number",
34580
+ description: "Fail if the video is longer than this many seconds.",
34581
+ minimum: 0
34582
+ },
34583
+ resolution: {
34584
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
34585
+ anyOf: [
34586
+ {
34587
+ type: "boolean",
34588
+ title: "Verify resolution (boolean)"
34589
+ },
34590
+ {
34591
+ type: "object",
34592
+ title: "Verify resolution (detailed)",
34593
+ additionalProperties: false,
34594
+ required: [
34595
+ "width",
34596
+ "height"
34597
+ ],
34598
+ properties: {
34599
+ width: {
34600
+ type: "integer",
34601
+ minimum: 1
34602
+ },
34603
+ height: {
34604
+ type: "integer",
34605
+ minimum: 1
34606
+ }
34607
+ }
34608
+ }
34609
+ ]
34610
+ },
34611
+ notBlack: {
34612
+ type: "boolean",
34613
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
34614
+ }
34615
+ }
34616
+ },
34617
+ checkpoints: {
34618
+ title: "Recording checkpoints",
34619
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
34620
+ anyOf: [
34621
+ {
34622
+ type: "boolean",
34623
+ title: "Recording checkpoints (boolean)",
34624
+ description: "If `true`, enables checkpoints with default settings."
34625
+ },
34626
+ {
34627
+ type: "object",
34628
+ title: "Recording checkpoints (detailed)",
34629
+ additionalProperties: false,
34630
+ properties: {
34631
+ maxVariation: {
34632
+ type: "number",
34633
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
34634
+ default: 0.05,
34635
+ minimum: 0,
34636
+ maximum: 1
34637
+ },
34638
+ directory: {
34639
+ type: "string",
34640
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
34641
+ transform: [
34642
+ "trim"
34643
+ ]
34644
+ }
34645
+ }
34646
+ }
34647
+ ]
34559
34648
  }
34560
34649
  },
34561
34650
  title: "Record (detailed)"
@@ -34817,10 +34906,11 @@ var schemas_default = {
34817
34906
  },
34818
34907
  overwrite: {
34819
34908
  type: "string",
34820
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
34909
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
34821
34910
  enum: [
34822
34911
  "true",
34823
- "false"
34912
+ "false",
34913
+ "aboveVariation"
34824
34914
  ]
34825
34915
  },
34826
34916
  name: {
@@ -34878,6 +34968,88 @@ var schemas_default = {
34878
34968
  }
34879
34969
  }
34880
34970
  ]
34971
+ },
34972
+ verify: {
34973
+ title: "Recording verify guards",
34974
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
34975
+ type: "object",
34976
+ additionalProperties: false,
34977
+ properties: {
34978
+ minDuration: {
34979
+ type: "number",
34980
+ description: "Fail if the video is shorter than this many seconds.",
34981
+ minimum: 0
34982
+ },
34983
+ maxDuration: {
34984
+ type: "number",
34985
+ description: "Fail if the video is longer than this many seconds.",
34986
+ minimum: 0
34987
+ },
34988
+ resolution: {
34989
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
34990
+ anyOf: [
34991
+ {
34992
+ type: "boolean",
34993
+ title: "Verify resolution (boolean)"
34994
+ },
34995
+ {
34996
+ type: "object",
34997
+ title: "Verify resolution (detailed)",
34998
+ additionalProperties: false,
34999
+ required: [
35000
+ "width",
35001
+ "height"
35002
+ ],
35003
+ properties: {
35004
+ width: {
35005
+ type: "integer",
35006
+ minimum: 1
35007
+ },
35008
+ height: {
35009
+ type: "integer",
35010
+ minimum: 1
35011
+ }
35012
+ }
35013
+ }
35014
+ ]
35015
+ },
35016
+ notBlack: {
35017
+ type: "boolean",
35018
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
35019
+ }
35020
+ }
35021
+ },
35022
+ checkpoints: {
35023
+ title: "Recording checkpoints",
35024
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
35025
+ anyOf: [
35026
+ {
35027
+ type: "boolean",
35028
+ title: "Recording checkpoints (boolean)",
35029
+ description: "If `true`, enables checkpoints with default settings."
35030
+ },
35031
+ {
35032
+ type: "object",
35033
+ title: "Recording checkpoints (detailed)",
35034
+ additionalProperties: false,
35035
+ properties: {
35036
+ maxVariation: {
35037
+ type: "number",
35038
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
35039
+ default: 0.05,
35040
+ minimum: 0,
35041
+ maximum: 1
35042
+ },
35043
+ directory: {
35044
+ type: "string",
35045
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
35046
+ transform: [
35047
+ "trim"
35048
+ ]
35049
+ }
35050
+ }
35051
+ }
35052
+ ]
34881
35053
  }
34882
35054
  },
34883
35055
  title: "Record (detailed)"
@@ -34944,6 +35116,17 @@ var schemas_default = {
34944
35116
  path: "results.mp4",
34945
35117
  engine: "ffmpeg"
34946
35118
  },
35119
+ {
35120
+ path: "results.mp4",
35121
+ checkpoints: true
35122
+ },
35123
+ {
35124
+ path: "results.mp4",
35125
+ checkpoints: {
35126
+ maxVariation: 0.02,
35127
+ directory: "baselines/results"
35128
+ }
35129
+ },
34947
35130
  {
34948
35131
  path: "results.mp4",
34949
35132
  engine: {
@@ -76108,9 +76291,10 @@ var schemas_default = {
76108
76291
  anyOf: [
76109
76292
  {
76110
76293
  title: "Screenshot (simple)",
76294
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
76111
76295
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
76112
76296
  type: "string",
76113
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76297
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76114
76298
  transform: [
76115
76299
  "trim"
76116
76300
  ]
@@ -76344,9 +76528,10 @@ var schemas_default = {
76344
76528
  },
76345
76529
  path: {
76346
76530
  title: "Screenshot (simple)",
76531
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
76347
76532
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
76348
76533
  type: "string",
76349
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76534
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76350
76535
  transform: [
76351
76536
  "trim"
76352
76537
  ]
@@ -76604,9 +76789,10 @@ var schemas_default = {
76604
76789
  schemas: {
76605
76790
  path: {
76606
76791
  title: "Screenshot (simple)",
76792
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
76607
76793
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
76608
76794
  type: "string",
76609
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76795
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76610
76796
  transform: [
76611
76797
  "trim"
76612
76798
  ]
@@ -76840,9 +77026,10 @@ var schemas_default = {
76840
77026
  },
76841
77027
  path: {
76842
77028
  title: "Screenshot (simple)",
77029
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
76843
77030
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
76844
77031
  type: "string",
76845
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
77032
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
76846
77033
  transform: [
76847
77034
  "trim"
76848
77035
  ]
@@ -77316,9 +77503,10 @@ var schemas_default = {
77316
77503
  },
77317
77504
  path: {
77318
77505
  title: "Screenshot (simple)",
77506
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
77319
77507
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
77320
77508
  type: "string",
77321
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
77509
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
77322
77510
  transform: [
77323
77511
  "trim"
77324
77512
  ]
@@ -77700,6 +77888,7 @@ var schemas_default = {
77700
77888
  "image.png",
77701
77889
  "static/images/image.png",
77702
77890
  "/User/manny/projects/doc-detective/static/images/image.png",
77891
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
77703
77892
  "https://example.com/static/images/image.png",
77704
77893
  {
77705
77894
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -80134,10 +80323,11 @@ var schemas_default = {
80134
80323
  },
80135
80324
  overwrite: {
80136
80325
  type: "string",
80137
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
80326
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
80138
80327
  enum: [
80139
80328
  "true",
80140
- "false"
80329
+ "false",
80330
+ "aboveVariation"
80141
80331
  ]
80142
80332
  },
80143
80333
  name: {
@@ -80195,6 +80385,88 @@ var schemas_default = {
80195
80385
  }
80196
80386
  }
80197
80387
  ]
80388
+ },
80389
+ verify: {
80390
+ title: "Recording verify guards",
80391
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
80392
+ type: "object",
80393
+ additionalProperties: false,
80394
+ properties: {
80395
+ minDuration: {
80396
+ type: "number",
80397
+ description: "Fail if the video is shorter than this many seconds.",
80398
+ minimum: 0
80399
+ },
80400
+ maxDuration: {
80401
+ type: "number",
80402
+ description: "Fail if the video is longer than this many seconds.",
80403
+ minimum: 0
80404
+ },
80405
+ resolution: {
80406
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
80407
+ anyOf: [
80408
+ {
80409
+ type: "boolean",
80410
+ title: "Verify resolution (boolean)"
80411
+ },
80412
+ {
80413
+ type: "object",
80414
+ title: "Verify resolution (detailed)",
80415
+ additionalProperties: false,
80416
+ required: [
80417
+ "width",
80418
+ "height"
80419
+ ],
80420
+ properties: {
80421
+ width: {
80422
+ type: "integer",
80423
+ minimum: 1
80424
+ },
80425
+ height: {
80426
+ type: "integer",
80427
+ minimum: 1
80428
+ }
80429
+ }
80430
+ }
80431
+ ]
80432
+ },
80433
+ notBlack: {
80434
+ type: "boolean",
80435
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
80436
+ }
80437
+ }
80438
+ },
80439
+ checkpoints: {
80440
+ title: "Recording checkpoints",
80441
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
80442
+ anyOf: [
80443
+ {
80444
+ type: "boolean",
80445
+ title: "Recording checkpoints (boolean)",
80446
+ description: "If `true`, enables checkpoints with default settings."
80447
+ },
80448
+ {
80449
+ type: "object",
80450
+ title: "Recording checkpoints (detailed)",
80451
+ additionalProperties: false,
80452
+ properties: {
80453
+ maxVariation: {
80454
+ type: "number",
80455
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
80456
+ default: 0.05,
80457
+ minimum: 0,
80458
+ maximum: 1
80459
+ },
80460
+ directory: {
80461
+ type: "string",
80462
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
80463
+ transform: [
80464
+ "trim"
80465
+ ]
80466
+ }
80467
+ }
80468
+ }
80469
+ ]
80198
80470
  }
80199
80471
  },
80200
80472
  title: "Record (detailed)"
@@ -80456,10 +80728,11 @@ var schemas_default = {
80456
80728
  },
80457
80729
  overwrite: {
80458
80730
  type: "string",
80459
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
80731
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
80460
80732
  enum: [
80461
80733
  "true",
80462
- "false"
80734
+ "false",
80735
+ "aboveVariation"
80463
80736
  ]
80464
80737
  },
80465
80738
  name: {
@@ -80517,6 +80790,88 @@ var schemas_default = {
80517
80790
  }
80518
80791
  }
80519
80792
  ]
80793
+ },
80794
+ verify: {
80795
+ title: "Recording verify guards",
80796
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
80797
+ type: "object",
80798
+ additionalProperties: false,
80799
+ properties: {
80800
+ minDuration: {
80801
+ type: "number",
80802
+ description: "Fail if the video is shorter than this many seconds.",
80803
+ minimum: 0
80804
+ },
80805
+ maxDuration: {
80806
+ type: "number",
80807
+ description: "Fail if the video is longer than this many seconds.",
80808
+ minimum: 0
80809
+ },
80810
+ resolution: {
80811
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
80812
+ anyOf: [
80813
+ {
80814
+ type: "boolean",
80815
+ title: "Verify resolution (boolean)"
80816
+ },
80817
+ {
80818
+ type: "object",
80819
+ title: "Verify resolution (detailed)",
80820
+ additionalProperties: false,
80821
+ required: [
80822
+ "width",
80823
+ "height"
80824
+ ],
80825
+ properties: {
80826
+ width: {
80827
+ type: "integer",
80828
+ minimum: 1
80829
+ },
80830
+ height: {
80831
+ type: "integer",
80832
+ minimum: 1
80833
+ }
80834
+ }
80835
+ }
80836
+ ]
80837
+ },
80838
+ notBlack: {
80839
+ type: "boolean",
80840
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
80841
+ }
80842
+ }
80843
+ },
80844
+ checkpoints: {
80845
+ title: "Recording checkpoints",
80846
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
80847
+ anyOf: [
80848
+ {
80849
+ type: "boolean",
80850
+ title: "Recording checkpoints (boolean)",
80851
+ description: "If `true`, enables checkpoints with default settings."
80852
+ },
80853
+ {
80854
+ type: "object",
80855
+ title: "Recording checkpoints (detailed)",
80856
+ additionalProperties: false,
80857
+ properties: {
80858
+ maxVariation: {
80859
+ type: "number",
80860
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
80861
+ default: 0.05,
80862
+ minimum: 0,
80863
+ maximum: 1
80864
+ },
80865
+ directory: {
80866
+ type: "string",
80867
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
80868
+ transform: [
80869
+ "trim"
80870
+ ]
80871
+ }
80872
+ }
80873
+ }
80874
+ ]
80520
80875
  }
80521
80876
  },
80522
80877
  title: "Record (detailed)"
@@ -80583,6 +80938,17 @@ var schemas_default = {
80583
80938
  path: "results.mp4",
80584
80939
  engine: "ffmpeg"
80585
80940
  },
80941
+ {
80942
+ path: "results.mp4",
80943
+ checkpoints: true
80944
+ },
80945
+ {
80946
+ path: "results.mp4",
80947
+ checkpoints: {
80948
+ maxVariation: 0.02,
80949
+ directory: "baselines/results"
80950
+ }
80951
+ },
80586
80952
  {
80587
80953
  path: "results.mp4",
80588
80954
  engine: {
@@ -106419,10 +106785,11 @@ var schemas_default = {
106419
106785
  },
106420
106786
  overwrite: {
106421
106787
  type: "string",
106422
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
106788
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
106423
106789
  enum: [
106424
106790
  "true",
106425
- "false"
106791
+ "false",
106792
+ "aboveVariation"
106426
106793
  ]
106427
106794
  },
106428
106795
  name: {
@@ -106480,6 +106847,88 @@ var schemas_default = {
106480
106847
  }
106481
106848
  }
106482
106849
  ]
106850
+ },
106851
+ verify: {
106852
+ title: "Recording verify guards",
106853
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
106854
+ type: "object",
106855
+ additionalProperties: false,
106856
+ properties: {
106857
+ minDuration: {
106858
+ type: "number",
106859
+ description: "Fail if the video is shorter than this many seconds.",
106860
+ minimum: 0
106861
+ },
106862
+ maxDuration: {
106863
+ type: "number",
106864
+ description: "Fail if the video is longer than this many seconds.",
106865
+ minimum: 0
106866
+ },
106867
+ resolution: {
106868
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
106869
+ anyOf: [
106870
+ {
106871
+ type: "boolean",
106872
+ title: "Verify resolution (boolean)"
106873
+ },
106874
+ {
106875
+ type: "object",
106876
+ title: "Verify resolution (detailed)",
106877
+ additionalProperties: false,
106878
+ required: [
106879
+ "width",
106880
+ "height"
106881
+ ],
106882
+ properties: {
106883
+ width: {
106884
+ type: "integer",
106885
+ minimum: 1
106886
+ },
106887
+ height: {
106888
+ type: "integer",
106889
+ minimum: 1
106890
+ }
106891
+ }
106892
+ }
106893
+ ]
106894
+ },
106895
+ notBlack: {
106896
+ type: "boolean",
106897
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
106898
+ }
106899
+ }
106900
+ },
106901
+ checkpoints: {
106902
+ title: "Recording checkpoints",
106903
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
106904
+ anyOf: [
106905
+ {
106906
+ type: "boolean",
106907
+ title: "Recording checkpoints (boolean)",
106908
+ description: "If `true`, enables checkpoints with default settings."
106909
+ },
106910
+ {
106911
+ type: "object",
106912
+ title: "Recording checkpoints (detailed)",
106913
+ additionalProperties: false,
106914
+ properties: {
106915
+ maxVariation: {
106916
+ type: "number",
106917
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
106918
+ default: 0.05,
106919
+ minimum: 0,
106920
+ maximum: 1
106921
+ },
106922
+ directory: {
106923
+ type: "string",
106924
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
106925
+ transform: [
106926
+ "trim"
106927
+ ]
106928
+ }
106929
+ }
106930
+ }
106931
+ ]
106483
106932
  }
106484
106933
  },
106485
106934
  title: "Record (detailed)"
@@ -106741,10 +107190,11 @@ var schemas_default = {
106741
107190
  },
106742
107191
  overwrite: {
106743
107192
  type: "string",
106744
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
107193
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
106745
107194
  enum: [
106746
107195
  "true",
106747
- "false"
107196
+ "false",
107197
+ "aboveVariation"
106748
107198
  ]
106749
107199
  },
106750
107200
  name: {
@@ -106802,6 +107252,88 @@ var schemas_default = {
106802
107252
  }
106803
107253
  }
106804
107254
  ]
107255
+ },
107256
+ verify: {
107257
+ title: "Recording verify guards",
107258
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
107259
+ type: "object",
107260
+ additionalProperties: false,
107261
+ properties: {
107262
+ minDuration: {
107263
+ type: "number",
107264
+ description: "Fail if the video is shorter than this many seconds.",
107265
+ minimum: 0
107266
+ },
107267
+ maxDuration: {
107268
+ type: "number",
107269
+ description: "Fail if the video is longer than this many seconds.",
107270
+ minimum: 0
107271
+ },
107272
+ resolution: {
107273
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
107274
+ anyOf: [
107275
+ {
107276
+ type: "boolean",
107277
+ title: "Verify resolution (boolean)"
107278
+ },
107279
+ {
107280
+ type: "object",
107281
+ title: "Verify resolution (detailed)",
107282
+ additionalProperties: false,
107283
+ required: [
107284
+ "width",
107285
+ "height"
107286
+ ],
107287
+ properties: {
107288
+ width: {
107289
+ type: "integer",
107290
+ minimum: 1
107291
+ },
107292
+ height: {
107293
+ type: "integer",
107294
+ minimum: 1
107295
+ }
107296
+ }
107297
+ }
107298
+ ]
107299
+ },
107300
+ notBlack: {
107301
+ type: "boolean",
107302
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
107303
+ }
107304
+ }
107305
+ },
107306
+ checkpoints: {
107307
+ title: "Recording checkpoints",
107308
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
107309
+ anyOf: [
107310
+ {
107311
+ type: "boolean",
107312
+ title: "Recording checkpoints (boolean)",
107313
+ description: "If `true`, enables checkpoints with default settings."
107314
+ },
107315
+ {
107316
+ type: "object",
107317
+ title: "Recording checkpoints (detailed)",
107318
+ additionalProperties: false,
107319
+ properties: {
107320
+ maxVariation: {
107321
+ type: "number",
107322
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
107323
+ default: 0.05,
107324
+ minimum: 0,
107325
+ maximum: 1
107326
+ },
107327
+ directory: {
107328
+ type: "string",
107329
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
107330
+ transform: [
107331
+ "trim"
107332
+ ]
107333
+ }
107334
+ }
107335
+ }
107336
+ ]
106805
107337
  }
106806
107338
  },
106807
107339
  title: "Record (detailed)"
@@ -106868,6 +107400,17 @@ var schemas_default = {
106868
107400
  path: "results.mp4",
106869
107401
  engine: "ffmpeg"
106870
107402
  },
107403
+ {
107404
+ path: "results.mp4",
107405
+ checkpoints: true
107406
+ },
107407
+ {
107408
+ path: "results.mp4",
107409
+ checkpoints: {
107410
+ maxVariation: 0.02,
107411
+ directory: "baselines/results"
107412
+ }
107413
+ },
106871
107414
  {
106872
107415
  path: "results.mp4",
106873
107416
  engine: {
@@ -135034,9 +135577,10 @@ var schemas_default = {
135034
135577
  anyOf: [
135035
135578
  {
135036
135579
  title: "Screenshot (simple)",
135580
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
135037
135581
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
135038
135582
  type: "string",
135039
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135583
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135040
135584
  transform: [
135041
135585
  "trim"
135042
135586
  ]
@@ -135270,9 +135814,10 @@ var schemas_default = {
135270
135814
  },
135271
135815
  path: {
135272
135816
  title: "Screenshot (simple)",
135817
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
135273
135818
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
135274
135819
  type: "string",
135275
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135820
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135276
135821
  transform: [
135277
135822
  "trim"
135278
135823
  ]
@@ -135530,9 +136075,10 @@ var schemas_default = {
135530
136075
  schemas: {
135531
136076
  path: {
135532
136077
  title: "Screenshot (simple)",
136078
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
135533
136079
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
135534
136080
  type: "string",
135535
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
136081
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135536
136082
  transform: [
135537
136083
  "trim"
135538
136084
  ]
@@ -135766,9 +136312,10 @@ var schemas_default = {
135766
136312
  },
135767
136313
  path: {
135768
136314
  title: "Screenshot (simple)",
136315
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
135769
136316
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
135770
136317
  type: "string",
135771
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
136318
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
135772
136319
  transform: [
135773
136320
  "trim"
135774
136321
  ]
@@ -136242,9 +136789,10 @@ var schemas_default = {
136242
136789
  },
136243
136790
  path: {
136244
136791
  title: "Screenshot (simple)",
136792
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
136245
136793
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
136246
136794
  type: "string",
136247
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
136795
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
136248
136796
  transform: [
136249
136797
  "trim"
136250
136798
  ]
@@ -136626,6 +137174,7 @@ var schemas_default = {
136626
137174
  "image.png",
136627
137175
  "static/images/image.png",
136628
137176
  "/User/manny/projects/doc-detective/static/images/image.png",
137177
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
136629
137178
  "https://example.com/static/images/image.png",
136630
137179
  {
136631
137180
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -139060,10 +139609,11 @@ var schemas_default = {
139060
139609
  },
139061
139610
  overwrite: {
139062
139611
  type: "string",
139063
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
139612
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
139064
139613
  enum: [
139065
139614
  "true",
139066
- "false"
139615
+ "false",
139616
+ "aboveVariation"
139067
139617
  ]
139068
139618
  },
139069
139619
  name: {
@@ -139121,6 +139671,88 @@ var schemas_default = {
139121
139671
  }
139122
139672
  }
139123
139673
  ]
139674
+ },
139675
+ verify: {
139676
+ title: "Recording verify guards",
139677
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
139678
+ type: "object",
139679
+ additionalProperties: false,
139680
+ properties: {
139681
+ minDuration: {
139682
+ type: "number",
139683
+ description: "Fail if the video is shorter than this many seconds.",
139684
+ minimum: 0
139685
+ },
139686
+ maxDuration: {
139687
+ type: "number",
139688
+ description: "Fail if the video is longer than this many seconds.",
139689
+ minimum: 0
139690
+ },
139691
+ resolution: {
139692
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
139693
+ anyOf: [
139694
+ {
139695
+ type: "boolean",
139696
+ title: "Verify resolution (boolean)"
139697
+ },
139698
+ {
139699
+ type: "object",
139700
+ title: "Verify resolution (detailed)",
139701
+ additionalProperties: false,
139702
+ required: [
139703
+ "width",
139704
+ "height"
139705
+ ],
139706
+ properties: {
139707
+ width: {
139708
+ type: "integer",
139709
+ minimum: 1
139710
+ },
139711
+ height: {
139712
+ type: "integer",
139713
+ minimum: 1
139714
+ }
139715
+ }
139716
+ }
139717
+ ]
139718
+ },
139719
+ notBlack: {
139720
+ type: "boolean",
139721
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
139722
+ }
139723
+ }
139724
+ },
139725
+ checkpoints: {
139726
+ title: "Recording checkpoints",
139727
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
139728
+ anyOf: [
139729
+ {
139730
+ type: "boolean",
139731
+ title: "Recording checkpoints (boolean)",
139732
+ description: "If `true`, enables checkpoints with default settings."
139733
+ },
139734
+ {
139735
+ type: "object",
139736
+ title: "Recording checkpoints (detailed)",
139737
+ additionalProperties: false,
139738
+ properties: {
139739
+ maxVariation: {
139740
+ type: "number",
139741
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
139742
+ default: 0.05,
139743
+ minimum: 0,
139744
+ maximum: 1
139745
+ },
139746
+ directory: {
139747
+ type: "string",
139748
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
139749
+ transform: [
139750
+ "trim"
139751
+ ]
139752
+ }
139753
+ }
139754
+ }
139755
+ ]
139124
139756
  }
139125
139757
  },
139126
139758
  title: "Record (detailed)"
@@ -139382,10 +140014,11 @@ var schemas_default = {
139382
140014
  },
139383
140015
  overwrite: {
139384
140016
  type: "string",
139385
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
140017
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
139386
140018
  enum: [
139387
140019
  "true",
139388
- "false"
140020
+ "false",
140021
+ "aboveVariation"
139389
140022
  ]
139390
140023
  },
139391
140024
  name: {
@@ -139443,6 +140076,88 @@ var schemas_default = {
139443
140076
  }
139444
140077
  }
139445
140078
  ]
140079
+ },
140080
+ verify: {
140081
+ title: "Recording verify guards",
140082
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
140083
+ type: "object",
140084
+ additionalProperties: false,
140085
+ properties: {
140086
+ minDuration: {
140087
+ type: "number",
140088
+ description: "Fail if the video is shorter than this many seconds.",
140089
+ minimum: 0
140090
+ },
140091
+ maxDuration: {
140092
+ type: "number",
140093
+ description: "Fail if the video is longer than this many seconds.",
140094
+ minimum: 0
140095
+ },
140096
+ resolution: {
140097
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
140098
+ anyOf: [
140099
+ {
140100
+ type: "boolean",
140101
+ title: "Verify resolution (boolean)"
140102
+ },
140103
+ {
140104
+ type: "object",
140105
+ title: "Verify resolution (detailed)",
140106
+ additionalProperties: false,
140107
+ required: [
140108
+ "width",
140109
+ "height"
140110
+ ],
140111
+ properties: {
140112
+ width: {
140113
+ type: "integer",
140114
+ minimum: 1
140115
+ },
140116
+ height: {
140117
+ type: "integer",
140118
+ minimum: 1
140119
+ }
140120
+ }
140121
+ }
140122
+ ]
140123
+ },
140124
+ notBlack: {
140125
+ type: "boolean",
140126
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
140127
+ }
140128
+ }
140129
+ },
140130
+ checkpoints: {
140131
+ title: "Recording checkpoints",
140132
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
140133
+ anyOf: [
140134
+ {
140135
+ type: "boolean",
140136
+ title: "Recording checkpoints (boolean)",
140137
+ description: "If `true`, enables checkpoints with default settings."
140138
+ },
140139
+ {
140140
+ type: "object",
140141
+ title: "Recording checkpoints (detailed)",
140142
+ additionalProperties: false,
140143
+ properties: {
140144
+ maxVariation: {
140145
+ type: "number",
140146
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
140147
+ default: 0.05,
140148
+ minimum: 0,
140149
+ maximum: 1
140150
+ },
140151
+ directory: {
140152
+ type: "string",
140153
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
140154
+ transform: [
140155
+ "trim"
140156
+ ]
140157
+ }
140158
+ }
140159
+ }
140160
+ ]
139446
140161
  }
139447
140162
  },
139448
140163
  title: "Record (detailed)"
@@ -139509,6 +140224,17 @@ var schemas_default = {
139509
140224
  path: "results.mp4",
139510
140225
  engine: "ffmpeg"
139511
140226
  },
140227
+ {
140228
+ path: "results.mp4",
140229
+ checkpoints: true
140230
+ },
140231
+ {
140232
+ path: "results.mp4",
140233
+ checkpoints: {
140234
+ maxVariation: 0.02,
140235
+ directory: "baselines/results"
140236
+ }
140237
+ },
139512
140238
  {
139513
140239
  path: "results.mp4",
139514
140240
  engine: {
@@ -180673,9 +181399,10 @@ var schemas_default = {
180673
181399
  anyOf: [
180674
181400
  {
180675
181401
  title: "Screenshot (simple)",
181402
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
180676
181403
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
180677
181404
  type: "string",
180678
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181405
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
180679
181406
  transform: [
180680
181407
  "trim"
180681
181408
  ]
@@ -180909,9 +181636,10 @@ var schemas_default = {
180909
181636
  },
180910
181637
  path: {
180911
181638
  title: "Screenshot (simple)",
181639
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
180912
181640
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
180913
181641
  type: "string",
180914
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181642
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
180915
181643
  transform: [
180916
181644
  "trim"
180917
181645
  ]
@@ -181169,9 +181897,10 @@ var schemas_default = {
181169
181897
  schemas: {
181170
181898
  path: {
181171
181899
  title: "Screenshot (simple)",
181900
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
181172
181901
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
181173
181902
  type: "string",
181174
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181903
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181175
181904
  transform: [
181176
181905
  "trim"
181177
181906
  ]
@@ -181405,9 +182134,10 @@ var schemas_default = {
181405
182134
  },
181406
182135
  path: {
181407
182136
  title: "Screenshot (simple)",
182137
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
181408
182138
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
181409
182139
  type: "string",
181410
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
182140
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181411
182141
  transform: [
181412
182142
  "trim"
181413
182143
  ]
@@ -181881,9 +182611,10 @@ var schemas_default = {
181881
182611
  },
181882
182612
  path: {
181883
182613
  title: "Screenshot (simple)",
182614
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
181884
182615
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
181885
182616
  type: "string",
181886
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
182617
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
181887
182618
  transform: [
181888
182619
  "trim"
181889
182620
  ]
@@ -182265,6 +182996,7 @@ var schemas_default = {
182265
182996
  "image.png",
182266
182997
  "static/images/image.png",
182267
182998
  "/User/manny/projects/doc-detective/static/images/image.png",
182999
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
182268
183000
  "https://example.com/static/images/image.png",
182269
183001
  {
182270
183002
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -184699,10 +185431,11 @@ var schemas_default = {
184699
185431
  },
184700
185432
  overwrite: {
184701
185433
  type: "string",
184702
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
185434
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
184703
185435
  enum: [
184704
185436
  "true",
184705
- "false"
185437
+ "false",
185438
+ "aboveVariation"
184706
185439
  ]
184707
185440
  },
184708
185441
  name: {
@@ -184760,6 +185493,88 @@ var schemas_default = {
184760
185493
  }
184761
185494
  }
184762
185495
  ]
185496
+ },
185497
+ verify: {
185498
+ title: "Recording verify guards",
185499
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
185500
+ type: "object",
185501
+ additionalProperties: false,
185502
+ properties: {
185503
+ minDuration: {
185504
+ type: "number",
185505
+ description: "Fail if the video is shorter than this many seconds.",
185506
+ minimum: 0
185507
+ },
185508
+ maxDuration: {
185509
+ type: "number",
185510
+ description: "Fail if the video is longer than this many seconds.",
185511
+ minimum: 0
185512
+ },
185513
+ resolution: {
185514
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
185515
+ anyOf: [
185516
+ {
185517
+ type: "boolean",
185518
+ title: "Verify resolution (boolean)"
185519
+ },
185520
+ {
185521
+ type: "object",
185522
+ title: "Verify resolution (detailed)",
185523
+ additionalProperties: false,
185524
+ required: [
185525
+ "width",
185526
+ "height"
185527
+ ],
185528
+ properties: {
185529
+ width: {
185530
+ type: "integer",
185531
+ minimum: 1
185532
+ },
185533
+ height: {
185534
+ type: "integer",
185535
+ minimum: 1
185536
+ }
185537
+ }
185538
+ }
185539
+ ]
185540
+ },
185541
+ notBlack: {
185542
+ type: "boolean",
185543
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
185544
+ }
185545
+ }
185546
+ },
185547
+ checkpoints: {
185548
+ title: "Recording checkpoints",
185549
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
185550
+ anyOf: [
185551
+ {
185552
+ type: "boolean",
185553
+ title: "Recording checkpoints (boolean)",
185554
+ description: "If `true`, enables checkpoints with default settings."
185555
+ },
185556
+ {
185557
+ type: "object",
185558
+ title: "Recording checkpoints (detailed)",
185559
+ additionalProperties: false,
185560
+ properties: {
185561
+ maxVariation: {
185562
+ type: "number",
185563
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
185564
+ default: 0.05,
185565
+ minimum: 0,
185566
+ maximum: 1
185567
+ },
185568
+ directory: {
185569
+ type: "string",
185570
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
185571
+ transform: [
185572
+ "trim"
185573
+ ]
185574
+ }
185575
+ }
185576
+ }
185577
+ ]
184763
185578
  }
184764
185579
  },
184765
185580
  title: "Record (detailed)"
@@ -185021,10 +185836,11 @@ var schemas_default = {
185021
185836
  },
185022
185837
  overwrite: {
185023
185838
  type: "string",
185024
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
185839
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
185025
185840
  enum: [
185026
185841
  "true",
185027
- "false"
185842
+ "false",
185843
+ "aboveVariation"
185028
185844
  ]
185029
185845
  },
185030
185846
  name: {
@@ -185082,6 +185898,88 @@ var schemas_default = {
185082
185898
  }
185083
185899
  }
185084
185900
  ]
185901
+ },
185902
+ verify: {
185903
+ title: "Recording verify guards",
185904
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
185905
+ type: "object",
185906
+ additionalProperties: false,
185907
+ properties: {
185908
+ minDuration: {
185909
+ type: "number",
185910
+ description: "Fail if the video is shorter than this many seconds.",
185911
+ minimum: 0
185912
+ },
185913
+ maxDuration: {
185914
+ type: "number",
185915
+ description: "Fail if the video is longer than this many seconds.",
185916
+ minimum: 0
185917
+ },
185918
+ resolution: {
185919
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
185920
+ anyOf: [
185921
+ {
185922
+ type: "boolean",
185923
+ title: "Verify resolution (boolean)"
185924
+ },
185925
+ {
185926
+ type: "object",
185927
+ title: "Verify resolution (detailed)",
185928
+ additionalProperties: false,
185929
+ required: [
185930
+ "width",
185931
+ "height"
185932
+ ],
185933
+ properties: {
185934
+ width: {
185935
+ type: "integer",
185936
+ minimum: 1
185937
+ },
185938
+ height: {
185939
+ type: "integer",
185940
+ minimum: 1
185941
+ }
185942
+ }
185943
+ }
185944
+ ]
185945
+ },
185946
+ notBlack: {
185947
+ type: "boolean",
185948
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
185949
+ }
185950
+ }
185951
+ },
185952
+ checkpoints: {
185953
+ title: "Recording checkpoints",
185954
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
185955
+ anyOf: [
185956
+ {
185957
+ type: "boolean",
185958
+ title: "Recording checkpoints (boolean)",
185959
+ description: "If `true`, enables checkpoints with default settings."
185960
+ },
185961
+ {
185962
+ type: "object",
185963
+ title: "Recording checkpoints (detailed)",
185964
+ additionalProperties: false,
185965
+ properties: {
185966
+ maxVariation: {
185967
+ type: "number",
185968
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
185969
+ default: 0.05,
185970
+ minimum: 0,
185971
+ maximum: 1
185972
+ },
185973
+ directory: {
185974
+ type: "string",
185975
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
185976
+ transform: [
185977
+ "trim"
185978
+ ]
185979
+ }
185980
+ }
185981
+ }
185982
+ ]
185085
185983
  }
185086
185984
  },
185087
185985
  title: "Record (detailed)"
@@ -185148,6 +186046,17 @@ var schemas_default = {
185148
186046
  path: "results.mp4",
185149
186047
  engine: "ffmpeg"
185150
186048
  },
186049
+ {
186050
+ path: "results.mp4",
186051
+ checkpoints: true
186052
+ },
186053
+ {
186054
+ path: "results.mp4",
186055
+ checkpoints: {
186056
+ maxVariation: 0.02,
186057
+ directory: "baselines/results"
186058
+ }
186059
+ },
185151
186060
  {
185152
186061
  path: "results.mp4",
185153
186062
  engine: {
@@ -228051,9 +228960,10 @@ var schemas_default = {
228051
228960
  anyOf: [
228052
228961
  {
228053
228962
  title: "Screenshot (simple)",
228963
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
228054
228964
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
228055
228965
  type: "string",
228056
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
228966
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
228057
228967
  transform: [
228058
228968
  "trim"
228059
228969
  ]
@@ -228287,9 +229197,10 @@ var schemas_default = {
228287
229197
  },
228288
229198
  path: {
228289
229199
  title: "Screenshot (simple)",
229200
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
228290
229201
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
228291
229202
  type: "string",
228292
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
229203
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
228293
229204
  transform: [
228294
229205
  "trim"
228295
229206
  ]
@@ -228547,9 +229458,10 @@ var schemas_default = {
228547
229458
  schemas: {
228548
229459
  path: {
228549
229460
  title: "Screenshot (simple)",
229461
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
228550
229462
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
228551
229463
  type: "string",
228552
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
229464
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
228553
229465
  transform: [
228554
229466
  "trim"
228555
229467
  ]
@@ -228783,9 +229695,10 @@ var schemas_default = {
228783
229695
  },
228784
229696
  path: {
228785
229697
  title: "Screenshot (simple)",
229698
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
228786
229699
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
228787
229700
  type: "string",
228788
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
229701
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
228789
229702
  transform: [
228790
229703
  "trim"
228791
229704
  ]
@@ -229259,9 +230172,10 @@ var schemas_default = {
229259
230172
  },
229260
230173
  path: {
229261
230174
  title: "Screenshot (simple)",
230175
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
229262
230176
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
229263
230177
  type: "string",
229264
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
230178
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
229265
230179
  transform: [
229266
230180
  "trim"
229267
230181
  ]
@@ -229643,6 +230557,7 @@ var schemas_default = {
229643
230557
  "image.png",
229644
230558
  "static/images/image.png",
229645
230559
  "/User/manny/projects/doc-detective/static/images/image.png",
230560
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
229646
230561
  "https://example.com/static/images/image.png",
229647
230562
  {
229648
230563
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -232077,10 +232992,11 @@ var schemas_default = {
232077
232992
  },
232078
232993
  overwrite: {
232079
232994
  type: "string",
232080
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
232995
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
232081
232996
  enum: [
232082
232997
  "true",
232083
- "false"
232998
+ "false",
232999
+ "aboveVariation"
232084
233000
  ]
232085
233001
  },
232086
233002
  name: {
@@ -232138,6 +233054,88 @@ var schemas_default = {
232138
233054
  }
232139
233055
  }
232140
233056
  ]
233057
+ },
233058
+ verify: {
233059
+ title: "Recording verify guards",
233060
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
233061
+ type: "object",
233062
+ additionalProperties: false,
233063
+ properties: {
233064
+ minDuration: {
233065
+ type: "number",
233066
+ description: "Fail if the video is shorter than this many seconds.",
233067
+ minimum: 0
233068
+ },
233069
+ maxDuration: {
233070
+ type: "number",
233071
+ description: "Fail if the video is longer than this many seconds.",
233072
+ minimum: 0
233073
+ },
233074
+ resolution: {
233075
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
233076
+ anyOf: [
233077
+ {
233078
+ type: "boolean",
233079
+ title: "Verify resolution (boolean)"
233080
+ },
233081
+ {
233082
+ type: "object",
233083
+ title: "Verify resolution (detailed)",
233084
+ additionalProperties: false,
233085
+ required: [
233086
+ "width",
233087
+ "height"
233088
+ ],
233089
+ properties: {
233090
+ width: {
233091
+ type: "integer",
233092
+ minimum: 1
233093
+ },
233094
+ height: {
233095
+ type: "integer",
233096
+ minimum: 1
233097
+ }
233098
+ }
233099
+ }
233100
+ ]
233101
+ },
233102
+ notBlack: {
233103
+ type: "boolean",
233104
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
233105
+ }
233106
+ }
233107
+ },
233108
+ checkpoints: {
233109
+ title: "Recording checkpoints",
233110
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
233111
+ anyOf: [
233112
+ {
233113
+ type: "boolean",
233114
+ title: "Recording checkpoints (boolean)",
233115
+ description: "If `true`, enables checkpoints with default settings."
233116
+ },
233117
+ {
233118
+ type: "object",
233119
+ title: "Recording checkpoints (detailed)",
233120
+ additionalProperties: false,
233121
+ properties: {
233122
+ maxVariation: {
233123
+ type: "number",
233124
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
233125
+ default: 0.05,
233126
+ minimum: 0,
233127
+ maximum: 1
233128
+ },
233129
+ directory: {
233130
+ type: "string",
233131
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
233132
+ transform: [
233133
+ "trim"
233134
+ ]
233135
+ }
233136
+ }
233137
+ }
233138
+ ]
232141
233139
  }
232142
233140
  },
232143
233141
  title: "Record (detailed)"
@@ -232399,10 +233397,11 @@ var schemas_default = {
232399
233397
  },
232400
233398
  overwrite: {
232401
233399
  type: "string",
232402
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
233400
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
232403
233401
  enum: [
232404
233402
  "true",
232405
- "false"
233403
+ "false",
233404
+ "aboveVariation"
232406
233405
  ]
232407
233406
  },
232408
233407
  name: {
@@ -232460,6 +233459,88 @@ var schemas_default = {
232460
233459
  }
232461
233460
  }
232462
233461
  ]
233462
+ },
233463
+ verify: {
233464
+ title: "Recording verify guards",
233465
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
233466
+ type: "object",
233467
+ additionalProperties: false,
233468
+ properties: {
233469
+ minDuration: {
233470
+ type: "number",
233471
+ description: "Fail if the video is shorter than this many seconds.",
233472
+ minimum: 0
233473
+ },
233474
+ maxDuration: {
233475
+ type: "number",
233476
+ description: "Fail if the video is longer than this many seconds.",
233477
+ minimum: 0
233478
+ },
233479
+ resolution: {
233480
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
233481
+ anyOf: [
233482
+ {
233483
+ type: "boolean",
233484
+ title: "Verify resolution (boolean)"
233485
+ },
233486
+ {
233487
+ type: "object",
233488
+ title: "Verify resolution (detailed)",
233489
+ additionalProperties: false,
233490
+ required: [
233491
+ "width",
233492
+ "height"
233493
+ ],
233494
+ properties: {
233495
+ width: {
233496
+ type: "integer",
233497
+ minimum: 1
233498
+ },
233499
+ height: {
233500
+ type: "integer",
233501
+ minimum: 1
233502
+ }
233503
+ }
233504
+ }
233505
+ ]
233506
+ },
233507
+ notBlack: {
233508
+ type: "boolean",
233509
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
233510
+ }
233511
+ }
233512
+ },
233513
+ checkpoints: {
233514
+ title: "Recording checkpoints",
233515
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
233516
+ anyOf: [
233517
+ {
233518
+ type: "boolean",
233519
+ title: "Recording checkpoints (boolean)",
233520
+ description: "If `true`, enables checkpoints with default settings."
233521
+ },
233522
+ {
233523
+ type: "object",
233524
+ title: "Recording checkpoints (detailed)",
233525
+ additionalProperties: false,
233526
+ properties: {
233527
+ maxVariation: {
233528
+ type: "number",
233529
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
233530
+ default: 0.05,
233531
+ minimum: 0,
233532
+ maximum: 1
233533
+ },
233534
+ directory: {
233535
+ type: "string",
233536
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
233537
+ transform: [
233538
+ "trim"
233539
+ ]
233540
+ }
233541
+ }
233542
+ }
233543
+ ]
232463
233544
  }
232464
233545
  },
232465
233546
  title: "Record (detailed)"
@@ -232526,6 +233607,17 @@ var schemas_default = {
232526
233607
  path: "results.mp4",
232527
233608
  engine: "ffmpeg"
232528
233609
  },
233610
+ {
233611
+ path: "results.mp4",
233612
+ checkpoints: true
233613
+ },
233614
+ {
233615
+ path: "results.mp4",
233616
+ checkpoints: {
233617
+ maxVariation: 0.02,
233618
+ directory: "baselines/results"
233619
+ }
233620
+ },
232529
233621
  {
232530
233622
  path: "results.mp4",
232531
233623
  engine: {
@@ -272952,9 +274044,10 @@ var schemas_default = {
272952
274044
  anyOf: [
272953
274045
  {
272954
274046
  title: "Screenshot (simple)",
274047
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
272955
274048
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
272956
274049
  type: "string",
272957
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
274050
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
272958
274051
  transform: [
272959
274052
  "trim"
272960
274053
  ]
@@ -273188,9 +274281,10 @@ var schemas_default = {
273188
274281
  },
273189
274282
  path: {
273190
274283
  title: "Screenshot (simple)",
274284
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
273191
274285
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
273192
274286
  type: "string",
273193
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
274287
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
273194
274288
  transform: [
273195
274289
  "trim"
273196
274290
  ]
@@ -273448,9 +274542,10 @@ var schemas_default = {
273448
274542
  schemas: {
273449
274543
  path: {
273450
274544
  title: "Screenshot (simple)",
274545
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
273451
274546
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
273452
274547
  type: "string",
273453
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
274548
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
273454
274549
  transform: [
273455
274550
  "trim"
273456
274551
  ]
@@ -273684,9 +274779,10 @@ var schemas_default = {
273684
274779
  },
273685
274780
  path: {
273686
274781
  title: "Screenshot (simple)",
274782
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
273687
274783
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
273688
274784
  type: "string",
273689
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
274785
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
273690
274786
  transform: [
273691
274787
  "trim"
273692
274788
  ]
@@ -274160,9 +275256,10 @@ var schemas_default = {
274160
275256
  },
274161
275257
  path: {
274162
275258
  title: "Screenshot (simple)",
275259
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
274163
275260
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
274164
275261
  type: "string",
274165
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
275262
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
274166
275263
  transform: [
274167
275264
  "trim"
274168
275265
  ]
@@ -274544,6 +275641,7 @@ var schemas_default = {
274544
275641
  "image.png",
274545
275642
  "static/images/image.png",
274546
275643
  "/User/manny/projects/doc-detective/static/images/image.png",
275644
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
274547
275645
  "https://example.com/static/images/image.png",
274548
275646
  {
274549
275647
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -276978,10 +278076,11 @@ var schemas_default = {
276978
278076
  },
276979
278077
  overwrite: {
276980
278078
  type: "string",
276981
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
278079
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
276982
278080
  enum: [
276983
278081
  "true",
276984
- "false"
278082
+ "false",
278083
+ "aboveVariation"
276985
278084
  ]
276986
278085
  },
276987
278086
  name: {
@@ -277039,6 +278138,88 @@ var schemas_default = {
277039
278138
  }
277040
278139
  }
277041
278140
  ]
278141
+ },
278142
+ verify: {
278143
+ title: "Recording verify guards",
278144
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
278145
+ type: "object",
278146
+ additionalProperties: false,
278147
+ properties: {
278148
+ minDuration: {
278149
+ type: "number",
278150
+ description: "Fail if the video is shorter than this many seconds.",
278151
+ minimum: 0
278152
+ },
278153
+ maxDuration: {
278154
+ type: "number",
278155
+ description: "Fail if the video is longer than this many seconds.",
278156
+ minimum: 0
278157
+ },
278158
+ resolution: {
278159
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
278160
+ anyOf: [
278161
+ {
278162
+ type: "boolean",
278163
+ title: "Verify resolution (boolean)"
278164
+ },
278165
+ {
278166
+ type: "object",
278167
+ title: "Verify resolution (detailed)",
278168
+ additionalProperties: false,
278169
+ required: [
278170
+ "width",
278171
+ "height"
278172
+ ],
278173
+ properties: {
278174
+ width: {
278175
+ type: "integer",
278176
+ minimum: 1
278177
+ },
278178
+ height: {
278179
+ type: "integer",
278180
+ minimum: 1
278181
+ }
278182
+ }
278183
+ }
278184
+ ]
278185
+ },
278186
+ notBlack: {
278187
+ type: "boolean",
278188
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
278189
+ }
278190
+ }
278191
+ },
278192
+ checkpoints: {
278193
+ title: "Recording checkpoints",
278194
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
278195
+ anyOf: [
278196
+ {
278197
+ type: "boolean",
278198
+ title: "Recording checkpoints (boolean)",
278199
+ description: "If `true`, enables checkpoints with default settings."
278200
+ },
278201
+ {
278202
+ type: "object",
278203
+ title: "Recording checkpoints (detailed)",
278204
+ additionalProperties: false,
278205
+ properties: {
278206
+ maxVariation: {
278207
+ type: "number",
278208
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
278209
+ default: 0.05,
278210
+ minimum: 0,
278211
+ maximum: 1
278212
+ },
278213
+ directory: {
278214
+ type: "string",
278215
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
278216
+ transform: [
278217
+ "trim"
278218
+ ]
278219
+ }
278220
+ }
278221
+ }
278222
+ ]
277042
278223
  }
277043
278224
  },
277044
278225
  title: "Record (detailed)"
@@ -277300,10 +278481,11 @@ var schemas_default = {
277300
278481
  },
277301
278482
  overwrite: {
277302
278483
  type: "string",
277303
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
278484
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
277304
278485
  enum: [
277305
278486
  "true",
277306
- "false"
278487
+ "false",
278488
+ "aboveVariation"
277307
278489
  ]
277308
278490
  },
277309
278491
  name: {
@@ -277361,6 +278543,88 @@ var schemas_default = {
277361
278543
  }
277362
278544
  }
277363
278545
  ]
278546
+ },
278547
+ verify: {
278548
+ title: "Recording verify guards",
278549
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
278550
+ type: "object",
278551
+ additionalProperties: false,
278552
+ properties: {
278553
+ minDuration: {
278554
+ type: "number",
278555
+ description: "Fail if the video is shorter than this many seconds.",
278556
+ minimum: 0
278557
+ },
278558
+ maxDuration: {
278559
+ type: "number",
278560
+ description: "Fail if the video is longer than this many seconds.",
278561
+ minimum: 0
278562
+ },
278563
+ resolution: {
278564
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
278565
+ anyOf: [
278566
+ {
278567
+ type: "boolean",
278568
+ title: "Verify resolution (boolean)"
278569
+ },
278570
+ {
278571
+ type: "object",
278572
+ title: "Verify resolution (detailed)",
278573
+ additionalProperties: false,
278574
+ required: [
278575
+ "width",
278576
+ "height"
278577
+ ],
278578
+ properties: {
278579
+ width: {
278580
+ type: "integer",
278581
+ minimum: 1
278582
+ },
278583
+ height: {
278584
+ type: "integer",
278585
+ minimum: 1
278586
+ }
278587
+ }
278588
+ }
278589
+ ]
278590
+ },
278591
+ notBlack: {
278592
+ type: "boolean",
278593
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
278594
+ }
278595
+ }
278596
+ },
278597
+ checkpoints: {
278598
+ title: "Recording checkpoints",
278599
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
278600
+ anyOf: [
278601
+ {
278602
+ type: "boolean",
278603
+ title: "Recording checkpoints (boolean)",
278604
+ description: "If `true`, enables checkpoints with default settings."
278605
+ },
278606
+ {
278607
+ type: "object",
278608
+ title: "Recording checkpoints (detailed)",
278609
+ additionalProperties: false,
278610
+ properties: {
278611
+ maxVariation: {
278612
+ type: "number",
278613
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
278614
+ default: 0.05,
278615
+ minimum: 0,
278616
+ maximum: 1
278617
+ },
278618
+ directory: {
278619
+ type: "string",
278620
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
278621
+ transform: [
278622
+ "trim"
278623
+ ]
278624
+ }
278625
+ }
278626
+ }
278627
+ ]
277364
278628
  }
277365
278629
  },
277366
278630
  title: "Record (detailed)"
@@ -277427,6 +278691,17 @@ var schemas_default = {
277427
278691
  path: "results.mp4",
277428
278692
  engine: "ffmpeg"
277429
278693
  },
278694
+ {
278695
+ path: "results.mp4",
278696
+ checkpoints: true
278697
+ },
278698
+ {
278699
+ path: "results.mp4",
278700
+ checkpoints: {
278701
+ maxVariation: 0.02,
278702
+ directory: "baselines/results"
278703
+ }
278704
+ },
277430
278705
  {
277431
278706
  path: "results.mp4",
277432
278707
  engine: {
@@ -320814,9 +322089,10 @@ var schemas_default = {
320814
322089
  anyOf: [
320815
322090
  {
320816
322091
  title: "Screenshot (simple)",
322092
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
320817
322093
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
320818
322094
  type: "string",
320819
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
322095
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
320820
322096
  transform: [
320821
322097
  "trim"
320822
322098
  ]
@@ -321050,9 +322326,10 @@ var schemas_default = {
321050
322326
  },
321051
322327
  path: {
321052
322328
  title: "Screenshot (simple)",
322329
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
321053
322330
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
321054
322331
  type: "string",
321055
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
322332
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
321056
322333
  transform: [
321057
322334
  "trim"
321058
322335
  ]
@@ -321310,9 +322587,10 @@ var schemas_default = {
321310
322587
  schemas: {
321311
322588
  path: {
321312
322589
  title: "Screenshot (simple)",
322590
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
321313
322591
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
321314
322592
  type: "string",
321315
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
322593
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
321316
322594
  transform: [
321317
322595
  "trim"
321318
322596
  ]
@@ -321546,9 +322824,10 @@ var schemas_default = {
321546
322824
  },
321547
322825
  path: {
321548
322826
  title: "Screenshot (simple)",
322827
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
321549
322828
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
321550
322829
  type: "string",
321551
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
322830
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
321552
322831
  transform: [
321553
322832
  "trim"
321554
322833
  ]
@@ -322022,9 +323301,10 @@ var schemas_default = {
322022
323301
  },
322023
323302
  path: {
322024
323303
  title: "Screenshot (simple)",
323304
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
322025
323305
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
322026
323306
  type: "string",
322027
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
323307
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
322028
323308
  transform: [
322029
323309
  "trim"
322030
323310
  ]
@@ -322406,6 +323686,7 @@ var schemas_default = {
322406
323686
  "image.png",
322407
323687
  "static/images/image.png",
322408
323688
  "/User/manny/projects/doc-detective/static/images/image.png",
323689
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
322409
323690
  "https://example.com/static/images/image.png",
322410
323691
  {
322411
323692
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -324840,10 +326121,11 @@ var schemas_default = {
324840
326121
  },
324841
326122
  overwrite: {
324842
326123
  type: "string",
324843
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
326124
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
324844
326125
  enum: [
324845
326126
  "true",
324846
- "false"
326127
+ "false",
326128
+ "aboveVariation"
324847
326129
  ]
324848
326130
  },
324849
326131
  name: {
@@ -324901,6 +326183,88 @@ var schemas_default = {
324901
326183
  }
324902
326184
  }
324903
326185
  ]
326186
+ },
326187
+ verify: {
326188
+ title: "Recording verify guards",
326189
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
326190
+ type: "object",
326191
+ additionalProperties: false,
326192
+ properties: {
326193
+ minDuration: {
326194
+ type: "number",
326195
+ description: "Fail if the video is shorter than this many seconds.",
326196
+ minimum: 0
326197
+ },
326198
+ maxDuration: {
326199
+ type: "number",
326200
+ description: "Fail if the video is longer than this many seconds.",
326201
+ minimum: 0
326202
+ },
326203
+ resolution: {
326204
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
326205
+ anyOf: [
326206
+ {
326207
+ type: "boolean",
326208
+ title: "Verify resolution (boolean)"
326209
+ },
326210
+ {
326211
+ type: "object",
326212
+ title: "Verify resolution (detailed)",
326213
+ additionalProperties: false,
326214
+ required: [
326215
+ "width",
326216
+ "height"
326217
+ ],
326218
+ properties: {
326219
+ width: {
326220
+ type: "integer",
326221
+ minimum: 1
326222
+ },
326223
+ height: {
326224
+ type: "integer",
326225
+ minimum: 1
326226
+ }
326227
+ }
326228
+ }
326229
+ ]
326230
+ },
326231
+ notBlack: {
326232
+ type: "boolean",
326233
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
326234
+ }
326235
+ }
326236
+ },
326237
+ checkpoints: {
326238
+ title: "Recording checkpoints",
326239
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
326240
+ anyOf: [
326241
+ {
326242
+ type: "boolean",
326243
+ title: "Recording checkpoints (boolean)",
326244
+ description: "If `true`, enables checkpoints with default settings."
326245
+ },
326246
+ {
326247
+ type: "object",
326248
+ title: "Recording checkpoints (detailed)",
326249
+ additionalProperties: false,
326250
+ properties: {
326251
+ maxVariation: {
326252
+ type: "number",
326253
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
326254
+ default: 0.05,
326255
+ minimum: 0,
326256
+ maximum: 1
326257
+ },
326258
+ directory: {
326259
+ type: "string",
326260
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
326261
+ transform: [
326262
+ "trim"
326263
+ ]
326264
+ }
326265
+ }
326266
+ }
326267
+ ]
324904
326268
  }
324905
326269
  },
324906
326270
  title: "Record (detailed)"
@@ -325162,10 +326526,11 @@ var schemas_default = {
325162
326526
  },
325163
326527
  overwrite: {
325164
326528
  type: "string",
325165
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
326529
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
325166
326530
  enum: [
325167
326531
  "true",
325168
- "false"
326532
+ "false",
326533
+ "aboveVariation"
325169
326534
  ]
325170
326535
  },
325171
326536
  name: {
@@ -325223,6 +326588,88 @@ var schemas_default = {
325223
326588
  }
325224
326589
  }
325225
326590
  ]
326591
+ },
326592
+ verify: {
326593
+ title: "Recording verify guards",
326594
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
326595
+ type: "object",
326596
+ additionalProperties: false,
326597
+ properties: {
326598
+ minDuration: {
326599
+ type: "number",
326600
+ description: "Fail if the video is shorter than this many seconds.",
326601
+ minimum: 0
326602
+ },
326603
+ maxDuration: {
326604
+ type: "number",
326605
+ description: "Fail if the video is longer than this many seconds.",
326606
+ minimum: 0
326607
+ },
326608
+ resolution: {
326609
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
326610
+ anyOf: [
326611
+ {
326612
+ type: "boolean",
326613
+ title: "Verify resolution (boolean)"
326614
+ },
326615
+ {
326616
+ type: "object",
326617
+ title: "Verify resolution (detailed)",
326618
+ additionalProperties: false,
326619
+ required: [
326620
+ "width",
326621
+ "height"
326622
+ ],
326623
+ properties: {
326624
+ width: {
326625
+ type: "integer",
326626
+ minimum: 1
326627
+ },
326628
+ height: {
326629
+ type: "integer",
326630
+ minimum: 1
326631
+ }
326632
+ }
326633
+ }
326634
+ ]
326635
+ },
326636
+ notBlack: {
326637
+ type: "boolean",
326638
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
326639
+ }
326640
+ }
326641
+ },
326642
+ checkpoints: {
326643
+ title: "Recording checkpoints",
326644
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
326645
+ anyOf: [
326646
+ {
326647
+ type: "boolean",
326648
+ title: "Recording checkpoints (boolean)",
326649
+ description: "If `true`, enables checkpoints with default settings."
326650
+ },
326651
+ {
326652
+ type: "object",
326653
+ title: "Recording checkpoints (detailed)",
326654
+ additionalProperties: false,
326655
+ properties: {
326656
+ maxVariation: {
326657
+ type: "number",
326658
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
326659
+ default: 0.05,
326660
+ minimum: 0,
326661
+ maximum: 1
326662
+ },
326663
+ directory: {
326664
+ type: "string",
326665
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
326666
+ transform: [
326667
+ "trim"
326668
+ ]
326669
+ }
326670
+ }
326671
+ }
326672
+ ]
325226
326673
  }
325227
326674
  },
325228
326675
  title: "Record (detailed)"
@@ -325289,6 +326736,17 @@ var schemas_default = {
325289
326736
  path: "results.mp4",
325290
326737
  engine: "ffmpeg"
325291
326738
  },
326739
+ {
326740
+ path: "results.mp4",
326741
+ checkpoints: true
326742
+ },
326743
+ {
326744
+ path: "results.mp4",
326745
+ checkpoints: {
326746
+ maxVariation: 0.02,
326747
+ directory: "baselines/results"
326748
+ }
326749
+ },
325292
326750
  {
325293
326751
  path: "results.mp4",
325294
326752
  engine: {
@@ -365715,9 +367173,10 @@ var schemas_default = {
365715
367173
  anyOf: [
365716
367174
  {
365717
367175
  title: "Screenshot (simple)",
367176
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
365718
367177
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
365719
367178
  type: "string",
365720
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
367179
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
365721
367180
  transform: [
365722
367181
  "trim"
365723
367182
  ]
@@ -365951,9 +367410,10 @@ var schemas_default = {
365951
367410
  },
365952
367411
  path: {
365953
367412
  title: "Screenshot (simple)",
367413
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
365954
367414
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
365955
367415
  type: "string",
365956
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
367416
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
365957
367417
  transform: [
365958
367418
  "trim"
365959
367419
  ]
@@ -366211,9 +367671,10 @@ var schemas_default = {
366211
367671
  schemas: {
366212
367672
  path: {
366213
367673
  title: "Screenshot (simple)",
367674
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
366214
367675
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
366215
367676
  type: "string",
366216
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
367677
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
366217
367678
  transform: [
366218
367679
  "trim"
366219
367680
  ]
@@ -366447,9 +367908,10 @@ var schemas_default = {
366447
367908
  },
366448
367909
  path: {
366449
367910
  title: "Screenshot (simple)",
367911
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
366450
367912
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
366451
367913
  type: "string",
366452
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
367914
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
366453
367915
  transform: [
366454
367916
  "trim"
366455
367917
  ]
@@ -366923,9 +368385,10 @@ var schemas_default = {
366923
368385
  },
366924
368386
  path: {
366925
368387
  title: "Screenshot (simple)",
368388
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
366926
368389
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
366927
368390
  type: "string",
366928
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
368391
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
366929
368392
  transform: [
366930
368393
  "trim"
366931
368394
  ]
@@ -367307,6 +368770,7 @@ var schemas_default = {
367307
368770
  "image.png",
367308
368771
  "static/images/image.png",
367309
368772
  "/User/manny/projects/doc-detective/static/images/image.png",
368773
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
367310
368774
  "https://example.com/static/images/image.png",
367311
368775
  {
367312
368776
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -369741,10 +371205,11 @@ var schemas_default = {
369741
371205
  },
369742
371206
  overwrite: {
369743
371207
  type: "string",
369744
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
371208
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
369745
371209
  enum: [
369746
371210
  "true",
369747
- "false"
371211
+ "false",
371212
+ "aboveVariation"
369748
371213
  ]
369749
371214
  },
369750
371215
  name: {
@@ -369802,6 +371267,88 @@ var schemas_default = {
369802
371267
  }
369803
371268
  }
369804
371269
  ]
371270
+ },
371271
+ verify: {
371272
+ title: "Recording verify guards",
371273
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
371274
+ type: "object",
371275
+ additionalProperties: false,
371276
+ properties: {
371277
+ minDuration: {
371278
+ type: "number",
371279
+ description: "Fail if the video is shorter than this many seconds.",
371280
+ minimum: 0
371281
+ },
371282
+ maxDuration: {
371283
+ type: "number",
371284
+ description: "Fail if the video is longer than this many seconds.",
371285
+ minimum: 0
371286
+ },
371287
+ resolution: {
371288
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
371289
+ anyOf: [
371290
+ {
371291
+ type: "boolean",
371292
+ title: "Verify resolution (boolean)"
371293
+ },
371294
+ {
371295
+ type: "object",
371296
+ title: "Verify resolution (detailed)",
371297
+ additionalProperties: false,
371298
+ required: [
371299
+ "width",
371300
+ "height"
371301
+ ],
371302
+ properties: {
371303
+ width: {
371304
+ type: "integer",
371305
+ minimum: 1
371306
+ },
371307
+ height: {
371308
+ type: "integer",
371309
+ minimum: 1
371310
+ }
371311
+ }
371312
+ }
371313
+ ]
371314
+ },
371315
+ notBlack: {
371316
+ type: "boolean",
371317
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
371318
+ }
371319
+ }
371320
+ },
371321
+ checkpoints: {
371322
+ title: "Recording checkpoints",
371323
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
371324
+ anyOf: [
371325
+ {
371326
+ type: "boolean",
371327
+ title: "Recording checkpoints (boolean)",
371328
+ description: "If `true`, enables checkpoints with default settings."
371329
+ },
371330
+ {
371331
+ type: "object",
371332
+ title: "Recording checkpoints (detailed)",
371333
+ additionalProperties: false,
371334
+ properties: {
371335
+ maxVariation: {
371336
+ type: "number",
371337
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
371338
+ default: 0.05,
371339
+ minimum: 0,
371340
+ maximum: 1
371341
+ },
371342
+ directory: {
371343
+ type: "string",
371344
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
371345
+ transform: [
371346
+ "trim"
371347
+ ]
371348
+ }
371349
+ }
371350
+ }
371351
+ ]
369805
371352
  }
369806
371353
  },
369807
371354
  title: "Record (detailed)"
@@ -370063,10 +371610,11 @@ var schemas_default = {
370063
371610
  },
370064
371611
  overwrite: {
370065
371612
  type: "string",
370066
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
371613
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
370067
371614
  enum: [
370068
371615
  "true",
370069
- "false"
371616
+ "false",
371617
+ "aboveVariation"
370070
371618
  ]
370071
371619
  },
370072
371620
  name: {
@@ -370124,6 +371672,88 @@ var schemas_default = {
370124
371672
  }
370125
371673
  }
370126
371674
  ]
371675
+ },
371676
+ verify: {
371677
+ title: "Recording verify guards",
371678
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
371679
+ type: "object",
371680
+ additionalProperties: false,
371681
+ properties: {
371682
+ minDuration: {
371683
+ type: "number",
371684
+ description: "Fail if the video is shorter than this many seconds.",
371685
+ minimum: 0
371686
+ },
371687
+ maxDuration: {
371688
+ type: "number",
371689
+ description: "Fail if the video is longer than this many seconds.",
371690
+ minimum: 0
371691
+ },
371692
+ resolution: {
371693
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
371694
+ anyOf: [
371695
+ {
371696
+ type: "boolean",
371697
+ title: "Verify resolution (boolean)"
371698
+ },
371699
+ {
371700
+ type: "object",
371701
+ title: "Verify resolution (detailed)",
371702
+ additionalProperties: false,
371703
+ required: [
371704
+ "width",
371705
+ "height"
371706
+ ],
371707
+ properties: {
371708
+ width: {
371709
+ type: "integer",
371710
+ minimum: 1
371711
+ },
371712
+ height: {
371713
+ type: "integer",
371714
+ minimum: 1
371715
+ }
371716
+ }
371717
+ }
371718
+ ]
371719
+ },
371720
+ notBlack: {
371721
+ type: "boolean",
371722
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
371723
+ }
371724
+ }
371725
+ },
371726
+ checkpoints: {
371727
+ title: "Recording checkpoints",
371728
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
371729
+ anyOf: [
371730
+ {
371731
+ type: "boolean",
371732
+ title: "Recording checkpoints (boolean)",
371733
+ description: "If `true`, enables checkpoints with default settings."
371734
+ },
371735
+ {
371736
+ type: "object",
371737
+ title: "Recording checkpoints (detailed)",
371738
+ additionalProperties: false,
371739
+ properties: {
371740
+ maxVariation: {
371741
+ type: "number",
371742
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
371743
+ default: 0.05,
371744
+ minimum: 0,
371745
+ maximum: 1
371746
+ },
371747
+ directory: {
371748
+ type: "string",
371749
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
371750
+ transform: [
371751
+ "trim"
371752
+ ]
371753
+ }
371754
+ }
371755
+ }
371756
+ ]
370127
371757
  }
370128
371758
  },
370129
371759
  title: "Record (detailed)"
@@ -370190,6 +371820,17 @@ var schemas_default = {
370190
371820
  path: "results.mp4",
370191
371821
  engine: "ffmpeg"
370192
371822
  },
371823
+ {
371824
+ path: "results.mp4",
371825
+ checkpoints: true
371826
+ },
371827
+ {
371828
+ path: "results.mp4",
371829
+ checkpoints: {
371830
+ maxVariation: 0.02,
371831
+ directory: "baselines/results"
371832
+ }
371833
+ },
370193
371834
  {
370194
371835
  path: "results.mp4",
370195
371836
  engine: {
@@ -385726,9 +387367,10 @@ var schemas_default = {
385726
387367
  anyOf: [
385727
387368
  {
385728
387369
  title: "Screenshot (simple)",
387370
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
385729
387371
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
385730
387372
  type: "string",
385731
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
387373
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
385732
387374
  transform: [
385733
387375
  "trim"
385734
387376
  ]
@@ -385962,9 +387604,10 @@ var schemas_default = {
385962
387604
  },
385963
387605
  path: {
385964
387606
  title: "Screenshot (simple)",
387607
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
385965
387608
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
385966
387609
  type: "string",
385967
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
387610
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
385968
387611
  transform: [
385969
387612
  "trim"
385970
387613
  ]
@@ -386222,9 +387865,10 @@ var schemas_default = {
386222
387865
  schemas: {
386223
387866
  path: {
386224
387867
  title: "Screenshot (simple)",
387868
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
386225
387869
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
386226
387870
  type: "string",
386227
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
387871
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
386228
387872
  transform: [
386229
387873
  "trim"
386230
387874
  ]
@@ -386458,9 +388102,10 @@ var schemas_default = {
386458
388102
  },
386459
388103
  path: {
386460
388104
  title: "Screenshot (simple)",
388105
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
386461
388106
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
386462
388107
  type: "string",
386463
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
388108
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
386464
388109
  transform: [
386465
388110
  "trim"
386466
388111
  ]
@@ -386934,9 +388579,10 @@ var schemas_default = {
386934
388579
  },
386935
388580
  path: {
386936
388581
  title: "Screenshot (simple)",
388582
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
386937
388583
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
386938
388584
  type: "string",
386939
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
388585
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
386940
388586
  transform: [
386941
388587
  "trim"
386942
388588
  ]
@@ -387318,6 +388964,7 @@ var schemas_default = {
387318
388964
  "image.png",
387319
388965
  "static/images/image.png",
387320
388966
  "/User/manny/projects/doc-detective/static/images/image.png",
388967
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
387321
388968
  "https://example.com/static/images/image.png",
387322
388969
  {
387323
388970
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -416901,9 +418548,10 @@ var schemas_default = {
416901
418548
  anyOf: [
416902
418549
  {
416903
418550
  title: "Screenshot (simple)",
418551
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
416904
418552
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
416905
418553
  type: "string",
416906
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
418554
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
416907
418555
  transform: [
416908
418556
  "trim"
416909
418557
  ]
@@ -417137,9 +418785,10 @@ var schemas_default = {
417137
418785
  },
417138
418786
  path: {
417139
418787
  title: "Screenshot (simple)",
418788
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
417140
418789
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
417141
418790
  type: "string",
417142
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
418791
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
417143
418792
  transform: [
417144
418793
  "trim"
417145
418794
  ]
@@ -417397,9 +419046,10 @@ var schemas_default = {
417397
419046
  schemas: {
417398
419047
  path: {
417399
419048
  title: "Screenshot (simple)",
419049
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
417400
419050
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
417401
419051
  type: "string",
417402
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
419052
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
417403
419053
  transform: [
417404
419054
  "trim"
417405
419055
  ]
@@ -417633,9 +419283,10 @@ var schemas_default = {
417633
419283
  },
417634
419284
  path: {
417635
419285
  title: "Screenshot (simple)",
419286
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
417636
419287
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
417637
419288
  type: "string",
417638
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
419289
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
417639
419290
  transform: [
417640
419291
  "trim"
417641
419292
  ]
@@ -418109,9 +419760,10 @@ var schemas_default = {
418109
419760
  },
418110
419761
  path: {
418111
419762
  title: "Screenshot (simple)",
419763
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
418112
419764
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
418113
419765
  type: "string",
418114
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
419766
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
418115
419767
  transform: [
418116
419768
  "trim"
418117
419769
  ]
@@ -418493,6 +420145,7 @@ var schemas_default = {
418493
420145
  "image.png",
418494
420146
  "static/images/image.png",
418495
420147
  "/User/manny/projects/doc-detective/static/images/image.png",
420148
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
418496
420149
  "https://example.com/static/images/image.png",
418497
420150
  {
418498
420151
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -420927,10 +422580,11 @@ var schemas_default = {
420927
422580
  },
420928
422581
  overwrite: {
420929
422582
  type: "string",
420930
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
422583
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
420931
422584
  enum: [
420932
422585
  "true",
420933
- "false"
422586
+ "false",
422587
+ "aboveVariation"
420934
422588
  ]
420935
422589
  },
420936
422590
  name: {
@@ -420988,6 +422642,88 @@ var schemas_default = {
420988
422642
  }
420989
422643
  }
420990
422644
  ]
422645
+ },
422646
+ verify: {
422647
+ title: "Recording verify guards",
422648
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
422649
+ type: "object",
422650
+ additionalProperties: false,
422651
+ properties: {
422652
+ minDuration: {
422653
+ type: "number",
422654
+ description: "Fail if the video is shorter than this many seconds.",
422655
+ minimum: 0
422656
+ },
422657
+ maxDuration: {
422658
+ type: "number",
422659
+ description: "Fail if the video is longer than this many seconds.",
422660
+ minimum: 0
422661
+ },
422662
+ resolution: {
422663
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
422664
+ anyOf: [
422665
+ {
422666
+ type: "boolean",
422667
+ title: "Verify resolution (boolean)"
422668
+ },
422669
+ {
422670
+ type: "object",
422671
+ title: "Verify resolution (detailed)",
422672
+ additionalProperties: false,
422673
+ required: [
422674
+ "width",
422675
+ "height"
422676
+ ],
422677
+ properties: {
422678
+ width: {
422679
+ type: "integer",
422680
+ minimum: 1
422681
+ },
422682
+ height: {
422683
+ type: "integer",
422684
+ minimum: 1
422685
+ }
422686
+ }
422687
+ }
422688
+ ]
422689
+ },
422690
+ notBlack: {
422691
+ type: "boolean",
422692
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
422693
+ }
422694
+ }
422695
+ },
422696
+ checkpoints: {
422697
+ title: "Recording checkpoints",
422698
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
422699
+ anyOf: [
422700
+ {
422701
+ type: "boolean",
422702
+ title: "Recording checkpoints (boolean)",
422703
+ description: "If `true`, enables checkpoints with default settings."
422704
+ },
422705
+ {
422706
+ type: "object",
422707
+ title: "Recording checkpoints (detailed)",
422708
+ additionalProperties: false,
422709
+ properties: {
422710
+ maxVariation: {
422711
+ type: "number",
422712
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
422713
+ default: 0.05,
422714
+ minimum: 0,
422715
+ maximum: 1
422716
+ },
422717
+ directory: {
422718
+ type: "string",
422719
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
422720
+ transform: [
422721
+ "trim"
422722
+ ]
422723
+ }
422724
+ }
422725
+ }
422726
+ ]
420991
422727
  }
420992
422728
  },
420993
422729
  title: "Record (detailed)"
@@ -421249,10 +422985,11 @@ var schemas_default = {
421249
422985
  },
421250
422986
  overwrite: {
421251
422987
  type: "string",
421252
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
422988
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
421253
422989
  enum: [
421254
422990
  "true",
421255
- "false"
422991
+ "false",
422992
+ "aboveVariation"
421256
422993
  ]
421257
422994
  },
421258
422995
  name: {
@@ -421310,6 +423047,88 @@ var schemas_default = {
421310
423047
  }
421311
423048
  }
421312
423049
  ]
423050
+ },
423051
+ verify: {
423052
+ title: "Recording verify guards",
423053
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
423054
+ type: "object",
423055
+ additionalProperties: false,
423056
+ properties: {
423057
+ minDuration: {
423058
+ type: "number",
423059
+ description: "Fail if the video is shorter than this many seconds.",
423060
+ minimum: 0
423061
+ },
423062
+ maxDuration: {
423063
+ type: "number",
423064
+ description: "Fail if the video is longer than this many seconds.",
423065
+ minimum: 0
423066
+ },
423067
+ resolution: {
423068
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
423069
+ anyOf: [
423070
+ {
423071
+ type: "boolean",
423072
+ title: "Verify resolution (boolean)"
423073
+ },
423074
+ {
423075
+ type: "object",
423076
+ title: "Verify resolution (detailed)",
423077
+ additionalProperties: false,
423078
+ required: [
423079
+ "width",
423080
+ "height"
423081
+ ],
423082
+ properties: {
423083
+ width: {
423084
+ type: "integer",
423085
+ minimum: 1
423086
+ },
423087
+ height: {
423088
+ type: "integer",
423089
+ minimum: 1
423090
+ }
423091
+ }
423092
+ }
423093
+ ]
423094
+ },
423095
+ notBlack: {
423096
+ type: "boolean",
423097
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
423098
+ }
423099
+ }
423100
+ },
423101
+ checkpoints: {
423102
+ title: "Recording checkpoints",
423103
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
423104
+ anyOf: [
423105
+ {
423106
+ type: "boolean",
423107
+ title: "Recording checkpoints (boolean)",
423108
+ description: "If `true`, enables checkpoints with default settings."
423109
+ },
423110
+ {
423111
+ type: "object",
423112
+ title: "Recording checkpoints (detailed)",
423113
+ additionalProperties: false,
423114
+ properties: {
423115
+ maxVariation: {
423116
+ type: "number",
423117
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
423118
+ default: 0.05,
423119
+ minimum: 0,
423120
+ maximum: 1
423121
+ },
423122
+ directory: {
423123
+ type: "string",
423124
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
423125
+ transform: [
423126
+ "trim"
423127
+ ]
423128
+ }
423129
+ }
423130
+ }
423131
+ ]
421313
423132
  }
421314
423133
  },
421315
423134
  title: "Record (detailed)"
@@ -421376,6 +423195,17 @@ var schemas_default = {
421376
423195
  path: "results.mp4",
421377
423196
  engine: "ffmpeg"
421378
423197
  },
423198
+ {
423199
+ path: "results.mp4",
423200
+ checkpoints: true
423201
+ },
423202
+ {
423203
+ path: "results.mp4",
423204
+ checkpoints: {
423205
+ maxVariation: 0.02,
423206
+ directory: "baselines/results"
423207
+ }
423208
+ },
421379
423209
  {
421380
423210
  path: "results.mp4",
421381
423211
  engine: {
@@ -461802,9 +463632,10 @@ var schemas_default = {
461802
463632
  anyOf: [
461803
463633
  {
461804
463634
  title: "Screenshot (simple)",
463635
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
461805
463636
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
461806
463637
  type: "string",
461807
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
463638
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
461808
463639
  transform: [
461809
463640
  "trim"
461810
463641
  ]
@@ -462038,9 +463869,10 @@ var schemas_default = {
462038
463869
  },
462039
463870
  path: {
462040
463871
  title: "Screenshot (simple)",
463872
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
462041
463873
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
462042
463874
  type: "string",
462043
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
463875
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
462044
463876
  transform: [
462045
463877
  "trim"
462046
463878
  ]
@@ -462298,9 +464130,10 @@ var schemas_default = {
462298
464130
  schemas: {
462299
464131
  path: {
462300
464132
  title: "Screenshot (simple)",
464133
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
462301
464134
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
462302
464135
  type: "string",
462303
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
464136
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
462304
464137
  transform: [
462305
464138
  "trim"
462306
464139
  ]
@@ -462534,9 +464367,10 @@ var schemas_default = {
462534
464367
  },
462535
464368
  path: {
462536
464369
  title: "Screenshot (simple)",
464370
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
462537
464371
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
462538
464372
  type: "string",
462539
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
464373
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
462540
464374
  transform: [
462541
464375
  "trim"
462542
464376
  ]
@@ -463010,9 +464844,10 @@ var schemas_default = {
463010
464844
  },
463011
464845
  path: {
463012
464846
  title: "Screenshot (simple)",
464847
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
463013
464848
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
463014
464849
  type: "string",
463015
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
464850
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
463016
464851
  transform: [
463017
464852
  "trim"
463018
464853
  ]
@@ -463394,6 +465229,7 @@ var schemas_default = {
463394
465229
  "image.png",
463395
465230
  "static/images/image.png",
463396
465231
  "/User/manny/projects/doc-detective/static/images/image.png",
465232
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
463397
465233
  "https://example.com/static/images/image.png",
463398
465234
  {
463399
465235
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -465828,10 +467664,11 @@ var schemas_default = {
465828
467664
  },
465829
467665
  overwrite: {
465830
467666
  type: "string",
465831
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
467667
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
465832
467668
  enum: [
465833
467669
  "true",
465834
- "false"
467670
+ "false",
467671
+ "aboveVariation"
465835
467672
  ]
465836
467673
  },
465837
467674
  name: {
@@ -465889,6 +467726,88 @@ var schemas_default = {
465889
467726
  }
465890
467727
  }
465891
467728
  ]
467729
+ },
467730
+ verify: {
467731
+ title: "Recording verify guards",
467732
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
467733
+ type: "object",
467734
+ additionalProperties: false,
467735
+ properties: {
467736
+ minDuration: {
467737
+ type: "number",
467738
+ description: "Fail if the video is shorter than this many seconds.",
467739
+ minimum: 0
467740
+ },
467741
+ maxDuration: {
467742
+ type: "number",
467743
+ description: "Fail if the video is longer than this many seconds.",
467744
+ minimum: 0
467745
+ },
467746
+ resolution: {
467747
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
467748
+ anyOf: [
467749
+ {
467750
+ type: "boolean",
467751
+ title: "Verify resolution (boolean)"
467752
+ },
467753
+ {
467754
+ type: "object",
467755
+ title: "Verify resolution (detailed)",
467756
+ additionalProperties: false,
467757
+ required: [
467758
+ "width",
467759
+ "height"
467760
+ ],
467761
+ properties: {
467762
+ width: {
467763
+ type: "integer",
467764
+ minimum: 1
467765
+ },
467766
+ height: {
467767
+ type: "integer",
467768
+ minimum: 1
467769
+ }
467770
+ }
467771
+ }
467772
+ ]
467773
+ },
467774
+ notBlack: {
467775
+ type: "boolean",
467776
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
467777
+ }
467778
+ }
467779
+ },
467780
+ checkpoints: {
467781
+ title: "Recording checkpoints",
467782
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
467783
+ anyOf: [
467784
+ {
467785
+ type: "boolean",
467786
+ title: "Recording checkpoints (boolean)",
467787
+ description: "If `true`, enables checkpoints with default settings."
467788
+ },
467789
+ {
467790
+ type: "object",
467791
+ title: "Recording checkpoints (detailed)",
467792
+ additionalProperties: false,
467793
+ properties: {
467794
+ maxVariation: {
467795
+ type: "number",
467796
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
467797
+ default: 0.05,
467798
+ minimum: 0,
467799
+ maximum: 1
467800
+ },
467801
+ directory: {
467802
+ type: "string",
467803
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
467804
+ transform: [
467805
+ "trim"
467806
+ ]
467807
+ }
467808
+ }
467809
+ }
467810
+ ]
465892
467811
  }
465893
467812
  },
465894
467813
  title: "Record (detailed)"
@@ -466150,10 +468069,11 @@ var schemas_default = {
466150
468069
  },
466151
468070
  overwrite: {
466152
468071
  type: "string",
466153
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
468072
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
466154
468073
  enum: [
466155
468074
  "true",
466156
- "false"
468075
+ "false",
468076
+ "aboveVariation"
466157
468077
  ]
466158
468078
  },
466159
468079
  name: {
@@ -466211,6 +468131,88 @@ var schemas_default = {
466211
468131
  }
466212
468132
  }
466213
468133
  ]
468134
+ },
468135
+ verify: {
468136
+ title: "Recording verify guards",
468137
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
468138
+ type: "object",
468139
+ additionalProperties: false,
468140
+ properties: {
468141
+ minDuration: {
468142
+ type: "number",
468143
+ description: "Fail if the video is shorter than this many seconds.",
468144
+ minimum: 0
468145
+ },
468146
+ maxDuration: {
468147
+ type: "number",
468148
+ description: "Fail if the video is longer than this many seconds.",
468149
+ minimum: 0
468150
+ },
468151
+ resolution: {
468152
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
468153
+ anyOf: [
468154
+ {
468155
+ type: "boolean",
468156
+ title: "Verify resolution (boolean)"
468157
+ },
468158
+ {
468159
+ type: "object",
468160
+ title: "Verify resolution (detailed)",
468161
+ additionalProperties: false,
468162
+ required: [
468163
+ "width",
468164
+ "height"
468165
+ ],
468166
+ properties: {
468167
+ width: {
468168
+ type: "integer",
468169
+ minimum: 1
468170
+ },
468171
+ height: {
468172
+ type: "integer",
468173
+ minimum: 1
468174
+ }
468175
+ }
468176
+ }
468177
+ ]
468178
+ },
468179
+ notBlack: {
468180
+ type: "boolean",
468181
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
468182
+ }
468183
+ }
468184
+ },
468185
+ checkpoints: {
468186
+ title: "Recording checkpoints",
468187
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
468188
+ anyOf: [
468189
+ {
468190
+ type: "boolean",
468191
+ title: "Recording checkpoints (boolean)",
468192
+ description: "If `true`, enables checkpoints with default settings."
468193
+ },
468194
+ {
468195
+ type: "object",
468196
+ title: "Recording checkpoints (detailed)",
468197
+ additionalProperties: false,
468198
+ properties: {
468199
+ maxVariation: {
468200
+ type: "number",
468201
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
468202
+ default: 0.05,
468203
+ minimum: 0,
468204
+ maximum: 1
468205
+ },
468206
+ directory: {
468207
+ type: "string",
468208
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
468209
+ transform: [
468210
+ "trim"
468211
+ ]
468212
+ }
468213
+ }
468214
+ }
468215
+ ]
466214
468216
  }
466215
468217
  },
466216
468218
  title: "Record (detailed)"
@@ -466277,6 +468279,17 @@ var schemas_default = {
466277
468279
  path: "results.mp4",
466278
468280
  engine: "ffmpeg"
466279
468281
  },
468282
+ {
468283
+ path: "results.mp4",
468284
+ checkpoints: true
468285
+ },
468286
+ {
468287
+ path: "results.mp4",
468288
+ checkpoints: {
468289
+ maxVariation: 0.02,
468290
+ directory: "baselines/results"
468291
+ }
468292
+ },
466280
468293
  {
466281
468294
  path: "results.mp4",
466282
468295
  engine: {
@@ -508395,9 +510408,10 @@ var schemas_default = {
508395
510408
  anyOf: [
508396
510409
  {
508397
510410
  title: "Screenshot (simple)",
510411
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
508398
510412
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
508399
510413
  type: "string",
508400
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
510414
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
508401
510415
  transform: [
508402
510416
  "trim"
508403
510417
  ]
@@ -508631,9 +510645,10 @@ var schemas_default = {
508631
510645
  },
508632
510646
  path: {
508633
510647
  title: "Screenshot (simple)",
510648
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
508634
510649
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
508635
510650
  type: "string",
508636
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
510651
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
508637
510652
  transform: [
508638
510653
  "trim"
508639
510654
  ]
@@ -508891,9 +510906,10 @@ var schemas_default = {
508891
510906
  schemas: {
508892
510907
  path: {
508893
510908
  title: "Screenshot (simple)",
510909
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
508894
510910
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
508895
510911
  type: "string",
508896
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
510912
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
508897
510913
  transform: [
508898
510914
  "trim"
508899
510915
  ]
@@ -509127,9 +511143,10 @@ var schemas_default = {
509127
511143
  },
509128
511144
  path: {
509129
511145
  title: "Screenshot (simple)",
511146
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
509130
511147
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
509131
511148
  type: "string",
509132
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
511149
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
509133
511150
  transform: [
509134
511151
  "trim"
509135
511152
  ]
@@ -509603,9 +511620,10 @@ var schemas_default = {
509603
511620
  },
509604
511621
  path: {
509605
511622
  title: "Screenshot (simple)",
511623
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
509606
511624
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
509607
511625
  type: "string",
509608
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
511626
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
509609
511627
  transform: [
509610
511628
  "trim"
509611
511629
  ]
@@ -509987,6 +512005,7 @@ var schemas_default = {
509987
512005
  "image.png",
509988
512006
  "static/images/image.png",
509989
512007
  "/User/manny/projects/doc-detective/static/images/image.png",
512008
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
509990
512009
  "https://example.com/static/images/image.png",
509991
512010
  {
509992
512011
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -512421,10 +514440,11 @@ var schemas_default = {
512421
514440
  },
512422
514441
  overwrite: {
512423
514442
  type: "string",
512424
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
514443
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
512425
514444
  enum: [
512426
514445
  "true",
512427
- "false"
514446
+ "false",
514447
+ "aboveVariation"
512428
514448
  ]
512429
514449
  },
512430
514450
  name: {
@@ -512482,6 +514502,88 @@ var schemas_default = {
512482
514502
  }
512483
514503
  }
512484
514504
  ]
514505
+ },
514506
+ verify: {
514507
+ title: "Recording verify guards",
514508
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
514509
+ type: "object",
514510
+ additionalProperties: false,
514511
+ properties: {
514512
+ minDuration: {
514513
+ type: "number",
514514
+ description: "Fail if the video is shorter than this many seconds.",
514515
+ minimum: 0
514516
+ },
514517
+ maxDuration: {
514518
+ type: "number",
514519
+ description: "Fail if the video is longer than this many seconds.",
514520
+ minimum: 0
514521
+ },
514522
+ resolution: {
514523
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
514524
+ anyOf: [
514525
+ {
514526
+ type: "boolean",
514527
+ title: "Verify resolution (boolean)"
514528
+ },
514529
+ {
514530
+ type: "object",
514531
+ title: "Verify resolution (detailed)",
514532
+ additionalProperties: false,
514533
+ required: [
514534
+ "width",
514535
+ "height"
514536
+ ],
514537
+ properties: {
514538
+ width: {
514539
+ type: "integer",
514540
+ minimum: 1
514541
+ },
514542
+ height: {
514543
+ type: "integer",
514544
+ minimum: 1
514545
+ }
514546
+ }
514547
+ }
514548
+ ]
514549
+ },
514550
+ notBlack: {
514551
+ type: "boolean",
514552
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
514553
+ }
514554
+ }
514555
+ },
514556
+ checkpoints: {
514557
+ title: "Recording checkpoints",
514558
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
514559
+ anyOf: [
514560
+ {
514561
+ type: "boolean",
514562
+ title: "Recording checkpoints (boolean)",
514563
+ description: "If `true`, enables checkpoints with default settings."
514564
+ },
514565
+ {
514566
+ type: "object",
514567
+ title: "Recording checkpoints (detailed)",
514568
+ additionalProperties: false,
514569
+ properties: {
514570
+ maxVariation: {
514571
+ type: "number",
514572
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
514573
+ default: 0.05,
514574
+ minimum: 0,
514575
+ maximum: 1
514576
+ },
514577
+ directory: {
514578
+ type: "string",
514579
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
514580
+ transform: [
514581
+ "trim"
514582
+ ]
514583
+ }
514584
+ }
514585
+ }
514586
+ ]
512485
514587
  }
512486
514588
  },
512487
514589
  title: "Record (detailed)"
@@ -512743,10 +514845,11 @@ var schemas_default = {
512743
514845
  },
512744
514846
  overwrite: {
512745
514847
  type: "string",
512746
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
514848
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
512747
514849
  enum: [
512748
514850
  "true",
512749
- "false"
514851
+ "false",
514852
+ "aboveVariation"
512750
514853
  ]
512751
514854
  },
512752
514855
  name: {
@@ -512804,6 +514907,88 @@ var schemas_default = {
512804
514907
  }
512805
514908
  }
512806
514909
  ]
514910
+ },
514911
+ verify: {
514912
+ title: "Recording verify guards",
514913
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
514914
+ type: "object",
514915
+ additionalProperties: false,
514916
+ properties: {
514917
+ minDuration: {
514918
+ type: "number",
514919
+ description: "Fail if the video is shorter than this many seconds.",
514920
+ minimum: 0
514921
+ },
514922
+ maxDuration: {
514923
+ type: "number",
514924
+ description: "Fail if the video is longer than this many seconds.",
514925
+ minimum: 0
514926
+ },
514927
+ resolution: {
514928
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
514929
+ anyOf: [
514930
+ {
514931
+ type: "boolean",
514932
+ title: "Verify resolution (boolean)"
514933
+ },
514934
+ {
514935
+ type: "object",
514936
+ title: "Verify resolution (detailed)",
514937
+ additionalProperties: false,
514938
+ required: [
514939
+ "width",
514940
+ "height"
514941
+ ],
514942
+ properties: {
514943
+ width: {
514944
+ type: "integer",
514945
+ minimum: 1
514946
+ },
514947
+ height: {
514948
+ type: "integer",
514949
+ minimum: 1
514950
+ }
514951
+ }
514952
+ }
514953
+ ]
514954
+ },
514955
+ notBlack: {
514956
+ type: "boolean",
514957
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
514958
+ }
514959
+ }
514960
+ },
514961
+ checkpoints: {
514962
+ title: "Recording checkpoints",
514963
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
514964
+ anyOf: [
514965
+ {
514966
+ type: "boolean",
514967
+ title: "Recording checkpoints (boolean)",
514968
+ description: "If `true`, enables checkpoints with default settings."
514969
+ },
514970
+ {
514971
+ type: "object",
514972
+ title: "Recording checkpoints (detailed)",
514973
+ additionalProperties: false,
514974
+ properties: {
514975
+ maxVariation: {
514976
+ type: "number",
514977
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
514978
+ default: 0.05,
514979
+ minimum: 0,
514980
+ maximum: 1
514981
+ },
514982
+ directory: {
514983
+ type: "string",
514984
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
514985
+ transform: [
514986
+ "trim"
514987
+ ]
514988
+ }
514989
+ }
514990
+ }
514991
+ ]
512807
514992
  }
512808
514993
  },
512809
514994
  title: "Record (detailed)"
@@ -512870,6 +515055,17 @@ var schemas_default = {
512870
515055
  path: "results.mp4",
512871
515056
  engine: "ffmpeg"
512872
515057
  },
515058
+ {
515059
+ path: "results.mp4",
515060
+ checkpoints: true
515061
+ },
515062
+ {
515063
+ path: "results.mp4",
515064
+ checkpoints: {
515065
+ maxVariation: 0.02,
515066
+ directory: "baselines/results"
515067
+ }
515068
+ },
512873
515069
  {
512874
515070
  path: "results.mp4",
512875
515071
  engine: {
@@ -556641,9 +558837,10 @@ var schemas_default = {
556641
558837
  anyOf: [
556642
558838
  {
556643
558839
  title: "Screenshot (simple)",
558840
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
556644
558841
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
556645
558842
  type: "string",
556646
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
558843
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
556647
558844
  transform: [
556648
558845
  "trim"
556649
558846
  ]
@@ -556877,9 +559074,10 @@ var schemas_default = {
556877
559074
  },
556878
559075
  path: {
556879
559076
  title: "Screenshot (simple)",
559077
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
556880
559078
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
556881
559079
  type: "string",
556882
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
559080
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
556883
559081
  transform: [
556884
559082
  "trim"
556885
559083
  ]
@@ -557137,9 +559335,10 @@ var schemas_default = {
557137
559335
  schemas: {
557138
559336
  path: {
557139
559337
  title: "Screenshot (simple)",
559338
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
557140
559339
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
557141
559340
  type: "string",
557142
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
559341
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
557143
559342
  transform: [
557144
559343
  "trim"
557145
559344
  ]
@@ -557373,9 +559572,10 @@ var schemas_default = {
557373
559572
  },
557374
559573
  path: {
557375
559574
  title: "Screenshot (simple)",
559575
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
557376
559576
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
557377
559577
  type: "string",
557378
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
559578
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
557379
559579
  transform: [
557380
559580
  "trim"
557381
559581
  ]
@@ -557849,9 +560049,10 @@ var schemas_default = {
557849
560049
  },
557850
560050
  path: {
557851
560051
  title: "Screenshot (simple)",
560052
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
557852
560053
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
557853
560054
  type: "string",
557854
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
560055
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
557855
560056
  transform: [
557856
560057
  "trim"
557857
560058
  ]
@@ -558233,6 +560434,7 @@ var schemas_default = {
558233
560434
  "image.png",
558234
560435
  "static/images/image.png",
558235
560436
  "/User/manny/projects/doc-detective/static/images/image.png",
560437
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
558236
560438
  "https://example.com/static/images/image.png",
558237
560439
  {
558238
560440
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -560667,10 +562869,11 @@ var schemas_default = {
560667
562869
  },
560668
562870
  overwrite: {
560669
562871
  type: "string",
560670
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
562872
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
560671
562873
  enum: [
560672
562874
  "true",
560673
- "false"
562875
+ "false",
562876
+ "aboveVariation"
560674
562877
  ]
560675
562878
  },
560676
562879
  name: {
@@ -560728,6 +562931,88 @@ var schemas_default = {
560728
562931
  }
560729
562932
  }
560730
562933
  ]
562934
+ },
562935
+ verify: {
562936
+ title: "Recording verify guards",
562937
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
562938
+ type: "object",
562939
+ additionalProperties: false,
562940
+ properties: {
562941
+ minDuration: {
562942
+ type: "number",
562943
+ description: "Fail if the video is shorter than this many seconds.",
562944
+ minimum: 0
562945
+ },
562946
+ maxDuration: {
562947
+ type: "number",
562948
+ description: "Fail if the video is longer than this many seconds.",
562949
+ minimum: 0
562950
+ },
562951
+ resolution: {
562952
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
562953
+ anyOf: [
562954
+ {
562955
+ type: "boolean",
562956
+ title: "Verify resolution (boolean)"
562957
+ },
562958
+ {
562959
+ type: "object",
562960
+ title: "Verify resolution (detailed)",
562961
+ additionalProperties: false,
562962
+ required: [
562963
+ "width",
562964
+ "height"
562965
+ ],
562966
+ properties: {
562967
+ width: {
562968
+ type: "integer",
562969
+ minimum: 1
562970
+ },
562971
+ height: {
562972
+ type: "integer",
562973
+ minimum: 1
562974
+ }
562975
+ }
562976
+ }
562977
+ ]
562978
+ },
562979
+ notBlack: {
562980
+ type: "boolean",
562981
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
562982
+ }
562983
+ }
562984
+ },
562985
+ checkpoints: {
562986
+ title: "Recording checkpoints",
562987
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
562988
+ anyOf: [
562989
+ {
562990
+ type: "boolean",
562991
+ title: "Recording checkpoints (boolean)",
562992
+ description: "If `true`, enables checkpoints with default settings."
562993
+ },
562994
+ {
562995
+ type: "object",
562996
+ title: "Recording checkpoints (detailed)",
562997
+ additionalProperties: false,
562998
+ properties: {
562999
+ maxVariation: {
563000
+ type: "number",
563001
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
563002
+ default: 0.05,
563003
+ minimum: 0,
563004
+ maximum: 1
563005
+ },
563006
+ directory: {
563007
+ type: "string",
563008
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
563009
+ transform: [
563010
+ "trim"
563011
+ ]
563012
+ }
563013
+ }
563014
+ }
563015
+ ]
560731
563016
  }
560732
563017
  },
560733
563018
  title: "Record (detailed)"
@@ -560989,10 +563274,11 @@ var schemas_default = {
560989
563274
  },
560990
563275
  overwrite: {
560991
563276
  type: "string",
560992
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
563277
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
560993
563278
  enum: [
560994
563279
  "true",
560995
- "false"
563280
+ "false",
563281
+ "aboveVariation"
560996
563282
  ]
560997
563283
  },
560998
563284
  name: {
@@ -561050,6 +563336,88 @@ var schemas_default = {
561050
563336
  }
561051
563337
  }
561052
563338
  ]
563339
+ },
563340
+ verify: {
563341
+ title: "Recording verify guards",
563342
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
563343
+ type: "object",
563344
+ additionalProperties: false,
563345
+ properties: {
563346
+ minDuration: {
563347
+ type: "number",
563348
+ description: "Fail if the video is shorter than this many seconds.",
563349
+ minimum: 0
563350
+ },
563351
+ maxDuration: {
563352
+ type: "number",
563353
+ description: "Fail if the video is longer than this many seconds.",
563354
+ minimum: 0
563355
+ },
563356
+ resolution: {
563357
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
563358
+ anyOf: [
563359
+ {
563360
+ type: "boolean",
563361
+ title: "Verify resolution (boolean)"
563362
+ },
563363
+ {
563364
+ type: "object",
563365
+ title: "Verify resolution (detailed)",
563366
+ additionalProperties: false,
563367
+ required: [
563368
+ "width",
563369
+ "height"
563370
+ ],
563371
+ properties: {
563372
+ width: {
563373
+ type: "integer",
563374
+ minimum: 1
563375
+ },
563376
+ height: {
563377
+ type: "integer",
563378
+ minimum: 1
563379
+ }
563380
+ }
563381
+ }
563382
+ ]
563383
+ },
563384
+ notBlack: {
563385
+ type: "boolean",
563386
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
563387
+ }
563388
+ }
563389
+ },
563390
+ checkpoints: {
563391
+ title: "Recording checkpoints",
563392
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
563393
+ anyOf: [
563394
+ {
563395
+ type: "boolean",
563396
+ title: "Recording checkpoints (boolean)",
563397
+ description: "If `true`, enables checkpoints with default settings."
563398
+ },
563399
+ {
563400
+ type: "object",
563401
+ title: "Recording checkpoints (detailed)",
563402
+ additionalProperties: false,
563403
+ properties: {
563404
+ maxVariation: {
563405
+ type: "number",
563406
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
563407
+ default: 0.05,
563408
+ minimum: 0,
563409
+ maximum: 1
563410
+ },
563411
+ directory: {
563412
+ type: "string",
563413
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
563414
+ transform: [
563415
+ "trim"
563416
+ ]
563417
+ }
563418
+ }
563419
+ }
563420
+ ]
561053
563421
  }
561054
563422
  },
561055
563423
  title: "Record (detailed)"
@@ -561116,6 +563484,17 @@ var schemas_default = {
561116
563484
  path: "results.mp4",
561117
563485
  engine: "ffmpeg"
561118
563486
  },
563487
+ {
563488
+ path: "results.mp4",
563489
+ checkpoints: true
563490
+ },
563491
+ {
563492
+ path: "results.mp4",
563493
+ checkpoints: {
563494
+ maxVariation: 0.02,
563495
+ directory: "baselines/results"
563496
+ }
563497
+ },
561119
563498
  {
561120
563499
  path: "results.mp4",
561121
563500
  engine: {
@@ -601542,9 +603921,10 @@ var schemas_default = {
601542
603921
  anyOf: [
601543
603922
  {
601544
603923
  title: "Screenshot (simple)",
603924
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
601545
603925
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
601546
603926
  type: "string",
601547
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
603927
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
601548
603928
  transform: [
601549
603929
  "trim"
601550
603930
  ]
@@ -601778,9 +604158,10 @@ var schemas_default = {
601778
604158
  },
601779
604159
  path: {
601780
604160
  title: "Screenshot (simple)",
604161
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
601781
604162
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
601782
604163
  type: "string",
601783
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
604164
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
601784
604165
  transform: [
601785
604166
  "trim"
601786
604167
  ]
@@ -602038,9 +604419,10 @@ var schemas_default = {
602038
604419
  schemas: {
602039
604420
  path: {
602040
604421
  title: "Screenshot (simple)",
604422
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
602041
604423
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
602042
604424
  type: "string",
602043
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
604425
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
602044
604426
  transform: [
602045
604427
  "trim"
602046
604428
  ]
@@ -602274,9 +604656,10 @@ var schemas_default = {
602274
604656
  },
602275
604657
  path: {
602276
604658
  title: "Screenshot (simple)",
604659
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
602277
604660
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
602278
604661
  type: "string",
602279
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
604662
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
602280
604663
  transform: [
602281
604664
  "trim"
602282
604665
  ]
@@ -602750,9 +605133,10 @@ var schemas_default = {
602750
605133
  },
602751
605134
  path: {
602752
605135
  title: "Screenshot (simple)",
605136
+ $comment: "The pattern gates the target's EXTENSION, not its characters or location: any path ending in .png/.PNG is accepted, plus an http(s) URL to a PNG (optionally with a query string, for signed URLs) and a `$VAR` reference. It deliberately does not restrict the character set \u2014 an earlier pattern allowed any Windows absolute path but limited non-Windows paths to [A-Za-z0-9_./\\-], so ordinary macOS/Linux projects (a space, parentheses, '~', or non-ASCII anywhere in the path) failed validation, including for the absolute paths doc-detective synthesizes internally for autoScreenshot and recording checkpoints. That charset never bounded WHERE a screenshot could be written (traversal like ../../x.png always passed), so it only made non-Windows projects second-class. See ADR 01077.",
602753
605137
  description: "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step. If an `http(s)` URL is supplied, the remote image is downloaded and used as a read-only reference for comparison; the new capture is written to a local run-specific folder instead of being uploaded back to the URL.",
602754
605138
  type: "string",
602755
- pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|[A-Za-z]:[\\/\\\\].*\\.(?:png|PNG)|[\\/\\\\]?[A-Za-z0-9_.\\/\\\\-]*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
605139
+ pattern: "^(?:https?:\\/\\/.+\\.(?:png|PNG)(?:\\?.*)?|.*\\.(?:png|PNG)|\\$[A-Za-z0-9_]+)$",
602756
605140
  transform: [
602757
605141
  "trim"
602758
605142
  ]
@@ -603134,6 +605518,7 @@ var schemas_default = {
603134
605518
  "image.png",
603135
605519
  "static/images/image.png",
603136
605520
  "/User/manny/projects/doc-detective/static/images/image.png",
605521
+ "/Users/jane doe/projects/my docs (v2)/static/images/image.png",
603137
605522
  "https://example.com/static/images/image.png",
603138
605523
  {
603139
605524
  path: "https://promptless-customer-doc-assets.s3.amazonaws.com/docs-images/request-changes-button-0c851bb3.png",
@@ -605568,10 +607953,11 @@ var schemas_default = {
605568
607953
  },
605569
607954
  overwrite: {
605570
607955
  type: "string",
605571
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
607956
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
605572
607957
  enum: [
605573
607958
  "true",
605574
- "false"
607959
+ "false",
607960
+ "aboveVariation"
605575
607961
  ]
605576
607962
  },
605577
607963
  name: {
@@ -605629,6 +608015,88 @@ var schemas_default = {
605629
608015
  }
605630
608016
  }
605631
608017
  ]
608018
+ },
608019
+ verify: {
608020
+ title: "Recording verify guards",
608021
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
608022
+ type: "object",
608023
+ additionalProperties: false,
608024
+ properties: {
608025
+ minDuration: {
608026
+ type: "number",
608027
+ description: "Fail if the video is shorter than this many seconds.",
608028
+ minimum: 0
608029
+ },
608030
+ maxDuration: {
608031
+ type: "number",
608032
+ description: "Fail if the video is longer than this many seconds.",
608033
+ minimum: 0
608034
+ },
608035
+ resolution: {
608036
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
608037
+ anyOf: [
608038
+ {
608039
+ type: "boolean",
608040
+ title: "Verify resolution (boolean)"
608041
+ },
608042
+ {
608043
+ type: "object",
608044
+ title: "Verify resolution (detailed)",
608045
+ additionalProperties: false,
608046
+ required: [
608047
+ "width",
608048
+ "height"
608049
+ ],
608050
+ properties: {
608051
+ width: {
608052
+ type: "integer",
608053
+ minimum: 1
608054
+ },
608055
+ height: {
608056
+ type: "integer",
608057
+ minimum: 1
608058
+ }
608059
+ }
608060
+ }
608061
+ ]
608062
+ },
608063
+ notBlack: {
608064
+ type: "boolean",
608065
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
608066
+ }
608067
+ }
608068
+ },
608069
+ checkpoints: {
608070
+ title: "Recording checkpoints",
608071
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
608072
+ anyOf: [
608073
+ {
608074
+ type: "boolean",
608075
+ title: "Recording checkpoints (boolean)",
608076
+ description: "If `true`, enables checkpoints with default settings."
608077
+ },
608078
+ {
608079
+ type: "object",
608080
+ title: "Recording checkpoints (detailed)",
608081
+ additionalProperties: false,
608082
+ properties: {
608083
+ maxVariation: {
608084
+ type: "number",
608085
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
608086
+ default: 0.05,
608087
+ minimum: 0,
608088
+ maximum: 1
608089
+ },
608090
+ directory: {
608091
+ type: "string",
608092
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
608093
+ transform: [
608094
+ "trim"
608095
+ ]
608096
+ }
608097
+ }
608098
+ }
608099
+ ]
605632
608100
  }
605633
608101
  },
605634
608102
  title: "Record (detailed)"
@@ -605890,10 +608358,11 @@ var schemas_default = {
605890
608358
  },
605891
608359
  overwrite: {
605892
608360
  type: "string",
605893
- description: "If `true`, overwrites the existing recording at `path` if it exists.",
608361
+ description: "If `true`, overwrites the existing recording at `path` if it exists. If `false`, skips the recording when the file already exists. If `aboveVariation`, always records, but replaces the existing file (and its checkpoint baselines) only when the span's checkpoint screenshots show it meaningfully changed \u2014 requires `checkpoints`, so it turns them on with defaults when `checkpoints` is omitted or `false`; set `checkpoints` to an object to tune `maxVariation` or `directory`.",
605894
608362
  enum: [
605895
608363
  "true",
605896
- "false"
608364
+ "false",
608365
+ "aboveVariation"
605897
608366
  ]
605898
608367
  },
605899
608368
  name: {
@@ -605951,6 +608420,88 @@ var schemas_default = {
605951
608420
  }
605952
608421
  }
605953
608422
  ]
608423
+ },
608424
+ verify: {
608425
+ title: "Recording verify guards",
608426
+ description: "Structural assertions on the produced video file, evaluated when the recording stops. Unlike checkpoint drift (a WARNING), a violated guard FAILs the stopRecord step \u2014 these are properties you explicitly demand of the artifact.",
608427
+ type: "object",
608428
+ additionalProperties: false,
608429
+ properties: {
608430
+ minDuration: {
608431
+ type: "number",
608432
+ description: "Fail if the video is shorter than this many seconds.",
608433
+ minimum: 0
608434
+ },
608435
+ maxDuration: {
608436
+ type: "number",
608437
+ description: "Fail if the video is longer than this many seconds.",
608438
+ minimum: 0
608439
+ },
608440
+ resolution: {
608441
+ description: "Verify the video's dimensions (\xB12 pixels \u2014 encoders round to even dimensions). `true` compares against the capture plan's resolved expectation (the crop rectangle when a window/viewport crop applied, else the capture frame size; skipped when no expectation exists for the engine). An object compares literal dimensions.",
608442
+ anyOf: [
608443
+ {
608444
+ type: "boolean",
608445
+ title: "Verify resolution (boolean)"
608446
+ },
608447
+ {
608448
+ type: "object",
608449
+ title: "Verify resolution (detailed)",
608450
+ additionalProperties: false,
608451
+ required: [
608452
+ "width",
608453
+ "height"
608454
+ ],
608455
+ properties: {
608456
+ width: {
608457
+ type: "integer",
608458
+ minimum: 1
608459
+ },
608460
+ height: {
608461
+ type: "integer",
608462
+ minimum: 1
608463
+ }
608464
+ }
608465
+ }
608466
+ ]
608467
+ },
608468
+ notBlack: {
608469
+ type: "boolean",
608470
+ description: "Fail if the video is essentially all black (black frames cover 95% or more of its duration) \u2014 the classic symptom of a broken screen capture."
608471
+ }
608472
+ }
608473
+ },
608474
+ checkpoints: {
608475
+ title: "Recording checkpoints",
608476
+ description: "Capture a checkpoint screenshot after every step while this recording is active and compare each against a persistent baseline stored beside the recording (`<path>.checkpoints/` by default). Baselines seed on the first run; on later runs, per-checkpoint variation is reported in the `stopRecord` step's outputs, and variation beyond `maxVariation` surfaces as a WARNING. If `false` or unset, no checkpoints are captured.",
608477
+ anyOf: [
608478
+ {
608479
+ type: "boolean",
608480
+ title: "Recording checkpoints (boolean)",
608481
+ description: "If `true`, enables checkpoints with default settings."
608482
+ },
608483
+ {
608484
+ type: "object",
608485
+ title: "Recording checkpoints (detailed)",
608486
+ additionalProperties: false,
608487
+ properties: {
608488
+ maxVariation: {
608489
+ type: "number",
608490
+ description: "Maximum fractional pixel difference tolerated between a checkpoint and its baseline before the drift surfaces as a WARNING.",
608491
+ default: 0.05,
608492
+ minimum: 0,
608493
+ maximum: 1
608494
+ },
608495
+ directory: {
608496
+ type: "string",
608497
+ description: "Directory for the checkpoint baselines. If unset, defaults to a `.checkpoints` directory beside the recording (for example, `demo.mp4.checkpoints/`).",
608498
+ transform: [
608499
+ "trim"
608500
+ ]
608501
+ }
608502
+ }
608503
+ }
608504
+ ]
605954
608505
  }
605955
608506
  },
605956
608507
  title: "Record (detailed)"
@@ -606017,6 +608568,17 @@ var schemas_default = {
606017
608568
  path: "results.mp4",
606018
608569
  engine: "ffmpeg"
606019
608570
  },
608571
+ {
608572
+ path: "results.mp4",
608573
+ checkpoints: true
608574
+ },
608575
+ {
608576
+ path: "results.mp4",
608577
+ checkpoints: {
608578
+ maxVariation: 0.02,
608579
+ directory: "baselines/results"
608580
+ }
608581
+ },
606020
608582
  {
606021
608583
  path: "results.mp4",
606022
608584
  engine: {