sf-intelligence 0.1.16 → 0.1.17

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/index.js CHANGED
@@ -57375,6 +57375,7 @@ var init_synthesize_answer = __esm({
57375
57375
  let ungroundedAnnotationClaims;
57376
57376
  let grounded;
57377
57377
  let ungroundedAbsenceClaims;
57378
+ const evidenceEmpty = source === void 0 || source === null || typeof source === "string" && source.trim().length === 0 || Array.isArray(source) && source.length === 0 || typeof source === "object" && !Array.isArray(source) && Object.keys(source).length === 0;
57378
57379
  if (input2.draft !== void 0) {
57379
57380
  const draftIds = [...new Set(input2.draft.match(CANONICAL_ID_INLINE) ?? [])];
57380
57381
  groundedIds = draftIds.filter((id) => out.ids.has(id)).sort();
@@ -57384,6 +57385,10 @@ var init_synthesize_answer = __esm({
57384
57385
  const absenceClaims = findAbsenceClaims(input2.draft);
57385
57386
  ungroundedAbsenceClaims = out.coverageIncomplete ? absenceClaims : [];
57386
57387
  grounded = ungroundedAbsenceClaims.length === 0;
57388
+ if (evidenceEmpty) {
57389
+ grounded = false;
57390
+ out.caveats.unshift("GROUNDING NOT VERIFIED: no evidence was supplied in `input`, so the draft was not checked against any tool output. Do NOT present it as grounded \u2014 pass the prior sfi.* tool result(s) as `input` and retry.");
57391
+ }
57387
57392
  }
57388
57393
  const qPrefix = input2.question !== void 0 && input2.question.trim().length > 0 ? `Q: ${input2.question.trim()} \u2014 ` : "";
57389
57394
  const summary = `${qPrefix}Grounded in the supplied tool output: ${citations.length} component(s) cited, ${out.bullets.length} key fact(s), ${out.caveats.length} caveat(s)` + (hallucinatedIds !== void 0 ? `, ${hallucinatedIds.length} ungrounded id(s) in the draft` : "") + // I3c: only appended when a draft is present AND the guard fired, so the
@@ -65081,7 +65086,7 @@ var init_tools = __esm({
65081
65086
  },
65082
65087
  {
65083
65088
  name: "sfi.synthesize_answer",
65084
- description: "Answer-layer grounding pass: turns the JSON returned by prior sfi.* tool call(s) into a structured, citation-grounded answer skeleton \u2014 `summary`, `bullets` (headline facts extracted from the input), `citations` (ONLY canonical ids present in the input, parsed to type + apiName), and `caveats` (honesty/limitation strings carried verbatim; an input reduced by the global response byte budget \u2014 a `responseBudget` truncation block \u2014 becomes an explicit caveat with the dropped/trimmed counts, so a synthesis over truncated data never reads absence as evidence). It also returns a grounded `evidence` skeleton \u2014 `finding` \u2192 `evidence` (the cited ids) \u2192 `likelyCause` \u2192 `recommendedFix` \u2192 `risk` \u2192 `nextAction` \u2014 where every field is lifted VERBATIM from the source tool output (a `reason`/`recommendation`/`nextStep`/caveat field) and is `null` when the source carried nothing for it, so the recommended action is never fabricated; `nextAction` falls back to the recommended fix, and `orphanComponentIds` flags any id mentioned inside a cause/fix/next string that is not independently cited (an ungrounded reference). Pass the source tool output as `input` (any JSON), optionally the user `question` (echoed into the summary), and optionally a `draft` narrative \u2014 when given, `hallucinatedIds` lists canonical ids in the draft that do NOT appear in the source so they can be removed before answering. `provenance` rolls the source output(s) trust provenance up into `{ stamp, sources }` (`offline_snapshot` / `live_org` / `hybrid` when the input fuses both / `mixed` / `null`) so the host can stamp where the answer came from and never let a vault claim read as a live one. Pure transform: reads ONLY `input`, never the graph or live org, so it can never add a fact it was not handed. Prose wording stays with the caller; this guarantees grounding, not sentences.",
65089
+ description: "Answer-layer grounding pass: turns the JSON returned by prior sfi.* tool call(s) into a structured, citation-grounded answer skeleton \u2014 `summary`, `bullets` (headline facts extracted from the input), `citations` (ONLY canonical ids present in the input, parsed to type + apiName), and `caveats` (honesty/limitation strings carried verbatim; an input reduced by the global response byte budget \u2014 a `responseBudget` truncation block \u2014 becomes an explicit caveat with the dropped/trimmed counts, so a synthesis over truncated data never reads absence as evidence). It also returns a grounded `evidence` skeleton \u2014 `finding` \u2192 `evidence` (the cited ids) \u2192 `likelyCause` \u2192 `recommendedFix` \u2192 `risk` \u2192 `nextAction` \u2014 where every field is lifted VERBATIM from the source tool output (a `reason`/`recommendation`/`nextStep`/caveat field) and is `null` when the source carried nothing for it, so the recommended action is never fabricated; `nextAction` falls back to the recommended fix, and `orphanComponentIds` flags any id mentioned inside a cause/fix/next string that is not independently cited (an ungrounded reference). Pass the source tool output as `input` (any JSON), optionally the user `question` (echoed into the summary), and optionally a `draft` narrative \u2014 when given, `hallucinatedIds` lists canonical ids in the draft that do NOT appear in the source so they can be removed before answering. A `draft` supplied with an empty or missing `input` FAILS CLOSED to `grounded: false` with a caveat \u2014 grounding is never rubber-stamped when there is no evidence to check the draft against. `provenance` rolls the source output(s) trust provenance up into `{ stamp, sources }` (`offline_snapshot` / `live_org` / `hybrid` when the input fuses both / `mixed` / `null`) so the host can stamp where the answer came from and never let a vault claim read as a live one. Pure transform: reads ONLY `input`, never the graph or live org, so it can never add a fact it was not handed. Prose wording stays with the caller; this guarantees grounding, not sentences.",
65085
65090
  inputSchema: SYNTHESIZE_ANSWER_INPUT_SCHEMA
65086
65091
  },
65087
65092
  {
@@ -68015,7 +68020,7 @@ var init_package_version = __esm({
68015
68020
  "use strict";
68016
68021
  readCliPackageVersion = () => {
68017
68022
  if (true)
68018
- return "0.1.16";
68023
+ return "0.1.17";
68019
68024
  for (const rel of ["../package.json", "../../package.json"]) {
68020
68025
  try {
68021
68026
  const raw = readFileSync3(fileURLToPath(new URL(rel, import.meta.url)), "utf8");
@@ -137915,7 +137920,7 @@ var makeShutdownOnce = (ctx) => {
137915
137920
 
137916
137921
  // dist/src/commands/demo.js
137917
137922
  init_refresh();
137918
- var buildVersion = () => true ? "0.1.16" : "dev";
137923
+ var buildVersion = () => true ? "0.1.17" : "dev";
137919
137924
  var SHUTDOWN_SIGNALS2 = ["SIGINT", "SIGTERM"];
137920
137925
  var resolveDemoSource = () => {
137921
137926
  let dir = dirname21(fileURLToPath2(import.meta.url));
@@ -138889,7 +138894,7 @@ init_vault_git();
138889
138894
  init_watch();
138890
138895
  var readVersion = () => {
138891
138896
  if (true)
138892
- return "0.1.16";
138897
+ return "0.1.17";
138893
138898
  const pkgUrl = new URL("../../package.json", import.meta.url);
138894
138899
  const raw = readFileSync6(fileURLToPath3(pkgUrl), "utf8");
138895
138900
  const parsed = JSON.parse(raw);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sf-intelligence",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Offline-first, MCP-first knowledge base for a Salesforce org. Ask about your org's metadata, dependencies, permissions, and automation — grounded in real retrieved metadata. Ships the sfi CLI and an MCP server.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://salesforce-intelligence.pages.dev",
@@ -66,16 +66,16 @@
66
66
  "devDependencies": {
67
67
  "esbuild": "^0.28.0",
68
68
  "vitest": "^1.6.0",
69
+ "@sf-intelligence/contracts": "0.1.0",
69
70
  "@sf-intelligence/extractors": "0.1.0",
71
+ "@sf-intelligence/core": "0.1.0",
70
72
  "@sf-intelligence/graph": "0.1.0",
71
73
  "@sf-intelligence/parsers": "0.1.0",
72
- "@sf-intelligence/core": "0.1.0",
73
- "@sf-intelligence/patterns": "0.1.0",
74
- "@sf-intelligence/renderers": "0.1.0",
75
74
  "@sf-intelligence/tooling-api": "0.1.0",
76
75
  "@sf-intelligence/vault": "0.1.0",
76
+ "@sf-intelligence/renderers": "0.1.0",
77
77
  "@sf-intelligence/mcp": "0.1.0",
78
- "@sf-intelligence/contracts": "0.1.0"
78
+ "@sf-intelligence/patterns": "0.1.0"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsc --build && node build.mjs",
package/server.json CHANGED
@@ -7,13 +7,13 @@
7
7
  "url": "https://github.com/PranavNagrecha/Salesforce-Intelligence",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.1.16",
10
+ "version": "0.1.17",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "sf-intelligence",
16
- "version": "0.1.16",
16
+ "version": "0.1.17",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },