@nerviq/cli 0.9.2 → 0.9.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.
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Official source URL registry for platform technique catalogs.
3
+ *
4
+ * These URLs intentionally point to the nearest authoritative official page for
5
+ * a given category or check. Some advisory/internal heuristics do not have a
6
+ * single line-item normative doc, so they fall back to the closest official
7
+ * platform page that governs the surrounding feature area.
8
+ */
9
+
10
+ const SOURCE_URLS = {
11
+ claude: {
12
+ defaultUrl: 'https://code.claude.com/docs/en/overview',
13
+ byCategory: {
14
+ memory: 'https://code.claude.com/docs/en/memory',
15
+ quality: 'https://code.claude.com/docs/en/common-workflows',
16
+ git: 'https://code.claude.com/docs/en/settings',
17
+ workflow: 'https://code.claude.com/docs/en/common-workflows',
18
+ security: 'https://code.claude.com/docs/en/permissions',
19
+ automation: 'https://code.claude.com/docs/en/hooks',
20
+ design: 'https://code.claude.com/docs/en/best-practices',
21
+ devops: 'https://code.claude.com/docs/en/common-workflows',
22
+ hygiene: 'https://code.claude.com/docs/en/overview',
23
+ performance: 'https://code.claude.com/docs/en/memory',
24
+ tools: 'https://code.claude.com/docs/en/mcp',
25
+ prompting: 'https://code.claude.com/docs/en/best-practices',
26
+ features: 'https://code.claude.com/docs/en/commands',
27
+ 'quality-deep': 'https://code.claude.com/docs/en/best-practices',
28
+ },
29
+ byKey: {
30
+ customCommands: 'https://code.claude.com/docs/en/commands',
31
+ multipleCommands: 'https://code.claude.com/docs/en/commands',
32
+ deployCommand: 'https://code.claude.com/docs/en/commands',
33
+ reviewCommand: 'https://code.claude.com/docs/en/commands',
34
+ agents: 'https://code.claude.com/docs/en/sub-agents',
35
+ multipleAgents: 'https://code.claude.com/docs/en/sub-agents',
36
+ agentsHaveMaxTurns: 'https://code.claude.com/docs/en/sub-agents',
37
+ agentHasAllowedTools: 'https://code.claude.com/docs/en/sub-agents',
38
+ skills: 'https://code.claude.com/docs/en/skills',
39
+ multipleSkills: 'https://code.claude.com/docs/en/skills',
40
+ skillUsesPaths: 'https://code.claude.com/docs/en/skills',
41
+ frontendDesignSkill: 'https://code.claude.com/docs/en/skills',
42
+ },
43
+ },
44
+ codex: {
45
+ defaultUrl: 'https://developers.openai.com/codex/cli',
46
+ byCategory: {
47
+ instructions: 'https://developers.openai.com/codex/guides/agents-md',
48
+ config: 'https://developers.openai.com/codex/config-reference',
49
+ trust: 'https://developers.openai.com/codex/agent-approvals-security',
50
+ rules: 'https://developers.openai.com/codex/rules',
51
+ hooks: 'https://developers.openai.com/codex/hooks',
52
+ mcp: 'https://developers.openai.com/codex/mcp',
53
+ skills: 'https://developers.openai.com/codex/skills',
54
+ agents: 'https://developers.openai.com/codex/subagents',
55
+ automation: 'https://developers.openai.com/codex/cli',
56
+ review: 'https://developers.openai.com/codex/cli',
57
+ local: 'https://developers.openai.com/codex/app/local-environments',
58
+ 'quality-deep': 'https://developers.openai.com/codex/feature-maturity',
59
+ advisory: 'https://developers.openai.com/codex/cli',
60
+ 'pack-posture': 'https://developers.openai.com/codex/mcp',
61
+ 'repeat-usage': 'https://developers.openai.com/codex/cli',
62
+ 'release-freshness': 'https://developers.openai.com/codex/changelog',
63
+ },
64
+ byKey: {
65
+ codexAutomationManuallyTested: 'https://developers.openai.com/codex/app/automations',
66
+ codexAutomationAppPrereqAcknowledged: 'https://developers.openai.com/codex/app/automations',
67
+ codexGitHubActionSafeStrategy: 'https://developers.openai.com/codex/github-action',
68
+ codexGitHubActionPromptSourceExclusive: 'https://developers.openai.com/codex/github-action',
69
+ codexGitHubActionTriggerAllowlistsExplicit: 'https://developers.openai.com/codex/github-action',
70
+ codexCiAuthUsesManagedKey: 'https://developers.openai.com/codex/github-action',
71
+ codexPluginConfigValid: 'https://developers.openai.com/codex/skills',
72
+ codexUndoExplicit: 'https://developers.openai.com/codex/config-reference',
73
+ codexWorktreeLifecycleDocumented: 'https://developers.openai.com/codex/app/local-environments',
74
+ },
75
+ },
76
+ gemini: {
77
+ defaultUrl: 'https://geminicli.com/docs/get-started/',
78
+ byCategory: {
79
+ instructions: 'https://geminicli.com/docs/cli/gemini-md/',
80
+ config: 'https://geminicli.com/docs/reference/configuration/',
81
+ trust: 'https://geminicli.com/docs/cli/trusted-folders/',
82
+ hooks: 'https://geminicli.com/docs/hooks/reference/',
83
+ mcp: 'https://geminicli.com/docs/tools/mcp-server/',
84
+ sandbox: 'https://geminicli.com/docs/cli/sandbox/',
85
+ agents: 'https://geminicli.com/docs/core/subagents/',
86
+ skills: 'https://geminicli.com/docs/cli/skills/',
87
+ automation: 'https://google-gemini.github.io/gemini-cli/docs/cli/headless.html',
88
+ extensions: 'https://geminicli.com/docs/extensions/',
89
+ review: 'https://ai.google.dev/gemini-api/docs/coding-agents',
90
+ 'quality-deep': 'https://geminicli.com/docs/get-started/',
91
+ commands: 'https://geminicli.com/docs/cli/custom-commands/',
92
+ advisory: 'https://geminicli.com/docs/get-started/',
93
+ 'pack-posture': 'https://geminicli.com/docs/tools/mcp-server/',
94
+ 'repeat-usage': 'https://geminicli.com/docs/cli/session-management/',
95
+ 'release-freshness': 'https://geminicli.com/docs/changelogs/latest/',
96
+ },
97
+ },
98
+ copilot: {
99
+ defaultUrl: 'https://docs.github.com/copilot',
100
+ byCategory: {
101
+ instructions: 'https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot',
102
+ config: 'https://code.visualstudio.com/docs/copilot/customization/custom-instructions',
103
+ trust: 'https://code.visualstudio.com/docs/copilot/security',
104
+ mcp: 'https://code.visualstudio.com/docs/copilot/chat/mcp-servers',
105
+ 'cloud-agent': 'https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-coding-agent',
106
+ organization: 'https://docs.github.com/en/copilot/how-tos/administer-copilot/manage-for-organization/manage-policies',
107
+ 'prompt-files': 'https://code.visualstudio.com/docs/copilot/customization/prompt-files',
108
+ 'skills-agents': 'https://code.visualstudio.com/docs/copilot/agents/overview',
109
+ 'ci-automation': 'https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment',
110
+ enterprise: 'https://docs.github.com/en/copilot/how-tos/administer-copilot/manage-for-enterprise',
111
+ extensions: 'https://docs.github.com/en/copilot/building-copilot-extensions/about-building-copilot-extensions',
112
+ 'quality-deep': 'https://docs.github.com/copilot',
113
+ advisory: 'https://docs.github.com/copilot',
114
+ freshness: 'https://github.blog/changelog/',
115
+ },
116
+ },
117
+ cursor: {
118
+ defaultUrl: 'https://cursor.com/docs',
119
+ byCategory: {
120
+ rules: 'https://cursor.com/docs/context/rules',
121
+ config: 'https://cursor.com/docs',
122
+ trust: 'https://cursor.com/docs/enterprise/privacy-and-data-governance',
123
+ 'agent-mode': 'https://docs.cursor.com/en/chat/agent',
124
+ mcp: 'https://cursor.com/docs/cli/mcp',
125
+ 'instructions-quality': 'https://docs.cursor.com/guides/working-with-context',
126
+ 'background-agents': 'https://docs.cursor.com/en/background-agents',
127
+ automations: 'https://cursor.com/docs/cloud-agent/automations',
128
+ enterprise: 'https://cursor.com/docs/enterprise',
129
+ bugbot: 'https://cursor.com/docs/bugbot',
130
+ 'cross-surface': 'https://cursor.com/docs',
131
+ 'quality-deep': 'https://docs.cursor.com/guides/working-with-context',
132
+ advisory: 'https://cursor.com/docs',
133
+ freshness: 'https://cursor.com/changelog',
134
+ },
135
+ },
136
+ windsurf: {
137
+ defaultUrl: 'https://docs.windsurf.com/windsurf/cascade',
138
+ byCategory: {
139
+ rules: 'https://windsurf.com/university/general-education/intro-rules-memories',
140
+ config: 'https://docs.windsurf.com/windsurf/cascade/cascade',
141
+ trust: 'https://windsurf.com/security',
142
+ 'cascade-agent': 'https://docs.windsurf.com/windsurf/cascade/agents-md',
143
+ mcp: 'https://docs.windsurf.com/windsurf/cascade/mcp',
144
+ 'instructions-quality': 'https://docs.windsurf.com/windsurf/cascade/agents-md',
145
+ workflows: 'https://docs.windsurf.com/windsurf/cascade/workflows',
146
+ memories: 'https://docs.windsurf.com/windsurf/cascade/memories',
147
+ enterprise: 'https://windsurf.com/security',
148
+ cascadeignore: 'https://docs.windsurf.com/windsurf/cascade/cascade',
149
+ 'cross-surface': 'https://docs.windsurf.com/windsurf/cascade/cascade',
150
+ 'quality-deep': 'https://docs.windsurf.com/windsurf/cascade/cascade',
151
+ advisory: 'https://docs.windsurf.com/windsurf/cascade/cascade',
152
+ freshness: 'https://windsurf.com/changelog',
153
+ },
154
+ },
155
+ aider: {
156
+ defaultUrl: 'https://aider.chat/docs/',
157
+ byCategory: {
158
+ config: 'https://aider.chat/docs/config.html',
159
+ 'advanced-config': 'https://aider.chat/docs/config/aider_conf.html',
160
+ 'git-safety': 'https://aider.chat/docs/git.html',
161
+ 'model-config': 'https://aider.chat/docs/config/adv-model-settings.html',
162
+ conventions: 'https://aider.chat/docs/usage/conventions.html',
163
+ architecture: 'https://aider.chat/docs/usage/modes.html',
164
+ security: 'https://aider.chat/docs/config/dotenv.html',
165
+ ci: 'https://aider.chat/docs/scripting.html',
166
+ quality: 'https://aider.chat/docs/usage/lint-test.html',
167
+ 'workflow-patterns': 'https://aider.chat/docs/usage/modes.html',
168
+ 'editor-integration': 'https://aider.chat/docs/config/editor.html',
169
+ 'release-readiness': 'https://aider.chat/docs/',
170
+ },
171
+ },
172
+ opencode: {
173
+ defaultUrl: 'https://opencode.ai/docs/',
174
+ byCategory: {
175
+ instructions: 'https://opencode.ai/docs/rules/',
176
+ config: 'https://opencode.ai/docs/config/',
177
+ permissions: 'https://opencode.ai/docs/permissions',
178
+ plugins: 'https://opencode.ai/docs/plugins/',
179
+ security: 'https://opencode.ai/docs/tools/',
180
+ mcp: 'https://opencode.ai/docs/mcp-servers/',
181
+ ci: 'https://opencode.ai/docs/github/',
182
+ 'quality-deep': 'https://opencode.ai/docs/',
183
+ skills: 'https://opencode.ai/docs/skills/',
184
+ agents: 'https://opencode.ai/docs/agents/',
185
+ commands: 'https://opencode.ai/docs/commands/',
186
+ tui: 'https://opencode.ai/docs/themes/',
187
+ governance: 'https://opencode.ai/docs/github/',
188
+ 'release-freshness': 'https://opencode.ai/docs/',
189
+ 'mixed-agent': 'https://opencode.ai/docs/modes/',
190
+ propagation: 'https://opencode.ai/docs/config/',
191
+ },
192
+ },
193
+ };
194
+
195
+ function attachSourceUrls(platform, techniques) {
196
+ const mapping = SOURCE_URLS[platform];
197
+ if (!mapping) {
198
+ throw new Error(`Unknown source-url platform '${platform}'`);
199
+ }
200
+
201
+ for (const [key, technique] of Object.entries(techniques)) {
202
+ if (technique.sourceUrl) continue;
203
+ const resolved =
204
+ mapping.byKey?.[key] ||
205
+ mapping.byCategory?.[technique.category] ||
206
+ mapping.defaultUrl;
207
+ if (!resolved) {
208
+ throw new Error(`No sourceUrl mapping found for ${platform}:${key}`);
209
+ }
210
+ technique.sourceUrl = resolved;
211
+ }
212
+
213
+ return techniques;
214
+ }
215
+
216
+ module.exports = {
217
+ SOURCE_URLS,
218
+ attachSourceUrls,
219
+ };
package/src/techniques.js CHANGED
@@ -11,6 +11,7 @@ function hasFrontendSignals(ctx) {
11
11
  }
12
12
 
13
13
  const { containsEmbeddedSecret } = require('./secret-patterns');
14
+ const { attachSourceUrls } = require('./source-urls');
14
15
 
15
16
  const TECHNIQUES = {
16
17
  // ============================================================
@@ -1443,4 +1444,6 @@ const STACKS = {
1443
1444
  dotnet: { files: ['global.json', 'Directory.Build.props'], content: {}, label: '.NET' },
1444
1445
  };
1445
1446
 
1447
+ attachSourceUrls('claude', TECHNIQUES);
1448
+
1446
1449
  module.exports = { TECHNIQUES, STACKS, containsEmbeddedSecret };