@decantr/verifier 3.4.1 → 3.5.3
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 +13 -7
- package/dist/index.d.ts +262 -50
- package/dist/index.js +391 -18
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/schema/authority-resolution.v2.json +116 -0
- package/schema/decantr-ci-report.v2.json +55 -0
- package/schema/evidence-bundle.v2.json +35 -4
- package/schema/loop-readiness.v2.json +87 -0
- package/schema/project-health-report.v2.json +119 -0
- package/schema/proof-field-report.v2.json +51 -0
- package/schema/verification-report.common.v2.json +91 -0
- package/schema/workspace-health-report.v2.json +51 -0
package/dist/index.js
CHANGED
|
@@ -344,6 +344,300 @@ function auditComponentReuse(projectRoot, sourceFiles) {
|
|
|
344
344
|
};
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
+
// src/contracts-v2.ts
|
|
348
|
+
var VERIFICATION_COMMON_V2_SCHEMA_URL = "https://decantr.ai/schemas/verification-report.common.v2.json";
|
|
349
|
+
var PROJECT_HEALTH_REPORT_V2_SCHEMA_URL = "https://decantr.ai/schemas/project-health-report.v2.json";
|
|
350
|
+
var DECANTR_CI_REPORT_V2_SCHEMA_URL = "https://decantr.ai/schemas/decantr-ci-report.v2.json";
|
|
351
|
+
var WORKSPACE_HEALTH_REPORT_V2_SCHEMA_URL = "https://decantr.ai/schemas/workspace-health-report.v2.json";
|
|
352
|
+
var EVIDENCE_BUNDLE_V2_SCHEMA_URL = "https://decantr.ai/schemas/evidence-bundle.v2.json";
|
|
353
|
+
var RUNTIME_PROBE_PAYLOAD_V2_SCHEMA_URL = "https://decantr.ai/schemas/runtime-probe-payload.v2.json";
|
|
354
|
+
var LOOP_READINESS_V2_SCHEMA_URL = "https://decantr.ai/schemas/loop-readiness.v2.json";
|
|
355
|
+
var AUTHORITY_RESOLUTION_V2_SCHEMA_URL = "https://decantr.ai/schemas/authority-resolution.v2.json";
|
|
356
|
+
var PROOF_FIELD_REPORT_V2_SCHEMA_URL = "https://decantr.ai/schemas/proof-field-report.v2.json";
|
|
357
|
+
function unique(values) {
|
|
358
|
+
return [...new Set(values)];
|
|
359
|
+
}
|
|
360
|
+
function rounded(value) {
|
|
361
|
+
return Number(Math.max(0, Math.min(1, value)).toFixed(2));
|
|
362
|
+
}
|
|
363
|
+
function createEvidenceTier(report, options = {}) {
|
|
364
|
+
const runtimeProbeCount = options.runtimeProbeCount ?? (report.summary.runtimeAuditChecked ? 1 : 0);
|
|
365
|
+
const visualArtifactCount = options.visualArtifactCount ?? 0;
|
|
366
|
+
const findingsAnchored = report.findings.filter((finding) => finding.graph).length;
|
|
367
|
+
const findingsWithRepairPlan = report.findings.filter((finding) => finding.repairPlan).length;
|
|
368
|
+
const capabilities = ["static-audit", "project-health"];
|
|
369
|
+
if (report.graph.ready) capabilities.push("typed-graph");
|
|
370
|
+
if (runtimeProbeCount > 0) capabilities.push("runtime-probe");
|
|
371
|
+
if (report.summary.runtimeAuditChecked || visualArtifactCount > 0)
|
|
372
|
+
capabilities.push("browser-evidence");
|
|
373
|
+
if (visualArtifactCount > 0) capabilities.push("visual-baseline");
|
|
374
|
+
if (findingsWithRepairPlan > 0) capabilities.push("repair-plan");
|
|
375
|
+
if (options.benchmarkReplay) capabilities.push("benchmark-replay");
|
|
376
|
+
let stage = "static";
|
|
377
|
+
if (options.benchmarkReplay) stage = "proof";
|
|
378
|
+
else if (findingsWithRepairPlan > 0) stage = "repair";
|
|
379
|
+
else if (visualArtifactCount > 0) stage = "visual";
|
|
380
|
+
else if (runtimeProbeCount > 0 || report.summary.runtimeAuditChecked) stage = "runtime";
|
|
381
|
+
else if (report.graph.ready) stage = "graph";
|
|
382
|
+
const routeCoverage = report.routes.declared.length > 0 ? Math.min(1, report.routes.runtimeChecked.length / report.routes.declared.length) : report.summary.runtimeAuditChecked ? 1 : 0;
|
|
383
|
+
const graphCoverage = report.findings.length > 0 ? findingsAnchored / report.findings.length : report.graph.ready ? 1 : 0;
|
|
384
|
+
const repairCoverage = report.findings.length > 0 ? findingsWithRepairPlan / report.findings.length : 1;
|
|
385
|
+
const runtimeCoverage = runtimeProbeCount > 0 || report.summary.runtimeAuditChecked ? 1 : 0;
|
|
386
|
+
const score = rounded(
|
|
387
|
+
0.22 + (report.graph.ready ? 0.22 : 0) + routeCoverage * 0.16 + graphCoverage * 0.16 + repairCoverage * 0.14 + runtimeCoverage * 0.1
|
|
388
|
+
);
|
|
389
|
+
const level = score >= 0.78 ? "high" : score >= 0.48 ? "moderate" : "low";
|
|
390
|
+
const reasons = [];
|
|
391
|
+
reasons.push(report.graph.ready ? "typed graph is ready" : "typed graph is missing or stale");
|
|
392
|
+
reasons.push(
|
|
393
|
+
runtimeProbeCount > 0 || report.summary.runtimeAuditChecked ? "runtime evidence is present" : "runtime evidence has not run"
|
|
394
|
+
);
|
|
395
|
+
reasons.push(
|
|
396
|
+
report.findings.length === 0 ? "no open findings" : `${findingsAnchored}/${report.findings.length} finding(s) have graph anchors`
|
|
397
|
+
);
|
|
398
|
+
reasons.push(
|
|
399
|
+
report.findings.length === 0 ? "repair context is not needed" : `${findingsWithRepairPlan}/${report.findings.length} finding(s) include repair plans`
|
|
400
|
+
);
|
|
401
|
+
return {
|
|
402
|
+
schemaVersion: 2,
|
|
403
|
+
stage,
|
|
404
|
+
status: report.status === "healthy" ? "healthy" : report.status,
|
|
405
|
+
capabilities: unique(capabilities),
|
|
406
|
+
coverage: {
|
|
407
|
+
declaredRoutes: report.routes.declared.length,
|
|
408
|
+
runtimeRoutesChecked: report.routes.runtimeChecked.length,
|
|
409
|
+
findingsAnchored,
|
|
410
|
+
findingsWithRepairPlan,
|
|
411
|
+
runtimeProbeCount,
|
|
412
|
+
visualArtifactCount
|
|
413
|
+
},
|
|
414
|
+
confidence: {
|
|
415
|
+
level,
|
|
416
|
+
score,
|
|
417
|
+
reasons
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function createAuthorityOrder() {
|
|
422
|
+
return [
|
|
423
|
+
{
|
|
424
|
+
id: "production-source",
|
|
425
|
+
label: "Production source",
|
|
426
|
+
role: "Existing runtime/source wins first in Brownfield unless a human explicitly accepts a contract change.",
|
|
427
|
+
rank: 1
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
id: "local-law",
|
|
431
|
+
label: "Accepted local law",
|
|
432
|
+
role: "Project-owned rules and codified patterns constrain edits after they are accepted locally.",
|
|
433
|
+
rank: 2
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
id: "style-bridge",
|
|
437
|
+
label: "Accepted style bridge",
|
|
438
|
+
role: "Mapped native style tokens/components govern Hybrid styling once accepted locally.",
|
|
439
|
+
rank: 3
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
id: "essence-contract",
|
|
443
|
+
label: "Essence V4 contract",
|
|
444
|
+
role: "Structural route, section, page, guard, and DNA contract for Decantr context.",
|
|
445
|
+
rank: 4
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
id: "registry-guidance",
|
|
449
|
+
label: "Hosted packs and registry",
|
|
450
|
+
role: "Advisory guidance unless mapped into accepted local law or the local style bridge.",
|
|
451
|
+
rank: 5
|
|
452
|
+
}
|
|
453
|
+
];
|
|
454
|
+
}
|
|
455
|
+
function laneForFinding(finding) {
|
|
456
|
+
if (finding.source === "style-bridge") return "style-bridge";
|
|
457
|
+
if (finding.source === "brownfield" || finding.category.toLowerCase().includes("drift")) {
|
|
458
|
+
return "production-source";
|
|
459
|
+
}
|
|
460
|
+
if (finding.source === "check" || finding.source === "assertion") return "essence-contract";
|
|
461
|
+
if (finding.source === "pack") return "registry-guidance";
|
|
462
|
+
return "local-law";
|
|
463
|
+
}
|
|
464
|
+
function actionsForFinding(finding) {
|
|
465
|
+
const commands = finding.repairPlan?.commands ?? finding.remediation?.commands ?? [];
|
|
466
|
+
const repairCommand = commands[0] ?? null;
|
|
467
|
+
const source = finding.source;
|
|
468
|
+
const actions = [];
|
|
469
|
+
if (source === "graph") {
|
|
470
|
+
actions.push({
|
|
471
|
+
kind: "regenerate_graph",
|
|
472
|
+
label: "Regenerate graph/context evidence",
|
|
473
|
+
command: "decantr graph --check || decantr graph",
|
|
474
|
+
writes: true,
|
|
475
|
+
rationale: "Graph drift should be resolved by regenerating derived graph artifacts from current source."
|
|
476
|
+
});
|
|
477
|
+
} else if (source === "style-bridge") {
|
|
478
|
+
actions.push({
|
|
479
|
+
kind: "update_style_bridge",
|
|
480
|
+
label: "Update accepted style bridge",
|
|
481
|
+
command: "decantr codify --style-bridge",
|
|
482
|
+
writes: true,
|
|
483
|
+
rationale: "Style conflicts should be accepted through the explicit Hybrid style bridge workflow."
|
|
484
|
+
});
|
|
485
|
+
} else if (source === "brownfield") {
|
|
486
|
+
actions.push({
|
|
487
|
+
kind: "accept_observed_source",
|
|
488
|
+
label: "Accept observed source into contract",
|
|
489
|
+
command: "decantr init --existing --merge-proposal",
|
|
490
|
+
writes: true,
|
|
491
|
+
rationale: "Brownfield source is first authority; accept it explicitly before treating contract drift as repaired."
|
|
492
|
+
});
|
|
493
|
+
} else if (source === "pack") {
|
|
494
|
+
actions.push({
|
|
495
|
+
kind: "regenerate_context",
|
|
496
|
+
label: "Regenerate Decantr context",
|
|
497
|
+
command: "decantr refresh",
|
|
498
|
+
writes: true,
|
|
499
|
+
rationale: "Generated context and pack artifacts are derived from the local contract."
|
|
500
|
+
});
|
|
501
|
+
} else {
|
|
502
|
+
actions.push({
|
|
503
|
+
kind: "repair_source",
|
|
504
|
+
label: "Repair source to satisfy accepted authority",
|
|
505
|
+
command: repairCommand,
|
|
506
|
+
writes: false,
|
|
507
|
+
rationale: "The finding can be repaired by editing the relevant application source under human/agent control."
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
actions.push({
|
|
511
|
+
kind: "defer_to_drift_log",
|
|
512
|
+
label: "Defer to drift log",
|
|
513
|
+
command: `decantr resolve --defer ${finding.id}`,
|
|
514
|
+
writes: true,
|
|
515
|
+
rationale: "Record an explicit human deferral when this conflict should not block the current task."
|
|
516
|
+
});
|
|
517
|
+
if (finding.severity !== "error") {
|
|
518
|
+
actions.push({
|
|
519
|
+
kind: "mark_advisory",
|
|
520
|
+
label: "Mark advisory",
|
|
521
|
+
command: `decantr resolve --mark-advisory ${finding.id}`,
|
|
522
|
+
writes: true,
|
|
523
|
+
rationale: "Warnings can be documented as advisory when the observed source is intentionally different."
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
return actions;
|
|
527
|
+
}
|
|
528
|
+
function createAuthorityResolution(report) {
|
|
529
|
+
const conflicts = report.findings.filter((finding) => finding.severity !== "info").map((finding) => ({
|
|
530
|
+
id: finding.id,
|
|
531
|
+
source: finding.source,
|
|
532
|
+
category: finding.category,
|
|
533
|
+
severity: finding.severity,
|
|
534
|
+
message: finding.message,
|
|
535
|
+
...finding.graph ? { graphAnchor: finding.graph } : {},
|
|
536
|
+
lane: laneForFinding(finding),
|
|
537
|
+
status: finding.severity === "error" ? "blocking" : finding.source === "brownfield" || finding.source === "style-bridge" ? "repairable" : "advisory",
|
|
538
|
+
recommendedActions: actionsForFinding(finding)
|
|
539
|
+
}));
|
|
540
|
+
const activeLane = report.summary.workflowMode === "brownfield-attach" ? "production-source" : "essence-contract";
|
|
541
|
+
return {
|
|
542
|
+
schemaVersion: 2,
|
|
543
|
+
order: createAuthorityOrder(),
|
|
544
|
+
activeLane,
|
|
545
|
+
summary: activeLane === "production-source" ? "Brownfield authority: preserve observed production source first, then accepted local law/style bridge, then Essence V4 structure, with hosted packs advisory." : "Contract authority: Essence V4 and accepted local project law guide source changes; hosted packs remain advisory until accepted locally.",
|
|
546
|
+
conflicts,
|
|
547
|
+
stopRule: "If runtime source and Decantr context disagree, stop and report drift instead of guessing which truth to overwrite."
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function readTargetsForFindings(report) {
|
|
551
|
+
const targets = /* @__PURE__ */ new Set(["DECANTR.md", "decantr.essence.json"]);
|
|
552
|
+
for (const finding of report.findings) {
|
|
553
|
+
for (const target of finding.repairPlan?.readTargets ?? []) targets.add(target);
|
|
554
|
+
if (finding.file) targets.add(finding.file);
|
|
555
|
+
if (finding.source === "graph") targets.add(".decantr/graph/graph.manifest.json");
|
|
556
|
+
if (finding.source === "style-bridge") targets.add(".decantr/style-bridge.json");
|
|
557
|
+
}
|
|
558
|
+
return [...targets].sort();
|
|
559
|
+
}
|
|
560
|
+
function createLoopReadiness(report, authority = createAuthorityResolution(report), evidenceTier = createEvidenceTier(report)) {
|
|
561
|
+
const hasEssence = Boolean(report.summary.essenceVersion);
|
|
562
|
+
const graphMissing = !report.graph.ready;
|
|
563
|
+
const blockingConflicts = authority.conflicts.filter(
|
|
564
|
+
(conflict) => conflict.status === "blocking"
|
|
565
|
+
);
|
|
566
|
+
const repairableConflicts = authority.conflicts.filter(
|
|
567
|
+
(conflict) => conflict.status === "repairable"
|
|
568
|
+
);
|
|
569
|
+
let state = "verified";
|
|
570
|
+
const blockingReasons = [];
|
|
571
|
+
if (!hasEssence) {
|
|
572
|
+
state = "blocked_missing_context";
|
|
573
|
+
blockingReasons.push("Essence V4 context is missing.");
|
|
574
|
+
} else if (graphMissing) {
|
|
575
|
+
state = "blocked_missing_graph";
|
|
576
|
+
blockingReasons.push("Typed Contract graph is missing, stale, or incomplete.");
|
|
577
|
+
} else if (blockingConflicts.length > 0 && repairableConflicts.length > 0) {
|
|
578
|
+
state = "human_resolution_required";
|
|
579
|
+
blockingReasons.push("Blocking findings conflict with Brownfield or Hybrid authority.");
|
|
580
|
+
} else if (blockingConflicts.length > 0 || report.summary.errorCount > 0) {
|
|
581
|
+
state = "repair_required";
|
|
582
|
+
blockingReasons.push("Project Health has blocking errors.");
|
|
583
|
+
} else if (repairableConflicts.length > 0 || report.summary.warnCount > 0) {
|
|
584
|
+
state = "repair_required";
|
|
585
|
+
blockingReasons.push("Project Health has repairable warnings or drift.");
|
|
586
|
+
} else if (report.status === "healthy") {
|
|
587
|
+
state = "verified";
|
|
588
|
+
} else {
|
|
589
|
+
state = "verify_required";
|
|
590
|
+
blockingReasons.push("Verification needs to be rerun before the loop is complete.");
|
|
591
|
+
}
|
|
592
|
+
const nextActions = state === "verified" ? ["Continue normal route/task workflow."] : state === "blocked_missing_context" ? ["Run `decantr scan` for a read-only preview, then `decantr adopt` when ready."] : state === "blocked_missing_graph" ? ["Run `decantr graph` to regenerate typed graph artifacts, then rerun verification."] : state === "human_resolution_required" ? ["Run `decantr resolve` and choose an explicit resolution action before editing."] : state === "repair_required" ? ["Repair the highest-severity finding, then rerun the verify command."] : ["Run the verify command before treating the task as complete."];
|
|
593
|
+
const status = state.startsWith("blocked") || state === "human_resolution_required" ? "blocked" : report.status;
|
|
594
|
+
return {
|
|
595
|
+
schemaVersion: 2,
|
|
596
|
+
state,
|
|
597
|
+
status,
|
|
598
|
+
verdict: state === "verified" ? "Loop verified." : "Loop needs attention before it should be considered complete.",
|
|
599
|
+
summary: `${report.status} Project Health, ${evidenceTier.confidence.level} evidence confidence, ${authority.conflicts.length} authority conflict(s).`,
|
|
600
|
+
authority: {
|
|
601
|
+
activeLane: authority.activeLane,
|
|
602
|
+
summary: authority.summary,
|
|
603
|
+
stopRule: authority.stopRule
|
|
604
|
+
},
|
|
605
|
+
evidenceTier,
|
|
606
|
+
blockingReasons,
|
|
607
|
+
nextActions,
|
|
608
|
+
maker: {
|
|
609
|
+
title: "Maker instructions",
|
|
610
|
+
instructions: [
|
|
611
|
+
"Read the route/task context before editing source.",
|
|
612
|
+
"Preserve production source behavior and accepted local law unless a human chooses a resolution action.",
|
|
613
|
+
"Stop and report drift when runtime source and Decantr context disagree."
|
|
614
|
+
]
|
|
615
|
+
},
|
|
616
|
+
checker: {
|
|
617
|
+
title: "Checker instructions",
|
|
618
|
+
instructions: [
|
|
619
|
+
"Rerun the verify command after edits.",
|
|
620
|
+
"Check graph anchors and repair plans before accepting a fix.",
|
|
621
|
+
"Treat critique-only or advisory evidence as warning-level unless runtime evidence proves a failure."
|
|
622
|
+
]
|
|
623
|
+
},
|
|
624
|
+
readTargets: readTargetsForFindings(report),
|
|
625
|
+
graphImpact: {
|
|
626
|
+
status: !report.graph.present ? "missing" : report.graph.ready && report.graph.current !== false ? "ready" : "stale",
|
|
627
|
+
snapshotId: report.graph.snapshotId,
|
|
628
|
+
sourceHash: report.graph.sourceHash,
|
|
629
|
+
sourceArtifactCount: report.graph.sourceArtifactCount,
|
|
630
|
+
staleArtifacts: report.graph.staleArtifacts
|
|
631
|
+
},
|
|
632
|
+
stopConditions: [
|
|
633
|
+
"Runtime source and Decantr context disagree.",
|
|
634
|
+
"Typed graph is missing for the route or changed file.",
|
|
635
|
+
"A finding requires contract/source/local-law mutation outside the current explicit workflow."
|
|
636
|
+
],
|
|
637
|
+
verifyCommand: report.ci.recommendedCommand
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
|
|
347
641
|
// src/runtime.ts
|
|
348
642
|
import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
349
643
|
import { createServer } from "http";
|
|
@@ -2010,9 +2304,9 @@ function sourceLineCount(source) {
|
|
|
2010
2304
|
}
|
|
2011
2305
|
function verifyInteractionsInSource(interactions, sources) {
|
|
2012
2306
|
if (interactions.length === 0 || sources.size === 0) return [];
|
|
2013
|
-
const
|
|
2307
|
+
const unique2 = Array.from(new Set(interactions));
|
|
2014
2308
|
const missing = [];
|
|
2015
|
-
for (const interaction of
|
|
2309
|
+
for (const interaction of unique2) {
|
|
2016
2310
|
const requirement = INTERACTION_SIGNALS[interaction];
|
|
2017
2311
|
if (!requirement) {
|
|
2018
2312
|
continue;
|
|
@@ -2361,6 +2655,9 @@ function scanReactRouter(projectRoot) {
|
|
|
2361
2655
|
for (const route of detectPathnameBranchRoutes(content)) {
|
|
2362
2656
|
routes.set(route, { path: route, file, hasLayout: false });
|
|
2363
2657
|
}
|
|
2658
|
+
for (const route of detectDeclarativeRouteSpecRoutes(content)) {
|
|
2659
|
+
routes.set(route, { path: route, file, hasLayout: false });
|
|
2660
|
+
}
|
|
2364
2661
|
}
|
|
2365
2662
|
return { routes: [...routes.values()], hashRouting };
|
|
2366
2663
|
}
|
|
@@ -2401,6 +2698,17 @@ function detectPathnameBranchRoutes(content) {
|
|
|
2401
2698
|
}
|
|
2402
2699
|
return [...routes];
|
|
2403
2700
|
}
|
|
2701
|
+
function detectDeclarativeRouteSpecRoutes(content) {
|
|
2702
|
+
const routes = /* @__PURE__ */ new Set();
|
|
2703
|
+
const hasRouteSpecSignal = content.includes("@wasp.sh/spec") || /\b(?:const|export\s+const)\s+\w*Spec\b/.test(content) || /\bapp\s*\(\s*\{[\s\S]*\bspec\s*:/.test(content);
|
|
2704
|
+
if (!hasRouteSpecSignal) return [];
|
|
2705
|
+
collectRouteLiterals(
|
|
2706
|
+
/\broute\s*\(\s*["'`][^"'`]*["'`]\s*,\s*["'`](\/[^"'`]*)["'`]\s*,\s*page\s*\(/g,
|
|
2707
|
+
content,
|
|
2708
|
+
routes
|
|
2709
|
+
);
|
|
2710
|
+
return [...routes];
|
|
2711
|
+
}
|
|
2404
2712
|
function scanRoutes(projectRoot, detection) {
|
|
2405
2713
|
const appRoutes = ["src/app", "app"].flatMap(
|
|
2406
2714
|
(dir) => existsSync3(join3(projectRoot, dir)) ? walkNextAppRoutes(join3(projectRoot, dir), projectRoot, []) : []
|
|
@@ -3734,17 +4042,17 @@ function resolveSourceSymbolOrigin(context, pathOrSourceFile, localName, options
|
|
|
3734
4042
|
|
|
3735
4043
|
// src/index.ts
|
|
3736
4044
|
var VERIFICATION_SCHEMA_URLS = {
|
|
3737
|
-
common:
|
|
4045
|
+
common: VERIFICATION_COMMON_V2_SCHEMA_URL,
|
|
3738
4046
|
projectAudit: "https://decantr.ai/schemas/project-audit-report.v1.json",
|
|
3739
|
-
projectHealth:
|
|
3740
|
-
decantrCi:
|
|
3741
|
-
evidenceBundle:
|
|
4047
|
+
projectHealth: PROJECT_HEALTH_REPORT_V2_SCHEMA_URL,
|
|
4048
|
+
decantrCi: DECANTR_CI_REPORT_V2_SCHEMA_URL,
|
|
4049
|
+
evidenceBundle: EVIDENCE_BUNDLE_V2_SCHEMA_URL,
|
|
3742
4050
|
scanReport: "https://decantr.ai/schemas/scan-report.v1.json",
|
|
3743
|
-
workspaceHealth:
|
|
4051
|
+
workspaceHealth: WORKSPACE_HEALTH_REPORT_V2_SCHEMA_URL,
|
|
3744
4052
|
fileCritique: "https://decantr.ai/schemas/file-critique-report.v1.json",
|
|
3745
4053
|
showcaseShortlist: "https://decantr.ai/schemas/showcase-shortlist-report.v1.json"
|
|
3746
4054
|
};
|
|
3747
|
-
var EVIDENCE_BUNDLE_SCHEMA_URL =
|
|
4055
|
+
var EVIDENCE_BUNDLE_SCHEMA_URL = EVIDENCE_BUNDLE_V2_SCHEMA_URL;
|
|
3748
4056
|
function hashString(value) {
|
|
3749
4057
|
return createHash("sha256").update(value).digest("hex").slice(0, 16);
|
|
3750
4058
|
}
|
|
@@ -4033,6 +4341,8 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
4033
4341
|
}
|
|
4034
4342
|
function createEvidenceBundle(input) {
|
|
4035
4343
|
const assertions = input.assertions ?? createContractAssertions(input.projectRoot, input.audit);
|
|
4344
|
+
const evidenceTier = input.report.evidenceTier ?? createEvidenceTier(input.report);
|
|
4345
|
+
const authority = input.report.authority ?? createAuthorityResolution(input.report);
|
|
4036
4346
|
let resolvedProjectRoot = input.projectRoot;
|
|
4037
4347
|
try {
|
|
4038
4348
|
resolvedProjectRoot = realpathSync2(input.projectRoot);
|
|
@@ -4045,13 +4355,18 @@ function createEvidenceBundle(input) {
|
|
|
4045
4355
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4046
4356
|
project: {
|
|
4047
4357
|
id: projectId,
|
|
4048
|
-
rootLabel: basename2(input.projectRoot) || "project"
|
|
4358
|
+
rootLabel: basename2(input.projectRoot) || "project",
|
|
4359
|
+
workflowMode: input.report.summary.workflowMode,
|
|
4360
|
+
adoptionMode: input.report.summary.adoptionMode
|
|
4049
4361
|
},
|
|
4050
4362
|
toolchain: {
|
|
4051
|
-
verifierVersion: input.verifierVersion ?? null
|
|
4363
|
+
verifierVersion: input.verifierVersion ?? null,
|
|
4364
|
+
cliVersion: input.cliVersion ?? null,
|
|
4365
|
+
mcpServerVersion: input.mcpServerVersion ?? null
|
|
4052
4366
|
},
|
|
4053
4367
|
privacy: {
|
|
4054
4368
|
localOnly: true,
|
|
4369
|
+
sourceIncluded: false,
|
|
4055
4370
|
redactedFields: [
|
|
4056
4371
|
"source",
|
|
4057
4372
|
"prompt",
|
|
@@ -4060,8 +4375,10 @@ function createEvidenceBundle(input) {
|
|
|
4060
4375
|
"absolute_path",
|
|
4061
4376
|
"repository_name"
|
|
4062
4377
|
],
|
|
4063
|
-
screenshotsLocalOnly: true
|
|
4378
|
+
screenshotsLocalOnly: true,
|
|
4379
|
+
hostedUploadAllowed: false
|
|
4064
4380
|
},
|
|
4381
|
+
evidenceTier,
|
|
4065
4382
|
health: {
|
|
4066
4383
|
status: input.report.status,
|
|
4067
4384
|
score: input.report.score,
|
|
@@ -4079,7 +4396,9 @@ function createEvidenceBundle(input) {
|
|
|
4079
4396
|
graphDiff: provenanceEntry(input.projectRoot, ".decantr/graph/graph.diff.json"),
|
|
4080
4397
|
contractCapsule: provenanceEntry(input.projectRoot, ".decantr/graph/contract-capsule.json"),
|
|
4081
4398
|
...input.workspaceConfigPath ? { workspaceConfig: provenanceForPath(input.projectRoot, input.workspaceConfigPath) } : {},
|
|
4082
|
-
...input.designTokensPath ? { designTokens: provenanceForPath(input.projectRoot, input.designTokensPath) } : {}
|
|
4399
|
+
...input.designTokensPath ? { designTokens: provenanceForPath(input.projectRoot, input.designTokensPath) } : {},
|
|
4400
|
+
...input.runtimeProbePath ? { runtimeProbe: provenanceForPath(input.projectRoot, input.runtimeProbePath) } : {},
|
|
4401
|
+
...input.visualManifestPath ? { visualManifest: provenanceForPath(input.projectRoot, input.visualManifestPath) } : {}
|
|
4083
4402
|
},
|
|
4084
4403
|
assertions,
|
|
4085
4404
|
findings: input.report.findings.map((finding) => ({
|
|
@@ -4096,10 +4415,37 @@ function createEvidenceBundle(input) {
|
|
|
4096
4415
|
graph: finding.graph,
|
|
4097
4416
|
repair: redactRepairAction(input.projectRoot, finding.repair),
|
|
4098
4417
|
repairPlan: buildProjectHealthRepairPlan(input.projectRoot, finding),
|
|
4418
|
+
evidenceTier: finding.evidenceTier ?? evidenceTier,
|
|
4419
|
+
authorityLane: finding.authorityLane ?? authority.conflicts.find((conflict) => conflict.id === finding.id)?.lane ?? authority.activeLane,
|
|
4420
|
+
resolutionActions: finding.resolutionActions ?? authority.conflicts.find((conflict) => conflict.id === finding.id)?.recommendedActions,
|
|
4421
|
+
privacy: finding.privacy ?? {
|
|
4422
|
+
sourceIncluded: false,
|
|
4423
|
+
redacted: true,
|
|
4424
|
+
localOnly: true
|
|
4425
|
+
},
|
|
4426
|
+
loopVerdict: finding.loopVerdict ?? input.report.loop?.state,
|
|
4099
4427
|
remediationSummary: finding.remediation.summary,
|
|
4100
4428
|
commands: finding.remediation.commands,
|
|
4101
4429
|
promptCommand: `decantr health --prompt ${finding.id}`
|
|
4102
4430
|
})),
|
|
4431
|
+
runtimeProbe: input.runtimeProbe ?? null,
|
|
4432
|
+
artifacts: input.artifacts ?? [
|
|
4433
|
+
{
|
|
4434
|
+
id: "artifact:project-health",
|
|
4435
|
+
kind: "project-health",
|
|
4436
|
+
path: "decantr-health.json",
|
|
4437
|
+
hash: null,
|
|
4438
|
+
localOnly: true,
|
|
4439
|
+
redacted: true
|
|
4440
|
+
}
|
|
4441
|
+
],
|
|
4442
|
+
dashboard: {
|
|
4443
|
+
safeToUpload: false,
|
|
4444
|
+
retentionClass: "local-only",
|
|
4445
|
+
redactionNotes: [
|
|
4446
|
+
"Evidence Bundle v2 does not include raw source, prompts, secrets, absolute paths, or uploaded screenshots by default."
|
|
4447
|
+
]
|
|
4448
|
+
},
|
|
4103
4449
|
...input.browser ? { browser: input.browser } : {},
|
|
4104
4450
|
...input.designTokens ? { designTokens: input.designTokens } : {}
|
|
4105
4451
|
};
|
|
@@ -4854,6 +5200,10 @@ function buildRegistryContext(projectRoot) {
|
|
|
4854
5200
|
const patternRegistry = /* @__PURE__ */ new Map();
|
|
4855
5201
|
const cacheDir = join6(projectRoot, ".decantr", "cache");
|
|
4856
5202
|
const customDir = join6(projectRoot, ".decantr", "custom");
|
|
5203
|
+
const addPattern = (id, source, data = null) => {
|
|
5204
|
+
if (typeof id !== "string" || !id.trim() || patternRegistry.has(id)) return;
|
|
5205
|
+
patternRegistry.set(id, data ?? { id, source });
|
|
5206
|
+
};
|
|
4857
5207
|
const cachedThemesDir = join6(cacheDir, "@official", "themes");
|
|
4858
5208
|
try {
|
|
4859
5209
|
if (existsSync6(cachedThemesDir)) {
|
|
@@ -4887,17 +5237,27 @@ function buildRegistryContext(projectRoot) {
|
|
|
4887
5237
|
(name) => name.endsWith(".json") && name !== "index.json"
|
|
4888
5238
|
)) {
|
|
4889
5239
|
const data = JSON.parse(readFileSync6(join6(cachedPatternsDir, file), "utf-8"));
|
|
4890
|
-
|
|
4891
|
-
patternRegistry.set(data.id, data);
|
|
4892
|
-
}
|
|
5240
|
+
addPattern(data.id, "cache", data);
|
|
4893
5241
|
}
|
|
4894
5242
|
}
|
|
4895
5243
|
} catch {
|
|
4896
5244
|
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
5245
|
+
const customPatternsDir = join6(customDir, "patterns");
|
|
5246
|
+
try {
|
|
5247
|
+
if (existsSync6(customPatternsDir)) {
|
|
5248
|
+
for (const file of readdirSync5(customPatternsDir).filter((name) => name.endsWith(".json"))) {
|
|
5249
|
+
const data = JSON.parse(readFileSync6(join6(customPatternsDir, file), "utf-8"));
|
|
5250
|
+
addPattern(data.id, "custom", data);
|
|
5251
|
+
}
|
|
4900
5252
|
}
|
|
5253
|
+
} catch {
|
|
5254
|
+
}
|
|
5255
|
+
const localPatterns = readJsonIfExists(join6(projectRoot, ".decantr", "local-patterns.json"));
|
|
5256
|
+
for (const pattern of localPatterns?.patterns ?? []) {
|
|
5257
|
+
addPattern(pattern.id, "local-law", pattern);
|
|
5258
|
+
}
|
|
5259
|
+
for (const id of ["content-section", "footer", "form-basic", "hero", "nav-header"]) {
|
|
5260
|
+
addPattern(id, "bundled");
|
|
4901
5261
|
}
|
|
4902
5262
|
return { themeRegistry, patternRegistry };
|
|
4903
5263
|
}
|
|
@@ -15678,14 +16038,23 @@ async function critiqueFile(filePath, projectRoot) {
|
|
|
15678
16038
|
});
|
|
15679
16039
|
}
|
|
15680
16040
|
export {
|
|
16041
|
+
AUTHORITY_RESOLUTION_V2_SCHEMA_URL,
|
|
15681
16042
|
COMPONENT_REUSE_RULE_ID,
|
|
16043
|
+
DECANTR_CI_REPORT_V2_SCHEMA_URL,
|
|
15682
16044
|
EVIDENCE_BUNDLE_SCHEMA_URL,
|
|
16045
|
+
EVIDENCE_BUNDLE_V2_SCHEMA_URL,
|
|
15683
16046
|
INTERACTION_SIGNALS,
|
|
15684
16047
|
KNOWN_VERIFICATION_DIAGNOSTICS,
|
|
16048
|
+
LOOP_READINESS_V2_SCHEMA_URL,
|
|
16049
|
+
PROJECT_HEALTH_REPORT_V2_SCHEMA_URL,
|
|
16050
|
+
PROOF_FIELD_REPORT_V2_SCHEMA_URL,
|
|
15685
16051
|
RAW_CONTROL_REUSE_RULE_ID,
|
|
16052
|
+
RUNTIME_PROBE_PAYLOAD_V2_SCHEMA_URL,
|
|
15686
16053
|
SCAN_REPORT_SCHEMA_URL,
|
|
15687
16054
|
STYLE_BRIDGE_ARBITRARY_VALUE_RULE_ID,
|
|
16055
|
+
VERIFICATION_COMMON_V2_SCHEMA_URL,
|
|
15688
16056
|
VERIFICATION_SCHEMA_URLS,
|
|
16057
|
+
WORKSPACE_HEALTH_REPORT_V2_SCHEMA_URL,
|
|
15689
16058
|
anchorFindingsToGraph,
|
|
15690
16059
|
auditBuiltDist,
|
|
15691
16060
|
auditComponentReuse,
|
|
@@ -15695,8 +16064,12 @@ export {
|
|
|
15695
16064
|
collectMissingPackManifestFiles,
|
|
15696
16065
|
collectProjectSourceFiles,
|
|
15697
16066
|
collectSourceImports,
|
|
16067
|
+
createAuthorityOrder,
|
|
16068
|
+
createAuthorityResolution,
|
|
15698
16069
|
createContractAssertions,
|
|
15699
16070
|
createEvidenceBundle,
|
|
16071
|
+
createEvidenceTier,
|
|
16072
|
+
createLoopReadiness,
|
|
15700
16073
|
createProjectSourceProgram,
|
|
15701
16074
|
createSourceInventory,
|
|
15702
16075
|
createUnavailableScanReport,
|