@williambeto/ai-workflow 2.9.0 → 2.9.2

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.
@@ -25,6 +25,9 @@ function parseStatusLine(line) {
25
25
  function isManagedChangePath(file = "") {
26
26
  return /(^|\/)(node_modules|vendor|dist|coverage|\.cache)(\/|$)/.test(normalizePath(file));
27
27
  }
28
+ function isScreenshotPath(file = "") {
29
+ return /\.(png|jpe?g|webp)$/i.test(normalizePath(file));
30
+ }
28
31
  async function exists(target) {
29
32
  try {
30
33
  await fs.access(target);
@@ -163,17 +166,22 @@ var QualityGuard = class {
163
166
  }
164
167
  async verifyUiEvidence() {
165
168
  if (!this.isUiTask()) return { status: "NOT_RUN", reason: "Non-UI task." };
166
- const candidates = ["docs", "screenshots", "evidence"];
167
- const found = [];
169
+ const candidates = ["docs", "screenshots", "evidence", ".evidence"];
170
+ const found = /* @__PURE__ */ new Set();
171
+ for (const file of this.getScopedChangedFiles()) {
172
+ const normalized = normalizePath(file);
173
+ if (!isScreenshotPath(normalized) || path.isAbsolute(normalized) || normalized.startsWith("../")) continue;
174
+ if (await exists(path.join(this.cwd, normalized))) found.add(normalized);
175
+ }
168
176
  for (const dir of candidates) {
169
177
  const root = path.join(this.cwd, dir);
170
178
  if (!await exists(root)) continue;
171
179
  const entries = await fs.readdir(root, { recursive: true }).catch(() => []);
172
180
  for (const entry of entries) {
173
- if (/\.(png|jpe?g|webp)$/i.test(String(entry))) found.push(normalizePath(path.join(dir, String(entry))));
181
+ if (isScreenshotPath(String(entry))) found.add(normalizePath(path.join(dir, String(entry))));
174
182
  }
175
183
  }
176
- if (found.length) return { status: "PASS", screenshots: found.slice(0, 20) };
184
+ if (found.size) return { status: "PASS", screenshots: [...found].sort().slice(0, 20) };
177
185
  if (this.evidencePolicy === "required") {
178
186
  return { status: "FAIL_QUALITY_GATE", reason: "Required evidence for a high-risk or release UI change does not include a persisted screenshot." };
179
187
  }
@@ -673,6 +681,26 @@ var EvidenceCollector = class {
673
681
  const implementationFilesPresent = qualityGuard.isImplementationTask();
674
682
  const executableBehavior = await qualityGuard.hasExecutableBehaviorChanges(this.deliveryChangedFiles || void 0);
675
683
  const results = tasks.map((task) => this.runTask(task));
684
+ let visualEvidence = null;
685
+ if (this.visualDist) {
686
+ console.log(`
687
+ --- Capturing Visual Evidence ---`);
688
+ console.log(`Serving ${this.visualDist} on port ${this.port}...`);
689
+ try {
690
+ const verifier = new VisualVerifier({ cwd: this.cwd, visualDist: this.visualDist, port: this.port });
691
+ const screenshots = await verifier.captureScreenshots();
692
+ visualEvidence = {
693
+ desktop: path3.relative(this.cwd, screenshots[0]),
694
+ mobile: path3.relative(this.cwd, screenshots[1])
695
+ };
696
+ console.log(`Visual evidence captured successfully:`);
697
+ console.log(`- Desktop: ${visualEvidence.desktop}`);
698
+ console.log(`- Mobile: ${visualEvidence.mobile}`);
699
+ } catch (err) {
700
+ console.error(`Error capturing visual evidence: ${err.message}`);
701
+ throw err;
702
+ }
703
+ }
676
704
  const policyValidation = await qualityGuard.verify();
677
705
  const behaviorTests = results.filter((result) => result.kind === "test");
678
706
  const passingBehaviorTest = behaviorTests.some((result) => result.status === "PASS");
@@ -745,7 +773,8 @@ var EvidenceCollector = class {
745
773
  deliveryDecision: deliveryDecision.decision,
746
774
  claimedOutcome: this.claimedOutcome
747
775
  });
748
- if (["NEEDS_CLARIFICATION", "NOT_DELIVERED"].includes(deliveryOutcome) && ["PASS", "PASS_WITH_NOTES"].includes(overallStatus)) {
776
+ const deliveryOutcomeBlocks = ["NEEDS_CLARIFICATION", "NOT_DELIVERED"].includes(deliveryOutcome) && ["PASS", "PASS_WITH_NOTES"].includes(overallStatus);
777
+ if (deliveryOutcomeBlocks) {
749
778
  overallStatus = "BLOCKED";
750
779
  }
751
780
  const limitations = [];
@@ -811,7 +840,7 @@ var EvidenceCollector = class {
811
840
  "satisfy the stated decision requirement before finalizing"
812
841
  ));
813
842
  }
814
- if (["NEEDS_CLARIFICATION", "NOT_DELIVERED"].includes(deliveryOutcome)) {
843
+ if (deliveryOutcomeBlocks) {
815
844
  limitations.push(blockingDiagnostic(
816
845
  "delivery-outcome",
817
846
  `the resolved outcome is ${deliveryOutcome}`,
@@ -820,26 +849,6 @@ var EvidenceCollector = class {
820
849
  ));
821
850
  }
822
851
  const uniqueLimitations = [...new Set(limitations)];
823
- let visualEvidence = null;
824
- if (this.visualDist) {
825
- console.log(`
826
- --- Capturing Visual Evidence ---`);
827
- console.log(`Serving ${this.visualDist} on port ${this.port}...`);
828
- try {
829
- const verifier = new VisualVerifier({ cwd: this.cwd, visualDist: this.visualDist, port: this.port });
830
- const screenshots = await verifier.captureScreenshots();
831
- visualEvidence = {
832
- desktop: path3.relative(this.cwd, screenshots[0]),
833
- mobile: path3.relative(this.cwd, screenshots[1])
834
- };
835
- console.log(`Visual evidence captured successfully:`);
836
- console.log(`- Desktop: ${visualEvidence.desktop}`);
837
- console.log(`- Mobile: ${visualEvidence.mobile}`);
838
- } catch (err) {
839
- console.error(`Error capturing visual evidence: ${err.message}`);
840
- throw err;
841
- }
842
- }
843
852
  const evidence = {
844
853
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
845
854
  taskSlug: this.taskSlug,
@@ -1053,4 +1062,4 @@ export {
1053
1062
  EvidenceCollector,
1054
1063
  ValidationPlanner
1055
1064
  };
1056
- //# sourceMappingURL=chunk-GLYX3HEY.js.map
1065
+ //# sourceMappingURL=chunk-PP42PB7M.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williambeto/ai-workflow",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "AI Workflow Kit — OpenCode-first software delivery workflow with agents, commands, skills, validation, and evidence",
5
5
  "license": "MIT",
6
6
  "author": "José Willams",
@@ -3,7 +3,7 @@ import {
3
3
  QualityGuard,
4
4
  ValidationPlanner,
5
5
  VisualVerifier
6
- } from "./chunk-GLYX3HEY.js";
6
+ } from "./chunk-PP42PB7M.js";
7
7
  import "./chunk-H7GIKXFO.js";
8
8
  import "./chunk-5WRI5ZAA.js";
9
9
 
@@ -86,4 +86,4 @@ async function runValidate({
86
86
  export {
87
87
  runValidate
88
88
  };
89
- //# sourceMappingURL=validate-DDKN6ORS.js.map
89
+ //# sourceMappingURL=validate-7G3HBE2K.js.map