@adityaaria/spark 6.0.21 → 6.0.22
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
CHANGED
|
@@ -11,7 +11,12 @@ Use this skill to scan and document a codebase's architecture, operational rules
|
|
|
11
11
|
|
|
12
12
|
**Announce at start:** "spark detection 💥 Using project-scanner to analyze repository DNA"
|
|
13
13
|
|
|
14
|
-
**Save findings to:** The `.docs/` directory. **You must physically create this directory and save the files to disk using your tools. Do NOT just print the output to the user.**
|
|
14
|
+
**Save findings to:** The `.docs/` directory. **You must physically create this directory and save the files to disk using your tools. Do NOT just print the output to the user.**
|
|
15
|
+
|
|
16
|
+
## Multi-Project Workspaces (CRITICAL)
|
|
17
|
+
If the workspace contains multiple independent projects or repositories (e.g., a `frontend` folder and a `backend` folder), you MUST generate a separate `.docs/` directory inside EACH project's root folder (e.g., `frontend/.docs/`, `backend/.docs/`). Do NOT combine them into a single global `.docs/` or dump everything into just one project's folder. Treat each independent project as its own ecosystem that requires its own documentation.
|
|
18
|
+
|
|
19
|
+
For large projects, break down the documentation logically (e.g., `.docs/PROJECT_SCAN.md`, `.docs/API_CONTRACT.md`, `.docs/DOMAINS/`) instead of creating one massive monolithic file.
|
|
15
20
|
|
|
16
21
|
## Handling Massive Codebases (Subagent Delegation)
|
|
17
22
|
If the repository is extremely large and analyzing all four pillars sequentially risks exceeding context limits or taking too long:
|
|
@@ -53,7 +58,8 @@ Identify conventions, rules, and technical debt enforced or found in the codebas
|
|
|
53
58
|
## Execution Checklist
|
|
54
59
|
|
|
55
60
|
- `[ ]` **Step 1:** Announce skill usage exactly as required.
|
|
56
|
-
- `[ ]` **Step 2:**
|
|
57
|
-
- `[ ]` **Step 3:** Scan
|
|
58
|
-
- `[ ]` **Step 4:**
|
|
59
|
-
- `[ ]` **Step 5
|
|
61
|
+
- `[ ]` **Step 2:** Identify if the workspace contains multiple independent projects (e.g., frontend vs backend). If so, plan to scan and generate `.docs/` for EACH project separately.
|
|
62
|
+
- `[ ]` **Step 3:** Scan root configuration files and prioritize searching for Swagger/OpenAPI specifications.
|
|
63
|
+
- `[ ]` **Step 4:** Scan source directory structures to infer the language, framework, and architectural patterns.
|
|
64
|
+
- `[ ]` **Step 5:** Analyze testing frameworks, CI/CD workflows, and actively hunt for anti-patterns and legacy traps.
|
|
65
|
+
- `[ ]` **Step 6 (CRITICAL):** You MUST use your file-writing tools to physically create the `.docs/` directory (inside each project root if multi-repo) and save the markdown files (e.g. `PROJECT_SCAN.md`, `API_CONTRACT.md`) into it. DO NOT just print the summary into the chat! You must physically write the files to disk.
|
|
@@ -621,19 +621,81 @@ ${steps}
|
|
|
621
621
|
return;
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
//
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
624
|
+
// Dynamic Mermaid Parser
|
|
625
|
+
let nodesMap = new Map();
|
|
626
|
+
let edgesList = [];
|
|
627
|
+
let nodeIdCounter = 1;
|
|
628
|
+
|
|
629
|
+
function parseNode(str) {
|
|
630
|
+
const match = str.trim().match(/^([a-zA-Z0-9_-]+)(.*)$/);
|
|
631
|
+
if (!match) return null;
|
|
632
|
+
const rawId = match[1];
|
|
633
|
+
let label = rawId;
|
|
634
|
+
let shape = 'box';
|
|
635
|
+
const rest = match[2].trim();
|
|
636
|
+
if (rest) {
|
|
637
|
+
const labelMatch = rest.match(/[\[\(\{]+(.*?)[\]\}\)]+/);
|
|
638
|
+
if (labelMatch) label = labelMatch[1].replace(/["']/g, '');
|
|
639
|
+
if (rest.includes('[((') || rest.includes('[([')) shape = 'database';
|
|
640
|
+
else if (rest.includes('{')) shape = 'diamond';
|
|
641
|
+
else if (rest.includes('((')) shape = 'ellipse';
|
|
642
|
+
}
|
|
643
|
+
return { rawId, label, shape };
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
docsData.forEach(doc => {
|
|
647
|
+
const mermaidRegex = /```mermaid\s+([\s\S]*?)```/g;
|
|
648
|
+
let match;
|
|
649
|
+
while ((match = mermaidRegex.exec(doc.content)) !== null) {
|
|
650
|
+
const lines = match[1].split('\n');
|
|
651
|
+
lines.forEach(line => {
|
|
652
|
+
let l = line.trim();
|
|
653
|
+
if (!l || l.startsWith('graph') || l.startsWith('flowchart') || l.startsWith('subgraph') || l.startsWith('end')) return;
|
|
654
|
+
|
|
655
|
+
const parts = l.split('-->');
|
|
656
|
+
if (parts.length >= 2) {
|
|
657
|
+
let fromPart = parts[0].trim();
|
|
658
|
+
let toPart = parts.slice(1).join('-->').trim();
|
|
659
|
+
|
|
660
|
+
let edgeLabel = '';
|
|
661
|
+
if (toPart.startsWith('|')) {
|
|
662
|
+
const pipeEnd = toPart.indexOf('|', 1);
|
|
663
|
+
if (pipeEnd > -1) {
|
|
664
|
+
edgeLabel = toPart.substring(1, pipeEnd).trim();
|
|
665
|
+
toPart = toPart.substring(pipeEnd + 1).trim();
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const fNode = parseNode(fromPart);
|
|
670
|
+
const tNode = parseNode(toPart);
|
|
671
|
+
|
|
672
|
+
if (fNode && tNode) {
|
|
673
|
+
if (!nodesMap.has(fNode.rawId)) {
|
|
674
|
+
nodesMap.set(fNode.rawId, { id: nodeIdCounter++, label: fNode.label, shape: fNode.shape, color: { background: '#151515', border: '#2a2a2a' } });
|
|
675
|
+
}
|
|
676
|
+
if (!nodesMap.has(tNode.rawId)) {
|
|
677
|
+
nodesMap.set(tNode.rawId, { id: nodeIdCounter++, label: tNode.label, shape: tNode.shape, color: { background: '#151515', border: '#2a2a2a' } });
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
edgesList.push({
|
|
681
|
+
from: nodesMap.get(fNode.rawId).id,
|
|
682
|
+
to: nodesMap.get(tNode.rawId).id,
|
|
683
|
+
arrows: 'to',
|
|
684
|
+
label: edgeLabel
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
if (nodesMap.size === 0) {
|
|
693
|
+
container.innerHTML = '<div style="padding: 40px; text-align: center; color: var(--text-muted);">No Mermaid architecture graphs found in .docs/ files. Run the project-scanner skill first.</div>';
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const nodes = new vis.DataSet(Array.from(nodesMap.values()));
|
|
698
|
+
const edges = new vis.DataSet(edgesList);
|
|
637
699
|
const data = { nodes, edges };
|
|
638
700
|
const options = {
|
|
639
701
|
nodes: {
|
|
@@ -742,8 +804,15 @@ ${steps}
|
|
|
742
804
|
},
|
|
743
805
|
response: [{
|
|
744
806
|
name: "Success",
|
|
807
|
+
originalRequest: {
|
|
808
|
+
method: ep.method,
|
|
809
|
+
header: [{ key: "Authorization", value: "Bearer {{token}}" }, { key: "Content-Type", value: "application/json" }],
|
|
810
|
+
body: ep.method !== 'GET' ? { mode: "raw", raw: JSON.stringify(mock, null, 2) } : undefined,
|
|
811
|
+
url: { raw: `{{baseUrl}}/${pathArr.join('/')}`, host: ["{{baseUrl}}"], path: pathArr }
|
|
812
|
+
},
|
|
745
813
|
status: "OK",
|
|
746
814
|
code: 200,
|
|
815
|
+
_postman_previewlanguage: "json",
|
|
747
816
|
header: [{ key: "Content-Type", value: "application/json" }],
|
|
748
817
|
body: JSON.stringify({ success: true, data: mock }, null, 2)
|
|
749
818
|
}]
|
|
@@ -758,8 +827,15 @@ ${steps}
|
|
|
758
827
|
},
|
|
759
828
|
response: [{
|
|
760
829
|
name: "Bad Request",
|
|
830
|
+
originalRequest: {
|
|
831
|
+
method: ep.method,
|
|
832
|
+
header: [{ key: "Authorization", value: "Bearer {{token}}" }, { key: "Content-Type", value: "application/json" }],
|
|
833
|
+
body: ep.method !== 'GET' ? { mode: "raw", raw: "{}" } : undefined,
|
|
834
|
+
url: { raw: `{{baseUrl}}/${pathArr.join('/')}`, host: ["{{baseUrl}}"], path: pathArr }
|
|
835
|
+
},
|
|
761
836
|
status: "Bad Request",
|
|
762
837
|
code: 400,
|
|
838
|
+
_postman_previewlanguage: "json",
|
|
763
839
|
header: [{ key: "Content-Type", value: "application/json" }],
|
|
764
840
|
body: JSON.stringify({ success: false, error: { code: "VALIDATION_ERROR", message: "Invalid parameters provided" } }, null, 2)
|
|
765
841
|
}]
|
|
@@ -773,8 +849,14 @@ ${steps}
|
|
|
773
849
|
},
|
|
774
850
|
response: [{
|
|
775
851
|
name: "Unauthorized",
|
|
852
|
+
originalRequest: {
|
|
853
|
+
method: ep.method,
|
|
854
|
+
header: [], // No auth
|
|
855
|
+
url: { raw: `{{baseUrl}}/${pathArr.join('/')}`, host: ["{{baseUrl}}"], path: pathArr }
|
|
856
|
+
},
|
|
776
857
|
status: "Unauthorized",
|
|
777
858
|
code: 401,
|
|
859
|
+
_postman_previewlanguage: "json",
|
|
778
860
|
header: [{ key: "Content-Type", value: "application/json" }],
|
|
779
861
|
body: JSON.stringify({ success: false, error: { code: "UNAUTHORIZED", message: "Missing or invalid token" } }, null, 2)
|
|
780
862
|
}]
|