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.
- package/.agents/AGENTS.md +53 -33
- package/.agents/adapters/aider/export.js +41 -14
- package/.agents/adapters/claude/export.js +54 -3
- package/.agents/adapters/copilot/export.js +1 -1
- package/.agents/adapters/cursor/export.js +1 -1
- package/.agents/adapters/drift-detector.js +86 -10
- package/.agents/adapters/gemini/export.js +1 -1
- package/.agents/adapters/pure-compiler.js +28 -6
- package/.agents/adapters/shared.js +13 -4
- package/.agents/adapters/zed/export.js +1 -1
- package/.agents/compiled/registry.v2.json +29 -25
- package/.agents/compiled/registry.v2.sha256 +1 -1
- package/.agents/core/skills/context-os/SKILL.md +34 -37
- package/.agents/core/skills/engineering-workflow/SKILL.md +24 -24
- package/.agents/core/skills/gemini-precision/EXAMPLES.md +72 -0
- package/.agents/core/skills/gemini-precision/SKILL.md +2 -1
- package/.agents/core/skills/gemini-precision/TROUBLESHOOTING.md +25 -0
- package/.agents/core/skills/gemini-precision/skill.yaml +2 -0
- package/.agents/core/skills/gstack-roles/SKILL.md +7 -6
- package/.agents/core/skills/security/SKILL.md +44 -16
- package/.agents/core/skills/security/skill.yaml +0 -1
- package/.agents/ctx.js +20 -14
- package/.agents/generated/claude/skills/context-os/SKILL.md +34 -37
- package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +24 -24
- package/.agents/generated/claude/skills/gemini-precision/SKILL.md +102 -1
- package/.agents/generated/claude/skills/gstack-roles/SKILL.md +7 -6
- package/.agents/generated/claude/skills/security/SKILL.md +44 -16
- package/.agents/generated/gemini/skills/context-os/SKILL.md +34 -37
- package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +24 -24
- package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +105 -1
- package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +7 -6
- package/.agents/generated/gemini/skills/security/SKILL.md +44 -125
- package/.agents/plugins.js +105 -8
- package/.agents/profiles.js +32 -11
- package/.agents/resolver/canonical-resolver.js +7 -7
- package/.agents/validate.js +69 -1
- package/README.md +81 -24
- package/bin/commands/hook.js +167 -0
- package/bin/commands/scan.js +77 -0
- package/bin/commands.js +39 -1
- package/bin/index.js +151 -34
- package/bin/lib/gate.js +171 -0
- package/bin/lib/git-snapshot.js +214 -0
- package/bin/lib/scan.js +461 -0
- package/catalog/skills/adapters/EXAMPLES.md +19 -0
- package/catalog/skills/adapters/SKILL.md +101 -0
- package/catalog/skills/adapters/TROUBLESHOOTING.md +7 -0
- package/catalog/skills/adapters/VALIDATION.json +12 -0
- package/catalog/skills/adapters/skill.yaml +13 -0
- package/catalog/skills/api-design/EXAMPLES.md +91 -0
- package/catalog/skills/api-design/SKILL.md +63 -0
- package/catalog/skills/api-design/TROUBLESHOOTING.md +54 -0
- package/catalog/skills/api-design/VALIDATION.json +11 -0
- package/catalog/skills/api-design/skill.yaml +14 -0
- package/catalog/skills/architecture-diagrams/SKILL.md +108 -0
- package/catalog/skills/architecture-diagrams/VALIDATION.json +12 -0
- package/catalog/skills/architecture-diagrams/skill.yaml +9 -0
- package/catalog/skills/brutalist-design/EXAMPLES.md +59 -0
- package/catalog/skills/brutalist-design/SKILL.md +150 -0
- package/catalog/skills/brutalist-design/VALIDATION.json +12 -0
- package/catalog/skills/brutalist-design/skill.yaml +10 -0
- package/catalog/skills/ci-cd/EXAMPLES.md +79 -0
- package/catalog/skills/ci-cd/SKILL.md +69 -0
- package/catalog/skills/ci-cd/TROUBLESHOOTING.md +52 -0
- package/catalog/skills/ci-cd/VALIDATION.json +11 -0
- package/catalog/skills/ci-cd/skill.yaml +13 -0
- package/catalog/skills/database/EXAMPLES.md +74 -0
- package/catalog/skills/database/SKILL.md +101 -0
- package/catalog/skills/database/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/database/VALIDATION.json +11 -0
- package/catalog/skills/database/skill.yaml +14 -0
- package/catalog/skills/ddd/EXAMPLES.md +42 -0
- package/catalog/skills/ddd/SKILL.md +247 -0
- package/catalog/skills/ddd/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ddd/VALIDATION.json +12 -0
- package/catalog/skills/ddd/skill.yaml +14 -0
- package/catalog/skills/decisions/EXAMPLES.md +35 -0
- package/catalog/skills/decisions/SKILL.md +90 -0
- package/catalog/skills/decisions/TROUBLESHOOTING.md +13 -0
- package/catalog/skills/decisions/VALIDATION.json +12 -0
- package/catalog/skills/decisions/skill.yaml +13 -0
- package/catalog/skills/docker/EXAMPLES.md +56 -0
- package/catalog/skills/docker/SKILL.md +169 -0
- package/catalog/skills/docker/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/docker/VALIDATION.json +11 -0
- package/catalog/skills/docker/skill.yaml +13 -0
- package/catalog/skills/fastapi/EXAMPLES.md +36 -0
- package/catalog/skills/fastapi/SKILL.md +171 -0
- package/catalog/skills/fastapi/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/fastapi/VALIDATION.json +12 -0
- package/catalog/skills/fastapi/skill.yaml +14 -0
- package/catalog/skills/generators/EXAMPLES.md +19 -0
- package/catalog/skills/generators/SKILL.md +110 -0
- package/catalog/skills/generators/TROUBLESHOOTING.md +7 -0
- package/catalog/skills/generators/VALIDATION.json +12 -0
- package/catalog/skills/generators/skill.yaml +22 -0
- package/catalog/skills/generators/templates/API.md +77 -0
- package/catalog/skills/generators/templates/ARCHITECTURE.md +70 -0
- package/catalog/skills/generators/templates/DATABASE.md +42 -0
- package/catalog/skills/generators/templates/DECISION.md +46 -0
- package/catalog/skills/generators/templates/PRD.md +67 -0
- package/catalog/skills/generators/templates/PROJECT_GRAPH.md +56 -0
- package/catalog/skills/generators/templates/ROADMAP.md +51 -0
- package/catalog/skills/generators/templates/TASKS.md +43 -0
- package/catalog/skills/generators/templates/UI.md +73 -0
- package/catalog/skills/graphify/EXAMPLES.md +73 -0
- package/catalog/skills/graphify/SKILL.md +130 -0
- package/catalog/skills/graphify/VALIDATION.json +12 -0
- package/catalog/skills/graphify/skill.yaml +13 -0
- package/catalog/skills/impeccable-design/EXAMPLES.md +26 -0
- package/catalog/skills/impeccable-design/SKILL.md +201 -0
- package/catalog/skills/impeccable-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/impeccable-design/VALIDATION.json +12 -0
- package/catalog/skills/impeccable-design/skill.yaml +15 -0
- package/catalog/skills/interview-me/SKILL.md +97 -0
- package/catalog/skills/interview-me/VALIDATION.json +12 -0
- package/catalog/skills/interview-me/skill.yaml +9 -0
- package/catalog/skills/microservices/EXAMPLES.md +38 -0
- package/catalog/skills/microservices/SKILL.md +164 -0
- package/catalog/skills/microservices/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/microservices/VALIDATION.json +12 -0
- package/catalog/skills/microservices/skill.yaml +14 -0
- package/catalog/skills/minimalist-design/EXAMPLES.md +58 -0
- package/catalog/skills/minimalist-design/SKILL.md +113 -0
- package/catalog/skills/minimalist-design/VALIDATION.json +12 -0
- package/catalog/skills/minimalist-design/skill.yaml +10 -0
- package/catalog/skills/nestjs/EXAMPLES.md +40 -0
- package/catalog/skills/nestjs/SKILL.md +139 -0
- package/catalog/skills/nestjs/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/nestjs/VALIDATION.json +12 -0
- package/catalog/skills/nestjs/skill.yaml +14 -0
- package/catalog/skills/nextjs/EXAMPLES.md +40 -0
- package/catalog/skills/nextjs/SKILL.md +163 -0
- package/catalog/skills/nextjs/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/nextjs/VALIDATION.json +12 -0
- package/catalog/skills/nextjs/skill.yaml +14 -0
- package/catalog/skills/node/EXAMPLES.md +80 -0
- package/catalog/skills/node/SKILL.md +128 -0
- package/catalog/skills/node/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/node/VALIDATION.json +12 -0
- package/catalog/skills/node/skill.yaml +14 -0
- package/catalog/skills/performance/EXAMPLES.md +30 -0
- package/catalog/skills/performance/SKILL.md +75 -0
- package/catalog/skills/performance/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/performance/VALIDATION.json +12 -0
- package/catalog/skills/performance/skill.yaml +14 -0
- package/catalog/skills/react/EXAMPLES.md +79 -0
- package/catalog/skills/react/SKILL.md +132 -0
- package/catalog/skills/react/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/react/VALIDATION.json +12 -0
- package/catalog/skills/react/skill.yaml +14 -0
- package/catalog/skills/react-best-practices/SKILL.md +158 -0
- package/catalog/skills/react-best-practices/VALIDATION.json +12 -0
- package/catalog/skills/react-best-practices/skill.yaml +13 -0
- package/catalog/skills/redesign-audit/SKILL.md +117 -0
- package/catalog/skills/redesign-audit/VALIDATION.json +12 -0
- package/catalog/skills/redesign-audit/skill.yaml +9 -0
- package/catalog/skills/security-audit/EXAMPLES.md +79 -0
- package/catalog/skills/security-audit/SKILL.md +91 -0
- package/catalog/skills/security-audit/TROUBLESHOOTING.md +46 -0
- package/catalog/skills/security-audit/VALIDATION.json +11 -0
- package/catalog/skills/security-audit/skill.yaml +14 -0
- package/catalog/skills/soft-design/EXAMPLES.md +51 -0
- package/catalog/skills/soft-design/SKILL.md +108 -0
- package/catalog/skills/soft-design/VALIDATION.json +12 -0
- package/catalog/skills/soft-design/skill.yaml +10 -0
- package/catalog/skills/state-management/EXAMPLES.md +56 -0
- package/catalog/skills/state-management/SKILL.md +168 -0
- package/catalog/skills/state-management/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/state-management/VALIDATION.json +11 -0
- package/catalog/skills/state-management/skill.yaml +14 -0
- package/catalog/skills/subagent-orchestrator/SKILL.md +117 -0
- package/catalog/skills/subagent-orchestrator/VALIDATION.json +12 -0
- package/catalog/skills/subagent-orchestrator/skill.yaml +9 -0
- package/catalog/skills/system-design/EXAMPLES.md +75 -0
- package/catalog/skills/system-design/SKILL.md +419 -0
- package/catalog/skills/system-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/system-design/VALIDATION.json +12 -0
- package/catalog/skills/system-design/skill.yaml +14 -0
- package/catalog/skills/terraform/EXAMPLES.md +74 -0
- package/catalog/skills/terraform/SKILL.md +55 -0
- package/catalog/skills/terraform/TROUBLESHOOTING.md +53 -0
- package/catalog/skills/terraform/VALIDATION.json +11 -0
- package/catalog/skills/terraform/skill.yaml +14 -0
- package/catalog/skills/testing/EXAMPLES.md +122 -0
- package/catalog/skills/testing/SKILL.md +70 -0
- package/catalog/skills/testing/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/testing/VALIDATION.json +11 -0
- package/catalog/skills/testing/skill.yaml +14 -0
- package/catalog/skills/typescript/EXAMPLES.md +64 -0
- package/catalog/skills/typescript/SKILL.md +112 -0
- package/catalog/skills/typescript/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/typescript/VALIDATION.json +12 -0
- package/catalog/skills/typescript/skill.yaml +14 -0
- package/catalog/skills/ui-design/EXAMPLES.md +21 -0
- package/catalog/skills/ui-design/SKILL.md +124 -0
- package/catalog/skills/ui-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ui-design/VALIDATION.json +12 -0
- package/catalog/skills/ui-design/skill.yaml +16 -0
- package/catalog/skills/ui-ux-pro/EXAMPLES.md +62 -0
- package/catalog/skills/ui-ux-pro/SKILL.md +418 -0
- package/catalog/skills/ui-ux-pro/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ui-ux-pro/VALIDATION.json +12 -0
- package/catalog/skills/ui-ux-pro/skill.yaml +14 -0
- package/catalog/skills/ux-design/EXAMPLES.md +36 -0
- package/catalog/skills/ux-design/SKILL.md +116 -0
- package/catalog/skills/ux-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ux-design/VALIDATION.json +12 -0
- package/catalog/skills/ux-design/skill.yaml +16 -0
- package/catalog/skills/vercel-optimize/SKILL.md +83 -0
- package/catalog/skills/vercel-optimize/VALIDATION.json +12 -0
- package/catalog/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
- package/catalog/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
- package/catalog/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
- package/catalog/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
- package/catalog/skills/vercel-optimize/skill.yaml +15 -0
- package/catalog/skills/web-accessibility/EXAMPLES.md +39 -0
- package/catalog/skills/web-accessibility/SKILL.md +151 -0
- package/catalog/skills/web-accessibility/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/web-accessibility/VALIDATION.json +12 -0
- package/catalog/skills/web-accessibility/skill.yaml +14 -0
- package/package.json +5 -2
- package/.agents/core/skills/security/security.md +0 -106
package/.agents/AGENTS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ContextOS
|
|
1
|
+
# ContextOS - Deterministic context compiler and policy engine for AI coding agents.
|
|
2
2
|
|
|
3
3
|
You are working inside a project managed by **ContextOS**. This file is the **single source of truth** for how you must behave, think, and which skills to activate for every task.
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ You are working inside a project managed by **ContextOS**. This file is the **si
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## Step 0
|
|
9
|
+
## Step 0 - Identify Before Acting
|
|
10
10
|
|
|
11
11
|
Before writing a single line of code or plan, stop and answer three questions:
|
|
12
12
|
|
|
@@ -28,12 +28,12 @@ Skills loaded: react, typescript, ui-ux-pro, ponytail-mindset
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Skill Architecture (
|
|
31
|
+
## Skill Architecture (High Fidelity & Progressive Disclosure)
|
|
32
32
|
|
|
33
|
-
Skills
|
|
34
|
-
1. **
|
|
35
|
-
2. **
|
|
36
|
-
3. **
|
|
33
|
+
Skills provide deep, production-ready engineering standards. To maximize instruction adherence:
|
|
34
|
+
1. **High-Fidelity Guidance**: Skills must be complete, self-contained, and comprehensive. Never truncate essential rules, edge cases, or code examples for artificial brevity.
|
|
35
|
+
2. **Progressive Disclosure**: Use a `references/` directory for deep domain specifications, detailed schemas, and specialized manuals, loading them when the task explicitly targets those areas.
|
|
36
|
+
3. **Executable Scripts**: Place verification and automation scripts in a `scripts/` directory alongside the skill.
|
|
37
37
|
|
|
38
38
|
## Skill Registry
|
|
39
39
|
|
|
@@ -43,10 +43,10 @@ These 7 skills are always present in ContextOS Core:
|
|
|
43
43
|
|
|
44
44
|
| Skill | File | Activate When |
|
|
45
45
|
|-------|------|--------------|
|
|
46
|
-
| **engineering-workflow** | `engineering-workflow/SKILL.md` | **Every task**
|
|
47
|
-
| **gstack-roles** | `gstack-roles/SKILL.md` | **Every task**
|
|
48
|
-
| **ponytail-mindset** | `ponytail-mindset/SKILL.md` | **Every BUILD phase**
|
|
49
|
-
| **gemini-precision** | `gemini-precision/SKILL.md` | **All Gemini tasks**
|
|
46
|
+
| **engineering-workflow** | `engineering-workflow/SKILL.md` | **Every task** - defines the DEFINE→PLAN→BUILD→VERIFY→REVIEW→SHIP pipeline |
|
|
47
|
+
| **gstack-roles** | `gstack-roles/SKILL.md` | **Every task** - declare your specialist role before each phase |
|
|
48
|
+
| **ponytail-mindset** | `ponytail-mindset/SKILL.md` | **Every BUILD phase** - run the 7-rung ladder before writing any code |
|
|
49
|
+
| **gemini-precision** | `gemini-precision/SKILL.md` | **All Gemini tasks** - zero assumptions, zero placeholders, surgical blast radius, test proof |
|
|
50
50
|
| **security** | `security/SKILL.md` | Any feature with auth, data access, user input, external integration |
|
|
51
51
|
| **context-os** | `context-os/SKILL.md` | Managing context rules, compiler pipelines, project policies |
|
|
52
52
|
| **context-manager** | `context-manager/SKILL.md` | Context selection, dynamic skill resolution, project graph traversal |
|
|
@@ -58,14 +58,14 @@ The following domain skills are available in the extended catalog and can be add
|
|
|
58
58
|
| Domain | Skills | Install Command |
|
|
59
59
|
|--------|--------|-----------------|
|
|
60
60
|
| **Frontend** | `react`, `react-best-practices`, `nextjs`, `typescript`, `ui-ux-pro`, `impeccable-design`, `state-management`, `ui-design`, `ux-design`, `web-accessibility`, `brutalist-design`, `minimalist-design`, `soft-design`, `redesign-audit` | `contextos skill add <name>` |
|
|
61
|
-
| **Backend** | `system-design`, `node`, `fastapi`, `nestjs`, `microservices`, `ddd`, `database` | `contextos skill add <name>` |
|
|
62
|
-
| **Cross-Cutting** | `testing`, `docker`, `decisions`, `architecture-diagrams`, `adapters`, `generators`, `graphify`, `performance`, `vercel-optimize` | `contextos skill add <name>` |
|
|
61
|
+
| **Backend** | `system-design`, `api-design`, `node`, `fastapi`, `nestjs`, `microservices`, `ddd`, `database` | `contextos skill add <name>` |
|
|
62
|
+
| **Cross-Cutting** | `testing`, `docker`, `ci-cd`, `terraform`, `security-audit`, `decisions`, `architecture-diagrams`, `adapters`, `generators`, `graphify`, `performance`, `vercel-optimize` | `contextos skill add <name>` |
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
66
66
|
## Automatic Skill Activation Rules (Proactive Routing)
|
|
67
67
|
|
|
68
|
-
The following rules are **deterministic**
|
|
68
|
+
The following rules are **deterministic** - no judgment needed. If the condition is true, the skill is loaded.
|
|
69
69
|
|
|
70
70
|
> **Availability Guard**: Load only skills that are physically installed in `.agents/core/skills/`. For uninstalled catalog skills, rely on core skills (`engineering-workflow`, `ponytail-mindset`, `gemini-precision`, `security`) and recommend `contextos skill add <name>` when deep domain checklists are needed.
|
|
71
71
|
|
|
@@ -159,6 +159,22 @@ role: Staff Engineer (Orchestrator)
|
|
|
159
159
|
trigger: "graphify" OR "codebase graph" OR "project graph" OR "map codebase" OR "knowledge graph" OR "построй граф проекта"
|
|
160
160
|
load: [graphify, system-design, context-manager]
|
|
161
161
|
role: Architect
|
|
162
|
+
|
|
163
|
+
trigger: "security audit" OR "vulnerability" OR "pentest"
|
|
164
|
+
load: [security-audit, security, engineering-workflow]
|
|
165
|
+
role: Chief Security Officer (audit) -> Senior Developer (build)
|
|
166
|
+
|
|
167
|
+
trigger: "api design" OR "REST API" OR "contract" OR "openapi"
|
|
168
|
+
load: [api-design, system-design, engineering-workflow]
|
|
169
|
+
role: Architect (plan) -> Senior Developer (build)
|
|
170
|
+
|
|
171
|
+
trigger: "terraform" OR "opentofu" OR "iac" OR "infrastructure"
|
|
172
|
+
load: [terraform, decisions, engineering-workflow]
|
|
173
|
+
role: DevOps Engineer
|
|
174
|
+
|
|
175
|
+
trigger: "ci/cd" OR "github actions" OR "pipeline" OR "quality gates"
|
|
176
|
+
load: [ci-cd, engineering-workflow]
|
|
177
|
+
role: DevOps Engineer
|
|
162
178
|
```
|
|
163
179
|
|
|
164
180
|
### By Technology Detected in Codebase
|
|
@@ -178,7 +194,7 @@ files: "components/ui/*" present → shadcn detected, apply K9-K11 rules from im
|
|
|
178
194
|
|
|
179
195
|
---
|
|
180
196
|
|
|
181
|
-
## Pipeline
|
|
197
|
+
## Pipeline - Phase-by-Phase Rules
|
|
182
198
|
|
|
183
199
|
Every task MUST follow these phases in order. No skipping.
|
|
184
200
|
|
|
@@ -191,7 +207,7 @@ Required output before proceeding:
|
|
|
191
207
|
- Explicit in-scope / out-of-scope
|
|
192
208
|
- List of files that will change
|
|
193
209
|
- Acceptance criteria as testable statements
|
|
194
|
-
- **STOP
|
|
210
|
+
- **STOP - do not write code until spec is reviewed**
|
|
195
211
|
|
|
196
212
|
---
|
|
197
213
|
|
|
@@ -205,7 +221,7 @@ Required output before proceeding:
|
|
|
205
221
|
- Test requirement per task
|
|
206
222
|
- Risk assessment
|
|
207
223
|
- **If UI domain, read and incorporate `.interface-design/system.md` design memory**
|
|
208
|
-
- **STOP
|
|
224
|
+
- **STOP - do not write code until plan is approved**
|
|
209
225
|
|
|
210
226
|
---
|
|
211
227
|
|
|
@@ -236,12 +252,12 @@ Rules:
|
|
|
236
252
|
**Role**: `[ROLE: Staff Engineer]` + `[ROLE: Senior Designer]` if UI
|
|
237
253
|
**Load**: `engineering-workflow` (code review checklist) + `impeccable-design` (if UI)
|
|
238
254
|
|
|
239
|
-
For UI tasks
|
|
240
|
-
- Typography rules T1
|
|
241
|
-
- Color rules C1
|
|
242
|
-
- Layout rules L1
|
|
243
|
-
- Component rules K1
|
|
244
|
-
- Animation rules A1
|
|
255
|
+
For UI tasks - run the full impeccable-design audit:
|
|
256
|
+
- Typography rules T1-T10
|
|
257
|
+
- Color rules C1-C12
|
|
258
|
+
- Layout rules L1-L11 (including z-index check)
|
|
259
|
+
- Component rules K1-K11 (shadcn-first)
|
|
260
|
+
- Animation rules A1-A8 (Framer Motion exception noted)
|
|
245
261
|
|
|
246
262
|
---
|
|
247
263
|
|
|
@@ -276,6 +292,10 @@ Use this table to instantly determine which skills to load:
|
|
|
276
292
|
| Architecture visualization | `architecture-diagrams` + `system-design` | Architect |
|
|
277
293
|
| Multi-agent parallel tasks | `subagent-orchestrator` + `engineering-workflow` | Staff Engineer (Orchestrator) |
|
|
278
294
|
| Codebase graph / repo mapping | `graphify` + `context-manager` + `system-design` | Architect |
|
|
295
|
+
| Security audit / pen-test | `security-audit` + `security` + `engineering-workflow` | Chief Security Officer |
|
|
296
|
+
| API contract / interface design | `api-design` + `system-design` + `engineering-workflow` | Architect |
|
|
297
|
+
| Terraform / IaC | `terraform` + `decisions` + `engineering-workflow` | DevOps Engineer |
|
|
298
|
+
| CI/CD pipeline automation | `ci-cd` + `engineering-workflow` | DevOps Engineer |
|
|
279
299
|
|
|
280
300
|
---
|
|
281
301
|
|
|
@@ -326,18 +346,18 @@ These rules apply regardless of which skills are loaded:
|
|
|
326
346
|
|
|
327
347
|
### Code Quality
|
|
328
348
|
- Business logic NEVER lives in API route handlers → always in `services/` or `use-cases/`
|
|
329
|
-
- No `// TODO` in committed code
|
|
349
|
+
- No `// TODO` in committed code - create a tracked issue instead
|
|
330
350
|
- All async operations have explicit error handling
|
|
331
|
-
- No secrets hardcoded
|
|
351
|
+
- No secrets hardcoded - use environment variables
|
|
332
352
|
|
|
333
353
|
### Security
|
|
334
|
-
- Auth check BEFORE any data access
|
|
354
|
+
- Auth check BEFORE any data access - no exceptions
|
|
335
355
|
- All user input validated and sanitized before processing
|
|
336
|
-
- SQL queries use parameterized form
|
|
356
|
+
- SQL queries use parameterized form - no string concatenation
|
|
337
357
|
|
|
338
358
|
### Design
|
|
339
|
-
- No arbitrary Tailwind values (`gap-[17px]`)
|
|
340
|
-
- No hardcoded z-indexes (`z-[999]`)
|
|
359
|
+
- No arbitrary Tailwind values (`gap-[17px]`) - use scale utilities
|
|
360
|
+
- No hardcoded z-indexes (`z-[999]`) - use Radix/shadcn Portals
|
|
341
361
|
- Every list/table/feed has a designed empty state
|
|
342
362
|
|
|
343
363
|
### Engineering
|
|
@@ -348,10 +368,10 @@ These rules apply regardless of which skills are loaded:
|
|
|
348
368
|
|
|
349
369
|
### Completion Protocol
|
|
350
370
|
When finishing a workflow or task, always report your final status clearly using one of the following:
|
|
351
|
-
- **DONE**
|
|
352
|
-
- **DONE_WITH_CONCERNS**
|
|
353
|
-
- **BLOCKED**
|
|
354
|
-
- **NEEDS_CONTEXT**
|
|
371
|
+
- **DONE** - completed with evidence.
|
|
372
|
+
- **DONE_WITH_CONCERNS** - completed, but list specific concerns.
|
|
373
|
+
- **BLOCKED** - cannot proceed; state blocker and what was tried.
|
|
374
|
+
- **NEEDS_CONTEXT** - missing info; state exactly what is needed.
|
|
355
375
|
|
|
356
376
|
---
|
|
357
377
|
|
|
@@ -7,6 +7,7 @@ const fs = require('fs');
|
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const { AGENTS_MD_PATH, collectSkillDirectories, extractYamlField, stripFrontmatter } = require('../shared.js');
|
|
9
9
|
const { registerAdapter, applyArtifacts, createProvenanceHeader } = require('../pure-compiler.js');
|
|
10
|
+
const YAML = require('../../compiler/vendor/yaml.js');
|
|
10
11
|
|
|
11
12
|
const GENERATOR_ID = 'aider@2';
|
|
12
13
|
|
|
@@ -43,7 +44,7 @@ function buildSkillSection(skillDir) {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const descLine = description ? `> ${description.replace(/\r?\n+/g, ' ').trim()}\n` : '';
|
|
46
|
-
const skillRef = `*Source: \`.agents/skills/${skillName}/SKILL.md\`
|
|
47
|
+
const skillRef = `*Source: \`.agents/skills/${skillName}/SKILL.md\` - Load via \`/read .agents/skills/${skillName}/SKILL.md\`*\n`;
|
|
47
48
|
return `\n## Skill: ${title}\n${descLine}${skillRef}`;
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -68,23 +69,49 @@ function render(context) {
|
|
|
68
69
|
}, 'markdown');
|
|
69
70
|
|
|
70
71
|
// 1. .aider.conf.yml
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
const existingAiderConfPath = path.join(projectRoot, '.aider.conf.yml');
|
|
73
|
+
let aiderConfContent = '';
|
|
74
|
+
|
|
75
|
+
if (fs.existsSync(existingAiderConfPath)) {
|
|
76
|
+
try {
|
|
77
|
+
const rawUserConf = fs.readFileSync(existingAiderConfPath, 'utf8');
|
|
78
|
+
const parsed = YAML.parse(rawUserConf) || {};
|
|
79
|
+
|
|
80
|
+
if (!parsed.read) {
|
|
81
|
+
parsed.read = ['CONVENTIONS.md'];
|
|
82
|
+
} else if (Array.isArray(parsed.read)) {
|
|
83
|
+
if (!parsed.read.includes('CONVENTIONS.md')) {
|
|
84
|
+
parsed.read.push('CONVENTIONS.md');
|
|
85
|
+
}
|
|
86
|
+
} else if (typeof parsed.read === 'string') {
|
|
87
|
+
if (parsed.read !== 'CONVENTIONS.md') {
|
|
88
|
+
parsed.read = [parsed.read, 'CONVENTIONS.md'];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
aiderConfContent = yamlProv + '\n' + YAML.stringify(parsed);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
throw new Error(`Failed to parse existing .aider.conf.yml: ${err.message}. Aborting to protect existing configuration from data loss.`);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
aiderConfContent = [
|
|
98
|
+
yamlProv,
|
|
99
|
+
'# Load project conventions as a read-only context file on every session',
|
|
100
|
+
'read:',
|
|
101
|
+
' - CONVENTIONS.md',
|
|
102
|
+
'',
|
|
103
|
+
'# Auto commit edits with standard git format',
|
|
104
|
+
'auto-commits: true',
|
|
105
|
+
'dirty-commits: true',
|
|
106
|
+
'',
|
|
107
|
+
].join('\n');
|
|
108
|
+
}
|
|
82
109
|
|
|
83
110
|
// 2. CONVENTIONS.md
|
|
84
111
|
const convSections = [];
|
|
85
112
|
convSections.push(
|
|
86
113
|
mdProv +
|
|
87
|
-
`# ContextOS
|
|
114
|
+
`# ContextOS - Project Conventions for Aider\n\n` +
|
|
88
115
|
`> **Core law: Do not read everything. Read only what the current task requires.**\n\n`
|
|
89
116
|
);
|
|
90
117
|
|
|
@@ -97,7 +124,7 @@ function render(context) {
|
|
|
97
124
|
`Skills are loaded on demand. Use \`/read .agents/skills/<skill>/SKILL.md\` when needed.\n\n` +
|
|
98
125
|
`### Skill Index\n`);
|
|
99
126
|
|
|
100
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
127
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
101
128
|
for (const skill of skills) {
|
|
102
129
|
const section = buildSkillSection(skill);
|
|
103
130
|
if (section) convSections.push(section);
|
|
@@ -9,13 +9,15 @@ const { collectSkillDirectories, readMeaningfulMarkdown } = require('../shared.j
|
|
|
9
9
|
const { registerAdapter, applyArtifacts } = require('../pure-compiler.js');
|
|
10
10
|
|
|
11
11
|
const GENERATOR_ID = 'claude@2';
|
|
12
|
+
const CLAUDE_START_MARKER = '<!-- CONTEXTOS:START -->';
|
|
13
|
+
const CLAUDE_END_MARKER = '<!-- CONTEXTOS:END -->';
|
|
12
14
|
|
|
13
15
|
function describe() {
|
|
14
16
|
return {
|
|
15
17
|
name: 'claude',
|
|
16
18
|
version: '2.0.0',
|
|
17
|
-
description: 'Compiles clean markdown skills for Claude Code CLI',
|
|
18
|
-
targetPattern: '.agents/generated/claude/skills/**/SKILL.md',
|
|
19
|
+
description: 'Compiles clean markdown skills for Claude Code CLI and manages CLAUDE.md entrypoint',
|
|
20
|
+
targetPattern: '{CLAUDE.md,.agents/generated/claude/skills/**/SKILL.md}',
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -53,8 +55,52 @@ function renderClaudeSkill(skillDir, context) {
|
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
function renderClaudeRootIndex(skills, context) {
|
|
59
|
+
const projectRoot = context?.projectRoot || '.';
|
|
60
|
+
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
61
|
+
let existingContent = '';
|
|
62
|
+
if (fs.existsSync(claudePath)) {
|
|
63
|
+
try {
|
|
64
|
+
existingContent = fs.readFileSync(claudePath, 'utf8');
|
|
65
|
+
} catch {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const skillEntries = skills.map(skillDir => {
|
|
69
|
+
const name = path.basename(skillDir);
|
|
70
|
+
return `- [${name}](.agents/generated/claude/skills/${name}/SKILL.md)`;
|
|
71
|
+
}).join('\n');
|
|
72
|
+
|
|
73
|
+
const managedBlock = `${CLAUDE_START_MARKER}
|
|
74
|
+
<!-- Do not edit this section directly. Synchronized by ContextOS. -->
|
|
75
|
+
# ContextOS Agent Governance
|
|
76
|
+
|
|
77
|
+
The following skills are managed by ContextOS:
|
|
78
|
+
${skillEntries}
|
|
79
|
+
${CLAUDE_END_MARKER}`;
|
|
80
|
+
|
|
81
|
+
let finalContent;
|
|
82
|
+
if (existingContent.includes(CLAUDE_START_MARKER)) {
|
|
83
|
+
const regex = new RegExp(`${CLAUDE_START_MARKER}[\\s\\S]*?${CLAUDE_END_MARKER}`);
|
|
84
|
+
finalContent = existingContent.replace(regex, managedBlock);
|
|
85
|
+
} else if (existingContent.trim()) {
|
|
86
|
+
finalContent = `${existingContent.trimEnd()}\n\n${managedBlock}\n`;
|
|
87
|
+
} else {
|
|
88
|
+
finalContent = `${managedBlock}\n`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
path: 'CLAUDE.md',
|
|
93
|
+
content: finalContent.replace(/\r\n/g, '\n'),
|
|
94
|
+
mediaType: 'text/markdown',
|
|
95
|
+
kind: 'generated-adapter',
|
|
96
|
+
generator: GENERATOR_ID,
|
|
97
|
+
sourceSkillIds: skills.map(s => path.basename(s)),
|
|
98
|
+
inputsHash: context?.sourceGraphHash || 'none',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
56
102
|
function render(context) {
|
|
57
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
103
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
58
104
|
const artifacts = [];
|
|
59
105
|
|
|
60
106
|
for (const skill of skills) {
|
|
@@ -62,6 +108,11 @@ function render(context) {
|
|
|
62
108
|
if (art) artifacts.push(art);
|
|
63
109
|
}
|
|
64
110
|
|
|
111
|
+
if (skills.length > 0) {
|
|
112
|
+
const rootIndex = renderClaudeRootIndex(skills, context);
|
|
113
|
+
if (rootIndex) artifacts.push(rootIndex);
|
|
114
|
+
}
|
|
115
|
+
|
|
65
116
|
return artifacts;
|
|
66
117
|
}
|
|
67
118
|
|
|
@@ -79,7 +79,7 @@ function render(context) {
|
|
|
79
79
|
`| --- | --- | --- |\n`
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
82
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
83
83
|
for (const skill of skills) {
|
|
84
84
|
const skillName = path.basename(skill);
|
|
85
85
|
const yamlPath = path.join(skill, 'skill.yaml');
|
|
@@ -187,7 +187,7 @@ ${agentsMd}
|
|
|
187
187
|
});
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
190
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
191
191
|
for (const skill of skills) {
|
|
192
192
|
const mdc = generateCursorMdc(skill);
|
|
193
193
|
if (mdc) {
|
|
@@ -23,6 +23,9 @@ const DRIFT_STATES = {
|
|
|
23
23
|
ORPHAN_MANAGED_OUTPUT: 'ORPHAN_MANAGED_OUTPUT',
|
|
24
24
|
ADAPTER_VERSION_MISMATCH: 'ADAPTER_VERSION_MISMATCH',
|
|
25
25
|
PROFILE_MISMATCH: 'PROFILE_MISMATCH',
|
|
26
|
+
CORRUPT_LOCKFILE: 'CORRUPT_LOCKFILE',
|
|
27
|
+
EMPTY_PROJECTION: 'EMPTY_PROJECTION',
|
|
28
|
+
CONFIG_ERROR: 'CONFIG_ERROR',
|
|
26
29
|
};
|
|
27
30
|
|
|
28
31
|
/**
|
|
@@ -67,9 +70,6 @@ function computeDiffSnippet(beforeStr, afterStr, maxLines = 15) {
|
|
|
67
70
|
function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
68
71
|
const absRoot = path.resolve(projectRoot);
|
|
69
72
|
const lockManager = new LockfileV2Manager(absRoot);
|
|
70
|
-
const lockfile = lockManager.read();
|
|
71
|
-
|
|
72
|
-
const { artifacts, collisions, context } = renderAdapters(absRoot, adapters, options);
|
|
73
73
|
|
|
74
74
|
const findings = {
|
|
75
75
|
[DRIFT_STATES.STALE_INPUT]: [],
|
|
@@ -78,11 +78,57 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
78
78
|
[DRIFT_STATES.ORPHAN_MANAGED_OUTPUT]: [],
|
|
79
79
|
[DRIFT_STATES.ADAPTER_VERSION_MISMATCH]: [],
|
|
80
80
|
[DRIFT_STATES.PROFILE_MISMATCH]: [],
|
|
81
|
+
[DRIFT_STATES.CORRUPT_LOCKFILE]: [],
|
|
82
|
+
[DRIFT_STATES.EMPTY_PROJECTION]: [],
|
|
83
|
+
[DRIFT_STATES.CONFIG_ERROR]: [],
|
|
81
84
|
};
|
|
82
85
|
|
|
83
86
|
const diffs = [];
|
|
84
87
|
|
|
85
|
-
//
|
|
88
|
+
// 0. Safe lockfile load with corrupt lockfile detection
|
|
89
|
+
let lockfile = null;
|
|
90
|
+
try {
|
|
91
|
+
lockfile = lockManager.read();
|
|
92
|
+
} catch (err) {
|
|
93
|
+
findings[DRIFT_STATES.CORRUPT_LOCKFILE].push({
|
|
94
|
+
reason: `Lockfile is corrupt: ${err.message}`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 1. Adapter rendering with error containment
|
|
99
|
+
let rendered;
|
|
100
|
+
try {
|
|
101
|
+
rendered = renderAdapters(absRoot, adapters, options);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
findings[DRIFT_STATES.CONFIG_ERROR].push({
|
|
104
|
+
reason: err.message,
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
hasDrift: true,
|
|
108
|
+
hasError: true,
|
|
109
|
+
code: 2,
|
|
110
|
+
totalFindings: 1,
|
|
111
|
+
findings,
|
|
112
|
+
collisions: [],
|
|
113
|
+
diffs: [],
|
|
114
|
+
projectedCount: 0,
|
|
115
|
+
error: err.message,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { artifacts, collisions, context } = rendered;
|
|
120
|
+
|
|
121
|
+
// 2. Empty projection check
|
|
122
|
+
if (artifacts.length === 0) {
|
|
123
|
+
const hasAgentsDir = fs.existsSync(path.join(absRoot, '.agents'));
|
|
124
|
+
if (hasAgentsDir) {
|
|
125
|
+
findings[DRIFT_STATES.EMPTY_PROJECTION].push({
|
|
126
|
+
reason: 'Projected artifact set is empty while .agents directory exists',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 3. Check Profile Mismatch
|
|
86
132
|
if (lockfile && lockfile.profile) {
|
|
87
133
|
if (context.profileId && lockfile.profile.id !== context.profileId) {
|
|
88
134
|
findings[DRIFT_STATES.PROFILE_MISMATCH].push({
|
|
@@ -92,7 +138,7 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
92
138
|
}
|
|
93
139
|
}
|
|
94
140
|
|
|
95
|
-
//
|
|
141
|
+
// 4. Check Stale Input (Source Graph Hash)
|
|
96
142
|
if (lockfile && lockfile.sourceGraphHash) {
|
|
97
143
|
if (context.sourceGraphHash && lockfile.sourceGraphHash !== context.sourceGraphHash) {
|
|
98
144
|
findings[DRIFT_STATES.STALE_INPUT].push({
|
|
@@ -104,7 +150,7 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
104
150
|
|
|
105
151
|
const projectedPaths = new Set(artifacts.map(a => a.path));
|
|
106
152
|
|
|
107
|
-
//
|
|
153
|
+
// 5. Inspect each projected artifact against disk and lockfile
|
|
108
154
|
for (const art of artifacts) {
|
|
109
155
|
const fullPath = path.resolve(absRoot, art.path);
|
|
110
156
|
const projectedContent = art.content.toString('utf8');
|
|
@@ -124,10 +170,13 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
124
170
|
} else {
|
|
125
171
|
const diskContent = fs.readFileSync(fullPath, 'utf8');
|
|
126
172
|
const diskSemanticHash = computeSemanticHash(diskContent);
|
|
173
|
+
const lockRecord = lockfile?.managedFiles?.[art.path];
|
|
174
|
+
|
|
175
|
+
// Check if disk matches projected render and recorded lockfile
|
|
176
|
+
const matchesProjection = diskSemanticHash === projectedSemanticHash;
|
|
177
|
+
const matchesLock = lockRecord ? diskSemanticHash === lockRecord.semanticTextSha256 : matchesProjection;
|
|
127
178
|
|
|
128
|
-
|
|
129
|
-
if (diskSemanticHash !== projectedSemanticHash) {
|
|
130
|
-
const lockRecord = lockfile?.managedFiles?.[art.path];
|
|
179
|
+
if (!matchesProjection || !matchesLock) {
|
|
131
180
|
if (lockRecord && lockRecord.semanticTextSha256 !== diskSemanticHash) {
|
|
132
181
|
findings[DRIFT_STATES.MODIFIED_MANAGED_OUTPUT].push({
|
|
133
182
|
path: art.path,
|
|
@@ -151,14 +200,32 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
151
200
|
}
|
|
152
201
|
}
|
|
153
202
|
|
|
154
|
-
//
|
|
203
|
+
// 6. Check for orphan files recorded in lockfile but no longer projected
|
|
204
|
+
// Task 1.4: Scoped strictly to the active adapters being checked
|
|
155
205
|
if (lockfile && lockfile.managedFiles) {
|
|
206
|
+
const targetGenerators = new Set(artifacts.map(a => a.generator));
|
|
207
|
+
const adapterList = adapters === 'all' ? null : (Array.isArray(adapters) ? adapters : [adapters]);
|
|
208
|
+
const allowedPrefixes = adapterList ? adapterList.map(a => `${a}@`) : null;
|
|
209
|
+
|
|
156
210
|
for (const [recordedPath, meta] of Object.entries(lockfile.managedFiles)) {
|
|
211
|
+
if (meta && meta.generator && allowedPrefixes) {
|
|
212
|
+
const matchesTarget = targetGenerators.has(meta.generator) ||
|
|
213
|
+
allowedPrefixes.some(p => meta.generator.startsWith(p));
|
|
214
|
+
if (!matchesTarget) {
|
|
215
|
+
continue; // Skip files from adapters not currently being verified
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (meta && meta.kind && meta.kind !== 'generated-adapter') {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
157
223
|
if (!projectedPaths.has(recordedPath)) {
|
|
158
224
|
const fullRecorded = path.resolve(absRoot, recordedPath);
|
|
159
225
|
if (fs.existsSync(fullRecorded)) {
|
|
160
226
|
findings[DRIFT_STATES.ORPHAN_MANAGED_OUTPUT].push({
|
|
161
227
|
path: recordedPath,
|
|
228
|
+
generator: meta.generator,
|
|
162
229
|
reason: 'File recorded in lockfile is no longer generated by active skills/profile',
|
|
163
230
|
});
|
|
164
231
|
diffs.push({
|
|
@@ -178,9 +245,18 @@ function detectDrift(projectRoot, adapters = 'all', options = {}) {
|
|
|
178
245
|
|
|
179
246
|
const totalFindings = Object.values(findings).reduce((acc, list) => acc + list.length, 0);
|
|
180
247
|
const hasDrift = totalFindings > 0 || collisions.length > 0;
|
|
248
|
+
const hasError = findings[DRIFT_STATES.CORRUPT_LOCKFILE].length > 0 ||
|
|
249
|
+
findings[DRIFT_STATES.EMPTY_PROJECTION].length > 0 ||
|
|
250
|
+
findings[DRIFT_STATES.CONFIG_ERROR].length > 0;
|
|
251
|
+
const code = hasError ? 2 : (hasDrift ? 1 : 0);
|
|
252
|
+
const status = hasError ? 'error' : (hasDrift ? 'drift' : 'pass');
|
|
181
253
|
|
|
182
254
|
return {
|
|
255
|
+
schemaVersion: '2.0.0',
|
|
256
|
+
status,
|
|
183
257
|
hasDrift,
|
|
258
|
+
hasError,
|
|
259
|
+
code,
|
|
184
260
|
totalFindings,
|
|
185
261
|
findings,
|
|
186
262
|
collisions,
|
|
@@ -103,7 +103,7 @@ ${mergedContent.trimStart()}
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function render(context) {
|
|
106
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
106
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
107
107
|
const artifacts = [];
|
|
108
108
|
|
|
109
109
|
for (const skill of skills) {
|
|
@@ -86,11 +86,22 @@ function loadCompilerContext(projectRoot, options = {}) {
|
|
|
86
86
|
|
|
87
87
|
// 2. Profile v2
|
|
88
88
|
let profile = null;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
const profiles = require('../profiles.js');
|
|
90
|
+
if (options.profile) {
|
|
91
|
+
try {
|
|
92
|
+
profile = profiles.getProfile(options.profile, absRoot);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
throw new Error(`Failed to load profile '${options.profile}': ${err.message}`);
|
|
95
|
+
}
|
|
96
|
+
if (!profile) {
|
|
97
|
+
throw new Error(`Profile '${options.profile}' was specified but does not exist.`);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
try {
|
|
101
|
+
profile = profiles.getActiveProfile(absRoot);
|
|
102
|
+
} catch {
|
|
103
|
+
profile = null;
|
|
104
|
+
}
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
// 3. Workspace Graph
|
|
@@ -139,6 +150,13 @@ function registerAdapter(name, adapter) {
|
|
|
139
150
|
adaptersRegistry.set(name, adapter);
|
|
140
151
|
}
|
|
141
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Unregisters an adapter from the pure compiler registry.
|
|
155
|
+
*/
|
|
156
|
+
function unregisterAdapter(name) {
|
|
157
|
+
adaptersRegistry.delete(name);
|
|
158
|
+
}
|
|
159
|
+
|
|
142
160
|
/**
|
|
143
161
|
* Retrieves a registered adapter.
|
|
144
162
|
*/
|
|
@@ -165,9 +183,10 @@ function listAdapters() {
|
|
|
165
183
|
*/
|
|
166
184
|
function renderAdapters(projectRoot, adapterNames = 'all', options = {}) {
|
|
167
185
|
const context = loadCompilerContext(projectRoot, options);
|
|
168
|
-
const
|
|
186
|
+
const rawTargets = adapterNames === 'all'
|
|
169
187
|
? listAdapters()
|
|
170
188
|
: (Array.isArray(adapterNames) ? adapterNames : [adapterNames]);
|
|
189
|
+
const targets = rawTargets.flatMap(a => (typeof a === 'string' && a.includes(',') ? a.split(',').map(s => s.trim()).filter(Boolean) : a));
|
|
171
190
|
|
|
172
191
|
const allArtifacts = [];
|
|
173
192
|
const pathToArtifact = new Map();
|
|
@@ -436,8 +455,11 @@ module.exports = {
|
|
|
436
455
|
createProvenanceHeader,
|
|
437
456
|
loadCompilerContext,
|
|
438
457
|
registerAdapter,
|
|
458
|
+
unregisterAdapter,
|
|
439
459
|
getAdapter,
|
|
440
460
|
listAdapters,
|
|
441
461
|
renderAdapters,
|
|
442
462
|
applyArtifacts,
|
|
463
|
+
computeExactHash,
|
|
464
|
+
computeSemanticHash,
|
|
443
465
|
};
|
|
@@ -12,17 +12,26 @@ const AGENTS_MD_PATH = path.join(AGENTS_DIR, 'AGENTS.md');
|
|
|
12
12
|
* Plugins intentionally live outside `core/skills`, so adapters must use this
|
|
13
13
|
* helper rather than enumerate the core directory themselves.
|
|
14
14
|
*/
|
|
15
|
-
function collectSkillDirectories(overrideProfile = null) {
|
|
15
|
+
function collectSkillDirectories(overrideProfile = null, projectRoot = null) {
|
|
16
|
+
let profile = overrideProfile;
|
|
17
|
+
let root = projectRoot;
|
|
18
|
+
|
|
19
|
+
if (overrideProfile && typeof overrideProfile === 'object') {
|
|
20
|
+
if (overrideProfile.projectRoot && !root) {
|
|
21
|
+
root = overrideProfile.projectRoot;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const effectiveRoot = root ? path.resolve(root) : process.cwd();
|
|
16
26
|
const plugins = require(path.join(AGENTS_DIR, 'plugins.js'));
|
|
17
|
-
let dirs = plugins.collectAllSkillDirs()
|
|
27
|
+
let dirs = plugins.collectAllSkillDirs(effectiveRoot)
|
|
18
28
|
.filter(dir => fs.existsSync(dir) && fs.statSync(dir).isDirectory())
|
|
19
29
|
.sort((a, b) => path.basename(a).localeCompare(path.basename(b)));
|
|
20
30
|
|
|
21
|
-
let profile = overrideProfile;
|
|
22
31
|
if (!profile) {
|
|
23
32
|
try {
|
|
24
33
|
const profilesEngine = require(path.join(AGENTS_DIR, 'profiles.js'));
|
|
25
|
-
profile = profilesEngine.getActiveProfile();
|
|
34
|
+
profile = profilesEngine.getActiveProfile(effectiveRoot);
|
|
26
35
|
} catch {
|
|
27
36
|
profile = null;
|
|
28
37
|
}
|
|
@@ -95,7 +95,7 @@ function render(context) {
|
|
|
95
95
|
`### Available Skills\n`
|
|
96
96
|
);
|
|
97
97
|
|
|
98
|
-
const skills = collectSkillDirectories(context?.profile);
|
|
98
|
+
const skills = collectSkillDirectories(context?.profile, context?.projectRoot);
|
|
99
99
|
for (const skill of skills) {
|
|
100
100
|
const res = buildSkillSection(skill);
|
|
101
101
|
if (res) {
|