@amityco/social-plus-vise 0.14.26 → 0.14.27
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/CHANGELOG.md +18 -0
- package/README.md +22 -4
- package/dist/capabilities.js +1 -1
- package/dist/intelligence/grounding.js +107 -0
- package/dist/intelligence/placement.js +71 -0
- package/dist/outcomes.js +2 -2
- package/dist/server.js +182 -9
- package/dist/tools/compliance.js +161 -11
- package/dist/tools/creative.js +542 -106
- package/dist/tools/experienceCompiler.js +439 -0
- package/dist/tools/experienceSensors.js +406 -0
- package/dist/tools/harness.js +27 -7
- package/dist/tools/integration.js +43 -2
- package/dist/tools/learning.js +486 -0
- package/dist/tools/project.js +41 -6
- package/dist/tools/sensors.js +8 -0
- package/dist/tools/uxHarness.js +546 -0
- package/package.json +40 -9
- package/packages/intelligence/README.md +1 -1
- package/packages/intelligence/catalog/archetypes.json +10 -0
- package/packages/intelligence/catalog/business-goals.json +8 -0
- package/packages/intelligence/catalog/catalog.schema.json +224 -0
- package/packages/intelligence/catalog/experience-objects.json +18 -18
- package/packages/intelligence/catalog/variants.json +56 -7
- package/scripts/catalog-coverage-html.mjs +325 -0
- package/scripts/catalog-relationships-html.mjs +686 -0
- package/scripts/catalog-sheets.mjs +286 -0
- package/scripts/pilot-feedback.mjs +107 -0
- package/scripts/workshop-board-html.mjs +1018 -0
- package/scripts/workshop-kit.mjs +252 -0
- package/skills/vise-harness-engineer/SKILL.md +1 -1
- package/social.plus-vise.png +0 -0
package/dist/tools/compliance.js
CHANGED
|
@@ -10,8 +10,11 @@ import { packageVersion } from "../version.js";
|
|
|
10
10
|
import { DESIGN_CONTRACT_CONFIRMATION_ANSWER_ID, buildDesignBrief, designContractConfirmationFromAnswers, designPreviewPath, readDesignContract, } from "./design.js";
|
|
11
11
|
import { inspectProject, validateSetup } from "./project.js";
|
|
12
12
|
import { readCreativeSelection } from "./creative.js";
|
|
13
|
+
import { assessUxHarness, buildExperienceReport, buildUxHarness, readUxHarness, } from "./uxHarness.js";
|
|
13
14
|
const complianceDirName = "sp-vise";
|
|
14
15
|
const attestationsDirName = "attestations";
|
|
16
|
+
const experienceReportFileName = "experience-report.json";
|
|
17
|
+
const experienceSensorsFileName = "experience-sensors.json";
|
|
15
18
|
const schemaVersion = 1;
|
|
16
19
|
const confidenceRank = { low: 0, medium: 1, high: 2 };
|
|
17
20
|
export const initComplianceTool = {
|
|
@@ -57,6 +60,26 @@ export const checkComplianceTool = {
|
|
|
57
60
|
return textResult(await checkCompliance(stringField(args, "repoPath")));
|
|
58
61
|
},
|
|
59
62
|
};
|
|
63
|
+
export const experienceReportTool = {
|
|
64
|
+
name: "experience_report",
|
|
65
|
+
description: "Generate the advisory dimensioned Experience Report from the current compliance, design, UX, and business-alignment evidence.",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
repoPath: { type: "string" },
|
|
70
|
+
write: {
|
|
71
|
+
type: "boolean",
|
|
72
|
+
description: "Whether to write sp-vise/experience-report.json. Defaults to true.",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
required: ["repoPath"],
|
|
76
|
+
additionalProperties: false,
|
|
77
|
+
},
|
|
78
|
+
async call(input) {
|
|
79
|
+
const args = objectInput(input);
|
|
80
|
+
return textResult(await generateExperienceReport(stringField(args, "repoPath"), { write: optionalBooleanField(args, "write", true) }));
|
|
81
|
+
},
|
|
82
|
+
};
|
|
60
83
|
function answersFromInput(raw) {
|
|
61
84
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
62
85
|
return {};
|
|
@@ -303,6 +326,9 @@ export async function initCompliance(repoPath, request, surfacePath, answers = {
|
|
|
303
326
|
const creativeSelection = storedCreativeSelection && creativeSelectionAppliesToRequest(storedCreativeSelection, request)
|
|
304
327
|
? storedCreativeSelection
|
|
305
328
|
: undefined;
|
|
329
|
+
const uxHarness = creativeSelection
|
|
330
|
+
? await buildUxHarness({ repoPath: repoRoot, surfacePath, selection: creativeSelection, write: true })
|
|
331
|
+
: undefined;
|
|
306
332
|
const intake = intakeAuditFor({
|
|
307
333
|
request,
|
|
308
334
|
outcome,
|
|
@@ -352,6 +378,7 @@ export async function initCompliance(repoPath, request, surfacePath, answers = {
|
|
|
352
378
|
request,
|
|
353
379
|
outcome,
|
|
354
380
|
...(creativeSelection ? { creative_selection: creativeSelectionSummary(creativeSelection) } : {}),
|
|
381
|
+
...(uxHarness ? { ux_harness: uxHarnessSummary(uxHarness) } : {}),
|
|
355
382
|
design_review: designReview,
|
|
356
383
|
...intake,
|
|
357
384
|
});
|
|
@@ -380,6 +407,7 @@ export async function initCompliance(repoPath, request, surfacePath, answers = {
|
|
|
380
407
|
rules: refs.length,
|
|
381
408
|
engagement_id: engagement?.engagement_id,
|
|
382
409
|
...(creativeSelection ? { creative_selection: creativeSelectionSummary(creativeSelection) } : {}),
|
|
410
|
+
...(uxHarness ? { ux_harness: uxHarnessSummary(uxHarness) } : {}),
|
|
383
411
|
...(compliance.design_contract && { design_contract: compliance.design_contract }),
|
|
384
412
|
...(selectedOptionalCapabilities.length > 0 && { selected_optional_capabilities: selectedOptionalCapabilities }),
|
|
385
413
|
intake: {
|
|
@@ -496,6 +524,17 @@ function creativeSelectionSummary(selection) {
|
|
|
496
524
|
},
|
|
497
525
|
};
|
|
498
526
|
}
|
|
527
|
+
function uxHarnessSummary(harness) {
|
|
528
|
+
return {
|
|
529
|
+
status: harness.status,
|
|
530
|
+
harness_path: "sp-vise/ux-harness.json",
|
|
531
|
+
variant_id: harness.selectedVariant.id,
|
|
532
|
+
variant_title: harness.selectedVariant.title,
|
|
533
|
+
ux_pattern_ids: harness.uxPatterns.map((pattern) => pattern.id),
|
|
534
|
+
expectation_count: harness.uxPatterns.reduce((sum, pattern) => sum + pattern.expectations.length, 0),
|
|
535
|
+
advisory_only: "UX Harness guidance does not change deterministic compliance rules or exit codes in the MVP.",
|
|
536
|
+
};
|
|
537
|
+
}
|
|
499
538
|
function creativeSelectionAppliesToRequest(selection, request) {
|
|
500
539
|
const normalizedRequest = normalizeCreativeRequest(request);
|
|
501
540
|
const original = normalizeCreativeRequest(selection.source.request);
|
|
@@ -715,25 +754,133 @@ export async function checkCompliance(repoPath) {
|
|
|
715
754
|
: hasSelectedOptionalFailures
|
|
716
755
|
? "selected-capability-failures"
|
|
717
756
|
: "green";
|
|
757
|
+
const exitCode = hasBlocked
|
|
758
|
+
? 3
|
|
759
|
+
: hasDeterministicFailure
|
|
760
|
+
? 2
|
|
761
|
+
: needsAttestation
|
|
762
|
+
? 1
|
|
763
|
+
: hasCompletenessGap
|
|
764
|
+
? 5
|
|
765
|
+
: hasSelectedOptionalFailures
|
|
766
|
+
? 6
|
|
767
|
+
: 0;
|
|
768
|
+
const uxHarness = await readUxHarness(repoRoot);
|
|
769
|
+
const uxAssessment = await assessUxHarness(inspection.effectiveRoot, uxHarness, compliance.outcome);
|
|
770
|
+
const experienceReport = buildExperienceReport({
|
|
771
|
+
checkStatus: status,
|
|
772
|
+
exitCode,
|
|
773
|
+
summary,
|
|
774
|
+
designContract: compliance.design_contract,
|
|
775
|
+
uxAssessment,
|
|
776
|
+
uxHarness,
|
|
777
|
+
});
|
|
718
778
|
return {
|
|
719
779
|
status,
|
|
720
|
-
exitCode
|
|
721
|
-
? 3
|
|
722
|
-
: hasDeterministicFailure
|
|
723
|
-
? 2
|
|
724
|
-
: needsAttestation
|
|
725
|
-
? 1
|
|
726
|
-
: hasCompletenessGap
|
|
727
|
-
? 5
|
|
728
|
-
: hasSelectedOptionalFailures
|
|
729
|
-
? 6
|
|
730
|
-
: 0,
|
|
780
|
+
exitCode,
|
|
731
781
|
outcome: compliance.outcome,
|
|
732
782
|
surfacePath: compliance.surface?.path,
|
|
733
783
|
summary,
|
|
734
784
|
rules: results,
|
|
735
785
|
...(completeness && (completeness.missing.length > 0 || completeness.optedOut.length > 0 || completeness.present.length > 0) ? { completeness } : {}),
|
|
736
786
|
...(selectedOptionalCapabilities ? { selectedOptionalCapabilities } : {}),
|
|
787
|
+
uxHarness: uxAssessment,
|
|
788
|
+
experienceReport,
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
export async function generateExperienceReport(repoPath, options = {}) {
|
|
792
|
+
const repoRoot = path.resolve(repoPath);
|
|
793
|
+
const check = await checkCompliance(repoRoot);
|
|
794
|
+
const baseReport = check.experienceReport ?? fallbackExperienceReport(check);
|
|
795
|
+
const experienceSensors = await readExperienceSensorsReportSnapshot(repoRoot);
|
|
796
|
+
const report = experienceSensors ? { ...baseReport, experienceSensors } : baseReport;
|
|
797
|
+
const result = {
|
|
798
|
+
status: options.write === false ? "generated" : "written",
|
|
799
|
+
checkStatus: check.status,
|
|
800
|
+
checkExitCode: check.exitCode,
|
|
801
|
+
advisoryOnly: "Experience Report is advisory. Use `vise check --ci` when the caller needs compliance exit-code semantics.",
|
|
802
|
+
report,
|
|
803
|
+
};
|
|
804
|
+
if (options.write !== false) {
|
|
805
|
+
const reportPath = experienceReportPath(repoRoot);
|
|
806
|
+
await writeJson(reportPath, report);
|
|
807
|
+
result.artifact = path.join(complianceDirName, experienceReportFileName);
|
|
808
|
+
}
|
|
809
|
+
return result;
|
|
810
|
+
}
|
|
811
|
+
async function readExperienceSensorsReportSnapshot(repoRoot) {
|
|
812
|
+
const sidecar = await readJsonIfExists(path.join(sidecarDir(repoRoot), experienceSensorsFileName));
|
|
813
|
+
if (!sidecar) {
|
|
814
|
+
return undefined;
|
|
815
|
+
}
|
|
816
|
+
return {
|
|
817
|
+
artifact: "sp-vise/experience-sensors.json",
|
|
818
|
+
status: typeof sidecar.status === "string" ? sidecar.status : "unknown",
|
|
819
|
+
dimensions: sensorDimensionStatuses(sidecar.dimensions),
|
|
820
|
+
reviewGaps: sensorReviewGaps(sidecar.dimensions),
|
|
821
|
+
score: null,
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function sensorDimensionStatuses(raw) {
|
|
825
|
+
const dimensions = objectInput(raw);
|
|
826
|
+
const result = {};
|
|
827
|
+
for (const [dimensionId, value] of Object.entries(dimensions)) {
|
|
828
|
+
const dimension = objectInput(value);
|
|
829
|
+
result[dimensionId] = typeof dimension.status === "string" ? dimension.status : "unknown";
|
|
830
|
+
}
|
|
831
|
+
return result;
|
|
832
|
+
}
|
|
833
|
+
function sensorReviewGaps(raw) {
|
|
834
|
+
const dimensions = objectInput(raw);
|
|
835
|
+
const gaps = [];
|
|
836
|
+
for (const [dimensionId, value] of Object.entries(dimensions)) {
|
|
837
|
+
const dimension = objectInput(value);
|
|
838
|
+
const sensors = Array.isArray(dimension.sensors) ? dimension.sensors : [];
|
|
839
|
+
for (const rawSensor of sensors) {
|
|
840
|
+
const sensor = objectInput(rawSensor);
|
|
841
|
+
const status = typeof sensor.status === "string" ? sensor.status : "unknown";
|
|
842
|
+
if (status !== "needs-review" && status !== "needs-setup") {
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
gaps.push({
|
|
846
|
+
dimension: typeof sensor.dimension === "string" ? sensor.dimension : dimensionId,
|
|
847
|
+
id: typeof sensor.id === "string" ? sensor.id : "unknown",
|
|
848
|
+
status,
|
|
849
|
+
title: typeof sensor.title === "string" ? sensor.title : "Unknown sensor",
|
|
850
|
+
reason: typeof sensor.reason === "string" ? sensor.reason : "No reason recorded.",
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return gaps.slice(0, 50);
|
|
855
|
+
}
|
|
856
|
+
function fallbackExperienceReport(check) {
|
|
857
|
+
const uxAssessment = check.uxHarness ?? {
|
|
858
|
+
status: "absent",
|
|
859
|
+
advisoryOnly: "UX Harness guidance is advisory in the MVP. It does not change deterministic compliance exit codes until benchmark evidence justifies gating.",
|
|
860
|
+
assessedExpectations: [],
|
|
861
|
+
summary: {},
|
|
862
|
+
nextStep: "No UX Harness assessment is available for this check result.",
|
|
863
|
+
};
|
|
864
|
+
return {
|
|
865
|
+
status: "advisory",
|
|
866
|
+
dimensions: {
|
|
867
|
+
technical: {
|
|
868
|
+
status: check.status,
|
|
869
|
+
summary: check.summary,
|
|
870
|
+
exitCode: check.exitCode,
|
|
871
|
+
},
|
|
872
|
+
design: {
|
|
873
|
+
status: "absent",
|
|
874
|
+
summary: "No accepted design contract is available for this report.",
|
|
875
|
+
},
|
|
876
|
+
ux: uxAssessment,
|
|
877
|
+
businessAlignment: {
|
|
878
|
+
status: "absent",
|
|
879
|
+
summary: "No accepted creative variant is available for business-alignment reporting.",
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
score: null,
|
|
883
|
+
nextStep: "Resolve any technical check issue first, then regenerate the report. Do not publish a single Experience Score until repeated dogfood and benchmark evidence calibrates it responsibly.",
|
|
737
884
|
};
|
|
738
885
|
}
|
|
739
886
|
export async function syncCompliance(repoPath) {
|
|
@@ -1395,6 +1542,9 @@ function attestationsDir(repoRoot) {
|
|
|
1395
1542
|
function compliancePath(repoRoot) {
|
|
1396
1543
|
return path.join(sidecarDir(repoRoot), "compliance.json");
|
|
1397
1544
|
}
|
|
1545
|
+
function experienceReportPath(repoRoot) {
|
|
1546
|
+
return path.join(sidecarDir(repoRoot), experienceReportFileName);
|
|
1547
|
+
}
|
|
1398
1548
|
function attestationPathFor(ruleId) {
|
|
1399
1549
|
return `${ruleId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
|
|
1400
1550
|
}
|