@ryanstark24/sfgraph-skills 1.1.0 → 1.1.4
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/__tests__/installer.test.js +5 -5
- package/package.json +1 -1
- package/skills/sf-cross-layer-trace/SKILL.md +1 -8
- package/skills/sf-cross-org-diff/SKILL.md +5 -5
- package/skills/sf-dead-code-audit/SKILL.md +2 -1
- package/skills/sf-explain-code/SKILL.md +18 -3
- package/skills/sf-find-similar/SKILL.md +99 -0
- package/skills/sf-impact-from-diff/SKILL.md +7 -5
- package/skills/sf-snapshot-compare/SKILL.md +4 -4
- package/skills/sf-what-broke/SKILL.md +3 -3
- package/skills/sf-wip-impact/SKILL.md +5 -5
|
@@ -26,11 +26,11 @@ describe("skills installer", () => {
|
|
|
26
26
|
});
|
|
27
27
|
it("installs to the cursor target as .mdc files in Cursor's frontmatter shape", async () => {
|
|
28
28
|
const results = await install("cursor", { homeOverride: home });
|
|
29
|
-
expect(results.length).toBe(
|
|
29
|
+
expect(results.length).toBe(16);
|
|
30
30
|
const cursorDir = join(home, ".cursor", "rules");
|
|
31
31
|
const files = readdirSync(cursorDir);
|
|
32
32
|
expect(files.every((f) => f.endsWith(".mdc"))).toBe(true);
|
|
33
|
-
expect(files.length).toBe(
|
|
33
|
+
expect(files.length).toBe(16);
|
|
34
34
|
// Cursor-shaped frontmatter (the three keys Cursor's rule loader reads).
|
|
35
35
|
const sample = readFileSync(join(cursorDir, files[0] ?? ""), "utf8");
|
|
36
36
|
expect(sample).toMatch(/^description:/m);
|
|
@@ -48,9 +48,9 @@ describe("skills installer", () => {
|
|
|
48
48
|
const claudeCount = results.filter((r) => r.target === "claude").length;
|
|
49
49
|
const cursorCount = results.filter((r) => r.target === "cursor").length;
|
|
50
50
|
const vscodeCount = results.filter((r) => r.target === "vscode").length;
|
|
51
|
-
expect(claudeCount).toBe(
|
|
52
|
-
expect(cursorCount).toBe(
|
|
53
|
-
expect(vscodeCount).toBe(
|
|
51
|
+
expect(claudeCount).toBe(16);
|
|
52
|
+
expect(cursorCount).toBe(16);
|
|
53
|
+
expect(vscodeCount).toBe(16);
|
|
54
54
|
expect(existsSync(join(home, ".claude", "skills"))).toBe(true);
|
|
55
55
|
expect(existsSync(join(home, ".cursor", "rules"))).toBe(true);
|
|
56
56
|
});
|
package/package.json
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-cross-layer-trace
|
|
3
|
-
description: Trace a field, component, or method end-to-end across
|
|
3
|
+
description: Trace a Salesforce field, LWC/Aura/VF component, or method end-to-end across UI → Apex → Flow → SObject. Use when the user asks "where is X used" or wants the full call chain across layers. For a plain-English explanation of one code unit only, prefer sf-explain-code. For schema/ERD views of objects, prefer sf-schema-overview. May be offered as a follow-up after sf-explain-code completes on a UI artifact, but do not auto-invoke alongside it — let the user opt in.
|
|
4
4
|
triggers:
|
|
5
5
|
- "UI to DB"
|
|
6
6
|
- "trace this LWC"
|
|
7
7
|
- "end-to-end"
|
|
8
8
|
- "where is this field used"
|
|
9
9
|
- "where does this come from"
|
|
10
|
-
- "explain this LWC"
|
|
11
|
-
- "explain this component"
|
|
12
|
-
- "what does this component do"
|
|
13
|
-
- "what does this LWC do"
|
|
14
|
-
- "explain this Aura"
|
|
15
|
-
- "explain this VisualForce"
|
|
16
|
-
- "explain this ApexPage"
|
|
17
10
|
- "where is this component used"
|
|
18
11
|
- "what pages embed"
|
|
19
12
|
- "which pages use"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-cross-org-diff
|
|
3
|
-
description: Compare metadata between
|
|
3
|
+
description: Compare metadata between TWO DIFFERENT ORGS (sandbox vs prod, sandbox vs sandbox) and summarise configuration drift between them. Use only when the user names two orgs or clearly contrasts environments. For "what changed since deploy" in a single org use sf-what-broke; for comparing point-in-time snapshots of one org use sf-snapshot-compare.
|
|
4
4
|
triggers:
|
|
5
5
|
- "sandbox vs prod"
|
|
6
|
-
- "
|
|
7
|
-
- "org diff"
|
|
8
|
-
- "
|
|
9
|
-
- "
|
|
6
|
+
- "compare these two orgs"
|
|
7
|
+
- "org-to-org diff"
|
|
8
|
+
- "drift between orgs"
|
|
9
|
+
- "what's different between <orgA> and <orgB>"
|
|
10
10
|
tools_used:
|
|
11
11
|
- cross_org_diff
|
|
12
12
|
- point_in_time_diff
|
|
@@ -12,6 +12,7 @@ tools_used:
|
|
|
12
12
|
- freshness_report
|
|
13
13
|
- trace_upstream
|
|
14
14
|
- staleness_check
|
|
15
|
+
- find_similar
|
|
15
16
|
---
|
|
16
17
|
|
|
17
18
|
# sf-dead-code-audit
|
|
@@ -22,7 +23,7 @@ Use when the user wants to inventory metadata that appears unreferenced. Output
|
|
|
22
23
|
|
|
23
24
|
1. Call `dead_code_audit` over the user's chosen scope (entire org, single namespace, or one metadata category). Capture every candidate plus the evidence the tool used (no incoming edges, no inclusion in deploy manifests, etc.).
|
|
24
25
|
2. Call `freshness_report` to layer last-touched timestamps onto each candidate. Stale + unreferenced is stronger evidence than unreferenced alone.
|
|
25
|
-
3. For any candidate the user names interactively, call `trace_upstream` to confirm absence of indirect callers (dynamic Apex, Flow lookups, callable interfaces).
|
|
26
|
+
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.
|
|
26
27
|
4. Sort candidates into three buckets:
|
|
27
28
|
- **confident-dead** — no incoming edges, no dynamic-invocation signature match, freshness > 12 months, no inclusion in active permission sets / page layouts.
|
|
28
29
|
- **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).
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-explain-code
|
|
3
|
-
description: Explain
|
|
3
|
+
description: Explain a single Salesforce code unit (Apex method/class/trigger, LWC handler, Aura controller method) in plain English with conditional-branch annotation, then cache the explanation back to the sfgraph store. Salesforce metadata only — do NOT use for non-Salesforce code (e.g. Node, Python, ingest pipeline scripts) even when asked inside this repo. Scope is one named code unit; for end-to-end UI→DB tracing across layers use sf-cross-layer-trace, for whole-object schema views use sf-schema-overview.
|
|
4
4
|
triggers:
|
|
5
|
-
- "explain this method"
|
|
6
|
-
- "
|
|
5
|
+
- "explain this Apex method"
|
|
6
|
+
- "explain this trigger"
|
|
7
|
+
- "explain this LWC handler"
|
|
8
|
+
- "what does <ApexClass.method> do"
|
|
7
9
|
- "walk me through <qname>"
|
|
8
10
|
- "annotate the conditionals"
|
|
9
11
|
tools_used:
|
|
@@ -11,6 +13,7 @@ tools_used:
|
|
|
11
13
|
- trace_upstream
|
|
12
14
|
- trace_downstream
|
|
13
15
|
- staleness_check
|
|
16
|
+
- find_similar
|
|
14
17
|
---
|
|
15
18
|
|
|
16
19
|
# sf-explain-code
|
|
@@ -58,6 +61,18 @@ Continue the playbook either way; just flag the risk.
|
|
|
58
61
|
- **Mermaid** — only when conditional structure justifies it.
|
|
59
62
|
- **Cached** — confirm the explanation was cached back, with the qname.
|
|
60
63
|
|
|
64
|
+
## Follow-up: "what else is like this?"
|
|
65
|
+
|
|
66
|
+
After delivering the explanation, offer a one-line follow-up:
|
|
67
|
+
|
|
68
|
+
> _Want me to find semantically similar code? I can run `find_similar` on this qname._
|
|
69
|
+
|
|
70
|
+
If the user says yes, hand off to `sf-find-similar` with mode=qname and the same qname. Don't pre-emptively run it — the embedding query takes a moment and the user may not want it. The chain is most useful when:
|
|
71
|
+
|
|
72
|
+
- The user is reviewing legacy code and wants to spot duplicates.
|
|
73
|
+
- The method does something domain-specific (taxes, compliance, pricing) and the user wants to find every place that handles the same concept.
|
|
74
|
+
- The agent already produced an explanation but the user wonders "is this the only place this logic lives?".
|
|
75
|
+
|
|
61
76
|
## Don't
|
|
62
77
|
|
|
63
78
|
- Don't modify the source. This skill is read-only against the local graph.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sf-find-similar
|
|
3
|
+
description: Find Salesforce metadata that is semantically similar to an existing node OR a free-text concept. Two modes — pass a qname to anchor on an existing node (e.g. "show me other Apex methods like BillingSvc.run"), or pass free text to discover code by meaning when no name fits (e.g. "find code that handles order cancellation"). Use when exact-name search misses, when an agent wants to surface near-misses for review, or when the user describes a concept rather than a node. Powered by the MiniLM-L6 embeddings produced during ingest and the `vec0` SQLite KNN index. Filter by label to restrict to one node type. Do NOT use for structural edge traversal — for "what does X call" / "who reads field Y" use trace_downstream / analyze_field, which give exact answers; this skill is for fuzzy / conceptual matches.
|
|
4
|
+
triggers:
|
|
5
|
+
- "find similar"
|
|
6
|
+
- "show me code like"
|
|
7
|
+
- "what else is like"
|
|
8
|
+
- "find nodes similar to"
|
|
9
|
+
- "semantically similar"
|
|
10
|
+
- "find code that handles"
|
|
11
|
+
- "where do we"
|
|
12
|
+
- "anything related to"
|
|
13
|
+
- "fuzzy search"
|
|
14
|
+
- "more like this"
|
|
15
|
+
tools_used:
|
|
16
|
+
- find_similar
|
|
17
|
+
- explain_code
|
|
18
|
+
- trace_downstream
|
|
19
|
+
- analyze_field
|
|
20
|
+
- staleness_check
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# sf-find-similar
|
|
24
|
+
|
|
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
|
+
|
|
27
|
+
## When to choose this vs. the other tools
|
|
28
|
+
|
|
29
|
+
| Question shape | Use |
|
|
30
|
+
|---|---|
|
|
31
|
+
| "What does X call?" / "Who reads field Y?" | `trace_downstream` / `analyze_field` — exact graph edges |
|
|
32
|
+
| "Explain method X" | `sf-explain-code` |
|
|
33
|
+
| "What else is like X?" / "Find code that does Y" | **`sf-find-similar`** |
|
|
34
|
+
| "What changed?" / "What broke?" | `sf-what-broke`, `sf-cross-org-diff`, `sf-impact-from-diff` |
|
|
35
|
+
|
|
36
|
+
If the user mentions an exact qname *and* asks for relationships, prefer the structural tool. Reach for `find_similar` when names don't match or the user is describing a concept.
|
|
37
|
+
|
|
38
|
+
## Two modes
|
|
39
|
+
|
|
40
|
+
### Mode A — anchored on an existing node (`qname`)
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
find_similar(org="my-org", qname="ApexClass:BillingSvc", k=10, label="ApexClass")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use when the user names a node and wants "more like this." Pass `label` when restricting matters (e.g. "other LWCs like accountTile" — set `label="LWC"`).
|
|
47
|
+
|
|
48
|
+
### Mode B — free-text concept (`text`)
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
find_similar(org="my-org", text="code that computes compliance fees", k=10)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use when the user describes the *what* but not the *which*. The query is embedded on the fly with the same MiniLM-L6 pipeline the ingest uses. Most useful when:
|
|
55
|
+
|
|
56
|
+
- The user couldn't recall an exact class/method name.
|
|
57
|
+
- The concept spans multiple classes — semantic match surfaces them all.
|
|
58
|
+
- The user explicitly says "find code that does X" / "where do we Y".
|
|
59
|
+
|
|
60
|
+
## Playbook
|
|
61
|
+
|
|
62
|
+
1. **Pick the mode** based on whether the user named a node or described a concept.
|
|
63
|
+
2. **`staleness_check`** for the org. If stale, warn — embeddings may not reflect production code.
|
|
64
|
+
3. **`find_similar`** with the chosen mode. Use `k=10` by default; raise to 20–30 only if the user asks "more results."
|
|
65
|
+
4. **Read the response** — it returns a ranked table of `(qname, label, similarity, distance)`. Similarity is 0–1, higher is closer.
|
|
66
|
+
5. **Filter the noise.** Similarity < ~0.4 is usually unrelated text overlap, not real semantic match. Drop those before surfacing to the user unless they explicitly asked for everything.
|
|
67
|
+
6. **Offer to drill in.** For each hit the user seems interested in, propose chaining to `sf-explain-code` (what does this one do?) or `trace_downstream` (where does it flow?).
|
|
68
|
+
|
|
69
|
+
## Visualization
|
|
70
|
+
|
|
71
|
+
When the result set has 5+ hits, render a horizontal bar chart (Mermaid `xychart-beta`) of similarity scores so the user can eyeball the cluster vs. tail. For ≤4 hits the table alone is fine.
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
xychart-beta
|
|
75
|
+
title "Similarity to BillingSvc"
|
|
76
|
+
x-axis [OrderInvoiceSvc, CreditMemoSvc, TaxCalcSvc, RebateSvc]
|
|
77
|
+
y-axis "similarity" 0 --> 1
|
|
78
|
+
bar [0.82, 0.79, 0.71, 0.55]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Common failure modes & how to handle them
|
|
82
|
+
|
|
83
|
+
- **`reason: 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`.
|
|
84
|
+
- **`reason: 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.
|
|
85
|
+
- **`reason: embedder_unavailable`** (text mode) — the MiniLM runtime isn't present. Fall back to qname mode if the user can name a similar node.
|
|
86
|
+
- **`reason: no_neighbours`** — genuinely no similar nodes. Suggest dropping the `label` filter, or running structural `trace_upstream` / `trace_downstream` instead.
|
|
87
|
+
|
|
88
|
+
## Response shape
|
|
89
|
+
|
|
90
|
+
- **TL;DR** — "Top N matches for `<focal>`."
|
|
91
|
+
- **Ranked table** — qname, label, similarity (3 decimal places), distance.
|
|
92
|
+
- **Drop-low note** — if you filtered out scores <0.4, say so: "Skipped 3 results below the 0.4 noise floor."
|
|
93
|
+
- **Follow-ups** — propose `explain_code` / `trace_downstream` for the top hit.
|
|
94
|
+
|
|
95
|
+
## Don't
|
|
96
|
+
|
|
97
|
+
- Don't claim semantic match implies a structural edge. If the user wants "who actually calls X", route to `trace_upstream`. Similarity ≠ dependency.
|
|
98
|
+
- Don't surface scores below ~0.4 unless the user explicitly asked for a wider net. They are usually statistical noise from the embedding space.
|
|
99
|
+
- Don't use this for "what changed" / "what broke" questions — those need diff-style tools, not semantic neighbours.
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-impact-from-diff
|
|
3
|
-
description: Compute downstream blast radius and test-coverage gaps for a git diff before merge.
|
|
3
|
+
description: Compute downstream blast radius and test-coverage gaps for a COMMITTED git diff (a PR, a branch, a commit range) before merge. Requires the changes to already exist in git history. For uncommitted working-tree changes, use sf-wip-impact instead.
|
|
4
4
|
triggers:
|
|
5
5
|
- "what does this PR break"
|
|
6
|
-
- "impact of this
|
|
7
|
-
- "
|
|
8
|
-
- "
|
|
9
|
-
- "
|
|
6
|
+
- "impact of this PR"
|
|
7
|
+
- "blast radius of this branch"
|
|
8
|
+
- "before I merge this PR"
|
|
9
|
+
- "test gaps for this diff"
|
|
10
10
|
tools_used:
|
|
11
11
|
- impact_from_git_diff
|
|
12
12
|
- test_gap_intelligence_from_git_diff
|
|
13
13
|
- staleness_check
|
|
14
|
+
- find_similar
|
|
14
15
|
---
|
|
15
16
|
|
|
16
17
|
# sf-impact-from-diff
|
|
@@ -25,6 +26,7 @@ Use when the user wants to understand the downstream consequences of a pending c
|
|
|
25
26
|
4. Group findings by risk tier — **direct edits**, **first-degree dependents**, **transitive (depth ≥ 2)** — and call out anything that crosses metadata layers (LWC -> Apex -> Flow).
|
|
26
27
|
5. Render the Mermaid impact graph returned by the tool. If the impact set is large (>40 nodes), summarise by category and offer a follow-up call scoped to a single changed file.
|
|
27
28
|
6. If test gaps exist, list the specific impacted classes + methods that lack assertions, not just totals.
|
|
29
|
+
7. **Semantic-sibling check (optional).** For each top-level changed file, call `find_similar(qname=<changed-node>, k=5)` and surface any near-neighbour (similarity > 0.6) that is NOT in the structural impact set. Rationale: copy-paste duplicates of the changed logic often live elsewhere in the codebase without a structural edge linking them. The diff doesn't touch them, but a behaviour change to the original probably should propagate. Flag these as "siblings worth reviewing" — don't add them to the at-risk list automatically (similarity ≠ dependency), but offer them for the user to scan.
|
|
28
30
|
|
|
29
31
|
## Visualization
|
|
30
32
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-snapshot-compare
|
|
3
|
-
description: Compare two sfgraph
|
|
3
|
+
description: Compare two named sfgraph SNAPSHOTS of the same org (or one snapshot against current) for arbitrary point-in-time analysis. Use when the user explicitly references snapshots by name/id, wants to "rewind" to a prior state, or compare arbitrary points in time. For post-deploy regressions use sf-what-broke; for comparing two different orgs use sf-cross-org-diff.
|
|
4
4
|
triggers:
|
|
5
5
|
- "compare snapshots"
|
|
6
|
-
- "
|
|
6
|
+
- "diff snapshot <a> and <b>"
|
|
7
7
|
- "point in time diff"
|
|
8
|
-
- "rewind"
|
|
9
|
-
- "show me the state before"
|
|
8
|
+
- "rewind to snapshot"
|
|
9
|
+
- "show me the state before <snapshot>"
|
|
10
10
|
tools_used:
|
|
11
11
|
- snapshot_list
|
|
12
12
|
- snapshot_create
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-what-broke
|
|
3
|
-
description: Identify what regressed in
|
|
3
|
+
description: Identify what regressed in a SINGLE org since a recent deploy or sync — post-deployment regression triage. Use when the user reports something stopped working after a deploy, or asks what changed since the last ingest. For comparing two distinct orgs use sf-cross-org-diff; for arbitrary point-in-time snapshot comparison use sf-snapshot-compare.
|
|
4
4
|
triggers:
|
|
5
|
-
- "what broke"
|
|
5
|
+
- "what broke after the deploy"
|
|
6
6
|
- "post-deploy regression"
|
|
7
|
-
- "since deploy"
|
|
7
|
+
- "since the last deploy"
|
|
8
8
|
- "what changed since last sync"
|
|
9
9
|
- "regression triage"
|
|
10
10
|
tools_used:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf-wip-impact
|
|
3
|
-
description: Dry-run the
|
|
3
|
+
description: Dry-run the blast radius and test gaps for UNCOMMITTED local working-tree changes against the org graph — use before you commit. For committed PR/branch diffs use sf-impact-from-diff instead.
|
|
4
4
|
triggers:
|
|
5
|
-
- "dry-run
|
|
6
|
-
- "
|
|
7
|
-
- "local impact"
|
|
8
|
-
- "uncommitted changes"
|
|
5
|
+
- "dry-run my local changes"
|
|
6
|
+
- "impact of my uncommitted changes"
|
|
9
7
|
- "wip impact"
|
|
8
|
+
- "before I commit"
|
|
9
|
+
- "what would my working-tree changes affect"
|
|
10
10
|
tools_used:
|
|
11
11
|
- wip_impact
|
|
12
12
|
- wip_test_gap
|