contextos-agents 2.0.0 → 2.1.1

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.
Files changed (223) hide show
  1. package/.agents/AGENTS.md +53 -33
  2. package/.agents/adapters/aider/export.js +41 -14
  3. package/.agents/adapters/claude/export.js +54 -3
  4. package/.agents/adapters/copilot/export.js +1 -1
  5. package/.agents/adapters/cursor/export.js +1 -1
  6. package/.agents/adapters/drift-detector.js +86 -10
  7. package/.agents/adapters/gemini/export.js +1 -1
  8. package/.agents/adapters/pure-compiler.js +28 -6
  9. package/.agents/adapters/shared.js +13 -4
  10. package/.agents/adapters/zed/export.js +1 -1
  11. package/.agents/compiled/registry.v2.json +29 -25
  12. package/.agents/compiled/registry.v2.sha256 +1 -1
  13. package/.agents/core/skills/context-os/SKILL.md +34 -37
  14. package/.agents/core/skills/engineering-workflow/SKILL.md +24 -24
  15. package/.agents/core/skills/gemini-precision/EXAMPLES.md +72 -0
  16. package/.agents/core/skills/gemini-precision/SKILL.md +2 -1
  17. package/.agents/core/skills/gemini-precision/TROUBLESHOOTING.md +25 -0
  18. package/.agents/core/skills/gemini-precision/skill.yaml +2 -0
  19. package/.agents/core/skills/gstack-roles/SKILL.md +7 -6
  20. package/.agents/core/skills/security/SKILL.md +44 -16
  21. package/.agents/core/skills/security/skill.yaml +0 -1
  22. package/.agents/ctx.js +20 -14
  23. package/.agents/generated/claude/skills/context-os/SKILL.md +34 -37
  24. package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +24 -24
  25. package/.agents/generated/claude/skills/gemini-precision/SKILL.md +102 -1
  26. package/.agents/generated/claude/skills/gstack-roles/SKILL.md +7 -6
  27. package/.agents/generated/claude/skills/security/SKILL.md +44 -16
  28. package/.agents/generated/gemini/skills/context-os/SKILL.md +34 -37
  29. package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +24 -24
  30. package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +105 -1
  31. package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +7 -6
  32. package/.agents/generated/gemini/skills/security/SKILL.md +44 -125
  33. package/.agents/plugins.js +105 -8
  34. package/.agents/profiles.js +32 -11
  35. package/.agents/resolver/canonical-resolver.js +7 -7
  36. package/.agents/validate.js +69 -1
  37. package/README.md +81 -24
  38. package/bin/commands/hook.js +167 -0
  39. package/bin/commands/scan.js +77 -0
  40. package/bin/commands.js +39 -1
  41. package/bin/index.js +151 -34
  42. package/bin/lib/gate.js +171 -0
  43. package/bin/lib/git-snapshot.js +214 -0
  44. package/bin/lib/scan.js +461 -0
  45. package/catalog/skills/adapters/EXAMPLES.md +19 -0
  46. package/catalog/skills/adapters/SKILL.md +101 -0
  47. package/catalog/skills/adapters/TROUBLESHOOTING.md +7 -0
  48. package/catalog/skills/adapters/VALIDATION.json +12 -0
  49. package/catalog/skills/adapters/skill.yaml +13 -0
  50. package/catalog/skills/api-design/EXAMPLES.md +91 -0
  51. package/catalog/skills/api-design/SKILL.md +63 -0
  52. package/catalog/skills/api-design/TROUBLESHOOTING.md +54 -0
  53. package/catalog/skills/api-design/VALIDATION.json +11 -0
  54. package/catalog/skills/api-design/skill.yaml +14 -0
  55. package/catalog/skills/architecture-diagrams/SKILL.md +108 -0
  56. package/catalog/skills/architecture-diagrams/VALIDATION.json +12 -0
  57. package/catalog/skills/architecture-diagrams/skill.yaml +9 -0
  58. package/catalog/skills/brutalist-design/EXAMPLES.md +59 -0
  59. package/catalog/skills/brutalist-design/SKILL.md +150 -0
  60. package/catalog/skills/brutalist-design/VALIDATION.json +12 -0
  61. package/catalog/skills/brutalist-design/skill.yaml +10 -0
  62. package/catalog/skills/ci-cd/EXAMPLES.md +79 -0
  63. package/catalog/skills/ci-cd/SKILL.md +69 -0
  64. package/catalog/skills/ci-cd/TROUBLESHOOTING.md +52 -0
  65. package/catalog/skills/ci-cd/VALIDATION.json +11 -0
  66. package/catalog/skills/ci-cd/skill.yaml +13 -0
  67. package/catalog/skills/database/EXAMPLES.md +74 -0
  68. package/catalog/skills/database/SKILL.md +101 -0
  69. package/catalog/skills/database/TROUBLESHOOTING.md +18 -0
  70. package/catalog/skills/database/VALIDATION.json +11 -0
  71. package/catalog/skills/database/skill.yaml +14 -0
  72. package/catalog/skills/ddd/EXAMPLES.md +42 -0
  73. package/catalog/skills/ddd/SKILL.md +247 -0
  74. package/catalog/skills/ddd/TROUBLESHOOTING.md +19 -0
  75. package/catalog/skills/ddd/VALIDATION.json +12 -0
  76. package/catalog/skills/ddd/skill.yaml +14 -0
  77. package/catalog/skills/decisions/EXAMPLES.md +35 -0
  78. package/catalog/skills/decisions/SKILL.md +90 -0
  79. package/catalog/skills/decisions/TROUBLESHOOTING.md +13 -0
  80. package/catalog/skills/decisions/VALIDATION.json +12 -0
  81. package/catalog/skills/decisions/skill.yaml +13 -0
  82. package/catalog/skills/docker/EXAMPLES.md +56 -0
  83. package/catalog/skills/docker/SKILL.md +169 -0
  84. package/catalog/skills/docker/TROUBLESHOOTING.md +18 -0
  85. package/catalog/skills/docker/VALIDATION.json +11 -0
  86. package/catalog/skills/docker/skill.yaml +13 -0
  87. package/catalog/skills/fastapi/EXAMPLES.md +36 -0
  88. package/catalog/skills/fastapi/SKILL.md +171 -0
  89. package/catalog/skills/fastapi/TROUBLESHOOTING.md +19 -0
  90. package/catalog/skills/fastapi/VALIDATION.json +12 -0
  91. package/catalog/skills/fastapi/skill.yaml +14 -0
  92. package/catalog/skills/generators/EXAMPLES.md +19 -0
  93. package/catalog/skills/generators/SKILL.md +110 -0
  94. package/catalog/skills/generators/TROUBLESHOOTING.md +7 -0
  95. package/catalog/skills/generators/VALIDATION.json +12 -0
  96. package/catalog/skills/generators/skill.yaml +22 -0
  97. package/catalog/skills/generators/templates/API.md +77 -0
  98. package/catalog/skills/generators/templates/ARCHITECTURE.md +70 -0
  99. package/catalog/skills/generators/templates/DATABASE.md +42 -0
  100. package/catalog/skills/generators/templates/DECISION.md +46 -0
  101. package/catalog/skills/generators/templates/PRD.md +67 -0
  102. package/catalog/skills/generators/templates/PROJECT_GRAPH.md +56 -0
  103. package/catalog/skills/generators/templates/ROADMAP.md +51 -0
  104. package/catalog/skills/generators/templates/TASKS.md +43 -0
  105. package/catalog/skills/generators/templates/UI.md +73 -0
  106. package/catalog/skills/graphify/EXAMPLES.md +73 -0
  107. package/catalog/skills/graphify/SKILL.md +130 -0
  108. package/catalog/skills/graphify/VALIDATION.json +12 -0
  109. package/catalog/skills/graphify/skill.yaml +13 -0
  110. package/catalog/skills/impeccable-design/EXAMPLES.md +26 -0
  111. package/catalog/skills/impeccable-design/SKILL.md +201 -0
  112. package/catalog/skills/impeccable-design/TROUBLESHOOTING.md +19 -0
  113. package/catalog/skills/impeccable-design/VALIDATION.json +12 -0
  114. package/catalog/skills/impeccable-design/skill.yaml +15 -0
  115. package/catalog/skills/interview-me/SKILL.md +97 -0
  116. package/catalog/skills/interview-me/VALIDATION.json +12 -0
  117. package/catalog/skills/interview-me/skill.yaml +9 -0
  118. package/catalog/skills/microservices/EXAMPLES.md +38 -0
  119. package/catalog/skills/microservices/SKILL.md +164 -0
  120. package/catalog/skills/microservices/TROUBLESHOOTING.md +19 -0
  121. package/catalog/skills/microservices/VALIDATION.json +12 -0
  122. package/catalog/skills/microservices/skill.yaml +14 -0
  123. package/catalog/skills/minimalist-design/EXAMPLES.md +58 -0
  124. package/catalog/skills/minimalist-design/SKILL.md +113 -0
  125. package/catalog/skills/minimalist-design/VALIDATION.json +12 -0
  126. package/catalog/skills/minimalist-design/skill.yaml +10 -0
  127. package/catalog/skills/nestjs/EXAMPLES.md +40 -0
  128. package/catalog/skills/nestjs/SKILL.md +139 -0
  129. package/catalog/skills/nestjs/TROUBLESHOOTING.md +19 -0
  130. package/catalog/skills/nestjs/VALIDATION.json +12 -0
  131. package/catalog/skills/nestjs/skill.yaml +14 -0
  132. package/catalog/skills/nextjs/EXAMPLES.md +40 -0
  133. package/catalog/skills/nextjs/SKILL.md +163 -0
  134. package/catalog/skills/nextjs/TROUBLESHOOTING.md +19 -0
  135. package/catalog/skills/nextjs/VALIDATION.json +12 -0
  136. package/catalog/skills/nextjs/skill.yaml +14 -0
  137. package/catalog/skills/node/EXAMPLES.md +80 -0
  138. package/catalog/skills/node/SKILL.md +128 -0
  139. package/catalog/skills/node/TROUBLESHOOTING.md +19 -0
  140. package/catalog/skills/node/VALIDATION.json +12 -0
  141. package/catalog/skills/node/skill.yaml +14 -0
  142. package/catalog/skills/performance/EXAMPLES.md +30 -0
  143. package/catalog/skills/performance/SKILL.md +75 -0
  144. package/catalog/skills/performance/TROUBLESHOOTING.md +19 -0
  145. package/catalog/skills/performance/VALIDATION.json +12 -0
  146. package/catalog/skills/performance/skill.yaml +14 -0
  147. package/catalog/skills/react/EXAMPLES.md +79 -0
  148. package/catalog/skills/react/SKILL.md +132 -0
  149. package/catalog/skills/react/TROUBLESHOOTING.md +19 -0
  150. package/catalog/skills/react/VALIDATION.json +12 -0
  151. package/catalog/skills/react/skill.yaml +14 -0
  152. package/catalog/skills/react-best-practices/SKILL.md +158 -0
  153. package/catalog/skills/react-best-practices/VALIDATION.json +12 -0
  154. package/catalog/skills/react-best-practices/skill.yaml +13 -0
  155. package/catalog/skills/redesign-audit/SKILL.md +117 -0
  156. package/catalog/skills/redesign-audit/VALIDATION.json +12 -0
  157. package/catalog/skills/redesign-audit/skill.yaml +9 -0
  158. package/catalog/skills/security-audit/EXAMPLES.md +79 -0
  159. package/catalog/skills/security-audit/SKILL.md +91 -0
  160. package/catalog/skills/security-audit/TROUBLESHOOTING.md +46 -0
  161. package/catalog/skills/security-audit/VALIDATION.json +11 -0
  162. package/catalog/skills/security-audit/skill.yaml +14 -0
  163. package/catalog/skills/soft-design/EXAMPLES.md +51 -0
  164. package/catalog/skills/soft-design/SKILL.md +108 -0
  165. package/catalog/skills/soft-design/VALIDATION.json +12 -0
  166. package/catalog/skills/soft-design/skill.yaml +10 -0
  167. package/catalog/skills/state-management/EXAMPLES.md +56 -0
  168. package/catalog/skills/state-management/SKILL.md +168 -0
  169. package/catalog/skills/state-management/TROUBLESHOOTING.md +18 -0
  170. package/catalog/skills/state-management/VALIDATION.json +11 -0
  171. package/catalog/skills/state-management/skill.yaml +14 -0
  172. package/catalog/skills/subagent-orchestrator/SKILL.md +117 -0
  173. package/catalog/skills/subagent-orchestrator/VALIDATION.json +12 -0
  174. package/catalog/skills/subagent-orchestrator/skill.yaml +9 -0
  175. package/catalog/skills/system-design/EXAMPLES.md +75 -0
  176. package/catalog/skills/system-design/SKILL.md +419 -0
  177. package/catalog/skills/system-design/TROUBLESHOOTING.md +19 -0
  178. package/catalog/skills/system-design/VALIDATION.json +12 -0
  179. package/catalog/skills/system-design/skill.yaml +14 -0
  180. package/catalog/skills/terraform/EXAMPLES.md +74 -0
  181. package/catalog/skills/terraform/SKILL.md +55 -0
  182. package/catalog/skills/terraform/TROUBLESHOOTING.md +53 -0
  183. package/catalog/skills/terraform/VALIDATION.json +11 -0
  184. package/catalog/skills/terraform/skill.yaml +14 -0
  185. package/catalog/skills/testing/EXAMPLES.md +122 -0
  186. package/catalog/skills/testing/SKILL.md +70 -0
  187. package/catalog/skills/testing/TROUBLESHOOTING.md +18 -0
  188. package/catalog/skills/testing/VALIDATION.json +11 -0
  189. package/catalog/skills/testing/skill.yaml +14 -0
  190. package/catalog/skills/typescript/EXAMPLES.md +64 -0
  191. package/catalog/skills/typescript/SKILL.md +112 -0
  192. package/catalog/skills/typescript/TROUBLESHOOTING.md +19 -0
  193. package/catalog/skills/typescript/VALIDATION.json +12 -0
  194. package/catalog/skills/typescript/skill.yaml +14 -0
  195. package/catalog/skills/ui-design/EXAMPLES.md +21 -0
  196. package/catalog/skills/ui-design/SKILL.md +124 -0
  197. package/catalog/skills/ui-design/TROUBLESHOOTING.md +19 -0
  198. package/catalog/skills/ui-design/VALIDATION.json +12 -0
  199. package/catalog/skills/ui-design/skill.yaml +16 -0
  200. package/catalog/skills/ui-ux-pro/EXAMPLES.md +62 -0
  201. package/catalog/skills/ui-ux-pro/SKILL.md +418 -0
  202. package/catalog/skills/ui-ux-pro/TROUBLESHOOTING.md +19 -0
  203. package/catalog/skills/ui-ux-pro/VALIDATION.json +12 -0
  204. package/catalog/skills/ui-ux-pro/skill.yaml +14 -0
  205. package/catalog/skills/ux-design/EXAMPLES.md +36 -0
  206. package/catalog/skills/ux-design/SKILL.md +116 -0
  207. package/catalog/skills/ux-design/TROUBLESHOOTING.md +19 -0
  208. package/catalog/skills/ux-design/VALIDATION.json +12 -0
  209. package/catalog/skills/ux-design/skill.yaml +16 -0
  210. package/catalog/skills/vercel-optimize/SKILL.md +83 -0
  211. package/catalog/skills/vercel-optimize/VALIDATION.json +12 -0
  212. package/catalog/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
  213. package/catalog/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
  214. package/catalog/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
  215. package/catalog/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
  216. package/catalog/skills/vercel-optimize/skill.yaml +15 -0
  217. package/catalog/skills/web-accessibility/EXAMPLES.md +39 -0
  218. package/catalog/skills/web-accessibility/SKILL.md +151 -0
  219. package/catalog/skills/web-accessibility/TROUBLESHOOTING.md +19 -0
  220. package/catalog/skills/web-accessibility/VALIDATION.json +12 -0
  221. package/catalog/skills/web-accessibility/skill.yaml +14 -0
  222. package/package.json +5 -2
  223. package/.agents/core/skills/security/security.md +0 -106
@@ -0,0 +1,461 @@
1
+ /**
2
+ * bin/lib/scan.js
3
+ * ContextOS Staged Index Scanner & Code Governance Engine
4
+ *
5
+ * Inspects Git staged changes for:
6
+ * 1. Hardcoded secrets, API tokens, private keys, and blocked files
7
+ * 2. Unfinished lazy placeholder stubs in newly added code
8
+ * 3. Scope containment violations against declared task scopes
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const {
16
+ findGitRoot,
17
+ getStagedFiles,
18
+ getStagedBlob,
19
+ getStagedAddedLines,
20
+ } = require('./git-snapshot.js');
21
+
22
+ // ── Blocked File Names and Extensions ───────────────────────────────────────
23
+
24
+ const BLOCKED_EXACT_NAMES = new Set([
25
+ '.env',
26
+ '.env.local',
27
+ '.env.production',
28
+ '.env.development',
29
+ '.env.staging',
30
+ '.env.test',
31
+ '.netrc',
32
+ '.git-credentials',
33
+ '.npmrc',
34
+ 'credentials.json',
35
+ 'service-account.json',
36
+ 'serviceaccountkey.json',
37
+ 'id_rsa',
38
+ 'id_ed25519',
39
+ 'mcp_config.json',
40
+ ]);
41
+
42
+ const BLOCKED_EXTENSIONS = new Set([
43
+ '.key',
44
+ '.pem',
45
+ '.pfx',
46
+ '.p12',
47
+ '.pkcs12',
48
+ ]);
49
+
50
+ // ── Secret Content Patterns ──────────────────────────────────────────────────
51
+
52
+ const SECRET_PATTERNS = [
53
+ {
54
+ ruleId: 'SEC-001',
55
+ name: 'Private Key Header',
56
+ pattern: /-----BEGIN\s+(?:RSA|OPENSSH|EC|DSA|PGP)?\s*PRIVATE\s+KEY-----/,
57
+ },
58
+ {
59
+ ruleId: 'SEC-002',
60
+ name: 'Hardcoded User Home Path Leak',
61
+ pattern: /(?:[a-zA-Z]:[/\\]Users[/\\]|\/(?:home|Users)\/)[a-zA-Z0-9_-]+[/\\](?:Desktop|Documents|Downloads|code|projects|repos)\b/i,
62
+ },
63
+ {
64
+ ruleId: 'SEC-003',
65
+ name: 'GitHub Personal Access Token',
66
+ pattern: /\b(?:ghp|gho)_[A-Za-z0-9]{36}\b/,
67
+ },
68
+ {
69
+ ruleId: 'SEC-004',
70
+ name: 'GitHub Fine-Grained PAT',
71
+ pattern: /\bgithub_pat_[A-Za-z0-9_]{82}\b/,
72
+ },
73
+ {
74
+ ruleId: 'SEC-005',
75
+ name: 'Google API Key',
76
+ pattern: /\bAIza[A-Za-z0-9_-]{35}\b/,
77
+ },
78
+ {
79
+ ruleId: 'SEC-006',
80
+ name: 'OpenAI API Key',
81
+ pattern: /\bsk-[A-Za-z0-9]{32,}\b/,
82
+ },
83
+ {
84
+ ruleId: 'SEC-007',
85
+ name: 'Anthropic API Key',
86
+ pattern: /\bsk-ant-[A-Za-z0-9-]{90,}\b/,
87
+ },
88
+ {
89
+ ruleId: 'SEC-008',
90
+ name: 'OpenRouter API Key',
91
+ pattern: /\bsk-or-v1-[a-f0-9]{64}\b/,
92
+ },
93
+ {
94
+ ruleId: 'SEC-009',
95
+ name: 'Slack Token',
96
+ pattern: /\bxox[baprs]-[A-Za-z0-9_-]{10,48}\b/,
97
+ },
98
+ {
99
+ ruleId: 'SEC-010',
100
+ name: 'npm Access Token',
101
+ pattern: /\bnpm_[A-Za-z0-9]{32,36}\b/,
102
+ },
103
+ {
104
+ ruleId: 'SEC-011',
105
+ name: 'AWS Access Key ID',
106
+ pattern: /\bAKIA[0-9A-Z]{16}\b/,
107
+ },
108
+ ];
109
+
110
+ // ── Lazy Placeholder Patterns ───────────────────────────────────────────────
111
+
112
+ const PLACEHOLDER_PATTERNS = [
113
+ {
114
+ ruleId: 'CODE-001',
115
+ name: 'Lazy Stub Comment',
116
+ pattern: /(?:\/\/|\/\*|#)\s*(?:TODO:\s*implement later|\.\.\.\s*rest of code stays here\s*\.\.\.|TODO:\s*implement\b)/i,
117
+ },
118
+ {
119
+ ruleId: 'CODE-002',
120
+ name: 'NotImplementedError Stub',
121
+ pattern: /raise\s+NotImplementedError\s*\(\s*["'].*TODO.*["']\s*\)/i,
122
+ },
123
+ {
124
+ ruleId: 'CODE-003',
125
+ name: 'Python Pass Stub',
126
+ pattern: /^\s*pass\s*#\s*TODO\b/i,
127
+ },
128
+ ];
129
+
130
+ // Exempt path segments and exact files (e.g. test fixtures, test files)
131
+ const EXEMPT_SEGMENTS = new Set([
132
+ 'tests',
133
+ '.git',
134
+ 'node_modules',
135
+ ]);
136
+
137
+ const EXEMPT_EXACT_PATHS = new Set([
138
+ 'scripts/check-secrets.js',
139
+ 'bin/lib/scan.js',
140
+ ]);
141
+
142
+ function isExempt(filePath) {
143
+ const norm = filePath.replace(/\\/g, '/');
144
+ if (EXEMPT_EXACT_PATHS.has(norm)) {
145
+ return true;
146
+ }
147
+ const segments = norm.split('/');
148
+ return segments.some(seg => EXEMPT_SEGMENTS.has(seg));
149
+ }
150
+
151
+ function redact(str) {
152
+ if (str.length <= 8) return '***';
153
+ return str.slice(0, 4) + '...' + str.slice(-4);
154
+ }
155
+
156
+ /**
157
+ * Checks if a relative path matches a glob pattern or prefix with strict segment boundaries.
158
+ */
159
+ function matchesScope(filePath, pattern) {
160
+ const normFile = filePath.replace(/\\/g, '/').toLowerCase();
161
+ const normPattern = pattern.replace(/\\/g, '/').toLowerCase();
162
+
163
+ if (normPattern.endsWith('/**')) {
164
+ const prefix = normPattern.slice(0, -3);
165
+ return normFile === prefix || normFile.startsWith(prefix + '/');
166
+ }
167
+ if (normPattern.endsWith('/*')) {
168
+ const prefix = normPattern.slice(0, -2);
169
+ if (!normFile.startsWith(prefix + '/')) return false;
170
+ const rest = normFile.slice(prefix.length + 1);
171
+ return !rest.includes('/');
172
+ }
173
+ if (normPattern.includes('*')) {
174
+ const reg = new RegExp('^' + normPattern.replace(/\./g, '\\.').replace(/\*/g, '[^/]*') + '$');
175
+ return reg.test(normFile);
176
+ }
177
+ return normFile === normPattern || normFile.startsWith(normPattern + '/');
178
+ }
179
+
180
+ /**
181
+ * Runs the staged scanner on the given repository root.
182
+ *
183
+ * @param {Object} options - Scan configuration options
184
+ * @returns {Object} Structured scan results with findings and status code
185
+ */
186
+ function runScan(options = {}) {
187
+ const cwd = path.resolve(options.cwd || process.cwd());
188
+ const gitRoot = findGitRoot(cwd);
189
+
190
+ if (!gitRoot) {
191
+ return {
192
+ ok: false,
193
+ code: 2,
194
+ error: 'Not a Git repository. ContextOS scanner requires Git.',
195
+ findings: [],
196
+ stats: { filesScanned: 0, violations: 0 },
197
+ };
198
+ }
199
+
200
+ const checkSecrets = options.secrets !== false;
201
+ const checkPlaceholders = Boolean(options.placeholders);
202
+ const enforce = Boolean(options.enforce);
203
+
204
+ let targetScopeFile = options.scope || null;
205
+ let scopeStatus = 'not_configured';
206
+
207
+ if (!targetScopeFile) {
208
+ const defaultScope = path.join(gitRoot, '.agents', 'task-scope.json');
209
+ if (fs.existsSync(defaultScope)) {
210
+ targetScopeFile = '.agents/task-scope.json';
211
+ }
212
+ }
213
+
214
+ let allowedScopePatterns = null;
215
+ if (targetScopeFile) {
216
+ const resolvedScopePath = path.resolve(gitRoot, targetScopeFile);
217
+ if (!fs.existsSync(resolvedScopePath)) {
218
+ return {
219
+ ok: false,
220
+ code: 2,
221
+ error: `Scope file not found: ${targetScopeFile}`,
222
+ findings: [],
223
+ stats: { filesScanned: 0, violations: 0 },
224
+ };
225
+ }
226
+ try {
227
+ const scopeData = JSON.parse(fs.readFileSync(resolvedScopePath, 'utf8'));
228
+ const list = Array.isArray(scopeData) ? scopeData : scopeData.allowedPaths || scopeData.files;
229
+ if (!Array.isArray(list)) {
230
+ throw new Error('Scope declaration must be an array of paths or have an allowedPaths array');
231
+ }
232
+ for (const p of list) {
233
+ if (path.isAbsolute(p) || p.includes('..')) {
234
+ throw new Error(`Scope entry "${p}" is invalid (must be relative and cannot traverse outside repo)`);
235
+ }
236
+ }
237
+ allowedScopePatterns = list;
238
+ scopeStatus = `active (${targetScopeFile})`;
239
+ } catch (err) {
240
+ return {
241
+ ok: false,
242
+ code: 2,
243
+ error: `Invalid task scope file: ${err.message}`,
244
+ findings: [],
245
+ stats: { filesScanned: 0, violations: 0 },
246
+ };
247
+ }
248
+ }
249
+
250
+ let stagedEntries = [];
251
+ try {
252
+ stagedEntries = getStagedFiles(gitRoot);
253
+ } catch (err) {
254
+ return {
255
+ ok: false,
256
+ code: 2,
257
+ error: `Failed to inspect Git index: ${err.message}`,
258
+ findings: [],
259
+ stats: { filesScanned: 0, violations: 0 },
260
+ };
261
+ }
262
+
263
+ const findings = [];
264
+ let addedLinesMap = new Map();
265
+ if (checkPlaceholders) {
266
+ try {
267
+ const activePaths = stagedEntries.filter(e => e.status !== 'D').map(e => e.path);
268
+ addedLinesMap = getStagedAddedLines(gitRoot, activePaths);
269
+ } catch (err) {
270
+ return {
271
+ ok: false,
272
+ code: 2,
273
+ error: `Failed to inspect staged added lines: ${err.message}`,
274
+ findings: [],
275
+ stats: { filesScanned: stagedEntries.length, violations: 0 },
276
+ };
277
+ }
278
+ }
279
+
280
+ for (const entry of stagedEntries) {
281
+ const relPath = entry.path;
282
+ const baseName = path.basename(relPath).toLowerCase();
283
+ const extName = path.extname(relPath).toLowerCase();
284
+
285
+ // 1. Scope Containment Check (checked for ALL staged actions: added, modified, deleted, renamed)
286
+ if (allowedScopePatterns) {
287
+ const inScope = allowedScopePatterns.some(p => matchesScope(relPath, p));
288
+ if (!inScope) {
289
+ findings.push({
290
+ ruleId: 'SCOPE-001',
291
+ file: relPath,
292
+ type: 'Scope Violation',
293
+ severity: 'error',
294
+ details: `Staged file "${relPath}" is outside allowed task scope`,
295
+ });
296
+ }
297
+ if (entry.oldPath) {
298
+ const oldInScope = allowedScopePatterns.some(p => matchesScope(entry.oldPath, p));
299
+ if (!oldInScope) {
300
+ findings.push({
301
+ ruleId: 'SCOPE-001',
302
+ file: entry.oldPath,
303
+ type: 'Scope Violation',
304
+ severity: 'error',
305
+ details: `Source file of rename "${entry.oldPath}" is outside allowed task scope`,
306
+ });
307
+ }
308
+ }
309
+ }
310
+
311
+ // Skip deleted files from content and blocked filename checks
312
+ if (entry.status === 'D') continue;
313
+
314
+ // 2. Blocked Exact Names Check
315
+ if (checkSecrets && BLOCKED_EXACT_NAMES.has(baseName)) {
316
+ findings.push({
317
+ ruleId: 'SEC-000',
318
+ file: relPath,
319
+ type: 'Blocked Filename',
320
+ severity: 'error',
321
+ details: `Filename "${baseName}" is forbidden from being committed into Git.`,
322
+ });
323
+ continue;
324
+ }
325
+
326
+ // 3. Blocked Extensions Check
327
+ if (checkSecrets && BLOCKED_EXTENSIONS.has(extName)) {
328
+ findings.push({
329
+ ruleId: 'SEC-000',
330
+ file: relPath,
331
+ type: 'Blocked Extension',
332
+ severity: 'error',
333
+ details: `Extension "${extName}" indicates private cryptographic keys or certificates.`,
334
+ });
335
+ continue;
336
+ }
337
+
338
+ // Skip content scan for exempt paths
339
+ if (isExempt(relPath)) continue;
340
+
341
+ // Read blob from index (fails closed with code 2 on read errors in any mode)
342
+ let blob;
343
+ try {
344
+ blob = getStagedBlob(relPath, gitRoot);
345
+ } catch (err) {
346
+ return {
347
+ ok: false,
348
+ code: 2,
349
+ error: `Failed to read staged blob for "${relPath}": ${err.message}`,
350
+ findings,
351
+ stats: { filesScanned: stagedEntries.length, violations: findings.length },
352
+ };
353
+ }
354
+
355
+ if (!blob) {
356
+ return {
357
+ ok: false,
358
+ code: 2,
359
+ error: `Failed to read staged blob for "${relPath}": file unreadable in git index`,
360
+ findings,
361
+ stats: { filesScanned: stagedEntries.length, violations: findings.length },
362
+ };
363
+ }
364
+
365
+ // Large files (> 2MB): fail-closed in enforce mode
366
+ if (blob.length > 2 * 1024 * 1024) {
367
+ if (enforce) {
368
+ findings.push({
369
+ ruleId: 'SCAN-SKIP-001',
370
+ file: relPath,
371
+ type: 'Skipped Large File',
372
+ severity: 'error',
373
+ details: `Staged file "${relPath}" exceeds 2MB limit (${(blob.length / (1024 * 1024)).toFixed(2)}MB) and cannot be verified for secrets in enforce mode.`,
374
+ });
375
+ }
376
+ continue;
377
+ }
378
+
379
+ const content = blob.toString('utf8');
380
+ const lines = content.split(/\r?\n/);
381
+
382
+ // 4. Staged Content Secrets Check
383
+ if (checkSecrets) {
384
+ for (let lineNum = 1; lineNum <= lines.length; lineNum++) {
385
+ const line = lines[lineNum - 1];
386
+ for (const { ruleId, name, pattern } of SECRET_PATTERNS) {
387
+ const match = line.match(pattern);
388
+ if (match) {
389
+ findings.push({
390
+ ruleId,
391
+ file: relPath,
392
+ line: lineNum,
393
+ type: name,
394
+ severity: 'error',
395
+ details: `Detected pattern "${name}": ${redact(match[0])}`,
396
+ });
397
+ }
398
+ }
399
+ }
400
+ }
401
+
402
+ // 5. Newly Added Code Placeholders Check
403
+ if (checkPlaceholders && addedLinesMap.has(relPath)) {
404
+ const addedLines = addedLinesMap.get(relPath);
405
+ // Skip markdown and doc files for placeholder checks
406
+ if (extName !== '.md' && extName !== '.txt') {
407
+ for (const { line, content: addedLine } of addedLines) {
408
+ if (addedLine.includes('contextos:allow-placeholder')) continue;
409
+
410
+ for (const { ruleId, name, pattern } of PLACEHOLDER_PATTERNS) {
411
+ const match = addedLine.match(pattern);
412
+ if (match) {
413
+ findings.push({
414
+ ruleId,
415
+ file: relPath,
416
+ line,
417
+ type: name,
418
+ severity: 'warning',
419
+ details: `Detected un-implemented placeholder stub: "${match[0].trim()}"`,
420
+ });
421
+ }
422
+ }
423
+ }
424
+ }
425
+ }
426
+ }
427
+
428
+ const hasViolations = findings.length > 0;
429
+ // If enforce is true, violations return code 1. If enforce is false, warnings return code 0.
430
+ // Incomplete/failed inspection returns code 2 in all modes.
431
+ const exitCode = hasViolations && enforce ? 1 : 0;
432
+
433
+ return {
434
+ ok: exitCode === 0,
435
+ code: exitCode,
436
+ message: exitCode === 0 ? 'Verification completed cleanly, no blocking violations' : 'Blocking violations detected in staged index',
437
+ gitRoot,
438
+ enforce,
439
+ scope: {
440
+ file: targetScopeFile,
441
+ status: scopeStatus,
442
+ },
443
+ findings,
444
+ stats: {
445
+ stagedFilesCount: stagedEntries.length,
446
+ violationsCount: findings.length,
447
+ errorsCount: findings.filter(f => f.severity === 'error').length,
448
+ warningsCount: findings.filter(f => f.severity === 'warning').length,
449
+ },
450
+ };
451
+ }
452
+
453
+ module.exports = {
454
+ runScan,
455
+ BLOCKED_EXACT_NAMES,
456
+ BLOCKED_EXTENSIONS,
457
+ SECRET_PATTERNS,
458
+ PLACEHOLDER_PATTERNS,
459
+ matchesScope,
460
+ redact,
461
+ };
@@ -0,0 +1,19 @@
1
+ # adapters Examples - Anti-patterns vs ContextOS Standard
2
+
3
+ ## Example 1: Multi-Agent Configuration
4
+
5
+ ### Anti-pattern: Manually Syncing 6 Different Rule Files
6
+
7
+ ```text
8
+ Editing .cursorrules, then forgetting to update CLAUDE.md, then editing copilot-instructions.md.
9
+ Rules diverge across teammates using different IDEs.
10
+ ```
11
+
12
+ ### Best practice: ContextOS Standard (Single Source of Truth)
13
+
14
+ ```bash
15
+ # Edit skills once in .agents/core/skills/
16
+ # Compile to all agents with one command:
17
+ node .agents/ctx.js export all
18
+ # Automatically updates .cursorrules, CLAUDE.md, copilot-instructions.md, .aider, .zed
19
+ ```
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: adapters
3
+ description: >
4
+ Generates agent-specific configuration files from the unified ContextOS format.
5
+ One internal system, multiple output formats for Claude, Gemini, Copilot,
6
+ Cursor, Aider, Continue, OpenHands, and others.
7
+ ---
8
+
9
+ # agent-adapters
10
+
11
+ ## Overview
12
+
13
+ Unified cross-agent configuration engine. Translates single ContextOS source rules into optimized native formats for Claude Code (CLAUDE.md), Gemini (.agents/skills), Cursor (.cursorrules, .cursor/rules/*.mdc), GitHub Copilot, Zed, Aider, and Continue.
14
+
15
+ ## When to Use
16
+
17
+ Activate when configuring, synchronizing, or exporting agent rules and skills across multiple IDEs and AI programming assistants.
18
+
19
+ ## Rules & Patterns
20
+
21
+ ContextOS is agent-agnostic. This skill generates the right config format for any AI agent.
22
+
23
+ ## Supported Agents
24
+
25
+ | Agent | Config Target | Format |
26
+ | --- | --- | --- |
27
+ | **Gemini / Antigravity** | `.agents/generated/gemini/skills/` | Native modular skills |
28
+ | **Claude Code** | `.agents/generated/claude/skills/` | Aggregated markdown skills |
29
+ | **GitHub Copilot** | `.github/copilot-instructions.md` | Single instructions file with on-demand skill references |
30
+ | **Cursor** | `.cursor/rules/*.mdc` + `.cursorrules` | MDC modular glob rules + fallback |
31
+ | **Aider** | `.aider.conf.yml` + `CONVENTIONS.md` | YAML config + conventions markdown |
32
+ | **Zed IDE** | `.zed/rules.md` + `.zed/prompts/*.md` | Native rules and prompt templates |
33
+
34
+ ## Generation Commands
35
+
36
+ - `contextos export <agent>` (or `node .agents/ctx.js export <agent>`) - Generate config for a specific agent (`gemini`, `claude`, `cursor`, `copilot`, `aider`, `zed`).
37
+ - `contextos export all` - Generate configs for all supported agents in a single transaction.
38
+
39
+ ## Adapter Logic
40
+
41
+ ### For Claude Code (`CLAUDE.md`)
42
+
43
+ Compile into a single markdown file:
44
+
45
+ 1. Project overview from `docs/PRD.md` (summary only)
46
+ 2. Architecture summary from `docs/ARCHITECTURE.md`
47
+ 3. Coding rules from loaded skills
48
+ 4. Active Decision Records
49
+ 5. Current tasks from `docs/TASKS.md`
50
+
51
+ ### For Gemini (`.agents/AGENTS.md`)
52
+
53
+ Already native format. Just ensure:
54
+
55
+ 1. `AGENTS.md` references the skill directory
56
+ 2. Skills have proper SKILL.md with frontmatter
57
+ 3. Context Manager rules are in AGENTS.md
58
+
59
+ ### For Cursor (`.cursorrules`)
60
+
61
+ Compile into a flat text file:
62
+
63
+ 1. Project context (condensed)
64
+ 2. Coding style rules
65
+ 3. Framework-specific instructions
66
+ 4. Anti-patterns to avoid
67
+
68
+ ### For Aider (`.aider.conf.yml`)
69
+
70
+ ```yaml
71
+ read:
72
+ - docs/ARCHITECTURE.md
73
+ - docs/API.md
74
+ - docs/PROJECT_GRAPH.md
75
+ conventions:
76
+ - {{coding rules from skills}}
77
+ ```
78
+
79
+ ## Sync Rules
80
+
81
+ - Adapters read from the canonical ContextOS documents
82
+ - Never edit adapter output files directly
83
+ - Re-run `contextos export all` after any skill or rule change
84
+ - Each adapter file includes a header: `# Generated by ContextOS - do not edit directly`
85
+
86
+
87
+ ## Code Examples
88
+
89
+ See `EXAMPLES.md` for detailed code examples.
90
+
91
+ ## Validation Checklist
92
+
93
+ What to verify during the review phase before completing the task.
94
+
95
+ ## Common Mistakes
96
+
97
+ Anti-patterns and things to explicitly avoid. See `TROUBLESHOOTING.md`.
98
+
99
+ ## Integration Notes
100
+
101
+ How this skill interacts with other skills.
@@ -0,0 +1,7 @@
1
+ # adapters Troubleshooting & Common Mistakes
2
+
3
+ ## 1. Overwriting Custom Configs
4
+
5
+ - **Symptom**: Custom non-ContextOS rules wiped out during export.
6
+ - **Root Cause**: Running export with force flags over unmanaged files.
7
+ - **Fix**: Keep custom project overrides in dedicated config files or use plugin skills.
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "rules_followed": {
6
+ "type": "boolean"
7
+ }
8
+ },
9
+ "required": [
10
+ "rules_followed"
11
+ ]
12
+ }
@@ -0,0 +1,13 @@
1
+ schemaVersion: 2
2
+ name: adapters
3
+ category: engineering
4
+ type: compiler
5
+ description: >
6
+ Generates agent-specific configuration files from unified ContextOS format.
7
+ Produces configs for Claude, Gemini, Copilot, Cursor, Aider, Continue, and Zed.
8
+ version: 1.0.0
9
+ resources:
10
+ - EXAMPLES.md
11
+ - SKILL.md
12
+ - TROUBLESHOOTING.md
13
+ - VALIDATION.json
@@ -0,0 +1,91 @@
1
+ # API Design - Examples & Best Practices
2
+
3
+ ## Example 1: Contract-First Interface with Zod & TypeScript
4
+
5
+ ```typescript
6
+ import { z } from 'zod';
7
+
8
+ // 1. Unified Contract Definition
9
+ export const CreateTaskSchema = z.object({
10
+ title: z.string().min(1, 'Title is required').max(120, 'Title exceeds max length'),
11
+ description: z.string().max(1000).optional(),
12
+ priority: z.enum(['low', 'medium', 'high']).default('medium')
13
+ });
14
+
15
+ export type CreateTaskInput = z.infer<typeof CreateTaskSchema>;
16
+
17
+ export interface TaskDTO {
18
+ id: string;
19
+ title: string;
20
+ description: string | null;
21
+ priority: 'low' | 'medium' | 'high';
22
+ createdAt: string; // ISO 8601 string
23
+ }
24
+
25
+ export interface APIErrorResponse {
26
+ error: {
27
+ code: string;
28
+ message: string;
29
+ details?: Array<{ field: string; message: string }>;
30
+ };
31
+ }
32
+
33
+ // 2. Safe Edge Controller
34
+ export async function handleCreateTask(
35
+ body: unknown,
36
+ createTaskService: (input: CreateTaskInput) => Promise<TaskDTO>
37
+ ): Promise<{ status: number; data: TaskDTO | APIErrorResponse }> {
38
+ const result = CreateTaskSchema.safeParse(body);
39
+
40
+ if (!result.success) {
41
+ return {
42
+ status: 422,
43
+ data: {
44
+ error: {
45
+ code: 'VALIDATION_FAILED',
46
+ message: 'Request payload failed schema validation',
47
+ details: result.error.errors.map(err => ({
48
+ field: err.path.join('.'),
49
+ message: err.message
50
+ }))
51
+ }
52
+ }
53
+ };
54
+ }
55
+
56
+ const task = await createTaskService(result.data);
57
+ return { status: 201, data: task };
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Example 2: Idempotent Mutation Handler
64
+
65
+ ```typescript
66
+ import crypto from 'node:crypto';
67
+
68
+ interface IdempotencyStore {
69
+ get(key: string): Promise<{ status: number; body: unknown } | null>;
70
+ set(key: string, result: { status: number; body: unknown }, ttlSeconds: number): Promise<void>;
71
+ }
72
+
73
+ export async function withIdempotency<T>(
74
+ key: string | undefined,
75
+ store: IdempotencyStore,
76
+ handler: () => Promise<{ status: number; body: T }>
77
+ ): Promise<{ status: number; body: T }> {
78
+ if (!key) {
79
+ return handler();
80
+ }
81
+
82
+ const cached = await store.get(key);
83
+ if (cached) {
84
+ return cached as { status: number; body: T };
85
+ }
86
+
87
+ const response = await handler();
88
+ await store.set(key, response, 86400); // 24-hour cache
89
+ return response;
90
+ }
91
+ ```