contextos-agents 1.7.0 → 2.0.0-beta.3
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/.agents/AGENTS.md +16 -50
- package/.agents/adapters/aider/export.js +117 -99
- package/.agents/adapters/claude/export.js +68 -26
- package/.agents/adapters/copilot/export.js +90 -53
- package/.agents/adapters/cursor/export.js +100 -104
- package/.agents/adapters/drift-detector.js +196 -0
- package/.agents/adapters/gemini/export.js +76 -45
- package/.agents/adapters/pure-compiler.js +443 -0
- package/.agents/adapters/zed/export.js +104 -96
- package/.agents/compiled/registry.v2.json +504 -0
- package/.agents/compiled/registry.v2.sha256 +1 -0
- package/.agents/compiler/manifest-compiler.js +963 -0
- package/.agents/compiler/vendor/yaml.LICENSE.txt +13 -0
- package/.agents/compiler/vendor/yaml.SBOM.json +6 -0
- package/.agents/compiler/vendor/yaml.js +139 -0
- package/.agents/core/profiles/init.yaml +25 -0
- package/.agents/core/skills/context-manager/skill.yaml +3 -5
- package/.agents/core/skills/context-os/SKILL.md +3 -6
- package/.agents/core/skills/context-os/skill.yaml +3 -8
- package/.agents/core/skills/engineering-workflow/skill.yaml +1 -7
- package/.agents/core/skills/gemini-precision/skill.yaml +1 -6
- package/.agents/core/skills/gstack-roles/skill.yaml +3 -6
- package/.agents/core/skills/ponytail-mindset/skill.yaml +1 -7
- package/.agents/core/skills/security/skill.yaml +15 -3
- package/.agents/ctx.js +537 -112
- package/.agents/customization-dx.js +282 -0
- package/.agents/doctor.js +855 -66
- package/.agents/filesystem/index.js +71 -0
- package/.agents/filesystem/journaled-transaction.js +451 -0
- package/.agents/filesystem/lockfile-v2.js +275 -0
- package/.agents/filesystem/platform-hardening.js +222 -0
- package/.agents/filesystem/project-lock.js +218 -0
- package/.agents/filesystem/safe-path.js +256 -0
- package/.agents/generated/claude/skills/context-os/SKILL.md +1 -1
- package/.agents/generated/gemini/skills/context-os/SKILL.md +2 -2
- package/.agents/plugins/contextos/plugin.json +1 -1
- package/.agents/plugins.js +278 -64
- package/.agents/profiles.js +486 -51
- package/.agents/resolver/canonical-resolver.js +1348 -0
- package/.agents/resolver.js +50 -534
- package/.agents/rules/rule-catalog.js +525 -0
- package/.agents/schemas/attestation.review.v1.json +111 -0
- package/.agents/schemas/attestation.verification.v1.json +85 -0
- package/.agents/schemas/lockfile.v2.schema.json +134 -0
- package/.agents/schemas/profile.v2.schema.json +114 -0
- package/.agents/schemas/runtime.thread.v1.json +192 -0
- package/.agents/schemas/skill.manifest.v2.json +177 -0
- package/.agents/schemas/verification.spec.v1.json +39 -0
- package/.agents/schemas/workspace.graph.schema.json +106 -0
- package/.agents/skills-index.json +6 -166
- package/.agents/stats.js +9 -9
- package/.agents/transaction-core/event-store.js +288 -0
- package/.agents/transaction-core/idempotency.js +129 -0
- package/.agents/transaction-core/ipc-lock.js +311 -0
- package/.agents/transaction-core/plugin-supply-chain-bundle.js +436 -0
- package/.agents/validate.js +44 -1
- package/.agents/watch.js +354 -102
- package/.agents/workspace/workspace-graph.js +778 -0
- package/README.md +59 -387
- package/benchmarks/v2/analysis/statistics.js +140 -0
- package/benchmarks/v2/analysis/stats.js +69 -0
- package/benchmarks/v2/arms/arm-definitions.js +79 -0
- package/benchmarks/v2/dataset.schema.json +34 -0
- package/benchmarks/v2/evaluators/index.js +25 -0
- package/benchmarks/v2/evaluators/verified-success.js +116 -0
- package/benchmarks/v2/harness/runner.js +88 -0
- package/benchmarks/v2/pilot-tasks.json +392 -0
- package/bin/commands/recover.js +88 -0
- package/bin/commands/update.js +80 -17
- package/bin/commands.js +62 -25
- package/bin/index.js +138 -81
- package/bin/lib/lockfile.js +5 -3
- package/bin/lib/safe-writer.js +34 -3
- package/package.json +87 -72
- package/registry.json +2 -2
- package/registry.v2.schema.json +86 -0
- package/.agents/core/profiles/backend.yaml +0 -47
- package/.agents/core/profiles/enterprise.yaml +0 -46
- package/.agents/core/profiles/frontend.yaml +0 -46
- package/.agents/core/profiles/hackathon.yaml +0 -45
- package/.agents/core/profiles/mvp.yaml +0 -44
- package/.agents/core/profiles/startup.yaml +0 -48
- package/.agents/core/skills/adapters/EXAMPLES.md +0 -19
- package/.agents/core/skills/adapters/SKILL.md +0 -105
- package/.agents/core/skills/adapters/TROUBLESHOOTING.md +0 -7
- package/.agents/core/skills/adapters/VALIDATION.json +0 -12
- package/.agents/core/skills/adapters/skill.yaml +0 -16
- package/.agents/core/skills/architecture-diagrams/SKILL.md +0 -108
- package/.agents/core/skills/architecture-diagrams/VALIDATION.json +0 -12
- package/.agents/core/skills/architecture-diagrams/skill.yaml +0 -12
- package/.agents/core/skills/brutalist-design/SKILL.md +0 -150
- package/.agents/core/skills/brutalist-design/VALIDATION.json +0 -12
- package/.agents/core/skills/brutalist-design/skill.yaml +0 -12
- package/.agents/core/skills/database/EXAMPLES.md +0 -74
- package/.agents/core/skills/database/SKILL.md +0 -101
- package/.agents/core/skills/database/TROUBLESHOOTING.md +0 -18
- package/.agents/core/skills/database/VALIDATION.json +0 -11
- package/.agents/core/skills/database/skill.yaml +0 -31
- package/.agents/core/skills/ddd/EXAMPLES.md +0 -42
- package/.agents/core/skills/ddd/SKILL.md +0 -247
- package/.agents/core/skills/ddd/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/ddd/VALIDATION.json +0 -12
- package/.agents/core/skills/ddd/ddd.md +0 -178
- package/.agents/core/skills/ddd/skill.yaml +0 -17
- package/.agents/core/skills/decisions/EXAMPLES.md +0 -35
- package/.agents/core/skills/decisions/SKILL.md +0 -90
- package/.agents/core/skills/decisions/TROUBLESHOOTING.md +0 -13
- package/.agents/core/skills/decisions/VALIDATION.json +0 -12
- package/.agents/core/skills/decisions/skill.yaml +0 -16
- package/.agents/core/skills/docker/EXAMPLES.md +0 -56
- package/.agents/core/skills/docker/SKILL.md +0 -63
- package/.agents/core/skills/docker/TROUBLESHOOTING.md +0 -18
- package/.agents/core/skills/docker/VALIDATION.json +0 -11
- package/.agents/core/skills/docker/skill.yaml +0 -29
- package/.agents/core/skills/fastapi/EXAMPLES.md +0 -36
- package/.agents/core/skills/fastapi/SKILL.md +0 -148
- package/.agents/core/skills/fastapi/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/fastapi/VALIDATION.json +0 -12
- package/.agents/core/skills/fastapi/fastapi.md +0 -112
- package/.agents/core/skills/fastapi/skill.yaml +0 -17
- package/.agents/core/skills/generators/EXAMPLES.md +0 -19
- package/.agents/core/skills/generators/SKILL.md +0 -112
- package/.agents/core/skills/generators/TROUBLESHOOTING.md +0 -7
- package/.agents/core/skills/generators/VALIDATION.json +0 -12
- package/.agents/core/skills/generators/skill.yaml +0 -25
- package/.agents/core/skills/generators/templates/API.md +0 -77
- package/.agents/core/skills/generators/templates/ARCHITECTURE.md +0 -70
- package/.agents/core/skills/generators/templates/DATABASE.md +0 -42
- package/.agents/core/skills/generators/templates/DECISION.md +0 -46
- package/.agents/core/skills/generators/templates/PRD.md +0 -67
- package/.agents/core/skills/generators/templates/PROJECT_GRAPH.md +0 -56
- package/.agents/core/skills/generators/templates/ROADMAP.md +0 -51
- package/.agents/core/skills/generators/templates/TASKS.md +0 -43
- package/.agents/core/skills/generators/templates/UI.md +0 -73
- package/.agents/core/skills/graphify/EXAMPLES.md +0 -73
- package/.agents/core/skills/graphify/SKILL.md +0 -130
- package/.agents/core/skills/graphify/VALIDATION.json +0 -12
- package/.agents/core/skills/graphify/skill.yaml +0 -18
- package/.agents/core/skills/impeccable-design/EXAMPLES.md +0 -26
- package/.agents/core/skills/impeccable-design/SKILL.md +0 -201
- package/.agents/core/skills/impeccable-design/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/impeccable-design/VALIDATION.json +0 -12
- package/.agents/core/skills/impeccable-design/skill.yaml +0 -20
- package/.agents/core/skills/interview-me/SKILL.md +0 -97
- package/.agents/core/skills/interview-me/VALIDATION.json +0 -12
- package/.agents/core/skills/interview-me/skill.yaml +0 -12
- package/.agents/core/skills/microservices/EXAMPLES.md +0 -38
- package/.agents/core/skills/microservices/SKILL.md +0 -164
- package/.agents/core/skills/microservices/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/microservices/VALIDATION.json +0 -12
- package/.agents/core/skills/microservices/microservices.md +0 -119
- package/.agents/core/skills/microservices/skill.yaml +0 -17
- package/.agents/core/skills/minimalist-design/SKILL.md +0 -113
- package/.agents/core/skills/minimalist-design/VALIDATION.json +0 -12
- package/.agents/core/skills/minimalist-design/skill.yaml +0 -12
- package/.agents/core/skills/nestjs/EXAMPLES.md +0 -40
- package/.agents/core/skills/nestjs/SKILL.md +0 -139
- package/.agents/core/skills/nestjs/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/nestjs/VALIDATION.json +0 -12
- package/.agents/core/skills/nestjs/nestjs.md +0 -103
- package/.agents/core/skills/nestjs/skill.yaml +0 -17
- package/.agents/core/skills/nextjs/EXAMPLES.md +0 -40
- package/.agents/core/skills/nextjs/SKILL.md +0 -163
- package/.agents/core/skills/nextjs/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/nextjs/VALIDATION.json +0 -12
- package/.agents/core/skills/nextjs/nextjs.md +0 -67
- package/.agents/core/skills/nextjs/skill.yaml +0 -17
- package/.agents/core/skills/node/EXAMPLES.md +0 -80
- package/.agents/core/skills/node/SKILL.md +0 -128
- package/.agents/core/skills/node/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/node/VALIDATION.json +0 -12
- package/.agents/core/skills/node/node.md +0 -87
- package/.agents/core/skills/node/skill.yaml +0 -17
- package/.agents/core/skills/performance/EXAMPLES.md +0 -30
- package/.agents/core/skills/performance/SKILL.md +0 -75
- package/.agents/core/skills/performance/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/performance/VALIDATION.json +0 -12
- package/.agents/core/skills/performance/performance.md +0 -52
- package/.agents/core/skills/performance/skill.yaml +0 -17
- package/.agents/core/skills/react/EXAMPLES.md +0 -79
- package/.agents/core/skills/react/SKILL.md +0 -132
- package/.agents/core/skills/react/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/react/VALIDATION.json +0 -12
- package/.agents/core/skills/react/react.md +0 -93
- package/.agents/core/skills/react/skill.yaml +0 -17
- package/.agents/core/skills/react-best-practices/SKILL.md +0 -155
- package/.agents/core/skills/react-best-practices/VALIDATION.json +0 -12
- package/.agents/core/skills/react-best-practices/skill.yaml +0 -14
- package/.agents/core/skills/redesign-audit/SKILL.md +0 -117
- package/.agents/core/skills/redesign-audit/VALIDATION.json +0 -12
- package/.agents/core/skills/redesign-audit/skill.yaml +0 -12
- package/.agents/core/skills/soft-design/SKILL.md +0 -108
- package/.agents/core/skills/soft-design/VALIDATION.json +0 -12
- package/.agents/core/skills/soft-design/skill.yaml +0 -12
- package/.agents/core/skills/state-management/EXAMPLES.md +0 -56
- package/.agents/core/skills/state-management/SKILL.md +0 -48
- package/.agents/core/skills/state-management/TROUBLESHOOTING.md +0 -18
- package/.agents/core/skills/state-management/VALIDATION.json +0 -11
- package/.agents/core/skills/state-management/skill.yaml +0 -28
- package/.agents/core/skills/subagent-orchestrator/SKILL.md +0 -117
- package/.agents/core/skills/subagent-orchestrator/VALIDATION.json +0 -12
- package/.agents/core/skills/subagent-orchestrator/skill.yaml +0 -12
- package/.agents/core/skills/system-design/EXAMPLES.md +0 -75
- package/.agents/core/skills/system-design/SKILL.md +0 -419
- package/.agents/core/skills/system-design/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/system-design/VALIDATION.json +0 -12
- package/.agents/core/skills/system-design/skill.yaml +0 -20
- package/.agents/core/skills/system-design/system-design.md +0 -112
- package/.agents/core/skills/testing/EXAMPLES.md +0 -71
- package/.agents/core/skills/testing/SKILL.md +0 -70
- package/.agents/core/skills/testing/TROUBLESHOOTING.md +0 -18
- package/.agents/core/skills/testing/VALIDATION.json +0 -11
- package/.agents/core/skills/testing/skill.yaml +0 -32
- package/.agents/core/skills/typescript/EXAMPLES.md +0 -64
- package/.agents/core/skills/typescript/SKILL.md +0 -112
- package/.agents/core/skills/typescript/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/typescript/VALIDATION.json +0 -12
- package/.agents/core/skills/typescript/skill.yaml +0 -17
- package/.agents/core/skills/typescript/typescript.md +0 -71
- package/.agents/core/skills/ui-design/EXAMPLES.md +0 -21
- package/.agents/core/skills/ui-design/SKILL.md +0 -124
- package/.agents/core/skills/ui-design/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/ui-design/VALIDATION.json +0 -12
- package/.agents/core/skills/ui-design/skill.yaml +0 -17
- package/.agents/core/skills/ui-design/ui.md +0 -88
- package/.agents/core/skills/ui-ux-pro/EXAMPLES.md +0 -62
- package/.agents/core/skills/ui-ux-pro/SKILL.md +0 -375
- package/.agents/core/skills/ui-ux-pro/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/ui-ux-pro/VALIDATION.json +0 -12
- package/.agents/core/skills/ui-ux-pro/skill.yaml +0 -19
- package/.agents/core/skills/ux-design/EXAMPLES.md +0 -36
- package/.agents/core/skills/ux-design/SKILL.md +0 -116
- package/.agents/core/skills/ux-design/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/ux-design/VALIDATION.json +0 -12
- package/.agents/core/skills/ux-design/skill.yaml +0 -17
- package/.agents/core/skills/ux-design/ux.md +0 -80
- package/.agents/core/skills/vercel-optimize/SKILL.md +0 -83
- package/.agents/core/skills/vercel-optimize/VALIDATION.json +0 -12
- package/.agents/core/skills/vercel-optimize/scripts/collect-signals.mjs +0 -131
- package/.agents/core/skills/vercel-optimize/scripts/gate-investigations.mjs +0 -142
- package/.agents/core/skills/vercel-optimize/scripts/merge-signals.mjs +0 -143
- package/.agents/core/skills/vercel-optimize/scripts/scan-codebase.mjs +0 -174
- package/.agents/core/skills/vercel-optimize/skill.yaml +0 -18
- package/.agents/core/skills/web-accessibility/EXAMPLES.md +0 -39
- package/.agents/core/skills/web-accessibility/SKILL.md +0 -170
- package/.agents/core/skills/web-accessibility/TROUBLESHOOTING.md +0 -19
- package/.agents/core/skills/web-accessibility/VALIDATION.json +0 -12
- package/.agents/core/skills/web-accessibility/accessibility.md +0 -63
- package/.agents/core/skills/web-accessibility/skill.yaml +0 -17
- package/.agents/generated/claude/skills/adapters/SKILL.md +0 -126
- package/.agents/generated/claude/skills/architecture-diagrams/SKILL.md +0 -101
- package/.agents/generated/claude/skills/brutalist-design/SKILL.md +0 -145
- package/.agents/generated/claude/skills/database/SKILL.md +0 -191
- package/.agents/generated/claude/skills/ddd/SKILL.md +0 -305
- package/.agents/generated/claude/skills/decisions/SKILL.md +0 -134
- package/.agents/generated/claude/skills/docker/SKILL.md +0 -135
- package/.agents/generated/claude/skills/fastapi/SKILL.md +0 -200
- package/.agents/generated/claude/skills/generators/SKILL.md +0 -133
- package/.agents/generated/claude/skills/graphify/SKILL.md +0 -198
- package/.agents/generated/claude/skills/impeccable-design/SKILL.md +0 -241
- package/.agents/generated/claude/skills/interview-me/SKILL.md +0 -90
- package/.agents/generated/claude/skills/microservices/SKILL.md +0 -218
- package/.agents/generated/claude/skills/minimalist-design/SKILL.md +0 -108
- package/.agents/generated/claude/skills/nestjs/SKILL.md +0 -195
- package/.agents/generated/claude/skills/nextjs/SKILL.md +0 -219
- package/.agents/generated/claude/skills/node/SKILL.md +0 -224
- package/.agents/generated/claude/skills/performance/SKILL.md +0 -121
- package/.agents/generated/claude/skills/react/SKILL.md +0 -227
- package/.agents/generated/claude/skills/react-best-practices/SKILL.md +0 -146
- package/.agents/generated/claude/skills/redesign-audit/SKILL.md +0 -112
- package/.agents/generated/claude/skills/soft-design/SKILL.md +0 -103
- package/.agents/generated/claude/skills/state-management/SKILL.md +0 -120
- package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +0 -110
- package/.agents/generated/claude/skills/system-design/SKILL.md +0 -507
- package/.agents/generated/claude/skills/testing/SKILL.md +0 -157
- package/.agents/generated/claude/skills/typescript/SKILL.md +0 -192
- package/.agents/generated/claude/skills/ui-design/SKILL.md +0 -161
- package/.agents/generated/claude/skills/ui-ux-pro/SKILL.md +0 -451
- package/.agents/generated/claude/skills/ux-design/SKILL.md +0 -168
- package/.agents/generated/claude/skills/vercel-optimize/SKILL.md +0 -76
- package/.agents/generated/claude/skills/web-accessibility/SKILL.md +0 -225
- package/.agents/generated/gemini/skills/adapters/SKILL.md +0 -135
- package/.agents/generated/gemini/skills/architecture-diagrams/SKILL.md +0 -107
- package/.agents/generated/gemini/skills/brutalist-design/SKILL.md +0 -151
- package/.agents/generated/gemini/skills/database/SKILL.md +0 -200
- package/.agents/generated/gemini/skills/ddd/SKILL.md +0 -314
- package/.agents/generated/gemini/skills/decisions/SKILL.md +0 -143
- package/.agents/generated/gemini/skills/docker/SKILL.md +0 -144
- package/.agents/generated/gemini/skills/fastapi/SKILL.md +0 -209
- package/.agents/generated/gemini/skills/generators/SKILL.md +0 -142
- package/.agents/generated/gemini/skills/graphify/SKILL.md +0 -205
- package/.agents/generated/gemini/skills/impeccable-design/SKILL.md +0 -250
- package/.agents/generated/gemini/skills/interview-me/SKILL.md +0 -96
- package/.agents/generated/gemini/skills/microservices/SKILL.md +0 -227
- package/.agents/generated/gemini/skills/minimalist-design/SKILL.md +0 -114
- package/.agents/generated/gemini/skills/nestjs/SKILL.md +0 -204
- package/.agents/generated/gemini/skills/nextjs/SKILL.md +0 -298
- package/.agents/generated/gemini/skills/node/SKILL.md +0 -323
- package/.agents/generated/gemini/skills/performance/SKILL.md +0 -185
- package/.agents/generated/gemini/skills/react/SKILL.md +0 -332
- package/.agents/generated/gemini/skills/react-best-practices/SKILL.md +0 -152
- package/.agents/generated/gemini/skills/redesign-audit/SKILL.md +0 -118
- package/.agents/generated/gemini/skills/soft-design/SKILL.md +0 -109
- package/.agents/generated/gemini/skills/state-management/SKILL.md +0 -129
- package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +0 -116
- package/.agents/generated/gemini/skills/system-design/SKILL.md +0 -631
- package/.agents/generated/gemini/skills/testing/SKILL.md +0 -166
- package/.agents/generated/gemini/skills/typescript/SKILL.md +0 -275
- package/.agents/generated/gemini/skills/ui-design/SKILL.md +0 -170
- package/.agents/generated/gemini/skills/ui-ux-pro/SKILL.md +0 -460
- package/.agents/generated/gemini/skills/ux-design/SKILL.md +0 -177
- package/.agents/generated/gemini/skills/vercel-optimize/SKILL.md +0 -82
- package/.agents/generated/gemini/skills/web-accessibility/SKILL.md +0 -300
|
@@ -1,28 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .agents/adapters/cursor/export.js
|
|
3
|
+
* ContextOS Cursor Pure Adapter (.cursorrules and .cursor/rules/*.mdc)
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const fs = require('fs');
|
|
2
7
|
const path = require('path');
|
|
3
8
|
const { AGENTS_MD_PATH, collectSkillDirectories, extractYamlField, stripFrontmatter, readMeaningfulMarkdown } = require('../shared.js');
|
|
9
|
+
const { registerAdapter, applyArtifacts, createProvenanceHeader } = require('../pure-compiler.js');
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
const OUTPUT_FILE = path.join(process.cwd(), '.cursorrules');
|
|
7
|
-
const CURSOR_RULES_DIR = path.join(process.cwd(), '.cursor', 'rules');
|
|
11
|
+
const GENERATOR_ID = 'cursor@2';
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
13
|
+
function describe() {
|
|
14
|
+
return {
|
|
15
|
+
name: 'cursor',
|
|
16
|
+
version: '2.0.0',
|
|
17
|
+
description: 'Compiles modular rules for Cursor (.cursor/rules/*.mdc and legacy .cursorrules)',
|
|
18
|
+
targetPattern: '.cursor/rules/*.mdc',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
18
21
|
|
|
19
|
-
function getSkillGlobsAndFlags(skillName) {
|
|
20
|
-
const ALWAYS_APPLY_SKILLS = ['engineering-workflow', 'gstack-roles', 'ponytail-mindset'];
|
|
22
|
+
function getSkillGlobsAndFlags(skillName, skillDir = null) {
|
|
23
|
+
const ALWAYS_APPLY_SKILLS = ['engineering-workflow', 'gstack-roles', 'ponytail-mindset', 'gemini-precision'];
|
|
21
24
|
if (ALWAYS_APPLY_SKILLS.includes(skillName)) {
|
|
22
25
|
return { globs: '', alwaysApply: true };
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
//
|
|
28
|
+
// 1. Dynamic extraction from skill.yaml if available
|
|
29
|
+
if (skillDir) {
|
|
30
|
+
const yamlPath = path.join(skillDir, 'skill.yaml');
|
|
31
|
+
if (fs.existsSync(yamlPath)) {
|
|
32
|
+
try {
|
|
33
|
+
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
34
|
+
const match = yamlContent.match(/(?:fileGlobs|triggers\s*:\s*(?:files|globs)|globs)\s*:\s*\[?([^\r\n\]]+)\]?/i);
|
|
35
|
+
if (match && match[1]) {
|
|
36
|
+
const globsVal = match[1].replace(/['"]/g, '').trim();
|
|
37
|
+
if (globsVal) {
|
|
38
|
+
return { globs: globsVal, alwaysApply: false };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
const GLOB_MAP = {
|
|
27
46
|
'react': '**/*.{tsx,jsx}',
|
|
28
47
|
'react-best-practices': '**/*.{tsx,jsx}',
|
|
@@ -58,9 +77,9 @@ function getSkillGlobsAndFlags(skillName) {
|
|
|
58
77
|
}
|
|
59
78
|
|
|
60
79
|
function buildSkillSection(skillDir) {
|
|
61
|
-
const skillName
|
|
62
|
-
const skillMdPath
|
|
63
|
-
const yamlPath
|
|
80
|
+
const skillName = path.basename(skillDir);
|
|
81
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
82
|
+
const yamlPath = path.join(skillDir, 'skill.yaml');
|
|
64
83
|
|
|
65
84
|
let title = skillName;
|
|
66
85
|
let description = '';
|
|
@@ -70,9 +89,7 @@ function buildSkillSection(skillDir) {
|
|
|
70
89
|
description = extractYamlField(yaml, 'description') || '';
|
|
71
90
|
}
|
|
72
91
|
|
|
73
|
-
if (!fs.existsSync(skillMdPath))
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
92
|
+
if (!fs.existsSync(skillMdPath)) return null;
|
|
76
93
|
|
|
77
94
|
const raw = fs.readFileSync(skillMdPath, 'utf8');
|
|
78
95
|
const body = stripFrontmatter(raw);
|
|
@@ -110,7 +127,7 @@ function generateCursorMdc(skillDir) {
|
|
|
110
127
|
if (troubleshooting) raw += '\n\n' + troubleshooting;
|
|
111
128
|
|
|
112
129
|
const body = stripFrontmatter(raw);
|
|
113
|
-
const { globs, alwaysApply } = getSkillGlobsAndFlags(skillName);
|
|
130
|
+
const { globs, alwaysApply } = getSkillGlobsAndFlags(skillName, skillDir);
|
|
114
131
|
|
|
115
132
|
let cleanDescription = description.replace(/\r?\n+/g, ' ').replace(/"/g, "'").trim();
|
|
116
133
|
if (!globs && !alwaysApply) {
|
|
@@ -130,34 +147,22 @@ ${body}
|
|
|
130
147
|
return { skillName, mdcContent };
|
|
131
148
|
}
|
|
132
149
|
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const cursorRulesDir = path.join(process.cwd(), '.cursor', 'rules');
|
|
138
|
-
const agentsMdPath = fs.existsSync(path.join(process.cwd(), '.agents', 'AGENTS.md'))
|
|
139
|
-
? path.join(process.cwd(), '.agents', 'AGENTS.md')
|
|
150
|
+
function render(context) {
|
|
151
|
+
const projectRoot = context?.projectRoot || '.';
|
|
152
|
+
const agentsMdPath = fs.existsSync(path.join(projectRoot, '.agents', 'AGENTS.md'))
|
|
153
|
+
? path.join(projectRoot, '.agents', 'AGENTS.md')
|
|
140
154
|
: AGENTS_MD_PATH;
|
|
141
155
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
// ── Header ──────────────────────────────────────────────────────────────────
|
|
145
|
-
sections.push(
|
|
146
|
-
`# ContextOS — AI Rules for Cursor\n` +
|
|
147
|
-
`# Auto-generated by: node .agents/ctx.js export cursor\n` +
|
|
148
|
-
`# Source: .agents/core/skills/ · Do not edit manually.\n\n` +
|
|
149
|
-
`> **Core law: Do not read everything. Read only what the current task requires.**\n\n` +
|
|
150
|
-
`Detailed rules are modularized in \`.cursor/rules/*.mdc\` with file-glob activation.\n` +
|
|
151
|
-
`Core orchestration is handled by \`.cursor/rules/00-project-rules.mdc\`.\n`
|
|
152
|
-
);
|
|
156
|
+
const artifacts = [];
|
|
153
157
|
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
const prov = createProvenanceHeader({
|
|
159
|
+
generator: GENERATOR_ID,
|
|
160
|
+
sourceGraphHash: context?.sourceGraphHash,
|
|
161
|
+
profileId: context?.profileId,
|
|
162
|
+
profileHash: context?.profileHash,
|
|
163
|
+
});
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
let mdcCount = 0;
|
|
159
|
-
|
|
160
|
-
// Write 00-project-rules.mdc
|
|
165
|
+
// 1. 00-project-rules.mdc
|
|
161
166
|
if (fs.existsSync(agentsMdPath)) {
|
|
162
167
|
const agentsMd = fs.readFileSync(agentsMdPath, 'utf8');
|
|
163
168
|
const projectMdc = `---
|
|
@@ -166,78 +171,69 @@ globs: ""
|
|
|
166
171
|
alwaysApply: true
|
|
167
172
|
---
|
|
168
173
|
|
|
174
|
+
${prov}
|
|
169
175
|
# ContextOS — Project Operating System Rules
|
|
170
176
|
|
|
171
177
|
${agentsMd}
|
|
172
178
|
`;
|
|
173
|
-
|
|
174
|
-
|
|
179
|
+
artifacts.push({
|
|
180
|
+
path: '.cursor/rules/00-project-rules.mdc',
|
|
181
|
+
content: projectMdc.replace(/\r\n/g, '\n'),
|
|
182
|
+
mediaType: 'text/markdown',
|
|
183
|
+
kind: 'generated-adapter',
|
|
184
|
+
generator: GENERATOR_ID,
|
|
185
|
+
sourceSkillIds: ['project-rules'],
|
|
186
|
+
inputsHash: context?.sourceGraphHash || 'none',
|
|
187
|
+
});
|
|
175
188
|
}
|
|
176
189
|
|
|
177
|
-
|
|
178
|
-
sections.push('\n---\n\n# Skills Index (Loaded On-Demand)\n\n' +
|
|
179
|
-
'The following specialist skills are configured as `.cursor/rules/<skill>.mdc`:\n');
|
|
180
|
-
const skills = collectSkillDirectories();
|
|
181
|
-
const activeMdcFiles = new Set(['00-project-rules.mdc']);
|
|
182
|
-
|
|
190
|
+
const skills = collectSkillDirectories(context?.profile);
|
|
183
191
|
for (const skill of skills) {
|
|
184
|
-
const section = buildSkillSection(skill);
|
|
185
|
-
if (section) {
|
|
186
|
-
sections.push(section);
|
|
187
|
-
count++;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
192
|
const mdc = generateCursorMdc(skill);
|
|
191
193
|
if (mdc) {
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
const fullMdc = mdc.mdcContent.replace(/\r\n/g, '\n');
|
|
195
|
+
artifacts.push({
|
|
196
|
+
path: `.cursor/rules/${mdc.skillName}.mdc`,
|
|
197
|
+
content: fullMdc,
|
|
198
|
+
mediaType: 'text/markdown',
|
|
199
|
+
kind: 'generated-adapter',
|
|
200
|
+
generator: GENERATOR_ID,
|
|
201
|
+
sourceSkillIds: [mdc.skillName],
|
|
202
|
+
inputsHash: context?.sourceGraphHash || 'none',
|
|
203
|
+
});
|
|
196
204
|
}
|
|
197
205
|
}
|
|
198
206
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
} catch {}
|
|
208
|
-
|
|
209
|
-
for (const file of fs.readdirSync(cursorRulesDir)) {
|
|
210
|
-
if (file.endsWith('.mdc') && !activeMdcFiles.has(file)) {
|
|
211
|
-
const fullFilePath = path.join(cursorRulesDir, file);
|
|
212
|
-
const relPath = path.relative(process.cwd(), fullFilePath).replace(/\\/g, '/');
|
|
213
|
-
|
|
214
|
-
// Deletion permitted ONLY if recorded in lockfile OR content carries explicit ContextOS provenance
|
|
215
|
-
const isManagedInLock = Boolean(lockData?.managedFiles?.[relPath]?.managed);
|
|
216
|
-
let hasContextosMarker = false;
|
|
217
|
-
try {
|
|
218
|
-
const content = fs.readFileSync(fullFilePath, 'utf8');
|
|
219
|
-
hasContextosMarker =
|
|
220
|
-
content.includes('<!-- Auto-generated by: node .agents/ctx.js export cursor -->') ||
|
|
221
|
-
content.includes('ContextOS rules for') ||
|
|
222
|
-
content.includes('ContextOS — Project Operating System Rules');
|
|
223
|
-
} catch {}
|
|
224
|
-
|
|
225
|
-
if (isManagedInLock || hasContextosMarker) {
|
|
226
|
-
fs.unlinkSync(fullFilePath);
|
|
227
|
-
if (lockData?.managedFiles?.[relPath]) {
|
|
228
|
-
delete lockData.managedFiles[relPath];
|
|
229
|
-
try {
|
|
230
|
-
fs.writeFileSync(lockfilePath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
|
|
231
|
-
} catch {}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
207
|
+
return artifacts;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function validate(artifacts) {
|
|
211
|
+
const diagnostics = [];
|
|
212
|
+
for (const art of artifacts) {
|
|
213
|
+
if (!art.content || art.content.length === 0) {
|
|
214
|
+
diagnostics.push({ path: art.path, message: 'Empty artifact content' });
|
|
235
215
|
}
|
|
236
216
|
}
|
|
217
|
+
return diagnostics;
|
|
218
|
+
}
|
|
237
219
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
220
|
+
function run(options = {}) {
|
|
221
|
+
const { loadCompilerContext } = require('../pure-compiler.js');
|
|
222
|
+
const projectRoot = options.projectRoot || '.';
|
|
223
|
+
const context = loadCompilerContext(projectRoot, options);
|
|
224
|
+
const artifacts = render(context);
|
|
225
|
+
const result = applyArtifacts(projectRoot, artifacts, { command: 'export cursor', context });
|
|
226
|
+
console.log(`✓ Cursor export complete: ${result.appliedCount} files applied (tx: ${result.txId})`);
|
|
227
|
+
return result;
|
|
241
228
|
}
|
|
242
229
|
|
|
243
|
-
|
|
230
|
+
const adapter = {
|
|
231
|
+
describe,
|
|
232
|
+
render,
|
|
233
|
+
validate,
|
|
234
|
+
run,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
registerAdapter('cursor', adapter);
|
|
238
|
+
|
|
239
|
+
module.exports = adapter;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .agents/adapters/drift-detector.js
|
|
3
|
+
* ContextOS Adapter Output Drift & Out-of-Sync Detector
|
|
4
|
+
*
|
|
5
|
+
* Implements Section 12.4 drift states:
|
|
6
|
+
* - STALE_INPUT: Source graph or profile modified since last compile
|
|
7
|
+
* - MISSING_OUTPUT: Planned or recorded file absent from disk
|
|
8
|
+
* - MODIFIED_MANAGED_OUTPUT: Disk content differs from lockfile (user edits)
|
|
9
|
+
* - ORPHAN_MANAGED_OUTPUT: Lockfile records file no longer rendered
|
|
10
|
+
* - ADAPTER_VERSION_MISMATCH: Generator version differs
|
|
11
|
+
* - PROFILE_MISMATCH: Active profile differs from lockfile profile
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const { LockfileV2Manager, computeExactHash, computeSemanticHash } = require('../filesystem/index.js');
|
|
17
|
+
const { renderAdapters } = require('./pure-compiler.js');
|
|
18
|
+
|
|
19
|
+
const DRIFT_STATES = {
|
|
20
|
+
STALE_INPUT: 'STALE_INPUT',
|
|
21
|
+
MISSING_OUTPUT: 'MISSING_OUTPUT',
|
|
22
|
+
MODIFIED_MANAGED_OUTPUT: 'MODIFIED_MANAGED_OUTPUT',
|
|
23
|
+
ORPHAN_MANAGED_OUTPUT: 'ORPHAN_MANAGED_OUTPUT',
|
|
24
|
+
ADAPTER_VERSION_MISMATCH: 'ADAPTER_VERSION_MISMATCH',
|
|
25
|
+
PROFILE_MISMATCH: 'PROFILE_MISMATCH',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Computes a unified textual diff snippet between before and after strings.
|
|
30
|
+
*/
|
|
31
|
+
function computeDiffSnippet(beforeStr, afterStr, maxLines = 15) {
|
|
32
|
+
const beforeLines = beforeStr.split(/\r?\n/);
|
|
33
|
+
const afterLines = afterStr.split(/\r?\n/);
|
|
34
|
+
const diffLines = [];
|
|
35
|
+
|
|
36
|
+
let lineCount = 0;
|
|
37
|
+
for (let i = 0; i < Math.max(beforeLines.length, afterLines.length); i++) {
|
|
38
|
+
const b = beforeLines[i];
|
|
39
|
+
const a = afterLines[i];
|
|
40
|
+
if (b !== a) {
|
|
41
|
+
if (b !== undefined) {
|
|
42
|
+
diffLines.push(`- ${b}`);
|
|
43
|
+
lineCount++;
|
|
44
|
+
}
|
|
45
|
+
if (a !== undefined) {
|
|
46
|
+
diffLines.push(`+ ${a}`);
|
|
47
|
+
lineCount++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (lineCount >= maxLines) {
|
|
51
|
+
diffLines.push('... (diff truncated)');
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return diffLines.join('\n');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Analyzes drift between current project state, Lockfile v2, and projected adapter render.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} projectRoot
|
|
63
|
+
* @param {string[]|string} [adapters='all']
|
|
64
|
+
* @param {object} [options]
|
|
65
|
+
* @returns {object} Structured drift report
|
|
66
|
+
*/
|
|
67
|
+
function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
68
|
+
const absRoot = path.resolve(projectRoot);
|
|
69
|
+
const lockManager = new LockfileV2Manager(absRoot);
|
|
70
|
+
const lockfile = lockManager.read();
|
|
71
|
+
|
|
72
|
+
const { artifacts, collisions, context } = renderAdapters(absRoot, adapters, options);
|
|
73
|
+
|
|
74
|
+
const findings = {
|
|
75
|
+
[DRIFT_STATES.STALE_INPUT]: [],
|
|
76
|
+
[DRIFT_STATES.MISSING_OUTPUT]: [],
|
|
77
|
+
[DRIFT_STATES.MODIFIED_MANAGED_OUTPUT]: [],
|
|
78
|
+
[DRIFT_STATES.ORPHAN_MANAGED_OUTPUT]: [],
|
|
79
|
+
[DRIFT_STATES.ADAPTER_VERSION_MISMATCH]: [],
|
|
80
|
+
[DRIFT_STATES.PROFILE_MISMATCH]: [],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const diffs = [];
|
|
84
|
+
|
|
85
|
+
// 1. Check Profile Mismatch
|
|
86
|
+
if (lockfile && lockfile.profile) {
|
|
87
|
+
if (context.profileId && lockfile.profile.id !== context.profileId) {
|
|
88
|
+
findings[DRIFT_STATES.PROFILE_MISMATCH].push({
|
|
89
|
+
expected: context.profileId,
|
|
90
|
+
actual: lockfile.profile.id,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 2. Check Stale Input (Source Graph Hash)
|
|
96
|
+
if (lockfile && lockfile.sourceGraphHash) {
|
|
97
|
+
if (context.sourceGraphHash && lockfile.sourceGraphHash !== context.sourceGraphHash) {
|
|
98
|
+
findings[DRIFT_STATES.STALE_INPUT].push({
|
|
99
|
+
expected: context.sourceGraphHash,
|
|
100
|
+
actual: lockfile.sourceGraphHash,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const projectedPaths = new Set(artifacts.map(a => a.path));
|
|
106
|
+
|
|
107
|
+
// 3. Inspect each projected artifact against disk and lockfile
|
|
108
|
+
for (const art of artifacts) {
|
|
109
|
+
const fullPath = path.resolve(absRoot, art.path);
|
|
110
|
+
const projectedContent = art.content.toString('utf8');
|
|
111
|
+
const projectedExactHash = computeExactHash(art.content);
|
|
112
|
+
const projectedSemanticHash = computeSemanticHash(art.content);
|
|
113
|
+
|
|
114
|
+
if (!fs.existsSync(fullPath)) {
|
|
115
|
+
findings[DRIFT_STATES.MISSING_OUTPUT].push({
|
|
116
|
+
path: art.path,
|
|
117
|
+
reason: 'Projected artifact does not exist on disk',
|
|
118
|
+
});
|
|
119
|
+
diffs.push({
|
|
120
|
+
path: art.path,
|
|
121
|
+
type: 'missing',
|
|
122
|
+
diff: `+ (new file, ${projectedContent.length} bytes)`,
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
const diskContent = fs.readFileSync(fullPath, 'utf8');
|
|
126
|
+
const diskSemanticHash = computeSemanticHash(diskContent);
|
|
127
|
+
|
|
128
|
+
// Check if disk matches projected render
|
|
129
|
+
if (diskSemanticHash !== projectedSemanticHash) {
|
|
130
|
+
const lockRecord = lockfile?.managedFiles?.[art.path];
|
|
131
|
+
if (lockRecord && lockRecord.semanticTextSha256 !== diskSemanticHash) {
|
|
132
|
+
findings[DRIFT_STATES.MODIFIED_MANAGED_OUTPUT].push({
|
|
133
|
+
path: art.path,
|
|
134
|
+
reason: 'Managed file was modified by user on disk',
|
|
135
|
+
diskHash: diskSemanticHash,
|
|
136
|
+
lockHash: lockRecord.semanticTextSha256,
|
|
137
|
+
});
|
|
138
|
+
} else {
|
|
139
|
+
findings[DRIFT_STATES.STALE_INPUT].push({
|
|
140
|
+
path: art.path,
|
|
141
|
+
reason: 'Generated artifact differs from source skills projection',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
diffs.push({
|
|
146
|
+
path: art.path,
|
|
147
|
+
type: 'modified',
|
|
148
|
+
diff: computeDiffSnippet(diskContent, projectedContent),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 4. Check for orphan files recorded in lockfile but no longer projected
|
|
155
|
+
if (lockfile && lockfile.managedFiles) {
|
|
156
|
+
for (const [recordedPath, meta] of Object.entries(lockfile.managedFiles)) {
|
|
157
|
+
if (!projectedPaths.has(recordedPath)) {
|
|
158
|
+
const fullRecorded = path.resolve(absRoot, recordedPath);
|
|
159
|
+
if (fs.existsSync(fullRecorded)) {
|
|
160
|
+
findings[DRIFT_STATES.ORPHAN_MANAGED_OUTPUT].push({
|
|
161
|
+
path: recordedPath,
|
|
162
|
+
reason: 'File recorded in lockfile is no longer generated by active skills/profile',
|
|
163
|
+
});
|
|
164
|
+
diffs.push({
|
|
165
|
+
path: recordedPath,
|
|
166
|
+
type: 'orphan',
|
|
167
|
+
diff: `- (orphan file on disk, ${meta.kind})`,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (diffs.length === 0 && findings[DRIFT_STATES.ORPHAN_MANAGED_OUTPUT].length === 0) {
|
|
175
|
+
findings[DRIFT_STATES.STALE_INPUT] = [];
|
|
176
|
+
findings[DRIFT_STATES.PROFILE_MISMATCH] = [];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const totalFindings = Object.values(findings).reduce((acc, list) => acc + list.length, 0);
|
|
180
|
+
const hasDrift = totalFindings > 0 || collisions.length > 0;
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
hasDrift,
|
|
184
|
+
totalFindings,
|
|
185
|
+
findings,
|
|
186
|
+
collisions,
|
|
187
|
+
diffs,
|
|
188
|
+
projectedCount: artifacts.length,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
module.exports = {
|
|
193
|
+
detectDrift,
|
|
194
|
+
computeDiffSnippet,
|
|
195
|
+
DRIFT_STATES,
|
|
196
|
+
};
|
|
@@ -1,18 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .agents/adapters/gemini/export.js
|
|
3
|
+
* ContextOS Gemini & Antigravity IDE Pure Adapter
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const fs = require('fs');
|
|
2
7
|
const path = require('path');
|
|
3
|
-
const { collectSkillDirectories,
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
const { collectSkillDirectories, readMeaningfulMarkdown, extractYamlField } = require('../shared.js');
|
|
9
|
+
const { registerAdapter, applyArtifacts } = require('../pure-compiler.js');
|
|
10
|
+
|
|
11
|
+
const GENERATOR_ID = 'gemini@2';
|
|
12
|
+
|
|
13
|
+
function describe() {
|
|
14
|
+
return {
|
|
15
|
+
name: 'gemini',
|
|
16
|
+
version: '2.0.0',
|
|
17
|
+
description: 'Compiles modular skills for Gemini 3.8 and Google Antigravity IDE',
|
|
18
|
+
targetPattern: '.agents/generated/gemini/skills/**/SKILL.md',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
6
21
|
|
|
7
|
-
function
|
|
22
|
+
function renderGeminiSkill(skillDir, context) {
|
|
8
23
|
const skillName = path.basename(skillDir);
|
|
9
24
|
const yamlPath = path.join(skillDir, 'skill.yaml');
|
|
10
25
|
const existingSkillMdPath = path.join(skillDir, 'SKILL.md');
|
|
11
|
-
const outputDir = path.join(GENERATED_SKILLS_PATH, skillName);
|
|
12
26
|
|
|
13
27
|
if (!fs.existsSync(existingSkillMdPath) && !fs.existsSync(yamlPath)) {
|
|
14
|
-
|
|
15
|
-
return;
|
|
28
|
+
return [];
|
|
16
29
|
}
|
|
17
30
|
|
|
18
31
|
let name = skillName;
|
|
@@ -30,11 +43,9 @@ function generateGeminiSkill(skillDir) {
|
|
|
30
43
|
}
|
|
31
44
|
description = description || `ContextOS skill for ${name}`;
|
|
32
45
|
|
|
33
|
-
// Find all .md files in the skill directory deterministically
|
|
34
46
|
const files = fs.readdirSync(skillDir).sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }));
|
|
35
47
|
const mdFiles = files.filter(f => f.endsWith('.md'));
|
|
36
48
|
|
|
37
|
-
// Primary skill content first: SKILL.md is canonical; fallback to <skillName>.md
|
|
38
49
|
const primaryMd = mdFiles.includes('SKILL.md')
|
|
39
50
|
? 'SKILL.md'
|
|
40
51
|
: (mdFiles.find(f => f === `${skillName}.md`) || mdFiles[0]);
|
|
@@ -42,22 +53,16 @@ function generateGeminiSkill(skillDir) {
|
|
|
42
53
|
let mergedContent = '';
|
|
43
54
|
if (primaryMd) {
|
|
44
55
|
let primaryText = fs.readFileSync(path.join(skillDir, primaryMd), 'utf8');
|
|
45
|
-
// Strip existing frontmatter from source so we don't double-nest
|
|
46
56
|
primaryText = primaryText.replace(/^---[\s\S]*?---\r?\n/, '');
|
|
47
57
|
mergedContent += primaryText;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
|
-
// Partition supplemental markdown files for deterministic, logical ordering:
|
|
51
|
-
// 1. Specific topic / reference docs (e.g. accessibility.md), sorted alphabetically
|
|
52
|
-
// 2. EXAMPLES.md
|
|
53
|
-
// 3. TROUBLESHOOTING.md
|
|
54
60
|
const otherTopicFiles = mdFiles.filter(f => f !== primaryMd && f !== 'EXAMPLES.md' && f !== 'TROUBLESHOOTING.md');
|
|
55
61
|
const orderedExtras = [...otherTopicFiles];
|
|
56
62
|
if (mdFiles.includes('EXAMPLES.md') && primaryMd !== 'EXAMPLES.md') orderedExtras.push('EXAMPLES.md');
|
|
57
63
|
if (mdFiles.includes('TROUBLESHOOTING.md') && primaryMd !== 'TROUBLESHOOTING.md') orderedExtras.push('TROUBLESHOOTING.md');
|
|
58
64
|
|
|
59
65
|
for (const mdFile of orderedExtras) {
|
|
60
|
-
// Avoid re-appending content that was already inlined via Source comments in SKILL.md
|
|
61
66
|
if (mergedContent.includes(`<!-- Source: ${mdFile} -->`)) continue;
|
|
62
67
|
const extraContent = readMeaningfulMarkdown(path.join(skillDir, mdFile));
|
|
63
68
|
if (extraContent) {
|
|
@@ -65,7 +70,6 @@ function generateGeminiSkill(skillDir) {
|
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
// Construct Gemini SKILL.md format (normalizing line endings to \n)
|
|
69
73
|
const outputContent = `---
|
|
70
74
|
name: ${name}
|
|
71
75
|
description: >
|
|
@@ -74,42 +78,69 @@ description: >
|
|
|
74
78
|
${mergedContent.trimStart()}
|
|
75
79
|
`.replace(/\r\n/g, '\n');
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
const artifacts = [
|
|
82
|
+
{
|
|
83
|
+
path: `.agents/generated/gemini/skills/${skillName}/SKILL.md`,
|
|
84
|
+
content: outputContent,
|
|
85
|
+
mediaType: 'text/markdown',
|
|
86
|
+
kind: 'generated-adapter',
|
|
87
|
+
generator: GENERATOR_ID,
|
|
88
|
+
sourceSkillIds: [skillName],
|
|
89
|
+
inputsHash: context?.sourceGraphHash || 'none',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
path: `.agents/skills/${skillName}/SKILL.md`,
|
|
93
|
+
content: outputContent,
|
|
94
|
+
mediaType: 'text/markdown',
|
|
95
|
+
kind: 'generated-adapter',
|
|
96
|
+
generator: GENERATOR_ID,
|
|
97
|
+
sourceSkillIds: [skillName],
|
|
98
|
+
inputsHash: context?.sourceGraphHash || 'none',
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
return artifacts;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function render(context) {
|
|
106
|
+
const skills = collectSkillDirectories(context?.profile);
|
|
107
|
+
const artifacts = [];
|
|
108
|
+
|
|
109
|
+
for (const skill of skills) {
|
|
110
|
+
const rendered = renderGeminiSkill(skill, context);
|
|
111
|
+
artifacts.push(...rendered);
|
|
112
|
+
}
|
|
79
113
|
|
|
80
|
-
|
|
114
|
+
return artifacts;
|
|
81
115
|
}
|
|
82
116
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
for (const file of files) {
|
|
89
|
-
const curSource = path.join(source, file);
|
|
90
|
-
const curTarget = path.join(target, file);
|
|
91
|
-
if (fs.statSync(curSource).isDirectory()) {
|
|
92
|
-
copyFolderRecursiveSync(curSource, curTarget);
|
|
93
|
-
} else {
|
|
94
|
-
fs.copyFileSync(curSource, curTarget);
|
|
117
|
+
function validate(artifacts) {
|
|
118
|
+
const diagnostics = [];
|
|
119
|
+
for (const art of artifacts) {
|
|
120
|
+
if (!art.content || art.content.length === 0) {
|
|
121
|
+
diagnostics.push({ path: art.path, message: 'Empty artifact content' });
|
|
95
122
|
}
|
|
96
123
|
}
|
|
124
|
+
return diagnostics;
|
|
97
125
|
}
|
|
98
126
|
|
|
99
|
-
function run() {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
127
|
+
function run(options = {}) {
|
|
128
|
+
const { loadCompilerContext } = require('../pure-compiler.js');
|
|
129
|
+
const projectRoot = options.projectRoot || '.';
|
|
130
|
+
const context = loadCompilerContext(projectRoot, options);
|
|
131
|
+
const artifacts = render(context);
|
|
132
|
+
const result = applyArtifacts(projectRoot, artifacts, { command: 'export gemini', context });
|
|
133
|
+
console.log(`✓ Gemini export complete: ${result.appliedCount} files applied (tx: ${result.txId})`);
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
107
136
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
137
|
+
const adapter = {
|
|
138
|
+
describe,
|
|
139
|
+
render,
|
|
140
|
+
validate,
|
|
141
|
+
run,
|
|
142
|
+
};
|
|
111
143
|
|
|
112
|
-
|
|
113
|
-
}
|
|
144
|
+
registerAdapter('gemini', adapter);
|
|
114
145
|
|
|
115
|
-
module.exports =
|
|
146
|
+
module.exports = adapter;
|