@ryanstark24/sfgraph-skills 1.1.4 → 1.6.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/package.json +3 -2
- package/skills/sf-cross-layer-trace/SKILL.md +16 -5
- package/skills/sf-cross-org-diff/SKILL.md +7 -1
- package/skills/sf-dead-code-audit/SKILL.md +10 -3
- package/skills/sf-debug-log-analysis/SKILL.md +107 -0
- package/skills/sf-debug-root-cause/SKILL.md +111 -0
- package/skills/sf-deployment-manifest/SKILL.md +13 -7
- package/skills/sf-explain-code/SKILL.md +16 -1
- package/skills/sf-find-similar/SKILL.md +10 -4
- package/skills/sf-flow-impact/SKILL.md +6 -0
- package/skills/sf-governor-risk-fix/SKILL.md +50 -10
- package/skills/sf-graph-plus-source/SKILL.md +46 -0
- package/skills/sf-graph-router/SKILL.md +146 -0
- package/skills/sf-impact-from-diff/SKILL.md +11 -5
- package/skills/sf-metadata-refresh/SKILL.md +9 -3
- package/skills/sf-omnistudio-migration-audit/SKILL.md +15 -5
- package/skills/sf-schema-overview/SKILL.md +8 -2
- package/skills/sf-security-audit/SKILL.md +14 -6
- package/skills/sf-snapshot-compare/SKILL.md +6 -0
- package/skills/sf-web-explorer/SKILL.md +6 -1
- package/skills/sf-what-broke/SKILL.md +28 -22
- package/skills/sf-wip-impact/SKILL.md +8 -0
- package/dist/__tests__/cursor-format.test.d.ts +0 -2
- package/dist/__tests__/cursor-format.test.d.ts.map +0 -1
- package/dist/__tests__/cursor-format.test.js +0 -44
- package/dist/__tests__/cursor-format.test.js.map +0 -1
- package/dist/__tests__/installer.test.d.ts +0 -2
- package/dist/__tests__/installer.test.d.ts.map +0 -1
- package/dist/__tests__/installer.test.js +0 -64
- package/dist/__tests__/installer.test.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanstark24/sfgraph-skills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"url": "https://github.com/ryanStark24/sfgraph"
|
|
23
23
|
},
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=22"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"description": "sfgraph SKILL.md playbooks for Cursor and Claude",
|
|
31
31
|
"files": [
|
|
32
32
|
"dist",
|
|
33
|
+
"!dist/**/__tests__",
|
|
33
34
|
"skills",
|
|
34
35
|
"README.md"
|
|
35
36
|
],
|
|
@@ -21,6 +21,10 @@ tools_used:
|
|
|
21
21
|
|
|
22
22
|
Use when the user needs to follow a single artifact (field, LWC, Apex method) across every layer it touches — UI rendering, Apex controller, flow automation, data model.
|
|
23
23
|
|
|
24
|
+
## Evidence rule — say it only if something backs it
|
|
25
|
+
|
|
26
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
27
|
+
|
|
24
28
|
## When to volunteer this skill
|
|
25
29
|
|
|
26
30
|
Source-only tools (file grep, repo search, `explain_code`) can answer "where is this used?" inside the sfdx-source repo, but they cannot see:
|
|
@@ -37,16 +41,17 @@ Only skip the offer when the user has explicitly scoped the question to source (
|
|
|
37
41
|
|
|
38
42
|
## Playbook
|
|
39
43
|
|
|
40
|
-
1. Resolve the starting node.
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
1. Resolve the starting node. `cross_layer_flow_map` walks **downstream only**, from an `entry` (LWC, Aura, page, Flow, Apex, OmniScript, FlexCard, Integration Procedure) toward the data it touches. A field or object entry reaches nothing.
|
|
45
|
+
- **"Where is this field / component used"** is an upstream question: call `analyze_field(object, field)` for a field's direct readers and writers, or `trace_upstream` on the component's qname for the pages and components that reach it. Then run step 2 from each UI or automation entry you found.
|
|
46
|
+
2. Call `cross_layer_flow_map(entry=…)` with the resolved entry. Receive ordered paths across layers (UI -> Controller -> Service -> Selector -> SObject and any Flow / Process Builder branches).
|
|
47
|
+
3. For each distinct path, summarise the layer transitions with the edge type that bridges them (`@wire`, `@AuraEnabled`, `READS_FIELD`, `WRITES_FIELD`, `FLOW_INVOKES_APEX`).
|
|
43
48
|
4. Surface anything anomalous: cycles, missing `with sharing`, fields read by multiple LWCs but written only by Flow, etc.
|
|
44
49
|
5. Render the Mermaid layered diagram from `cross_layer_flow_map`. If the graph has more than 30 nodes, ask whether to filter to a single layer pair.
|
|
45
50
|
6. End with a one-line recommendation of which related skill to invoke next (e.g. `sf-security-audit` if FLS gaps appear).
|
|
46
51
|
|
|
47
52
|
## Visualization
|
|
48
53
|
|
|
49
|
-
Render a **`flowchart TD`** layered diagram with one subgraph per layer (UI / Controller / Service / Selector / Data). Edges are labelled with the edge type that bridges layers (`@wire`, `@AuraEnabled`, `READS_FIELD`, `
|
|
54
|
+
Render a **`flowchart TD`** layered diagram with one subgraph per layer (UI / Controller / Service / Selector / Data). Edges are labelled with the edge type that bridges layers (`@wire`, `@AuraEnabled`, `READS_FIELD`, `WRITES_FIELD`, `FLOW_INVOKES_APEX`).
|
|
50
55
|
|
|
51
56
|
```
|
|
52
57
|
flowchart TD
|
|
@@ -65,8 +70,14 @@ flowchart TD
|
|
|
65
70
|
|
|
66
71
|
If the resolved trace has >30 nodes, ask the user to narrow to a single layer-pair before rendering — a sprawling layered diagram is more misleading than no diagram.
|
|
67
72
|
|
|
73
|
+
## Trace-tool noise defaults
|
|
74
|
+
|
|
75
|
+
If you drop down to `trace_upstream` / `trace_downstream` for a raw dependency walk, note they **hide security-grant and inferred edges by default**. A class granted to 100+ profiles, or a Vlocity node with reflection-walker string-name matches, would otherwise drown the real dependencies. The response tells you "N edges hidden". Only pass `include_security: true` for an access-centric question, or `include_inferred: true` when the user explicitly wants low-confidence reflection links. Use `rel_types: [...]` to pin a walk to specific relationships (e.g. `["CALLS","IS_TEST_FOR"]`). `cross_layer_flow_map` is unaffected — it already follows curated layer edges.
|
|
76
|
+
|
|
68
77
|
## Staleness check
|
|
69
78
|
|
|
79
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
80
|
+
|
|
70
81
|
Before calling `cross_layer_flow_map`, invoke `staleness_check` for the target org. If the report says stale, surface a warning to the user:
|
|
71
82
|
|
|
72
83
|
> Your ingest is N days old. Run `sfgraph ingest --org <alias>` to refresh, or proceed with the understanding that the graph may not reflect recent changes.
|
|
@@ -84,7 +95,7 @@ Then continue with the playbook.
|
|
|
84
95
|
## Don't
|
|
85
96
|
|
|
86
97
|
- Do not collapse layers — the value of this skill is showing the layer boundaries explicitly.
|
|
87
|
-
-
|
|
98
|
+
- `cross_layer_flow_map` has no depth parameter; if its map is too broad, narrow by starting from a nearer entry, or use `trace_downstream` with `depth`.
|
|
88
99
|
- Do not modify anything. Pure read.
|
|
89
100
|
- Do not assume the starting node exists; if `analyze_field` returns empty, ask the user to refine.
|
|
90
101
|
- Do not stop at a source-only answer for LWC / Aura / ApexPage / field / Apex method questions without at least *offering* the cross-layer trace. Repo grep misses FlexiPage bindings, Quick Action targets, and the Apex→SObject tail — say so and offer to fill it in.
|
|
@@ -18,10 +18,14 @@ tools_used:
|
|
|
18
18
|
|
|
19
19
|
Use when the user wants to understand drift between two orgs — typically pre-deploy verification or post-deploy reconciliation.
|
|
20
20
|
|
|
21
|
+
## Evidence rule — say it only if something backs it
|
|
22
|
+
|
|
23
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
24
|
+
|
|
21
25
|
## Playbook
|
|
22
26
|
|
|
23
27
|
1. Call `list_orgs` first. Present the user with the authenticated orgs, each org's `ingested` flag, last sync timestamp, and `stale` flag. Ask the user to pick the two orgs to compare. Refuse to proceed if either selected org has `ingested=false` — instruct them to run `sfgraph ingest --org <alias>` first.
|
|
24
|
-
2. Call `cross_org_diff(
|
|
28
|
+
2. Call `cross_org_diff(org_a, org_b)` (optionally `category`). Capture added / removed / modified nodes grouped by metadata category. Managed-package and standard items found in one org only are hidden by default and counted in the report; pass `include_managed: true` / `include_standard: true` only when the user asks about them.
|
|
25
29
|
3. For high-churn categories, call `point_in_time_diff` inside each org to confirm the drift originated there (vs being a stale snapshot artifact).
|
|
26
30
|
4. Categorise drift: **structural** (new objects/fields), **logic** (Apex, Flow body changes), **security** (profile / sharing), **config** (custom metadata / settings).
|
|
27
31
|
5. Render the Mermaid drift summary from the tool. For each category, list the top-N items by impact.
|
|
@@ -48,6 +52,8 @@ For diffs with >50 nodes, switch to a bucketed table per category and skip the d
|
|
|
48
52
|
|
|
49
53
|
## Staleness check
|
|
50
54
|
|
|
55
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
56
|
+
|
|
51
57
|
Before calling `cross_org_diff`, invoke `staleness_check` for both orgs. If either is stale, surface a warning to the user:
|
|
52
58
|
|
|
53
59
|
> Your ingest for `<alias>` is N days old. Run `sfgraph ingest --org <alias>` to refresh, or proceed with the understanding that the graph may not reflect recent changes.
|
|
@@ -19,16 +19,21 @@ tools_used:
|
|
|
19
19
|
|
|
20
20
|
Use when the user wants to inventory metadata that appears unreferenced. Output must be bucketed by confidence — deletion in Salesforce is reversible only via backup, so we communicate uncertainty.
|
|
21
21
|
|
|
22
|
+
## Evidence rule — say it only if something backs it
|
|
23
|
+
|
|
24
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
25
|
+
|
|
22
26
|
## Playbook
|
|
23
27
|
|
|
24
|
-
1. Call `dead_code_audit`
|
|
25
|
-
|
|
28
|
+
1. Call `dead_code_audit` for the org. The tool **summarizes by confidence (`high`/`medium`/`low`) and by metadata type**, then renders a capped list (`limit`, default 50). On a large org there can be thousands of candidates — do NOT try to retrieve them all inline; work from the summary counts and drill in with `confidence: "high"` (most-likely-dead first) or raise `limit`. For the complete machine-readable set, use `export_sarif`. Each row carries a score + reasons (`no_incoming_edges`, `test_class` — an `@isTest` class nothing references, flagged `isTest: true`, `stale_freshness`). Test references count as references: production code that only tests reference is not dead and is listed apart in `referencedOnlyByTests` (reason `referenced_only_by_tests`); deleting it means deleting those tests too.
|
|
29
|
+
- **Unused fields:** call `dead_code_audit(label="CustomField")` (optionally `pattern="CustomField:Account.*"`). It lists fields that nothing reads or writes. A field on a page layout or in a report still counts as used; profile and permission-set access does not. Fields have no freshness score, so there is no confidence grade: treat each one as **likely-dead** until checked.
|
|
30
|
+
2. Confidence already reflects last-modified dates (`stale_freshness`). `freshness_report` is an org-wide view of what changed recently (20 rows per bucket); it cannot be filtered to the candidates, so use it only for context, not per candidate.
|
|
26
31
|
3. For any candidate the user names interactively, call `trace_upstream` to confirm absence of indirect callers (dynamic Apex, Flow lookups, callable interfaces). Optionally call `find_similar(qname=<candidate>, k=5)` — if the candidate has near-neighbours (similarity > 0.6) that ARE referenced, the candidate may be a copy-paste duplicate of live code and worth deleting; if every neighbour is also in the dead list, you've found a whole disused subsystem worth flagging as a group.
|
|
27
32
|
4. Sort candidates into three buckets:
|
|
28
33
|
- **confident-dead** — no incoming edges, no dynamic-invocation signature match, freshness > 12 months, no inclusion in active permission sets / page layouts.
|
|
29
34
|
- **likely-dead** — no incoming edges, but at least one weak signal (recently modified, referenced from a managed package boundary, or named in a metadata file we don't parse fully).
|
|
30
35
|
- **suspicious-uncertain** — looks dead but the graph has known blind spots (dynamic SOQL string-interpolated field name, reflection-style `Type.forName`, external system reference).
|
|
31
|
-
5. Render
|
|
36
|
+
5. Render a bar-chart / treemap as Mermaid yourself, grouped by category, by counting the candidates the report lists (each line names its kind and confidence). The tool does not draw a diagram.
|
|
32
37
|
6. For confident-dead items, propose a destructive-changes.xml snippet but do not save it. The user owns the delete decision.
|
|
33
38
|
|
|
34
39
|
## Visualization
|
|
@@ -50,6 +55,8 @@ When the org has >100 dead candidates, drop the diagram and rely on the per-buck
|
|
|
50
55
|
|
|
51
56
|
## Staleness check
|
|
52
57
|
|
|
58
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
59
|
+
|
|
53
60
|
Before calling `dead_code_audit`, invoke `staleness_check` for the target org. Stale ingests make dead-code analysis dangerously wrong (a recently-added caller would be invisible). If the report says stale, surface a warning to the user:
|
|
54
61
|
|
|
55
62
|
> Your ingest is N days old. Run `sfgraph ingest --org <alias>` to refresh, or proceed with the understanding that the graph may not reflect recent changes.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sf-debug-log-analysis
|
|
3
|
+
description: Read and analyse a Salesforce Apex debug log — exceptions/FATAL_ERROR, governor-limit consumption (SOQL/DML/CPU/heap), the execution call tree, and slow or repeated code units — then ground every finding in the org graph (map the log's code units/methods to qnames and explain WHY with trace/governor/analyze_field). Use when the user pastes or points to a debug log, an `sf apex get log` output, or asks to interpret a System.debug / stack trace / "Too many SOQL queries" / CPU-time log. Pairs with sf-debug-root-cause (log = symptom, graph = cause).
|
|
4
|
+
triggers:
|
|
5
|
+
- "debug log"
|
|
6
|
+
- "read this log"
|
|
7
|
+
- "analyze this log"
|
|
8
|
+
- "apex log"
|
|
9
|
+
- "Too many SOQL queries"
|
|
10
|
+
- "Apex CPU time limit"
|
|
11
|
+
- "System.debug output"
|
|
12
|
+
- "FATAL_ERROR"
|
|
13
|
+
- "LIMIT_USAGE"
|
|
14
|
+
- "sf apex get log"
|
|
15
|
+
- "stack trace from the log"
|
|
16
|
+
tools_used:
|
|
17
|
+
- find_nodes
|
|
18
|
+
- explain_code
|
|
19
|
+
- trace_upstream
|
|
20
|
+
- trace_downstream
|
|
21
|
+
- analyze_field
|
|
22
|
+
- governor_risk_check
|
|
23
|
+
- staleness_check
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# sf-debug-log-analysis
|
|
27
|
+
|
|
28
|
+
A Salesforce debug log is the ground truth of what *actually executed* — but on its own
|
|
29
|
+
it's a wall of pipe-delimited lines and it can't tell you *why* (what other code calls the
|
|
30
|
+
slow method, where the in-loop SOQL is declared, what writes the field that reverted).
|
|
31
|
+
This skill reads the log, extracts the signal, and **grounds each finding in the org graph**
|
|
32
|
+
so the answer is "the CPU went here because `OrderTriggerHandler.recalc` runs a SOQL inside
|
|
33
|
+
a `for` over `Trigger.new` — here are its 3 callers", not "looks like a CPU issue".
|
|
34
|
+
|
|
35
|
+
Format reference: <https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_debugging_debug_log.htm>
|
|
36
|
+
|
|
37
|
+
## Evidence rule — say it only if something backs it
|
|
38
|
+
|
|
39
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
40
|
+
|
|
41
|
+
## Getting the log (if the user hasn't supplied one)
|
|
42
|
+
|
|
43
|
+
- Salesforce CLI: `sf apex list log` → `sf apex get log --log-id <id> > debug.log`, or live: `sf apex tail log --color none`.
|
|
44
|
+
- Setup → Debug Logs (trace flags on the user), then download.
|
|
45
|
+
- Tell the user the log level matters: `Apex Code = FINE`/`FINER` captures method entry/exit and SOQL; `Apex Profiling`/`System = FINE` captures the `CUMULATIVE_LIMIT_USAGE` block. `FINEST` is huge and often truncated at the 20 MB cap — prefer `FINE`/`FINER` unless you need variable-level detail.
|
|
46
|
+
|
|
47
|
+
## Reading the log (format)
|
|
48
|
+
|
|
49
|
+
The header line lists the API version + per-category log levels. Every subsequent line is
|
|
50
|
+
`HH:mm:ss.SSS (elapsedNanos)|EVENT_TYPE|details`. The event types that carry signal:
|
|
51
|
+
|
|
52
|
+
| Event | What it tells you |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `CODE_UNIT_STARTED` / `_FINISHED` | The unit boundaries — triggers, `Class.method`, flows, VF, anonymous. Top of the call tree. |
|
|
55
|
+
| `METHOD_ENTRY` / `METHOD_EXIT` | Method call tree (needs Apex Code ≥ FINER). Indentation/elapsed time = where time goes. |
|
|
56
|
+
| `SOQL_EXECUTE_BEGIN` / `_END` | Each query + `Rows:` returned + aggregations. **Count them** — repeated identical SOQL = in-loop. |
|
|
57
|
+
| `SOSL_EXECUTE_*`, `DML_BEGIN` / `_END` | SOSL and DML operations + row counts. |
|
|
58
|
+
| `CALLOUT_REQUEST` / `_RESPONSE` | HTTP callouts + endpoints + timing. |
|
|
59
|
+
| `EXCEPTION_THROWN` | The thrown exception + type + the offending `Class.method: line`. |
|
|
60
|
+
| `FATAL_ERROR` | The uncaught error + full Apex stack trace — the prime anchor for a failure. |
|
|
61
|
+
| `USER_DEBUG` | `System.debug()` output the developer planted. |
|
|
62
|
+
| `LIMIT_USAGE_FOR_NS` / `CUMULATIVE_LIMIT_USAGE` | **The governor scorecard** — SOQL queries, query rows, DML statements/rows, CPU time, heap, callouts used vs limit. |
|
|
63
|
+
| `HEAP_ALLOCATE`, `STATEMENT_EXECUTE`, `VARIABLE_*` | FINEST-only, very noisy — skip unless chasing a heap/variable bug. |
|
|
64
|
+
| `FLOW_*` / `WF_*` | Flow elements and Workflow-rule evaluation (order-of-execution bugs). |
|
|
65
|
+
|
|
66
|
+
## Method
|
|
67
|
+
|
|
68
|
+
1. **If the log is large, filter before reading.** Don't load a 20 MB log into context. Grep for the signal first:
|
|
69
|
+
`grep -nE 'FATAL_ERROR|EXCEPTION_THROWN|CUMULATIVE_LIMIT_USAGE|LIMIT_USAGE_FOR_NS' debug.log` for failures + limits;
|
|
70
|
+
`grep -c 'SOQL_EXECUTE_BEGIN' debug.log` for query count;
|
|
71
|
+
`grep -E 'CODE_UNIT_(STARTED|FINISHED)' debug.log` for the unit skeleton.
|
|
72
|
+
Read only the relevant slices.
|
|
73
|
+
2. **Classify the problem** from the evidence: an uncaught failure (`FATAL_ERROR`), a governor breach (limit at/over 100% in the cumulative block, or a `System.LimitException`), a performance issue (one `CODE_UNIT` dominating elapsed time), or just `USER_DEBUG` tracing.
|
|
74
|
+
3. **Extract the anchor:**
|
|
75
|
+
- Failure → the exception type + the top in-org frame `Class.method: line` from the stack trace.
|
|
76
|
+
- Governor → which limit, the count vs cap, and the `CODE_UNIT`/method where consumption spiked (repeated SOQL/DML lines under one unit).
|
|
77
|
+
- Performance → the `CODE_UNIT`/method with the largest elapsed delta.
|
|
78
|
+
4. **Ground it in the graph** (the part a log reader alone can't do):
|
|
79
|
+
- `find_nodes ApexClass:<Name>` / `ApexMethod:<Name>.*` to resolve the anchor to a qname; `explain_code` reads stored source for Apex methods, trigger bodies (`ApexTrigger:<Name>`), and Flows (`Flow:<Name>`). For a **whole class, LWC JS, or managed code the graph has no source** — fetch it (local `force-app/main/default/{classes,triggers,flows}/...` or `sf project retrieve start -m "ApexTrigger:<Name>"`); don't analyse from an empty stub. See `sf-explain-code`.
|
|
80
|
+
- `trace_upstream` — who invokes this unit, and in what context (trigger vs batch vs LWC). Order-of-execution and "why was this even called" answers live here.
|
|
81
|
+
- `trace_downstream` — what it calls/reads/writes; a NullPointer or limit usually originates in a callee.
|
|
82
|
+
- Governor breach → `governor_risk_check` (it scans the whole org; keep the findings for that class) to find the in-loop query or DML the log proved is hot. Its evidence is the query text or DML target, not a line number.
|
|
83
|
+
- Field misbehaviour seen in the log → `analyze_field` for every trigger/Flow/validation that fires on that field (competing automation).
|
|
84
|
+
5. **State a single root-cause hypothesis** backed by *both* the log evidence and the graph evidence, then hand the fix to the right design skill (`sf-architect-apex` / `sf-architect-performance` / `sf-governor-risk-fix`) — grounded, never generic.
|
|
85
|
+
|
|
86
|
+
## Staleness
|
|
87
|
+
|
|
88
|
+
If you'll ground in the graph, call `staleness_check` first. A stale graph maps the log's
|
|
89
|
+
code units to outdated source — warn and recommend `sfgraph ingest --org <alias>`. The log
|
|
90
|
+
itself is always current; the mismatch is on the graph side.
|
|
91
|
+
|
|
92
|
+
## Response shape
|
|
93
|
+
|
|
94
|
+
- **Verdict** — one line: failure / governor breach / performance / trace-only, with the anchor `Class.method:line`.
|
|
95
|
+
- **Log evidence** — the decisive lines (exception, the cumulative-limit row that breached, the repeated SOQL count, the dominant code unit) — quote them, don't paraphrase.
|
|
96
|
+
- **Graph grounding** — callers, callees, competing automation, or the in-loop source line that explains the log.
|
|
97
|
+
- **Root cause** — one hypothesis, confidence, tied to both evidence sources.
|
|
98
|
+
- **Fix** — described and handed off to a design skill; not auto-applied.
|
|
99
|
+
- **Mermaid** — optional call-tree or caller→unit→callee path when it clarifies.
|
|
100
|
+
|
|
101
|
+
## Don't
|
|
102
|
+
|
|
103
|
+
- Don't load a multi-MB log wholesale — filter with grep first, then read slices. Say what you filtered so nothing looks silently dropped.
|
|
104
|
+
- Don't stop at the log. The log shows *what*; grounding in the graph shows *why* — that's the value. A log-only answer is a guess about the cause.
|
|
105
|
+
- Don't trust `FINEST` noise (`STATEMENT_EXECUTE`/`VARIABLE_ASSIGNMENT`) as signal — anchor on CODE_UNIT/SOQL/DML/limit/exception events.
|
|
106
|
+
- Don't edit code here — produce evidence + root cause; design hands off.
|
|
107
|
+
- Don't confuse a logged, *caught* `EXCEPTION_THROWN` with the actual failure — the uncaught `FATAL_ERROR` (if present) is the one that ended the transaction.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sf-debug-root-cause
|
|
3
|
+
description: Root-cause a SPECIFIC Salesforce failure — an Apex exception or stack trace, a failing test, a flow fault, or "this field/record isn't behaving right" — by grounding the symptom in the org graph (callers, callees, recent changes, automation on the object, test coverage). Use when the user reports a concrete error/symptom and wants to know WHY. For "what changed since deploy" broadly use sf-what-broke; for pre-commit blast radius use sf-wip-impact.
|
|
4
|
+
triggers:
|
|
5
|
+
- "why is this failing"
|
|
6
|
+
- "debug this error"
|
|
7
|
+
- "this test fails"
|
|
8
|
+
- "stack trace"
|
|
9
|
+
- "NullPointerException"
|
|
10
|
+
- "System.LimitException"
|
|
11
|
+
- "this trigger isn't firing"
|
|
12
|
+
- "field isn't updating"
|
|
13
|
+
- "flow fault"
|
|
14
|
+
- "root cause"
|
|
15
|
+
tools_used:
|
|
16
|
+
- find_nodes
|
|
17
|
+
- explain_code
|
|
18
|
+
- trace_upstream
|
|
19
|
+
- trace_downstream
|
|
20
|
+
- analyze_field
|
|
21
|
+
- what_broke
|
|
22
|
+
- test_gap_intelligence_from_git_diff
|
|
23
|
+
- staleness_check
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# sf-debug-root-cause
|
|
27
|
+
|
|
28
|
+
Use when the user has a **concrete failure** and wants the cause, not a guess. Salesforce
|
|
29
|
+
failures are rarely in the one method that threw — they come from another trigger on the
|
|
30
|
+
same object, a recent change upstream, an order-of-execution surprise, or automation the
|
|
31
|
+
developer forgot exists. The graph makes those visible. Debug by narrowing with evidence,
|
|
32
|
+
never by pattern-matching the error message to a generic fix.
|
|
33
|
+
|
|
34
|
+
## Evidence rule — say it only if something backs it
|
|
35
|
+
|
|
36
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
37
|
+
|
|
38
|
+
## Method (scientific, evidence-first)
|
|
39
|
+
|
|
40
|
+
0. **If a debug log is available, start there.** A debug log is the strongest anchor — it
|
|
41
|
+
has the exact `FATAL_ERROR` stack frame and the real governor scorecard. Hand the log to
|
|
42
|
+
**`sf-debug-log-analysis`** to extract the anchor + limit evidence, then continue this
|
|
43
|
+
playbook from step 2 with that anchor. Without a log, anchor from the error text/symptom:
|
|
44
|
+
|
|
45
|
+
1. **Anchor the symptom to a node.** Parse the error / test name / symptom for the failing
|
|
46
|
+
unit and resolve its qname:
|
|
47
|
+
- Apex class/method in the trace → `find_nodes ApexClass:<Name>` / `ApexMethod:<Name>.*`.
|
|
48
|
+
- Failing test → the test method, then its `IS_TEST_FOR` target.
|
|
49
|
+
- "Field X isn't updating" → `analyze_field` on `<Object>.<Field>`.
|
|
50
|
+
If you can't anchor it, ask the user for the class/object name — don't guess.
|
|
51
|
+
|
|
52
|
+
2. **Read the failing unit.** `explain_code(qname=…)` reads stored source for Apex methods
|
|
53
|
+
(`ApexMethod:…`), trigger bodies (`ApexTrigger:…`), and Flows (`Flow:…`). For a **whole
|
|
54
|
+
class, LWC JS, or managed/`(hidden)` code the graph has no source** — fetch it: read the local
|
|
55
|
+
sfdx file (`force-app/main/default/{classes,triggers,flows}/<Name>.{cls,trigger,flow-meta.xml}`)
|
|
56
|
+
or `sf project retrieve start -m "ApexTrigger:<Name>"`. See `sf-explain-code` for the full
|
|
57
|
+
fallback. Confirm the trace's line maps to a real branch (SOQL, DML, deref).
|
|
58
|
+
|
|
59
|
+
3. **Look outward for the real cause — this is where graphs beat grep:**
|
|
60
|
+
- `trace_downstream(qname)` — what it calls / reads / writes. A `System.NullPointer` or
|
|
61
|
+
`LimitException` usually originates in a callee or a SOQL/DML it triggers.
|
|
62
|
+
- `trace_upstream(qname)` — who invokes it, and with what context (trigger vs batch vs
|
|
63
|
+
LWC). Order-of-execution bugs hide here.
|
|
64
|
+
- For an object symptom: `sf-flow-impact` / `analyze_field` — every trigger, Flow,
|
|
65
|
+
Process Builder, and validation rule that fires on the object. "Trigger isn't firing"
|
|
66
|
+
and "field reverts" are almost always a competing automation.
|
|
67
|
+
- **If the cause depends on actual data** (a field's real value, a CMDT/setting the code
|
|
68
|
+
reads, a record-type/picklist value, data skew) and the graph doesn't hold it, pull it
|
|
69
|
+
from the org — config/metadata records freely (`sf data query … FROM <Type>__mdt`), live
|
|
70
|
+
business records only as a small bounded `LIMIT` sample (real/PII data — see
|
|
71
|
+
`sf-graph-router` → "When the graph doesn't hold what the analysis needs").
|
|
72
|
+
- Governor `LimitException` → hand to `sf-governor-risk-fix` scoped to the class to find
|
|
73
|
+
the SOQL/DML-in-loop.
|
|
74
|
+
|
|
75
|
+
4. **Check what recently changed.** `sf-what-broke` (or `what_broke`) for the org since the
|
|
76
|
+
last deploy/ingest — if the failing node or any node it depends on changed recently,
|
|
77
|
+
that's your prime suspect. Correlate the failure's first-seen time with the change.
|
|
78
|
+
|
|
79
|
+
5. **Check test coverage of the suspect path** — `test_gap_intelligence_from_git_diff` (if a
|
|
80
|
+
diff exists) or the `IS_TEST_FOR` edges — a path with no test is where regressions live.
|
|
81
|
+
|
|
82
|
+
6. **State a single hypothesis, then confirm it** against the graph before recommending a
|
|
83
|
+
fix. "I think X because the graph shows Y." If the evidence doesn't support it, form a
|
|
84
|
+
new hypothesis — don't stack speculative fixes.
|
|
85
|
+
|
|
86
|
+
## Staleness check
|
|
87
|
+
|
|
88
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
89
|
+
|
|
90
|
+
Call `staleness_check` first. A stale graph misleads root-cause analysis (the change that
|
|
91
|
+
caused the bug may not be ingested yet). If stale, warn and recommend
|
|
92
|
+
`sfgraph ingest --org <alias>` before trusting the upstream/recent-change steps.
|
|
93
|
+
|
|
94
|
+
## Response shape
|
|
95
|
+
|
|
96
|
+
- **Symptom** — the error/test/behaviour, anchored to a qname.
|
|
97
|
+
- **Evidence chain** — the graph facts that narrow the cause (callers, callees, competing
|
|
98
|
+
automation, recent changes, coverage gaps), each tied to the tool that surfaced it.
|
|
99
|
+
- **Root-cause hypothesis** — one, with the supporting evidence. Confidence level.
|
|
100
|
+
- **Recommended fix** — described, not auto-applied; hand to `sf-architect-apex` /
|
|
101
|
+
`sf-architect-ui` / `sf-governor-risk-fix` to design it, grounded in this evidence.
|
|
102
|
+
- **Mermaid** — optional: the failing path (caller → unit → callee/field) when it clarifies.
|
|
103
|
+
|
|
104
|
+
## Don't
|
|
105
|
+
|
|
106
|
+
- Don't propose a fix before anchoring the symptom to a real node and reading its source.
|
|
107
|
+
- Don't ignore competing automation — on object symptoms it's the most common root cause and
|
|
108
|
+
the thing a stack trace alone never shows.
|
|
109
|
+
- Don't stack multiple speculative fixes; one hypothesis, confirmed, at a time.
|
|
110
|
+
- Don't edit code here — root-cause + evidence is the deliverable; design hands off.
|
|
111
|
+
- Don't trust a stale graph for "what recently changed" without flagging it.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-deployment-manifest
|
|
3
|
-
description: Generate
|
|
3
|
+
description: Generate package.xml and destructiveChanges.xml from the difference between two ingested orgs. The tool adds no dependencies; extra ones are added by hand with the user.
|
|
4
4
|
triggers:
|
|
5
5
|
- "deployment manifest"
|
|
6
6
|
- "package.xml"
|
|
@@ -17,18 +17,22 @@ tools_used:
|
|
|
17
17
|
|
|
18
18
|
Use when the user wants a `package.xml` that captures a set of changes plus everything they transitively depend on for a successful deploy.
|
|
19
19
|
|
|
20
|
+
## Evidence rule — say it only if something backs it
|
|
21
|
+
|
|
22
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
23
|
+
|
|
20
24
|
## Playbook
|
|
21
25
|
|
|
22
26
|
1. Establish the source and target orgs. The tool's contract today is a strict cross-org diff: it inputs `from_org` (source) and `to_org` (target) and emits the metadata that exists in `from_org` but is missing or different in `to_org` (plus a `destructiveChanges.xml` for things present only in `to_org`).
|
|
23
27
|
2. Optionally call `cross_org_diff` first to preview the set difference before generating the manifest XML.
|
|
24
|
-
3. Call `deployment_manifest_gen` with `from_org` + `to_org` (+ optional `category` filter). The tool does
|
|
25
|
-
4.
|
|
28
|
+
3. Call `deployment_manifest_gen` with `from_org` + `to_org` (+ optional `category` filter). The tool does not walk dependency edges: it returns the set difference as `package.xml` / `destructiveChanges.xml`, and the user is responsible for any parent metadata the diff does not surface. Managed-package and standard items found in one org only are left out of both files by default and named in the report; pass `include_managed: true` / `include_standard: true` only when the user asks for them.
|
|
29
|
+
4. Surface the report's notes as warnings: items left out because they have no deployment type, items hidden as managed or standard, and an incomplete comparison. Go through every `destructiveChanges.xml` member with the user before they deploy it.
|
|
26
30
|
5. Emit the `package.xml` inside a fenced code block. Also emit `destructiveChanges.xml` if the diff includes removals.
|
|
27
31
|
6. If extra dependencies are needed beyond the raw diff, ask the user to extend the set manually — do not silently fabricate dependency edges the graph doesn't have.
|
|
28
32
|
|
|
29
|
-
## Visualization
|
|
33
|
+
## Visualization (optional — you build it)
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
`deployment_manifest_gen` returns only the package.xml / destructiveChanges.xml (plus an `incomplete` block flagging dropped/truncated members) — it does NOT return a diagram or walk dependency edges. If a visual helps, render a **`flowchart LR`** closure graph YOURSELF from the manifest's member list: the user's explicit change set is one subgraph; any dependencies you add manually are another. Edge labels carry the dependency reason (`parent-of`, `layout-for`, `required-permission`).
|
|
32
36
|
|
|
33
37
|
```
|
|
34
38
|
flowchart LR
|
|
@@ -47,6 +51,8 @@ If the closure expands past 60 nodes, summarise per metadata type and only rende
|
|
|
47
51
|
|
|
48
52
|
## Staleness check
|
|
49
53
|
|
|
54
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
55
|
+
|
|
50
56
|
Before calling `deployment_manifest_gen`, invoke `staleness_check` for the source org. A stale graph means missing dependencies in the manifest, which fail at deploy time. If the report says stale, surface a warning to the user:
|
|
51
57
|
|
|
52
58
|
> Your ingest is N days old. Run `sfgraph ingest --org <alias>` to refresh, or proceed with the understanding that the graph may not reflect recent changes.
|
|
@@ -56,11 +62,11 @@ Then continue with the playbook.
|
|
|
56
62
|
## Response Shape
|
|
57
63
|
|
|
58
64
|
- **Source set** — what was requested.
|
|
59
|
-
- **
|
|
65
|
+
- **Manual additions** — dependencies the user chose to add (the tool adds none), grouped by metadata type.
|
|
60
66
|
- **Warnings** — managed-package / namespace / ambiguous-dependency notes.
|
|
61
67
|
- **package.xml** — fenced code block.
|
|
62
68
|
- **destructiveChanges.xml** — fenced code block (only if applicable).
|
|
63
|
-
- **Mermaid dependency graph** —
|
|
69
|
+
- **Mermaid dependency graph** — optional, drawn by you (see Visualization).
|
|
64
70
|
|
|
65
71
|
## Don't
|
|
66
72
|
|
|
@@ -20,11 +20,23 @@ tools_used:
|
|
|
20
20
|
|
|
21
21
|
Use this skill when the user wants a plain-English explanation of a specific code unit (an Apex method, an LWC handler, a trigger body). It reads the stored source via the graph's snippet store, generates an annotated explanation, and caches that explanation back so the next caller gets it for free.
|
|
22
22
|
|
|
23
|
+
## Evidence rule — say it only if something backs it
|
|
24
|
+
|
|
25
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
26
|
+
|
|
23
27
|
## Playbook
|
|
24
28
|
|
|
25
|
-
1. **Resolve the target qname.**
|
|
29
|
+
1. **Resolve the target qname.** Snippets are stored for Apex methods (`ApexMethod:AccountSvc.calculate(N)`, N = arity), Apex triggers (`ApexTrigger:AccountTrigger`) and Flows (`Flow:Lead_Router`, the Flow XML). A class qname like `ApexClass:AccountSvc` has no snippet of its own (it returns "No snippet stored"): enumerate its methods with `find_nodes(pattern="ApexMethod:AccountSvc.*")` and either pick the method the user meant or explain each in turn. For fields and objects there is no snippet: redirect to `analyze_field` / `sf-cross-layer-trace` instead. If the arity is unknown or the name is ambiguous, use `find_nodes` to enumerate candidates and confirm with the user.
|
|
26
30
|
2. **`staleness_check`** for the linked org. If stale, surface a warning so the user knows the cached source may not reflect production.
|
|
27
31
|
3. **`explain_code(qname=X)`** — pull the stored snippet and any prior cached explanation. The tool returns the source text in a fenced code block.
|
|
32
|
+
- **If the graph doesn't have the full source, FETCH it — don't explain from a stub.** The ingest stores source for Apex methods, Apex triggers and Flows, and **nothing for managed/`(hidden)` code**. When `explain_code` returns "No snippet stored" or an empty body, or you need a whole class, get the real source in this order:
|
|
33
|
+
1. **Local sfdx working tree** (fastest, reflects un-deployed changes) — read the file directly:
|
|
34
|
+
- Apex class → `force-app/main/default/classes/<Name>.cls`
|
|
35
|
+
- Apex trigger → `force-app/main/default/triggers/<Name>.trigger`
|
|
36
|
+
- Flow → `force-app/main/default/flows/<Name>.flow-meta.xml`
|
|
37
|
+
(the package dir may differ — check `packageDirectories` in `sfdx-project.json`).
|
|
38
|
+
2. **Retrieve from the org** when there's no local copy: `sf project retrieve start -m "ApexTrigger:<Name>"` (or `ApexClass:<Name>` / `Flow:<Name>`), then read the retrieved file. For an Apex body without a project, `sf data query --use-tooling-api -q "SELECT Body FROM ApexClass WHERE Name='<Name>'"` (or `ApexTrigger`).
|
|
39
|
+
- State which source you used (graph snippet / local file / org retrieve) so the reader knows whether it reflects production or local edits.
|
|
28
40
|
4. **Generate the explanation**, structured as:
|
|
29
41
|
- **One-paragraph summary**: what the method does at a high level.
|
|
30
42
|
- **Annotated source block**: re-emit the source with terse `// → ...` comments after each conditional branch and each loop. Keep comments to one line.
|
|
@@ -47,6 +59,8 @@ flowchart TD
|
|
|
47
59
|
|
|
48
60
|
## Staleness check
|
|
49
61
|
|
|
62
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
63
|
+
|
|
50
64
|
Before reading the snippet, call `staleness_check` for the org. If the ingest is stale:
|
|
51
65
|
|
|
52
66
|
> Your ingest is N days old. The source you're explaining may not match production. Run `sfgraph ingest --org <alias>` to refresh.
|
|
@@ -79,3 +93,4 @@ If the user says yes, hand off to `sf-find-similar` with mode=qname and the same
|
|
|
79
93
|
- Don't write anything to Salesforce.
|
|
80
94
|
- Always render the source inside a fenced code block tagged with the `sourceFormat` returned by `explain_code` (`apex`, `js`, `html`, etc.).
|
|
81
95
|
- Don't fabricate behaviour — if the source is empty or stubbed, say so plainly.
|
|
96
|
+
- Don't pass a class or field qname expecting source: only `ApexMethod:...(N)`, `ApexTrigger:...` and `Flow:...` have a snippet. On "No snippet stored" for a class, resolve to a method qname rather than reporting failure.
|
|
@@ -24,6 +24,10 @@ tools_used:
|
|
|
24
24
|
|
|
25
25
|
Use this skill when the user wants discovery rather than exact lookup: *"what other Apex methods are like this one"*, *"find code that handles order cancellation"*, *"is there anything similar to `accountTile`?"*. Powered by the in-process MiniLM-L6 embeddings sfgraph produces during every ingest.
|
|
26
26
|
|
|
27
|
+
## Evidence rule — say it only if something backs it
|
|
28
|
+
|
|
29
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
30
|
+
|
|
27
31
|
## When to choose this vs. the other tools
|
|
28
32
|
|
|
29
33
|
| Question shape | Use |
|
|
@@ -80,10 +84,12 @@ xychart-beta
|
|
|
80
84
|
|
|
81
85
|
## Common failure modes & how to handle them
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
+
The report says which case applies in plain words; the reason code below is only in the tool's structured data.
|
|
88
|
+
|
|
89
|
+
- **Search by meaning not set up** (`vector_index_unavailable`) — the org's graph was ingested before embeddings were wired up, or the optional `@ryanstark24/sfgraph-models` install was skipped. Tell the user verbatim what the tool's markdown suggests: re-install with `npm install -g @ryanstark24/sfgraph` and re-ingest with `--rebuild`.
|
|
90
|
+
- **No stored meaning for the qname** (`no_focal_vector`, qname mode) — the qname is wrong or its label isn't embedded. Confirm the qname spelling. If correct, suggest re-trying with `text` mode using the user's description of the node.
|
|
91
|
+
- **Model files missing** (`embedder_unavailable`, text mode) — the MiniLM runtime isn't present. Fall back to qname mode if the user can name a similar node.
|
|
92
|
+
- **Nothing similar** (`no_neighbours`) — genuinely no similar nodes. Suggest dropping the `label` filter, or running structural `trace_upstream` / `trace_downstream` instead.
|
|
87
93
|
|
|
88
94
|
## Response shape
|
|
89
95
|
|
|
@@ -17,6 +17,10 @@ tools_used:
|
|
|
17
17
|
|
|
18
18
|
Use when the user asks which automation references a specific field or object — typically before a field rename, type change, or deletion.
|
|
19
19
|
|
|
20
|
+
## Evidence rule — say it only if something backs it
|
|
21
|
+
|
|
22
|
+
State a fact about this org or the Salesforce platform **only when evidence backs it**: a tool/graph result, source you actually read (local sfdx file or an org fetch), a live org query, or official Salesforce documentation. If you don't have that, say so plainly — "the graph doesn't show this", "unverified", "I'd need to check the org" — and either go get the evidence or stop. **Never fill the gap with a plausible-sounding guess**: an invented field/method/object name, an assumed dependency, or a governor number recalled from memory. Label each claim as **graph-confirmed** (a tool returned it), **inferred** (you reasoned it from graph facts — say which facts), or **general Salesforce knowledge**. For platform behaviour — governor limits, order of execution, sharing/FLS semantics, API rules — cite the official doc (developer.salesforce.com; fetch it if unsure) instead of asserting from memory. If the graph is stale or the org was never ingested, lead with that caveat — your grounding may be wrong.
|
|
23
|
+
|
|
20
24
|
## Playbook
|
|
21
25
|
|
|
22
26
|
1. Resolve the target. Call `analyze_field` for a single field; for an SObject, list its fields first and ask the user to narrow if the scope is large.
|
|
@@ -44,6 +48,8 @@ If more than 20 flows reference the field, group leaves by entry-trigger type an
|
|
|
44
48
|
|
|
45
49
|
## Staleness check
|
|
46
50
|
|
|
51
|
+
If `staleness_check` is not available (the server runs with `SFGRAPH_TOOLS=core`), skip this step and say the graph's freshness was not checked.
|
|
52
|
+
|
|
47
53
|
Before calling `analyze_field`, invoke `staleness_check` for the target org. Newly-created or recently-modified Flows are invisible in a stale graph, which makes this skill produce false negatives. If the report says stale, surface a warning to the user:
|
|
48
54
|
|
|
49
55
|
> Your ingest is N days old. Run `sfgraph ingest --org <alias>` to refresh, or proceed with the understanding that the graph may not reflect recent changes.
|