@amityco/social-plus-vise 1.0.0 → 1.1.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +71 -24
  2. package/LICENSE +8 -6
  3. package/README.md +168 -358
  4. package/dist/capabilities.js +19 -62
  5. package/dist/intelligence/grounding.js +0 -23
  6. package/dist/intelligence/placement.js +0 -9
  7. package/dist/outcomes.js +44 -22
  8. package/dist/server.js +75 -38
  9. package/dist/tools/ast.js +3 -209
  10. package/dist/tools/blocks.js +6 -20
  11. package/dist/tools/compliance.js +168 -43
  12. package/dist/tools/creative.js +15 -41
  13. package/dist/tools/debug.js +0 -16
  14. package/dist/tools/design.js +18 -364
  15. package/dist/tools/docs.js +53 -24
  16. package/dist/tools/experienceCompiler.js +7 -10
  17. package/dist/tools/experienceSensors.js +1 -1
  18. package/dist/tools/harness.js +2 -27
  19. package/dist/tools/integration.js +6 -38
  20. package/dist/tools/learning.js +1 -1
  21. package/dist/tools/project.js +763 -546
  22. package/dist/tools/sdkFacts.js +2 -15
  23. package/dist/tools/sdkVersion.js +3 -36
  24. package/dist/tools/sensors.js +0 -6
  25. package/dist/tools/uxHarness.js +12 -9
  26. package/package.json +8 -97
  27. package/rules/chat.yaml +225 -0
  28. package/rules/event.yaml +45 -0
  29. package/rules/feed.yaml +24 -24
  30. package/rules/invitation.yaml +58 -0
  31. package/rules/live-data.yaml +104 -2
  32. package/rules/notification-tray.yaml +106 -0
  33. package/rules/poll.yaml +71 -0
  34. package/rules/sdk-lifecycle.yaml +112 -6
  35. package/rules/search.yaml +131 -0
  36. package/rules/story.yaml +221 -0
  37. package/rules/user-blocking.yaml +71 -0
  38. package/sdk-surface/flutter.json +1 -1
  39. package/sdk-surface/ios.json +1 -1
  40. package/sdk-surface/manifest.json +12 -12
  41. package/sdk-surface/models.flutter.json +96 -96
  42. package/sdk-surface/models.ios.json +1 -1
  43. package/sdk-surface/typescript.json +4 -4
  44. package/skills/social-plus-vise/SKILL.md +25 -5
  45. package/scripts/catalog-coverage-html.mjs +0 -325
  46. package/scripts/catalog-relationships-html.mjs +0 -686
  47. package/scripts/catalog-sheets.mjs +0 -286
  48. package/scripts/dart-model-extractor/bin/extract_models.dart +0 -169
  49. package/scripts/dart-model-extractor/pubspec.lock +0 -149
  50. package/scripts/dart-model-extractor/pubspec.yaml +0 -16
  51. package/scripts/extract-sdk-models.mjs +0 -749
  52. package/scripts/import-sdk-surface.mjs +0 -161
  53. package/scripts/pilot-feedback.mjs +0 -107
  54. package/scripts/workshop-board-html.mjs +0 -1018
  55. package/scripts/workshop-kit.mjs +0 -252
  56. package/skills/vise-harness-engineer/SKILL.md +0 -35
package/dist/server.js CHANGED
@@ -57,9 +57,6 @@ const tools = new Map([
57
57
  getSdkFactsTool,
58
58
  ].map((tool) => [tool.name, tool]));
59
59
  const bundledSkillName = "social-plus-vise";
60
- // Pre-rebrand `install-skill` runs created skill dirs/files under this name. We
61
- // supersede (remove) them on install so a host doesn't keep serving stale
62
- // foundry/spf guidance alongside the current skill.
63
60
  const legacySkillName = "social-plus-foundry";
64
61
  const cliResult = await handleCli(process.argv.slice(2));
65
62
  if (cliResult === "exit") {
@@ -102,6 +99,10 @@ async function handleCli(args) {
102
99
  console.log(`${packageName} ${packageVersion}`);
103
100
  return "exit";
104
101
  }
102
+ if (command === "--help-internal") {
103
+ console.log(helpText() + internalCommandsSection());
104
+ return "exit";
105
+ }
105
106
  if (command === "--help" || command === "-h" || command === "help") {
106
107
  console.log(helpText(args[1]));
107
108
  return "exit";
@@ -253,7 +254,17 @@ async function handleCli(args) {
253
254
  if (!errorMessage) {
254
255
  const errorFile = flagValue(args, "error-file");
255
256
  if (errorFile) {
256
- errorMessage = await readFile(path.resolve(errorFile), "utf8");
257
+ const resolved = path.resolve(errorFile);
258
+ try {
259
+ errorMessage = await readFile(resolved, "utf8");
260
+ }
261
+ catch (error) {
262
+ const code = error?.code;
263
+ const why = code === "ENOENT" ? "file not found" : code === "EISDIR" ? "path is a directory" : "could not be read";
264
+ console.error(`Could not read --error-file (${why}): ${resolved}`);
265
+ process.exitCode = 1;
266
+ return "exit";
267
+ }
257
268
  }
258
269
  else if (!process.stdin.isTTY) {
259
270
  const { readFileSync } = await import("node:fs");
@@ -324,9 +335,6 @@ async function handleCli(args) {
324
335
  dryRun: hasFlag(args, "dry-run"),
325
336
  surfacePath: flagValue(args, "surface") ?? flagValue(args, "surface-path"),
326
337
  });
327
- // Reflect sensor outcome in the exit code so `vise run-sensors` is usable as a CI gate.
328
- // Previously it always exited 0, so a failed/timed-out build silently read as green.
329
- // dry-run / passed / no-sensors stay 0; only real failures fail.
330
338
  const status = toolResultStatus(printed);
331
339
  if (status === "failed" || status === "timed-out") {
332
340
  process.exitCode = 1;
@@ -547,6 +555,17 @@ async function handleCli(args) {
547
555
  process.exitCode = 1;
548
556
  return "exit";
549
557
  }
558
+ function internalCommandsSection() {
559
+ return `
560
+
561
+ Internal commands (not part of the public surface — see docs/TOOLS.md):
562
+ vise sdk-facts --platform <p> [--capability <c>] Read bundled SDK surface facts. Projectless, read-only.
563
+ vise blocks <list|plan|add> ... Install and validate social.plus blocks in customer projects.
564
+ vise resolve --request "..." Resolve a request into the closest supported Vise outcome.
565
+ vise skill-path Print the bundled skill source path and install targets.
566
+
567
+ Run \`vise <command> --help\` for any of the above.`;
568
+ }
550
569
  function helpText(command) {
551
570
  if (command === "inspect") {
552
571
  return `${packageName} inspect
@@ -648,7 +667,7 @@ Usage:
648
667
  vise experience sensors [repoPath] --surface apps/web --no-write
649
668
 
650
669
  Output:
651
- compile writes sp-vise/experience-compiler.json by default. The artifact summarizes install guidance, navigation wiring, per-surface plan/init commands, UX expectations, optional Block Factory bridge candidates, design adaptation, and validation commands. It does not edit source code.
670
+ compile writes sp-vise/experience-compiler.json by default. The artifact summarizes install guidance, navigation wiring, per-surface plan/init commands, UX expectations, optional block bridge candidates, design adaptation, and validation commands. It does not edit source code.
652
671
 
653
672
  sensors writes sp-vise/experience-sensors.json by default. The artifact summarizes advisory technical, design, UX, accessibility, and business-alignment evidence without changing vise check exit codes or producing a calibrated score.`;
654
673
  }
@@ -711,7 +730,7 @@ Targets:
711
730
  cursor Installs to <repoPath>/.cursor/skills/social-plus-vise
712
731
  vscode Installs to <repoPath>/.github/skills/social-plus-vise
713
732
  copilot Installs to <repoPath>/.github/skills/social-plus-vise
714
- cursor-rules Writes <repoPath>/.cursor/rules/social-plus-vise.mdc
733
+ cursor-rules Writes <repoPath>/.cursor/rules/social-plus-vise.mdc plus .cursor/rules/reference/*.md
715
734
  custom Use --dest <skillsRoot or exact skill directory>`;
716
735
  }
717
736
  if (command === "print-skill" || command === "print_skill") {
@@ -776,7 +795,7 @@ Usage:
776
795
  if (command === "sdk-facts" || command === "sdk_facts") {
777
796
  return `${packageName} sdk-facts
778
797
 
779
- Read bundled SDK surface facts for social.plus Block Factory planning. Internal, projectless, and read-only.
798
+ Read bundled social.plus SDK surface facts for block packaging. Projectless and read-only.
780
799
  Symbol facts prove existence; --include-models adds extraction-grounded field-level model schemas
781
800
  (modelSchemas, plus capability model entries gain a schema). Platforms without grounded field data
782
801
  report modelFacts.status=absent instead of fabricated fields.
@@ -791,7 +810,7 @@ Usage:
791
810
  if (command === "blocks") {
792
811
  return `${packageName} blocks
793
812
 
794
- Install and validate social.plus Block Factory blocks inside customer projects.
813
+ Install and validate social.plus blocks inside customer projects.
795
814
 
796
815
  Usage:
797
816
  vise blocks list --registry <path> --format json
@@ -892,6 +911,27 @@ init-tokens Scaffold src/styles/social-plus-tokens.css in the customer's project
892
911
  concrete values. Idempotent (never overwrites); use --force to overwrite.
893
912
  After editing, run vise design extract --from-project to refresh the contract.`;
894
913
  }
914
+ if (command === "engagement") {
915
+ return `${packageName} engagement
916
+
917
+ Record and inspect the engagement-scope artifact (sp-vise/engagement.json) — the
918
+ contractual record of which broad-social outcomes are in scope for this project.
919
+
920
+ Usage:
921
+ vise engagement init [repoPath] --tier <free|pro|partner> --customer-id <id> --scope <outcome,...>
922
+ vise engagement init [repoPath] --scope feed,communities --target-completion 2026-12-31 \\
923
+ --reviewer-name "Jane Doe" --reviewer-email jane@example.com --evidence-upload-consent
924
+ vise engagement show [repoPath]
925
+
926
+ Flags (init):
927
+ --tier <free|pro|partner> Engagement tier (validated).
928
+ --customer-id <id> Customer identifier recorded in the artifact.
929
+ --scope <outcome,...> In-scope broad-social outcomes (repeatable; comma-separated).
930
+ --target-completion <date> Target completion date, YYYY-MM-DD.
931
+ --reviewer-name <name> Human reviewer recorded on the engagement.
932
+ --reviewer-email <email> Human reviewer contact.
933
+ --evidence-upload-consent Record consent to upload evidence during review.`;
934
+ }
895
935
  return `${packageName}
896
936
 
897
937
  Skill-guided deterministic CLI for social.plus SDK integration assistance.
@@ -919,11 +959,11 @@ Usage:
919
959
  vise sync [repoPath] Persist deterministic-pass evidence
920
960
  vise attest [repoPath] --rule ... Record a compliance attestation
921
961
  vise explain <ruleId> Explain one compliance rule
962
+ vise engagement init [repoPath] Record the engagement-scope artifact (see vise engagement --help)
963
+ vise engagement show [repoPath] Show the recorded engagement scope
922
964
  vise status [repoPath] Print compliance summary
923
965
  vise validate [repoPath] Validate setup and common risks
924
966
  vise run-sensors [repoPath] Run detected project sensors
925
- vise sdk-facts --platform ... Internal SDK surface facts for Block Factory
926
- vise blocks ... Install and validate Block Factory blocks
927
967
  vise design extract <prototype> Extract a design contract from an HTML/CSS prototype
928
968
  vise design check [repoPath] Advisory (non-blocking) UI-vs-contract conformance report
929
969
  vise design preview [repoPath] Write an HTML visual review of the contract + conformance
@@ -932,7 +972,7 @@ Usage:
932
972
  vise --version Show package version
933
973
 
934
974
  Compatibility aliases:
935
- spf, social-plus-vise, foundry, social-plus-foundry, foundry-mcp
975
+ spf, social-plus-vise
936
976
 
937
977
  MCP config:
938
978
  {
@@ -953,7 +993,6 @@ async function printToolResult(tool, input) {
953
993
  console.log(text);
954
994
  return { result, text };
955
995
  }
956
- // Parse the `status` field from a tool's printed JSON payload (best-effort).
957
996
  function toolResultStatus(printed) {
958
997
  try {
959
998
  const payload = JSON.parse(printed.text);
@@ -984,11 +1023,6 @@ async function installSkill(args) {
984
1023
  nextStep: "Restart or reload the host AI coding tool so it discovers the installed skill.",
985
1024
  };
986
1025
  }
987
- // Supersede a pre-rebrand skill install: a prior `install-skill` under the old
988
- // package name created a sibling `<skillsRoot>/social-plus-foundry/` directory. Left
989
- // in place, the host keeps offering stale spf/foundry guidance next to the current
990
- // skill. Remove it on install — but only when it actually looks like a skill dir
991
- // (contains SKILL.md) and is not the directory we're installing into.
992
1026
  async function removeLegacySkillDir(destination) {
993
1027
  const legacyDir = path.join(path.dirname(destination), legacySkillName);
994
1028
  if (legacyDir === destination) {
@@ -1002,43 +1036,46 @@ async function removeLegacySkillDir(destination) {
1002
1036
  }
1003
1037
  async function installInstructionFile(target, args) {
1004
1038
  const force = hasFlag(args, "force");
1005
- const source = path.join(skillSourceDir(), "SKILL.md");
1039
+ const skillDir = skillSourceDir();
1040
+ const source = path.join(skillDir, "SKILL.md");
1006
1041
  const content = await readFile(source, "utf8");
1007
- const legacyRule = path.join(path.dirname(target.destination), `${legacySkillName}.mdc`);
1042
+ const rulesDir = path.dirname(target.destination);
1043
+ const legacyRule = path.join(rulesDir, `${legacySkillName}.mdc`);
1008
1044
  const supersededLegacy = [];
1009
1045
  if (legacyRule !== target.destination && (await fileExists(legacyRule))) {
1010
1046
  await rm(legacyRule, { force: true });
1011
1047
  supersededLegacy.push(legacyRule);
1012
1048
  }
1049
+ const installedFiles = [];
1050
+ let mdcUpToDate = false;
1013
1051
  if (await fileExists(target.destination)) {
1014
1052
  const existing = await readFile(target.destination, "utf8");
1015
1053
  if (existing === content) {
1016
- return {
1017
- status: "already-current",
1018
- skill: bundledSkillName,
1019
- host: target.host,
1020
- source,
1021
- destination: target.destination,
1022
- force,
1023
- installedFiles: [],
1024
- supersededLegacy,
1025
- nextStep: "Restart or reload the host AI coding tool so it discovers the updated project instructions.",
1026
- };
1054
+ mdcUpToDate = true;
1027
1055
  }
1028
- if (!force) {
1056
+ else if (!force) {
1029
1057
  throw new Error(`Instruction file already exists with different content: ${target.destination}. Re-run with --force to overwrite.`);
1030
1058
  }
1031
1059
  }
1032
- await mkdir(path.dirname(target.destination), { recursive: true });
1033
- await writeFile(target.destination, content, "utf8");
1060
+ if (!mdcUpToDate) {
1061
+ await mkdir(rulesDir, { recursive: true });
1062
+ await writeFile(target.destination, content, "utf8");
1063
+ installedFiles.push(target.destination);
1064
+ }
1065
+ const referenceSource = path.join(skillDir, "reference");
1066
+ const hasReferenceDir = await stat(referenceSource).then((info) => info.isDirectory()).catch(() => false);
1067
+ if (hasReferenceDir) {
1068
+ const referenceDest = path.join(rulesDir, "reference");
1069
+ installedFiles.push(...(await copyDirectory(referenceSource, referenceDest, force)));
1070
+ }
1034
1071
  return {
1035
- status: "installed",
1072
+ status: installedFiles.length > 0 ? "installed" : "already-current",
1036
1073
  skill: bundledSkillName,
1037
1074
  host: target.host,
1038
1075
  source,
1039
1076
  destination: target.destination,
1040
1077
  force,
1041
- installedFiles: [target.destination],
1078
+ installedFiles,
1042
1079
  supersededLegacy,
1043
1080
  nextStep: "Restart or reload the host AI coding tool so it discovers the updated project instructions.",
1044
1081
  };