@amityco/social-plus-vise 1.1.1 → 1.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/dist/server.js CHANGED
@@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url";
6
6
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
8
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
9
- import { attestRule, attestRuleTool, checkCompliance, checkComplianceTool, explainRule, explainRuleTool, experienceReportTool, initCompliance, initComplianceTool, initEngagement, initEngagementTool, showEngagement, showEngagementTool, statusCompliance, syncCompliance, syncComplianceTool, } from "./tools/compliance.js";
9
+ import { attestRule, attestRuleTool, checkCompliance, checkComplianceTool, explainRule, explainRuleTool, experienceReportTool, initCompliance, initComplianceTool, recordBaseline, initEngagement, initEngagementTool, listRules, showEngagement, showEngagementTool, statusCompliance, syncCompliance, syncComplianceTool, } from "./tools/compliance.js";
10
10
  import { designCheckTool, designExtractTool, designInitTokensTool, designPreviewTool, designReferenceTool } from "./tools/design.js";
11
11
  import { getDocPageTool, searchDocsTool } from "./tools/docs.js";
12
12
  import { compileExperienceTool } from "./tools/experienceCompiler.js";
@@ -22,7 +22,10 @@ import { addBlockInstall, listRegistryBlocks, planBlockInstall, validateBlockIns
22
22
  import { debugIssueTool, debugIssue } from "./tools/debug.js";
23
23
  import { creativeAcceptTool, creativeBriefTool } from "./tools/creative.js";
24
24
  import { uxHarnessTool } from "./tools/uxHarness.js";
25
+ import { exploreRequest } from "./explore.js";
26
+ import { renderHuman, wantsHumanFormat } from "./humanFormat.js";
25
27
  import { packageName, packageVersion } from "./version.js";
28
+ const SUPPORT_URL = "mailto:support@social.plus";
26
29
  const tools = new Map([
27
30
  searchDocsTool,
28
31
  getDocPageTool,
@@ -107,14 +110,14 @@ async function handleCli(args) {
107
110
  console.log(helpText(args[1]));
108
111
  return "exit";
109
112
  }
110
- if (command === "doctor" || command === "--doctor") {
111
- console.log(JSON.stringify(doctorResult(), null, 2));
112
- return "exit";
113
- }
114
113
  if (isHelpRequest(args)) {
115
114
  console.log(helpText(command));
116
115
  return "exit";
117
116
  }
117
+ if (command === "doctor" || command === "--doctor") {
118
+ emitResult("doctor", doctorResult(), args);
119
+ return "exit";
120
+ }
118
121
  try {
119
122
  if (command === "install-skill" || command === "install_skill") {
120
123
  console.log(JSON.stringify(await installSkill(args.slice(1)), null, 2));
@@ -285,12 +288,11 @@ async function handleCli(args) {
285
288
  return "exit";
286
289
  }
287
290
  if (command === "plan" || command === "plan-integration") {
288
- await printToolResult(planIntegrationTool, {
289
- repoPath: positionalRepoPath(args.slice(1)),
290
- request: requiredFlagValue(args, "request", "plan requires --request."),
291
- surfacePath: flagValue(args, "surface") ?? flagValue(args, "surface-path"),
292
- answers: keyValueFlag(args, "answer"),
293
- });
291
+ const input = await planCliInput(args);
292
+ const result = await planIntegrationTool.call(input);
293
+ const text = result.content.map((item) => item.text).join("\n");
294
+ const payload = JSON.parse(text);
295
+ emitResult("plan", hasFlag(args, "summary") ? planSummary(payload) : payload, args);
294
296
  return "exit";
295
297
  }
296
298
  if (command === "plan-harness") {
@@ -414,21 +416,30 @@ async function handleCli(args) {
414
416
  return "exit";
415
417
  }
416
418
  if (command === "init") {
417
- assertOnlyKnownFlags(args, ["request", "surface", "surface-path", "answer", "allow-unresolved-intake"], "init");
418
- const result = await initCompliance(positionalRepoPath(args.slice(1)), requiredFlagValue(args, "request", "init requires --request."), flagValue(args, "surface") ?? flagValue(args, "surface-path"), keyValueFlag(args, "answer"), { allowUnresolvedIntake: hasFlag(args, "allow-unresolved-intake") });
419
+ assertOnlyKnownFlags(args, ["request", "surface", "surface-path", "answer", "allow-unresolved-intake", "baseline"], "init");
420
+ const initRepo = positionalRepoPath(args.slice(1));
421
+ const result = await initCompliance(initRepo, requiredFlagValue(args, "request", "init requires --request."), flagValue(args, "surface") ?? flagValue(args, "surface-path"), keyValueFlag(args, "answer"), { allowUnresolvedIntake: hasFlag(args, "allow-unresolved-intake") });
419
422
  if (result.status === "needs-clarification" && typeof result.exitCode === "number") {
420
423
  process.exitCode = result.exitCode;
421
424
  }
425
+ if (hasFlag(args, "baseline") && result.status === "initialized") {
426
+ result.baseline_recorded = await recordBaseline(initRepo);
427
+ }
422
428
  console.log(JSON.stringify(result, null, 2));
423
429
  return "exit";
424
430
  }
425
431
  if (command === "check") {
426
- assertOnlyKnownFlags(args, ["ci"], "check");
427
- const result = await checkCompliance(positionalRepoPath(args.slice(1)));
428
- console.log(JSON.stringify(hasFlag(args, "ci") ? ciCheckResult(result) : result, null, 2));
432
+ assertOnlyKnownFlags(args, ["ci", "format", "new-only"], "check");
433
+ const result = await checkCompliance(positionalRepoPath(args.slice(1)), { newOnly: hasFlag(args, "new-only") });
434
+ emitResult("check", hasFlag(args, "ci") ? ciCheckResult(result) : result, args);
429
435
  process.exitCode = result.exitCode;
430
436
  return "exit";
431
437
  }
438
+ if (command === "baseline") {
439
+ assertOnlyKnownFlags(args, [], "baseline");
440
+ console.log(JSON.stringify(await recordBaseline(positionalRepoPath(args.slice(1))), null, 2));
441
+ return "exit";
442
+ }
432
443
  if (command === "sync") {
433
444
  assertOnlyKnownFlags(args, [], "sync");
434
445
  console.log(JSON.stringify(await syncCompliance(positionalRepoPath(args.slice(1))), null, 2));
@@ -448,13 +459,26 @@ async function handleCli(args) {
448
459
  return "exit";
449
460
  }
450
461
  if (command === "explain") {
451
- assertOnlyKnownFlags(args, [], "explain");
452
- console.log(JSON.stringify(await explainRule(requiredPositionalText(args.slice(1), "explain requires a rule id.")), null, 2));
462
+ assertOnlyKnownFlags(args, ["format"], "explain");
463
+ const explainRuleId = positionalValues(args.slice(1))[0];
464
+ const payload = explainRuleId ? await explainRule(explainRuleId) : await listRules();
465
+ emitResult("explain", payload, args);
466
+ return "exit";
467
+ }
468
+ if (command === "explore") {
469
+ assertOnlyKnownFlags(args, ["request", "platform", "format"], "explore");
470
+ const request = flagValue(args, "request") ??
471
+ requiredPositionalText(args.slice(1), 'explore requires a request, e.g. `vise explore "add a social feed"`.');
472
+ emitResult("explore", exploreRequest(request, flagValue(args, "platform")), args);
453
473
  return "exit";
454
474
  }
455
475
  if (command === "status") {
456
- assertOnlyKnownFlags(args, [], "status");
457
- console.log(JSON.stringify(await statusCompliance(positionalRepoPath(args.slice(1))), null, 2));
476
+ assertOnlyKnownFlags(args, ["format", "new-only"], "status");
477
+ const result = await statusCompliance(positionalRepoPath(args.slice(1)), { newOnly: hasFlag(args, "new-only") });
478
+ emitResult("status", result, args);
479
+ if (typeof result.exitCode === "number") {
480
+ process.exitCode = result.exitCode;
481
+ }
458
482
  return "exit";
459
483
  }
460
484
  if (command === "engagement") {
@@ -583,13 +607,17 @@ Create the evidence-backed implementation packet before editing code.
583
607
 
584
608
  Usage:
585
609
  vise plan [repoPath] --request "Add a social feed"
610
+ vise plan --summary "Use UIKit for a standard feed"
586
611
  vise plan apps/web --request "Create posts" --surface apps/web
612
+ vise plan . --request "Use UIKit for a standard feed" --summary
587
613
 
588
614
  Re-plan with collected answers (repeat --answer for each intake question):
589
615
  vise plan . --request "Add a social feed" \\
590
616
  --answer feed_scope=community \\
591
617
  --answer feed_target=existing\\ communityId \\
592
- --answer target_screen_or_route=app/feed/page.tsx`;
618
+ --answer target_screen_or_route=app/feed/page.tsx
619
+
620
+ Output is JSON by default (for agents/CI). Add --format human for a readable plan summary.`;
593
621
  }
594
622
  if (command === "creative") {
595
623
  return `${packageName} creative
@@ -838,7 +866,9 @@ Usage:
838
866
  Check the current source and recorded attestations against the compliance contract. Read-only.
839
867
 
840
868
  Usage:
841
- vise check [repoPath] [--ci]`;
869
+ vise check [repoPath] [--ci] [--format human]
870
+
871
+ Output is JSON by default (for agents/CI). Add --format human for a readable verdict summary.`;
842
872
  }
843
873
  if (command === "sync") {
844
874
  return `${packageName} sync
@@ -854,23 +884,45 @@ Usage:
854
884
  Record a host-agent or local-human attestation for one compliance rule.
855
885
 
856
886
  Usage:
857
- vise attest [repoPath] --rule sdk.init.at-startup --confidence high --signer host-agent --evidence-file evidence.json --rationale "Why this rule is satisfied."`;
887
+ vise attest [repoPath] --rule typescript.client.region --confidence high --signer host-agent --evidence-file evidence.json --rationale "Why this rule is satisfied."`;
858
888
  }
859
889
  if (command === "explain") {
860
890
  return `${packageName} explain
861
891
 
862
- Explain one compliance rule.
892
+ Explain one compliance rule, or list every valid rule id when run with no id.
863
893
 
864
894
  Usage:
865
- vise explain sdk.init.at-startup`;
895
+ vise explain [--format human] List all rule ids (public + contract) with where each applies
896
+ vise explain typescript.client.region [--format human]`;
897
+ }
898
+ if (command === "explore") {
899
+ return `${packageName} explore
900
+
901
+ Discover what social.plus offers for a request — before any project or credentials exist. Read-only:
902
+ maps the request to a candidate outcome (or lists the full menu when it can't), and for each shows the
903
+ capabilities involved, the canonical docs, and the command to start. No project, no API key, no writes.
904
+
905
+ Usage:
906
+ vise explore "add a social feed" [--platform typescript] [--format human]`;
907
+ }
908
+ if (command === "doctor") {
909
+ return `${packageName} doctor
910
+
911
+ Print install diagnostics (Node version, transport, docs source, registered tools).
912
+ Read-only. JSON by default; --format human for a readable summary.
913
+
914
+ Usage:
915
+ vise doctor [--format human]
916
+
917
+ If diagnostics report a problem, see ${SUPPORT_URL}`;
866
918
  }
867
919
  if (command === "status") {
868
920
  return `${packageName} status
869
921
 
870
- Print a compact compliance summary.
922
+ Print a compact compliance summary. JSON by default; --format human for a readable verdict.
871
923
 
872
924
  Usage:
873
- vise status [repoPath]`;
925
+ vise status [repoPath] [--format human]`;
874
926
  }
875
927
  if (command === "design") {
876
928
  return `${packageName} design
@@ -919,14 +971,17 @@ contractual record of which broad-social outcomes are in scope for this project.
919
971
 
920
972
  Usage:
921
973
  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 \\
974
+ vise engagement init [repoPath] --scope add-feed,add-community --target-completion 2026-12-31 \\
923
975
  --reviewer-name "Jane Doe" --reviewer-email jane@example.com --evidence-upload-consent
924
976
  vise engagement show [repoPath]
925
977
 
926
978
  Flags (init):
927
979
  --tier <free|pro|partner> Engagement tier (validated).
928
980
  --customer-id <id> Customer identifier recorded in the artifact.
929
- --scope <outcome,...> In-scope broad-social outcomes (repeatable; comma-separated).
981
+ --scope <outcome,...> In-scope outcomes, comma-separated. One or more of: setup-sdk,
982
+ setup-push, setup-live-data, add-feed, add-comments, add-chat,
983
+ add-community, add-follow, add-moderation, add-notifications,
984
+ troubleshoot, validate-setup.
930
985
  --target-completion <date> Target completion date, YYYY-MM-DD.
931
986
  --reviewer-name <name> Human reviewer recorded on the engagement.
932
987
  --reviewer-email <email> Human reviewer contact.
@@ -952,10 +1007,12 @@ Usage:
952
1007
  vise learning record [repoPath] Record a local-only learning event
953
1008
  vise learning show [repoPath] Show local learning summary
954
1009
  vise debug [repoPath] --error ... Debug an SDK-specific runtime error and emit a repair brief
1010
+ vise explore "<request>" Discover what social.plus offers for a request (no project/credentials needed)
955
1011
  vise plan [repoPath] --request "..." Create an implementation plan
956
1012
  vise workplan next [repoPath] --request "..." Get the next broad-social surface to implement
957
- vise init [repoPath] --request "..." Initialize compliance sidecar
958
- vise check [repoPath] Check compliance contract
1013
+ vise init [repoPath] --request "..." Initialize compliance sidecar (add --baseline on a brownfield app)
1014
+ vise check [repoPath] Check compliance contract (add --new-only to gate on findings since the baseline)
1015
+ vise baseline [repoPath] Snapshot pre-existing findings so check --new-only gates only new ones
959
1016
  vise sync [repoPath] Persist deterministic-pass evidence
960
1017
  vise attest [repoPath] --rule ... Record a compliance attestation
961
1018
  vise explain <ruleId> Explain one compliance rule
@@ -993,6 +1050,43 @@ async function printToolResult(tool, input) {
993
1050
  console.log(text);
994
1051
  return { result, text };
995
1052
  }
1053
+ function emitResult(command, payload, args) {
1054
+ if (wantsHumanFormat(flagValue(args, "format"))) {
1055
+ const human = renderHuman(command, payload);
1056
+ if (human !== null) {
1057
+ console.log(human);
1058
+ return;
1059
+ }
1060
+ }
1061
+ console.log(JSON.stringify(payload, null, 2));
1062
+ }
1063
+ async function planCliInput(args) {
1064
+ const subArgs = args.slice(1);
1065
+ const requestFromFlag = flagValue(args, "request");
1066
+ if (requestFromFlag) {
1067
+ return {
1068
+ repoPath: positionalRepoPath(subArgs),
1069
+ request: requestFromFlag,
1070
+ surfacePath: flagValue(args, "surface") ?? flagValue(args, "surface-path"),
1071
+ answers: keyValueFlag(args, "answer"),
1072
+ };
1073
+ }
1074
+ const positional = positionalValues(subArgs);
1075
+ const [first, ...rest] = positional;
1076
+ if (!first) {
1077
+ throw new Error("plan requires --request or a quoted request argument.");
1078
+ }
1079
+ const firstLooksLikePath = await pathExists(first);
1080
+ if (firstLooksLikePath && rest.length === 0) {
1081
+ throw new Error("plan requires --request when the only positional argument is a repository path.");
1082
+ }
1083
+ return {
1084
+ repoPath: firstLooksLikePath ? first : ".",
1085
+ request: firstLooksLikePath ? rest.join(" ").trim() : positional.join(" ").trim(),
1086
+ surfacePath: flagValue(args, "surface") ?? flagValue(args, "surface-path"),
1087
+ answers: keyValueFlag(args, "answer"),
1088
+ };
1089
+ }
996
1090
  function toolResultStatus(printed) {
997
1091
  try {
998
1092
  const payload = JSON.parse(printed.text);
@@ -1002,6 +1096,125 @@ function toolResultStatus(printed) {
1002
1096
  return undefined;
1003
1097
  }
1004
1098
  }
1099
+ function planSummary(payload) {
1100
+ const solutionPath = objectProp(payload, "solutionPath");
1101
+ const uikitCustomization = objectProp(payload, "uikitCustomization");
1102
+ const intake = objectProp(payload, "intake");
1103
+ const answers = objectProp(intake, "answers") ?? {};
1104
+ const workplan = objectProp(payload, "socialWorkplan");
1105
+ const questions = arrayProp(intake, "questions").map(questionSummary);
1106
+ const decisionsRequired = stringArrayProp(payload, "decisionsRequired");
1107
+ const solutionPathAnswerId = stringProp(solutionPath, "answerId");
1108
+ const uikitCustomizationAnswerId = stringProp(uikitCustomization, "answerId");
1109
+ return stripUndefined({
1110
+ kind: "plan-summary",
1111
+ outcome: stringProp(payload, "outcome"),
1112
+ platform: stringProp(payload, "platform"),
1113
+ supportLevel: stringProp(payload, "supportLevel"),
1114
+ solutionPath: solutionPath
1115
+ ? {
1116
+ recommendation: stringProp(solutionPath, "recommendation"),
1117
+ confidence: stringProp(solutionPath, "confidence"),
1118
+ summary: stringProp(solutionPath, "summary"),
1119
+ answerId: solutionPathAnswerId,
1120
+ decisionRequired: booleanProp(objectProp(solutionPath, "decision"), "requiredBeforeHandRolledUi") === true
1121
+ && !hasAnswerValue(answers, solutionPathAnswerId),
1122
+ }
1123
+ : undefined,
1124
+ uikitCustomization: uikitCustomization
1125
+ ? {
1126
+ status: stringProp(uikitCustomization, "status"),
1127
+ recommendedLevel: stringProp(uikitCustomization, "recommendedLevel"),
1128
+ confidence: stringProp(uikitCustomization, "confidence"),
1129
+ summary: stringProp(uikitCustomization, "summary"),
1130
+ answerId: uikitCustomizationAnswerId,
1131
+ decisionRequired: booleanProp(objectProp(uikitCustomization, "decision"), "requiredBeforeCustomization") === true
1132
+ && !hasAnswerValue(answers, uikitCustomizationAnswerId),
1133
+ }
1134
+ : undefined,
1135
+ intake: intake
1136
+ ? {
1137
+ status: stringProp(intake, "status"),
1138
+ remainingBlocking: numberProp(intake, "remainingBlocking"),
1139
+ blockingQuestions: questions.filter((question) => question.blocksImplementationWhenMissing),
1140
+ openQuestions: questions,
1141
+ answers,
1142
+ }
1143
+ : undefined,
1144
+ decisionsRequired,
1145
+ workplan: workplan ? workplanSummary(workplan) : undefined,
1146
+ nextStep: stringProp(payload, "nextStep"),
1147
+ });
1148
+ }
1149
+ function hasAnswerValue(answers, answerId) {
1150
+ if (!answerId) {
1151
+ return false;
1152
+ }
1153
+ const answer = answers[answerId];
1154
+ return typeof answer === "string" && answer.trim() !== "";
1155
+ }
1156
+ function workplanSummary(workplan) {
1157
+ return stripUndefined({
1158
+ kind: stringProp(workplan, "kind"),
1159
+ status: stringProp(workplan, "status"),
1160
+ nextStep: stringProp(workplan, "nextStep"),
1161
+ surfaces: arrayProp(workplan, "sequence").map((surface) => {
1162
+ const surfaceObject = asObject(surface);
1163
+ const intake = objectProp(surfaceObject, "intake");
1164
+ return stripUndefined({
1165
+ id: stringProp(surfaceObject, "id"),
1166
+ order: numberProp(surfaceObject, "order"),
1167
+ outcome: stringProp(surfaceObject, "outcome"),
1168
+ label: stringProp(surfaceObject, "label"),
1169
+ remainingBlocking: numberProp(intake, "remainingBlocking"),
1170
+ intakeStatus: stringProp(intake, "status"),
1171
+ });
1172
+ }),
1173
+ });
1174
+ }
1175
+ function questionSummary(value) {
1176
+ const question = asObject(value);
1177
+ return {
1178
+ id: stringProp(question, "id"),
1179
+ question: stringProp(question, "question"),
1180
+ required: booleanProp(question, "required"),
1181
+ blocksImplementationWhenMissing: booleanProp(question, "blocksImplementationWhenMissing"),
1182
+ };
1183
+ }
1184
+ function objectProp(value, key) {
1185
+ if (!value) {
1186
+ return undefined;
1187
+ }
1188
+ return asObject(value[key]);
1189
+ }
1190
+ function asObject(value) {
1191
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
1192
+ }
1193
+ function arrayProp(value, key) {
1194
+ if (!value) {
1195
+ return [];
1196
+ }
1197
+ const item = value[key];
1198
+ return Array.isArray(item) ? item : [];
1199
+ }
1200
+ function stringArrayProp(value, key) {
1201
+ return arrayProp(value, key).filter((item) => typeof item === "string");
1202
+ }
1203
+ function stringProp(value, key) {
1204
+ const item = value?.[key];
1205
+ return typeof item === "string" ? item : undefined;
1206
+ }
1207
+ function numberProp(value, key) {
1208
+ const item = value?.[key];
1209
+ return typeof item === "number" ? item : undefined;
1210
+ }
1211
+ function booleanProp(value, key) {
1212
+ const item = value?.[key];
1213
+ return typeof item === "boolean" ? item : undefined;
1214
+ }
1215
+ function stripUndefined(value) {
1216
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
1217
+ }
1005
1218
  async function installSkill(args) {
1006
1219
  const source = skillSourceDir();
1007
1220
  const instructionInstall = instructionInstallDestination(args);
@@ -1281,7 +1494,7 @@ async function completeWorkplanSurface(args) {
1281
1494
  throw new Error(`Surface "${surfaceId}" is not in this social workplan. Available surfaces: ${sequence.map((item) => item.id).join(", ") || "(none)"}.`);
1282
1495
  }
1283
1496
  const now = new Date().toISOString();
1284
- const check = await greenWorkplanCheck(repoRoot, surfaceId);
1497
+ const check = await greenWorkplanCheck(repoRoot, surfaceId, surface.outcome);
1285
1498
  const snapshot = await writeWorkplanSurfaceSnapshot(repoRoot, surfaceId, check, now);
1286
1499
  const existing = await readWorkplanProgress(repoRoot);
1287
1500
  const base = existing?.request === request
@@ -1331,7 +1544,7 @@ async function completeWorkplanSurface(args) {
1331
1544
  nextStep: status.nextStep,
1332
1545
  };
1333
1546
  }
1334
- async function greenWorkplanCheck(repoRoot, surfaceId) {
1547
+ async function greenWorkplanCheck(repoRoot, surfaceId, expectedOutcome) {
1335
1548
  let check;
1336
1549
  try {
1337
1550
  check = await checkCompliance(repoRoot);
@@ -1340,6 +1553,9 @@ async function greenWorkplanCheck(repoRoot, surfaceId) {
1340
1553
  const message = error instanceof Error ? error.message : String(error);
1341
1554
  throw new Error(`Cannot mark "${surfaceId}" complete because the current compliance check could not run. Run the focused \`vise init\` command for this surface first, then \`vise check .\`. ${message}`);
1342
1555
  }
1556
+ if (expectedOutcome && check.outcome !== expectedOutcome) {
1557
+ throw new Error(`Cannot mark "${surfaceId}" complete: the sp-vise sidecar is currently scoped to outcome "${check.outcome}", not this surface's outcome "${expectedOutcome}". Each workplan surface has its own sidecar scope — run this surface's focused \`vise init\` command (it sets \`--answer feature_surface=${surfaceId}\`) and \`vise check .\` before recording it. (The check reported "${check.status}" only because it ran against the other surface's contract.)`);
1558
+ }
1343
1559
  if (check.status !== "green") {
1344
1560
  throw new Error(`Cannot mark "${surfaceId}" complete because \`vise check\` returned "${check.status}" (exit ${check.exitCode}). Resolve the check result before recording workplan progress.`);
1345
1561
  }
@@ -1432,13 +1648,25 @@ function ciCheckResult(result) {
1432
1648
  enabled: true,
1433
1649
  passed: result.exitCode === 0,
1434
1650
  exitCode: result.exitCode,
1435
- blockingResultStatuses: ["contract-drift", "blocked", "deterministic-failures", "needs-attestation"],
1651
+ blockingResultStatuses: [
1652
+ "contract-drift",
1653
+ "blocked",
1654
+ "deterministic-failures",
1655
+ "needs-attestation",
1656
+ "completeness-gap",
1657
+ "selected-capability-failures",
1658
+ ],
1436
1659
  message: result.exitCode === 0 ? "Compliance green for CI." : `Compliance failed for CI with status: ${result.status}.`,
1437
1660
  },
1438
1661
  };
1439
1662
  }
1440
1663
  function positionalRepoPath(args) {
1441
- const flagsWithValues = new Set(["request", "requirements", "prototype", "variant", "variant-id", "brief", "brief-path", "surface", "surface-path", "platform", "capability", "surface-dir", "format", "include", "timeout-ms", "query", "path", "limit", "answer", "target", "dest", "destination", "rule", "confidence", "signer", "identity", "evidence-file", "rationale", "repo", "reference", "registry", "block", "package-source", "note", "kind", "sentiment", "metric"]);
1664
+ const values = positionalValues(args);
1665
+ return values[0] ?? ".";
1666
+ }
1667
+ function positionalValues(args) {
1668
+ const flagsWithValues = new Set(["request", "requirements", "prototype", "variant", "variant-id", "brief", "brief-path", "surface", "surface-path", "platform", "capability", "surface-dir", "format", "include", "timeout-ms", "query", "path", "limit", "answer", "target", "dest", "destination", "rule", "confidence", "signer", "identity", "evidence-file", "rationale", "repo", "reference", "registry", "block", "package-source", "note", "kind", "sentiment", "metric", "tier", "customer-id", "scope", "target-completion", "reviewer-name", "reviewer-email"]);
1669
+ const values = [];
1442
1670
  for (let index = 0; index < args.length; index += 1) {
1443
1671
  const arg = args[index];
1444
1672
  if (!arg) {
@@ -1454,9 +1682,18 @@ function positionalRepoPath(args) {
1454
1682
  if (arg.startsWith("-")) {
1455
1683
  continue;
1456
1684
  }
1457
- return arg;
1685
+ values.push(arg);
1686
+ }
1687
+ return values;
1688
+ }
1689
+ async function pathExists(input) {
1690
+ try {
1691
+ await stat(path.resolve(expandHome(input)));
1692
+ return true;
1693
+ }
1694
+ catch {
1695
+ return false;
1458
1696
  }
1459
- return ".";
1460
1697
  }
1461
1698
  function requiredPositionalText(args, message) {
1462
1699
  const values = [];
@@ -1609,5 +1846,6 @@ function doctorResult() {
1609
1846
  docsBaseUrl: process.env.SOCIAL_PLUS_DOCS_BASE_URL ?? "https://learn.social.plus",
1610
1847
  transport: "stdio",
1611
1848
  tools: Array.from(tools.keys()),
1849
+ support: SUPPORT_URL,
1612
1850
  };
1613
1851
  }