clckernel 1.2.6 → 1.2.9

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 (47) hide show
  1. package/README.es.md +103 -110
  2. package/README.md +100 -108
  3. package/package.json +14 -2
  4. package/src/adapters/agent-os.js +206 -0
  5. package/src/catalog.js +16 -0
  6. package/src/detector.js +2 -0
  7. package/src/generator.js +39 -62
  8. package/src/index.js +11 -0
  9. package/src/ui.js +79 -35
  10. package/tools/audit.js +0 -0
  11. package/tools/audit.py +0 -0
  12. package/tools/check_custom.js +0 -0
  13. package/tools/check_custom.py +0 -0
  14. package/tools/check_db_efficiency.py +0 -0
  15. package/tools/check_domain_data.js +100 -0
  16. package/tools/check_hitl.js +93 -0
  17. package/tools/check_responsive.js +0 -0
  18. package/tools/check_seo.js +1 -1
  19. package/tools/check_symlinks.js +76 -0
  20. package/tools/check_test_calendar_sync.js +111 -0
  21. package/tools/scan_secrets.js +12 -1
  22. package/tools/scan_secrets.py +0 -0
  23. package/AGENTS.md +0 -124
  24. package/docs/Journal/001-adr-clckernel-governance.md +0 -18
  25. package/test/adapters/astro.test.js +0 -102
  26. package/test/adapters/base.test.js +0 -86
  27. package/test/adapters/django.test.js +0 -95
  28. package/test/adapters/fastapi.test.js +0 -88
  29. package/test/adapters/go.test.js +0 -81
  30. package/test/adapters/laravel.test.js +0 -106
  31. package/test/adapters/nextjs.test.js +0 -113
  32. package/test/adapters/rails.test.js +0 -108
  33. package/test/adapters/rust.test.js +0 -83
  34. package/test/catalog.test.js +0 -170
  35. package/test/config.test.js +0 -512
  36. package/test/detector.test.js +0 -345
  37. package/test/doctor.test.js +0 -302
  38. package/test/generator.test.js +0 -419
  39. package/test/guards_new.test.js +0 -95
  40. package/test/helpers.js +0 -36
  41. package/test/integration/cli-flow.test.js +0 -270
  42. package/test/technologies/celery_guard.test.js +0 -185
  43. package/test/technologies/detector.test.js +0 -342
  44. package/test/technologies/docker_guard.test.js +0 -187
  45. package/test/technologies/integration.test.js +0 -123
  46. package/test/technologies/postgres_guard.test.js +0 -87
  47. package/test/technologies/redis_guard.test.js +0 -128
@@ -0,0 +1,206 @@
1
+ /**
2
+ * CLC Kernel — Agent-OS & Domain Workflows Stack Adapter
3
+ * Supports AI Agent Operating Systems (Marketing OS, Content Ops, Research OS)
4
+ * featuring Dual-Layer Governance and Domain Integrity Safeguards.
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const BaseAdapter = require('./base');
10
+
11
+ class AgentOSAdapter extends BaseAdapter {
12
+ constructor() {
13
+ super('Agent-OS (Domain & AI Workflows)', 'agent-os', 'Playbook / Contract Test');
14
+ }
15
+
16
+ detect(targetDir) {
17
+ // 1. package.json check
18
+ const pkgPath = path.join(targetDir, 'package.json');
19
+ if (fs.existsSync(pkgPath)) {
20
+ try {
21
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
22
+ const name = (pkg.name || '').toLowerCase();
23
+ const desc = (pkg.description || '').toLowerCase();
24
+ const keywords = Array.isArray(pkg.keywords) ? pkg.keywords.map(k => k.toLowerCase()) : [];
25
+ if (
26
+ name.includes('agent-os') || name.includes('marketing-os') || name.includes('laila-mos') ||
27
+ desc.includes('agent-os') || desc.includes('marketing operating system') ||
28
+ keywords.includes('agent-os') || keywords.includes('marketing-os') || keywords.includes('ai-agents')
29
+ ) {
30
+ return true;
31
+ }
32
+ } catch {}
33
+ }
34
+
35
+ // 2. skills/ or .agents/skills/ directory check
36
+ const skillsDir = path.join(targetDir, 'skills');
37
+ const agentSkillsDir = path.join(targetDir, '.agents', 'skills');
38
+ if (fs.existsSync(skillsDir) || fs.existsSync(agentSkillsDir)) {
39
+ const dirToCheck = fs.existsSync(skillsDir) ? skillsDir : agentSkillsDir;
40
+ try {
41
+ const files = fs.readdirSync(dirToCheck);
42
+ if (files.some(f => f.endsWith('.md'))) {
43
+ return true;
44
+ }
45
+ } catch {}
46
+ }
47
+
48
+ // 3. brand/ or templates/ check alongside README referencing agents/workflows
49
+ const brandPath = path.join(targetDir, 'brand');
50
+ const templatesPath = path.join(targetDir, 'templates');
51
+ const readmePath = path.join(targetDir, 'README.md');
52
+ if ((fs.existsSync(brandPath) || fs.existsSync(templatesPath)) && fs.existsSync(readmePath)) {
53
+ try {
54
+ const readme = fs.readFileSync(readmePath, 'utf-8').toLowerCase();
55
+ if (readme.includes('subagent') || readme.includes('operating system') || readme.includes('agent')) {
56
+ return true;
57
+ }
58
+ } catch {}
59
+ }
60
+
61
+ return false;
62
+ }
63
+
64
+ getSafeguards() {
65
+ return [
66
+ 'Dual-Layer Architecture: Layer 1 (Engineering) & Layer 2 (Domain Runtime)',
67
+ 'Mandatory Human-in-the-Loop (HITL) Checkpoints',
68
+ 'Symlink Interoperability (.cursorrules, CLAUDE.md, GEMINI.md, .windsurfrules)',
69
+ 'Domain Data Integrity & Clean Creation State (No Hallucinated Metrics)',
70
+ 'Single Source of Truth (SSOT) Memory Primacy',
71
+ 'Local-only Spec Driven Development (sdds/)'
72
+ ];
73
+ }
74
+
75
+ getTools() {
76
+ return [
77
+ {
78
+ name: 'check_symlinks',
79
+ language: 'node',
80
+ path: 'tools/check_symlinks.js',
81
+ command: 'node tools/check_symlinks.js',
82
+ description: 'AI IDE symlinks and rule mirror verification'
83
+ },
84
+ {
85
+ name: 'check_hitl',
86
+ language: 'node',
87
+ path: 'tools/check_hitl.js',
88
+ command: 'node tools/check_hitl.js',
89
+ description: 'Human-in-the-Loop review checkpoint validator'
90
+ },
91
+ {
92
+ name: 'check_domain_data',
93
+ language: 'node',
94
+ path: 'tools/check_domain_data.js',
95
+ command: 'node tools/check_domain_data.js',
96
+ description: 'Domain deliverables schema and clean state integrity'
97
+ },
98
+ {
99
+ name: 'check_test_calendar_sync',
100
+ language: 'node',
101
+ path: 'tools/check_test_calendar_sync.js',
102
+ command: 'node tools/check_test_calendar_sync.js',
103
+ description: 'Test calendar harness synchronization and parity check'
104
+ },
105
+ {
106
+ name: 'scan_secrets',
107
+ language: 'node',
108
+ path: 'tools/scan_secrets.js',
109
+ command: 'node tools/scan_secrets.js',
110
+ description: 'Security & API key leak scanner'
111
+ }
112
+ ];
113
+ }
114
+
115
+ provision(targetDir, config) {
116
+ // 1. Create docs/, sdds/, and tools/
117
+ super.provision(targetDir, config);
118
+
119
+ // 2. Write Dual-Layer AGENTS.md
120
+ const dualLayerAgents = `# Standard Operating Procedure (SOP) — AGENTS
121
+ Governed by **CLC Kernel: The Universal AI Agent Governance Engine**.
122
+ Target System: **${this.name}**
123
+
124
+ ---
125
+
126
+ ## 🛠️ Layer 1: Development & Maintenance Governance (Engineering)
127
+ All AI Agents (Antigravity, OpenCode, Claude Code, Cursor, Windsurf, Copilot) developing or maintaining this codebase MUST adhere to strict engineering standards:
128
+
129
+ > 🚨 **RULE #0: MANDATORY EXECUTION OVERRIDE RULE (UNBYPASSABLE)**
130
+ > Even when the user issues a direct or urgent fix request ("fix this bug", "fix this error", "quick fix"):
131
+ > YOU ARE STRICTLY FORBIDDEN from modifying source code or workflows directly without completing the full quality harness:
132
+ > 1. **Research & Root Cause Analysis:** Investigate tracebacks and affected files before editing.
133
+ > 2. **SDD Specification:** Document non-trivial changes in \`sdds/{change-name}/01-spec.md\` (gitignored).
134
+ > 3. **Verification (Red Phase):** Write a failing test or contract validation first.
135
+ > 4. **Clean Implementation (Green Phase):** Make tests pass maintaining strict layer isolation.
136
+ > 5. **Mandatory Audit Gate:** Execute \`node tools/audit.js\` and output summary to stdout.
137
+
138
+ ### Engineering Rules
139
+ 1. **Conventional Commits Only**: Commits must use Conventional Commits (e.g. \`feat(...): ...\`, \`fix(...): ...\`). NEVER add \`Co-Authored-By\` or AI attribution.
140
+ 2. **Mirror Links Interoperability**: \`CLAUDE.md\`, \`GEMINI.md\`, \`.cursorrules\`, and \`.windsurfrules\` must remain valid symlinks to \`AGENTS.md\`.
141
+ 3. **No Superficial Symptom Patches**: Always address root causes.
142
+
143
+ ---
144
+
145
+ ## 🚀 Layer 2: Domain Runtime Directives (Agent Workflows & Operations)
146
+ When operating as domain agents for end-users and non-technical operators:
147
+
148
+ 1. **Non-Technical Operator Friendly**: Interact naturally with the operator. Guide step-by-step through conversational prompts without technical jargon.
149
+ 2. **Mandatory Human-in-the-Loop (HITL) Checkpoints**: Always pause phase-by-phase during multi-step pipelines. Present draft output and WAIT for explicit user confirmation before executing irreversible steps.
150
+ 3. **SSOT Memory Primacy**: Always read from and persist to designated single-source-of-truth memory files (e.g. \`brand/client-profile.md\` or \`docs/\`).
151
+ 4. **Clean Creation State (No Hallucinated Data)**: When new records, calendars, or deliverables are drafted, metric fields must initialize as \`null\` / empty. Never invent fictional stats.
152
+ 5. **Deterministic Output Standard**: Outputs must strictly follow valid Markdown, JSON schema, or domain templates.
153
+
154
+ ---
155
+
156
+ ## 🎮 Universal Command Interface (All LLMs & Agents)
157
+ When given a command matching \`clckernel <action>\` or \`/clckernel <action>\`, execute the deterministic state machine below:
158
+
159
+ | Command | Lifecycle Phase | Mandatory Execution Protocol |
160
+ |---|---|---|
161
+ | \`clckernel feature <name>\` | New Feature | 1. Research affected layers.<br>2. Author local spec in \`sdds/{name}/spec.md\`.<br>3. Present HIT review to user and wait for approval.<br>4. Write failing test (Red Phase).<br>5. Implement clean code (Green Phase).<br>6. Run \`node tools/audit.js\` (or \`audit.py\`). |
162
+ | \`clckernel fix <issue>\` | Bug Fix | 1. Investigate root cause (no code edits).<br>2. Reproduce with failing test (Red Phase).<br>3. Minimal surgical fix respecting Clean Arch (Green Phase).<br>4. Run audit gate without skipping. |
163
+ | \`clckernel test\` | Verification | Run test suite and verify clean pass (exit code 0). |
164
+ | \`clckernel audit\` | Verification | Run \`node tools/audit.js\` or \`python tools/audit.py\` and output the Educational Summary. |
165
+ | \`clckernel doctor\` | Diagnostics | Check git pre-commit hooks, IDE symlinks, and AST engine integrity. |
166
+ | \`clckernel commit <message>\` | Version Control | Run full audit, verify tests pass, ensure no changes outside SDD scope, and commit with conventional commits (never add AI attribution). |
167
+ | \`clckernel guard create <name>\` | Safeguards | Scaffold a new AST guard in the stack's native language in \`tools/guards/\`. |
168
+ | \`clckernel start\` | Setup | Scan codebase, propose governance plan, and materialize \`.clckernel.yaml\`. |
169
+
170
+ ---
171
+
172
+ ## 🛡️ Core AI Safeguards
173
+ ${this.getSafeguards().map(s => `- ${s}`).join('\n')}
174
+ `;
175
+
176
+ fs.writeFileSync(path.join(targetDir, 'AGENTS.md'), dualLayerAgents, 'utf-8');
177
+
178
+ // 3. Create AI IDE mirror symlinks
179
+ const mirrors = ['CLAUDE.md', 'GEMINI.md', '.cursorrules', '.windsurfrules'];
180
+ for (const mirror of mirrors) {
181
+ const mirrorPath = path.join(targetDir, mirror);
182
+ try {
183
+ if (!fs.existsSync(mirrorPath)) {
184
+ fs.symlinkSync('AGENTS.md', mirrorPath);
185
+ }
186
+ } catch {}
187
+ }
188
+
189
+ // 4. Copy domain guard tools into tools/
190
+ const srcToolsDir = path.join(__dirname, '..', '..', 'tools');
191
+ const targetToolsDir = path.join(targetDir, 'tools');
192
+ const toolsToCopy = ['check_symlinks.js', 'check_hitl.js', 'check_domain_data.js', 'scan_secrets.js', 'audit.js'];
193
+
194
+ for (const toolFile of toolsToCopy) {
195
+ const srcFile = path.join(srcToolsDir, toolFile);
196
+ const destFile = path.join(targetToolsDir, toolFile);
197
+ if (fs.existsSync(srcFile) && !fs.existsSync(destFile)) {
198
+ try {
199
+ fs.copyFileSync(srcFile, destFile);
200
+ } catch {}
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ module.exports = AgentOSAdapter;
package/src/catalog.js CHANGED
@@ -110,6 +110,21 @@ const SAFEGUARD_CATALOG = [
110
110
  applies_when: 'docker', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
111
111
  phase: 'audit', file: 'docker_guard.py', manifest: true, planned: false },
112
112
 
113
+ { name: 'check_symlinks', labels: ['check_symlinks', 'check_symlinks.js'],
114
+ checks: 'AI IDE symlinks and rule mirror verification', verify: ['verify_symlinks', 'verify_rule_mirrors'],
115
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['scope'],
116
+ phase: 'audit', file: 'check_symlinks.js', manifest: true, planned: false },
117
+
118
+ { name: 'check_hitl', labels: ['check_hitl', 'check_hitl.js'],
119
+ checks: 'Human-in-the-Loop review checkpoint validator in subagent skills', verify: ['verify_hitl', 'verify_human_review_checkpoints'],
120
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['scope'],
121
+ phase: 'audit', file: 'check_hitl.js', manifest: true, planned: false },
122
+
123
+ { name: 'check_domain_data', labels: ['check_domain_data', 'check_domain_data.js'],
124
+ checks: 'Domain deliverables schema and clean state integrity', verify: ['verify_domain_data', 'verify_clean_state_metrics'],
125
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['scope'],
126
+ phase: 'audit', file: 'check_domain_data.js', manifest: true, planned: false },
127
+
113
128
  { name: 'ruff', labels: ['ruff'],
114
129
  checks: 'Python AST linter (external CLI)', verify: ['verify_python_lint'],
115
130
  applies_when: 'backend', severity: 'warning', gate_mode: 'advisory', config_keys: [],
@@ -172,6 +187,7 @@ const VALID_PHASES = ['audit', 'test', 'review', 'handover'];
172
187
  const VALID_APPLIES_WHEN = [
173
188
  'always', 'frontend', 'backend', 'fastapi', 'django', 'django|sqlalchemy',
174
189
  'celery', 'redis', 'postgresql', 'docker', 'frontend,backend', 'backend,fastapi,django',
190
+ 'agent-os',
175
191
  ];
176
192
 
177
193
  /** Normalize an input label for catalog lookup. */
package/src/detector.js CHANGED
@@ -15,9 +15,11 @@ const RailsAdapter = require('./adapters/rails');
15
15
  const GoAdapter = require('./adapters/go');
16
16
  const RustAdapter = require('./adapters/rust');
17
17
  const LaravelAdapter = require('./adapters/laravel');
18
+ const AgentOSAdapter = require('./adapters/agent-os');
18
19
  const { TechnologyDetector } = require('./technologies/detector');
19
20
 
20
21
  const adapters = [
22
+ new AgentOSAdapter(),
21
23
  new NextjsAdapter(),
22
24
  new FastApiAdapter(),
23
25
  new DjangoAdapter(),
package/src/generator.js CHANGED
@@ -325,6 +325,20 @@ ${isFront ? `- UI Component Reuse First (components/ui/ & semantic tokens)
325
325
  - Database Efficiency & N+1 Performance Guard
326
326
  - Database Migration Idempotency Guard
327
327
  - Memory Guard (Engram / Graphify)`}
328
+
329
+ ## 3. Universal Command Interface (All LLMs & Agents)
330
+ When given a command matching \`clckernel <action>\` or \`/clckernel <action>\`, execute the deterministic state machine below:
331
+
332
+ | Command | Lifecycle Phase | Mandatory Execution Protocol |
333
+ |---|---|---|
334
+ | \`clckernel feature <name>\` | New Feature | 1. Research affected layers.<br>2. Author local spec in \`sdds/{name}/spec.md\`.<br>3. Present HIT review to user and wait for approval.<br>4. Write failing test (Red Phase).<br>5. Implement clean code (Green Phase).<br>6. Run \`node tools/audit.js\` (or \`audit.py\`). |
335
+ | \`clckernel fix <issue>\` | Bug Fix | 1. Investigate root cause (no code edits).<br>2. Reproduce with failing test (Red Phase).<br>3. Minimal surgical fix respecting Clean Arch (Green Phase).<br>4. Run audit gate without skipping. |
336
+ | \`clckernel test\` | Verification | Run test suite (\`${config.testRunner || 'npm test'}\`) and verify clean pass (exit code 0). |
337
+ | \`clckernel audit\` | Verification | Run \`node tools/audit.js\` or \`python tools/audit.py\` and output the Educational Summary. |
338
+ | \`clckernel doctor\` | Diagnostics | Check git pre-commit hooks, IDE symlinks, and AST engine integrity. |
339
+ | \`clckernel commit <message>\` | Version Control | Run full audit, verify tests pass, ensure no changes outside SDD scope, and commit with conventional commits (never add AI attribution). |
340
+ | \`clckernel guard create <name>\` | Safeguards | Scaffold a new AST guard in the stack's native language in \`tools/guards/\`. |
341
+ | \`clckernel start\` | Setup | Scan codebase, propose governance plan, and materialize \`.clckernel.yaml\`. |
328
342
  `;
329
343
  fs.writeFileSync(path.join(targetDir, 'AGENTS.md'), agentsContent, 'utf-8');
330
344
  }
@@ -372,68 +386,31 @@ function installAgenticCLI(targetDir) {
372
386
  // 1. Crear el Directorio de Skills
373
387
  const skillDir = path.join(targetDir, '.agents', 'skills', 'clckernel_cli');
374
388
  const legacySkillDir = path.join(targetDir, '.agents', 'skills', 'clc_forge_cli');
375
- fs.mkdirSync(skillDir, { recursive: true });
376
- fs.mkdirSync(legacySkillDir, { recursive: true });
377
-
378
- // 2. Inyectar el SKILL.md Maestro
379
- const skillContent = `---
380
- name: clckernel_cli
381
- description: Conversational CLI Orchestrator for the CLC Kernel AI Agent Governance Engine.
382
- triggers:
383
- - clckernel start
384
- - clckernel create_guard
385
- - clckernel remove_guard
386
- - clckernel add_phase
387
- - clckernel remove_phase
388
- - clc_forge start
389
- - clc_forge create_guard
390
- ---
391
-
392
- # 🤖 CLC Kernel — Conversational CLI
393
-
394
- You are the internal runtime engine of CLC Kernel (AIUP Orchestrator).
395
- DO NOT suggest terminal bash commands for these triggers; YOU are the execution environment. Your job is to guide the user through the agent governance lifecycle via chat, dynamically discovering the environment, and manipulating configuration files.
396
-
397
- ## 🚀 INTENT: \`clckernel start\` (or \`clc_forge start\`)
398
- Execute this exact sequence without skipping steps:
399
-
400
- ### Phase 1: Silent Discovery
401
- Scan the current project using your file-reading capabilities. Identify the primary tech stack by looking for signature files (e.g., \`package.json\`, \`Gemfile\`, \`Cargo.toml\`, \`go.mod\`).
402
- *Golden Rule: Do not assume the language. Read the files to establish context.*
403
-
404
- ### Phase 2: Interview & Proposal
405
- Introduce yourself as CLC Kernel and state the detected stack.
406
- Propose a standard governance plan for that ecosystem (SDD + TDD + stack-specific Safeguards).
407
- ASK the user directly:
408
- 1. "Should we activate these standard phases, or do you want to define custom ones?"
409
- 2. "Do you have any specific security needs that require a custom Guard?"
410
- **STOP.** Wait for the user's response.
411
-
412
- ### Phase 3: Materialization
413
- Based on user approval, generate and write the \`.clckernel.yaml\` file in the project root.
414
-
415
- ---
416
-
417
- ## 🛠️ INTENT: \`clckernel create_guard\`
418
- 1. Ask the user what behavior they want to audit or block. **STOP.** Wait for technical details.
419
- 2. Based on the detected stack, write the linter/guard script in the **NATIVE ECOSYSTEM LANGUAGE** (Ruby for Rails, Go \`ast\` for Golang, Python \`ast\` for FastAPI, JS for Node). Save it in \`tools/guards/\`.
420
- 3. Update the \`.clckernel.yaml\` file to include the new Guard.
421
-
422
- ---
423
-
424
- ## 🗑️ INTENT: \`clckernel remove_guard\`
425
- 1. Ask which guard to remove and if the script should be deleted. **STOP.** Wait for response.
426
- 2. Update \`.clckernel.yaml\` and delete the script from \`tools/guards/\` if requested.
427
-
428
- ---
429
-
430
- ## 🔄 INTENT: \`clckernel add_phase\` / \`clckernel remove_phase\`
431
- 1. Ask for details of the lifecycle phase to add or remove. **STOP.** Wait for response.
432
- 2. Update the \`execution_phases\` block in \`.clckernel.yaml\`, preserving the logical sequence.
433
- `;
434
-
435
- fs.writeFileSync(path.join(skillDir, 'SKILL.md'), skillContent, 'utf-8');
436
- fs.writeFileSync(path.join(legacySkillDir, 'SKILL.md'), skillContent, 'utf-8');
389
+ const skillRefDir = path.join(skillDir, 'reference');
390
+ const legacySkillRefDir = path.join(legacySkillDir, 'reference');
391
+ fs.mkdirSync(skillRefDir, { recursive: true });
392
+ fs.mkdirSync(legacySkillRefDir, { recursive: true });
393
+
394
+ // 2. Inyectar el SKILL.md Maestro y Playbooks de Referencia
395
+ const bundledSkillDir = path.join(__dirname, '..', '.agents', 'skills', 'clckernel_cli');
396
+ const bundledSkillFile = path.join(bundledSkillDir, 'SKILL.md');
397
+ const bundledRefDir = path.join(bundledSkillDir, 'reference');
398
+
399
+ if (fs.existsSync(bundledSkillFile)) {
400
+ fs.copyFileSync(bundledSkillFile, path.join(skillDir, 'SKILL.md'));
401
+ fs.copyFileSync(bundledSkillFile, path.join(legacySkillDir, 'SKILL.md'));
402
+ }
403
+
404
+ if (fs.existsSync(bundledRefDir)) {
405
+ const playbooks = fs.readdirSync(bundledRefDir);
406
+ for (const pb of playbooks) {
407
+ const srcPb = path.join(bundledRefDir, pb);
408
+ if (fs.statSync(srcPb).isFile()) {
409
+ fs.copyFileSync(srcPb, path.join(skillRefDir, pb));
410
+ fs.copyFileSync(srcPb, path.join(legacySkillRefDir, pb));
411
+ }
412
+ }
413
+ }
437
414
 
438
415
  // 3. Crear Symlinks Dinámicos al AGENTS.md (El Single Source of Truth)
439
416
  const sourceFile = 'AGENTS.md';
package/src/index.js CHANGED
@@ -43,8 +43,19 @@ async function runCli() {
43
43
  const finalConfig = await promptOptions(detected);
44
44
 
45
45
  // 5. Generate Harness & Safeguards
46
+ let s;
47
+ if (Boolean(process.stdin.isTTY) && !process.env.CI) {
48
+ const p = require('@clack/prompts');
49
+ s = p.spinner();
50
+ s.start('Configurando salvaguardas y motor de gobernanza...');
51
+ }
52
+
46
53
  generateHarness(targetDir, finalConfig);
47
54
 
55
+ if (s) {
56
+ s.stop('Salvaguardas y motor de gobernanza configurados.');
57
+ }
58
+
48
59
  // 6. Render Pro Success Card
49
60
  printSuccess(targetDir, finalConfig.projectType === 'frontend', finalConfig);
50
61
  }
package/src/ui.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Brand Identity: The AI Agent Governance & Quality Engineering Engine
4
4
  */
5
5
 
6
- const readline = require('readline');
6
+ const p = require('@clack/prompts');
7
7
 
8
8
  // ANSI Color Palette
9
9
  const colors = {
@@ -33,7 +33,7 @@ function printBanner() {
33
33
  ╚██████╗███████╗╚██████╗ ██║ ╚██╗███████╗██║ ██║██║ ╚████║███████╗███████╗
34
34
  ╚═════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝
35
35
  ${colors.reset}`);
36
- console.log(` ${colors.bgCyan} CLC KERNEL ${colors.reset} ${colors.bold}The AI Agent Governance & Quality Engineering Engine${colors.reset} ${colors.gray}v1.2.4${colors.reset}\n`);
36
+ console.log(` ${colors.bgCyan} CLC KERNEL ${colors.reset} ${colors.bold}The AI Agent Governance & Quality Engineering Engine${colors.reset} ${colors.gray}v1.2.6${colors.reset}\n`);
37
37
  }
38
38
 
39
39
  function printBox(title, items) {
@@ -52,44 +52,88 @@ function printBox(title, items) {
52
52
  console.log(`${colors.dim}└${'─'.repeat(width)}┘${colors.reset}\n`);
53
53
  }
54
54
 
55
- function promptOptions(detected) {
56
- return new Promise((resolve) => {
57
- const rl = readline.createInterface({
58
- input: process.stdin,
59
- output: process.stdout
60
- });
61
-
62
- console.log(`${colors.bold} \x1b[32m[1]\x1b[0m Confirmar e Instalar CLC Kernel ${colors.dim}(Recomendado)${colors.reset}`);
63
- console.log(` \x1b[33m[2]\x1b[0m Forzar modo FRONTEND`);
64
- console.log(` \x1b[33m[3]\x1b[0m Forzar modo BACKEND`);
65
- console.log(` \x1b[90m[4] Cancelar${colors.reset}\n`);
66
-
67
- rl.question(`${colors.cyan}${colors.bold}➔ Seleccioná una opción [1]: ${colors.reset}`, (answer) => {
68
- const choice = answer.trim() || '1';
69
- rl.close();
70
-
71
- if (choice === '1') {
72
- resolve(detected);
73
- } else if (choice === '2') {
74
- detected.projectType = 'frontend';
75
- resolve(detected);
76
- } else if (choice === '3') {
77
- detected.projectType = 'backend';
78
- resolve(detected);
79
- } else {
80
- console.log(`\n${colors.red}❌ Instalación de CLC Kernel cancelada.${colors.reset}`);
81
- process.exit(0);
55
+ async function promptOptions(detected) {
56
+ const isInteractive = Boolean(process.stdin.isTTY) &&
57
+ !process.env.CI &&
58
+ !process.argv.includes('--yes') &&
59
+ !process.argv.includes('-y');
60
+
61
+ if (!isInteractive) {
62
+ return detected;
63
+ }
64
+
65
+ p.intro(`${colors.cyan}${colors.bold}CLC Kernel Setup${colors.reset}`);
66
+
67
+ const choice = await p.select({
68
+ message: '¿Cómo deseas inicializar CLC Kernel en este proyecto?',
69
+ initialValue: 'confirm',
70
+ options: [
71
+ {
72
+ value: 'confirm',
73
+ label: 'Confirmar e Instalar CLC Kernel',
74
+ hint: `Recomendado (${detected.projectType.toUpperCase()} - ${detected.framework})`
75
+ },
76
+ {
77
+ value: 'frontend',
78
+ label: 'Forzar modo FRONTEND',
79
+ hint: 'Salvaguardas A11y, Zod, Next/Image, UI Reuse'
80
+ },
81
+ {
82
+ value: 'backend',
83
+ label: 'Forzar modo BACKEND',
84
+ hint: 'Salvaguardas TDD, Clean Arch, N+1, Secrets'
85
+ },
86
+ {
87
+ value: 'agent-os',
88
+ label: 'Forzar modo AGENT-OS',
89
+ hint: 'Salvaguardas HITL, Symlinks, Schemas, Memoria SSOT'
90
+ },
91
+ {
92
+ value: 'cancel',
93
+ label: 'Cancelar',
94
+ hint: 'Salir sin realizar cambios'
82
95
  }
83
- });
96
+ ]
84
97
  });
98
+
99
+ if (p.isCancel(choice) || choice === 'cancel') {
100
+ p.cancel('Instalación de CLC Kernel cancelada.');
101
+ process.exit(0);
102
+ }
103
+
104
+ if (choice === 'frontend') {
105
+ detected.projectType = 'frontend';
106
+ } else if (choice === 'backend') {
107
+ detected.projectType = 'backend';
108
+ } else if (choice === 'agent-os') {
109
+ detected.projectType = 'agent-os';
110
+ }
111
+
112
+ return detected;
85
113
  }
86
114
 
87
115
  function printSuccess(targetDir, isFront, config) {
88
- console.log(`\n${colors.bgEmerald} SUCCESS ${colors.reset} ${colors.bold}${colors.emerald}¡CLC Kernel instalado exitosamente!${colors.reset}\n`);
89
- console.log(` 🔨 ${colors.bold}Proyecto Inicializado:${colors.reset} ${colors.cyan}${targetDir}${colors.reset}`);
90
- console.log(` 🛡️ ${colors.bold}Salvaguardas:${colors.reset} ${isFront ? `${colors.emerald}10 Guardias Frontend (A11y, Zod, Next/Image, UI Reuse, Storybook)` : `${colors.violet}7 Guardias Backend (TDD, Architecture, Scope, Secret Scan)`}${colors.reset}`);
91
- console.log(` 📝 ${colors.bold}Leyes & SDD:${colors.reset} AGENTS.md, sdds/, docs/Journal/ precargados`);
92
- console.log(` 🔒 ${colors.bold}Git Hooks:${colors.reset} Configurados en ${colors.amber}${config.gitHooks === 'husky' ? '.husky/pre-commit' : '.githooks/pre-commit'}${colors.reset}\n`);
116
+ const isAgentOS = config.projectType === 'agent-os';
117
+ const guardsDesc = isAgentOS
118
+ ? `${colors.cyan}6 Guardias Agent-OS (HITL, Symlinks, Schemas, Memoria, Secrets)${colors.reset}`
119
+ : isFront
120
+ ? `${colors.emerald}10 Guardias Frontend (A11y, Zod, Image, UI Reuse, Storybook)${colors.reset}`
121
+ : `${colors.violet}7 Guardias Backend (TDD, Architecture, Scope, Secret Scan)${colors.reset}`;
122
+
123
+ const summary = [
124
+ `🔨 ${colors.bold}Proyecto Inicializado:${colors.reset} ${colors.cyan}${targetDir}${colors.reset}`,
125
+ `🛡️ ${colors.bold}Salvaguardas:${colors.reset} ${guardsDesc}`,
126
+ `📝 ${colors.bold}Leyes & SDD:${colors.reset} AGENTS.md, sdds/, docs/Journal/ precargados`,
127
+ `🔒 ${colors.bold}Git Hooks:${colors.reset} Configurados en ${colors.amber}${config.gitHooks === 'husky' ? '.husky/pre-commit' : '.githooks/pre-commit'}${colors.reset}`
128
+ ].join('\n');
129
+
130
+ if (p.note && p.outro) {
131
+ p.note(summary, '🚀 Resumen de Instalación');
132
+ p.outro(`${colors.emerald}${colors.bold}¡CLC Kernel instalado exitosamente!${colors.reset}`);
133
+ } else {
134
+ console.log(`\n${colors.bgEmerald} SUCCESS ${colors.reset} ${colors.bold}${colors.emerald}¡CLC Kernel instalado exitosamente!${colors.reset}\n`);
135
+ console.log(summary + '\n');
136
+ }
93
137
  }
94
138
 
95
139
  module.exports = {
package/tools/audit.js CHANGED
File without changes
package/tools/audit.py CHANGED
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Domain Data Integrity & Clean State Guard
4
+ * Validates domain deliverables (content.json, calendar.json, voc.json)
5
+ * to ensure valid JSON structure and clean creation state (no fake hallucinated metrics on pending posts).
6
+ * Self-contained: uses only Node.js built-ins.
7
+ *
8
+ * @param {string} targetDir - Directory to scan (defaults to cwd)
9
+ * @returns {{ exitCode: number, skipped: boolean, name: string, data: object }}
10
+ */
11
+ const check = async function checkDomainData(targetDir) {
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ const dir = targetDir || process.cwd();
16
+ const searchDirs = [
17
+ dir,
18
+ path.join(dir, 'output'),
19
+ path.join(dir, 'content-calendar'),
20
+ path.join(dir, 'data')
21
+ ];
22
+
23
+ const jsonFiles = [];
24
+ for (const sDir of searchDirs) {
25
+ if (fs.existsSync(sDir)) {
26
+ try {
27
+ const files = fs.readdirSync(sDir);
28
+ for (const file of files) {
29
+ if (file.endsWith('.json') && !file.includes('package') && !file.includes('tsconfig')) {
30
+ jsonFiles.push(path.join(sDir, file));
31
+ }
32
+ }
33
+ } catch {}
34
+ }
35
+ }
36
+
37
+ if (jsonFiles.length === 0) {
38
+ return {
39
+ exitCode: 0,
40
+ skipped: true,
41
+ name: 'check_domain_data',
42
+ data: { violations: [], message: 'No domain data JSON files to validate' }
43
+ };
44
+ }
45
+
46
+ const violations = [];
47
+ for (const file of jsonFiles) {
48
+ try {
49
+ const raw = fs.readFileSync(file, 'utf-8');
50
+ const data = JSON.parse(raw);
51
+
52
+ // Clean Creation State Check: If array of posts/calendar entries
53
+ const entries = Array.isArray(data) ? data : (data.posts || data.items || data.calendar || []);
54
+ if (Array.isArray(entries)) {
55
+ for (let i = 0; i < entries.length; i++) {
56
+ const item = entries[i];
57
+ if (item && (item.status === 'pending' || item.status === 'draft')) {
58
+ // Check if metrics are falsely pre-filled with non-null numbers
59
+ if (item.metrics && typeof item.metrics === 'object') {
60
+ const fakeMetrics = Object.entries(item.metrics).filter(([_, val]) => typeof val === 'number' && val > 0);
61
+ if (fakeMetrics.length > 0) {
62
+ violations.push({
63
+ file: path.relative(dir, file),
64
+ message: `Entry #${i + 1} (${item.title || item.id || 'draft'}) has pre-filled fake metrics on pending/draft post`
65
+ });
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ } catch (err) {
72
+ violations.push({
73
+ file: path.relative(dir, file),
74
+ message: `JSON syntax or structural error: ${err.message}`
75
+ });
76
+ }
77
+ }
78
+
79
+ const exitCode = violations.length > 0 ? 1 : 0;
80
+ return {
81
+ exitCode,
82
+ skipped: false,
83
+ name: 'check_domain_data',
84
+ data: {
85
+ violations,
86
+ message: violations.length > 0
87
+ ? `${violations.length} domain data integrity violation(s) found`
88
+ : 'All domain deliverables & state data verified'
89
+ }
90
+ };
91
+ };
92
+
93
+ module.exports = check;
94
+
95
+ if (require.main === module) {
96
+ check(process.argv[2]).then(result => {
97
+ console.log(JSON.stringify(result, null, 2));
98
+ process.exit(result.exitCode);
99
+ });
100
+ }