@decantr/verifier 2.1.0 → 2.3.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/README.md CHANGED
@@ -18,8 +18,9 @@ npm install @decantr/verifier
18
18
  - `critiqueFile()` for file-level review against compiled review-pack contracts
19
19
  - `createContractAssertions()` for explicit route, shell, accessibility, context, and design-token assertions derived from Essence/context
20
20
  - `createEvidenceBundle()` for privacy-redacted local evidence artifacts used by AI repair loops and CI
21
- - schema-backed report types for project audits, Project Health, Evidence Bundles, Workspace Health, file critiques, and showcase verification
21
+ - schema-backed report types for project audits, Project Health, Decantr CI reports, Evidence Bundles, Workspace Health, file critiques, and showcase verification
22
22
  - `ProjectHealthReport`, `ProjectHealthFinding`, and `ProjectHealthRemediation` types for the CLI's end-user health surface
23
+ - interaction findings now include scanned file counts, file line ranges, and expected signal evidence where available, so CLI health/check output can point agents at source-grounded remediation
23
24
  - published verifier report schemas are exercised by AJV-backed round-trip tests against real audit, critique, and shortlist-report outputs
24
25
  - project audits include runtime evidence when a built `dist/` output is present:
25
26
  - root document
@@ -55,6 +56,7 @@ function isBlocking(report: ProjectHealthReport) {
55
56
  - `@decantr/verifier/schema/verification-report.common.v1.json`
56
57
  - `@decantr/verifier/schema/project-audit-report.v1.json`
57
58
  - `@decantr/verifier/schema/project-health-report.v1.json`
59
+ - `@decantr/verifier/schema/decantr-ci-report.v1.json`
58
60
  - `@decantr/verifier/schema/evidence-bundle.v1.json`
59
61
  - `@decantr/verifier/schema/workspace-health-report.v1.json`
60
62
  - `@decantr/verifier/schema/file-critique-report.v1.json`
package/dist/index.d.ts CHANGED
@@ -97,6 +97,13 @@ declare const INTERACTION_SIGNALS: Record<string, InteractionRequirement>;
97
97
  interface InteractionMissingFinding {
98
98
  interaction: string;
99
99
  suggestion: string;
100
+ scannedFiles?: number;
101
+ scannedLocations?: Array<{
102
+ file: string;
103
+ startLine: number;
104
+ endLine: number;
105
+ }>;
106
+ expectedSignals?: string[];
100
107
  }
101
108
  /**
102
109
  * Scan a source-tree map (file path → file contents) for evidence of each
@@ -119,6 +126,7 @@ declare const VERIFICATION_SCHEMA_URLS: {
119
126
  readonly common: "https://decantr.ai/schemas/verification-report.common.v1.json";
120
127
  readonly projectAudit: "https://decantr.ai/schemas/project-audit-report.v1.json";
121
128
  readonly projectHealth: "https://decantr.ai/schemas/project-health-report.v1.json";
129
+ readonly decantrCi: "https://decantr.ai/schemas/decantr-ci-report.v1.json";
122
130
  readonly evidenceBundle: "https://decantr.ai/schemas/evidence-bundle.v1.json";
123
131
  readonly workspaceHealth: "https://decantr.ai/schemas/workspace-health-report.v1.json";
124
132
  readonly fileCritique: "https://decantr.ai/schemas/file-critique-report.v1.json";
package/dist/index.js CHANGED
@@ -653,7 +653,7 @@ var INTERACTION_SIGNALS = {
653
653
  },
654
654
  "click-connect": {
655
655
  interaction: "click-connect",
656
- signals: [/onClick.*?port|connect/i, /connections?\s*[:\[=]/i],
656
+ signals: [/onClick.*?port|connect/i, /connections?\s*[:[=]/i],
657
657
  suggestion: "Implement a two-click state machine: first click selects a port, second click on another port creates a connection. Store connections in component state."
658
658
  },
659
659
  "inline-edit": {
@@ -697,9 +697,11 @@ var INTERACTION_SIGNALS = {
697
697
  suggestion: "Implement focus trap inside modal/dialog \u2014 listen for Tab key, cycle focus within the dialog, restore focus on close."
698
698
  }
699
699
  };
700
+ function sourceLineCount(source) {
701
+ return Math.max(1, source.replace(/\r?\n$/, "").split(/\r?\n/).length);
702
+ }
700
703
  function verifyInteractionsInSource(interactions, sources) {
701
704
  if (interactions.length === 0 || sources.size === 0) return [];
702
- const combined = Array.from(sources.values()).join("\n\n");
703
705
  const unique = Array.from(new Set(interactions));
704
706
  const missing = [];
705
707
  for (const interaction of unique) {
@@ -707,16 +709,30 @@ function verifyInteractionsInSource(interactions, sources) {
707
709
  if (!requirement) {
708
710
  continue;
709
711
  }
710
- const matched = requirement.signals.some((signal) => {
711
- if (typeof signal === "string") {
712
- return combined.includes(signal);
713
- }
714
- return signal.test(combined);
715
- });
712
+ let matched = false;
713
+ for (const source of sources.values()) {
714
+ matched = requirement.signals.some((signal) => {
715
+ if (typeof signal === "string") {
716
+ return source.includes(signal);
717
+ }
718
+ signal.lastIndex = 0;
719
+ return signal.test(source);
720
+ });
721
+ if (matched) break;
722
+ }
716
723
  if (!matched) {
717
724
  missing.push({
718
725
  interaction,
719
- suggestion: requirement.suggestion
726
+ suggestion: requirement.suggestion,
727
+ scannedFiles: sources.size,
728
+ scannedLocations: [...sources.entries()].slice(0, 8).map(([file, source]) => ({
729
+ file,
730
+ startLine: 1,
731
+ endLine: sourceLineCount(source)
732
+ })),
733
+ expectedSignals: requirement.signals.map(
734
+ (signal) => typeof signal === "string" ? signal : String(signal)
735
+ )
720
736
  });
721
737
  }
722
738
  }
@@ -731,6 +747,7 @@ var VERIFICATION_SCHEMA_URLS = {
731
747
  common: "https://decantr.ai/schemas/verification-report.common.v1.json",
732
748
  projectAudit: "https://decantr.ai/schemas/project-audit-report.v1.json",
733
749
  projectHealth: "https://decantr.ai/schemas/project-health-report.v1.json",
750
+ decantrCi: "https://decantr.ai/schemas/decantr-ci-report.v1.json",
734
751
  evidenceBundle: "https://decantr.ai/schemas/evidence-bundle.v1.json",
735
752
  workspaceHealth: "https://decantr.ai/schemas/workspace-health-report.v1.json",
736
753
  fileCritique: "https://decantr.ai/schemas/file-critique-report.v1.json",
@@ -1689,6 +1706,11 @@ function buildRegistryContext(projectRoot) {
1689
1706
  }
1690
1707
  } catch {
1691
1708
  }
1709
+ for (const id of ["content-section", "footer", "form-basic", "hero", "nav-header"]) {
1710
+ if (!patternRegistry.has(id)) {
1711
+ patternRegistry.set(id, { id, source: "bundled" });
1712
+ }
1713
+ }
1692
1714
  return { themeRegistry, patternRegistry };
1693
1715
  }
1694
1716
  function guardViolationToFinding(violation) {
@@ -2862,7 +2884,10 @@ function appendSourceAuditFindings(findings, sourceAudit, essence, reviewPack) {
2862
2884
  })
2863
2885
  );
2864
2886
  }
2865
- if (topology.hasAuthFeature && topology.primaryRoutes.length > 0 && sourceAudit.protectedSurfaceSignals.count > 0 && sourceAudit.authGuardSignals.count > 0 && !sourceAuditBucketsOverlap(sourceAudit.protectedSurfaceSignals, sourceAudit.authGuardSignals) && !sourceAuditBucketsOverlap(sourceAudit.protectedSurfaceSignals, sourceAudit.authSessionSignals) && !sourceAuditProtectedSurfacesCoveredByGuardedNextLayouts(
2887
+ if (topology.hasAuthFeature && topology.primaryRoutes.length > 0 && sourceAudit.protectedSurfaceSignals.count > 0 && sourceAudit.authGuardSignals.count > 0 && !sourceAuditBucketsOverlap(sourceAudit.protectedSurfaceSignals, sourceAudit.authGuardSignals) && !sourceAuditBucketsOverlap(
2888
+ sourceAudit.protectedSurfaceSignals,
2889
+ sourceAudit.authSessionSignals
2890
+ ) && !sourceAuditProtectedSurfacesCoveredByGuardedNextLayouts(
2866
2891
  sourceAudit.protectedSurfaceSignals,
2867
2892
  sourceAudit.authGuardSignals,
2868
2893
  topology