chati-dev 4.1.0 → 4.1.2

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.
@@ -28,6 +28,8 @@ export const HOOK_MAP = {
28
28
  'constitution-guard': { event: 'BeforeTool', description: 'Block destructive commands and secret writes' },
29
29
  'read-protection': { event: 'BeforeTool', description: 'Block reads of sensitive files' },
30
30
  'session-digest': { event: 'PreCompress', description: 'Save session state before context compression' },
31
+ 'undercover-guard': { event: 'BeforeTool', description: 'Advisory: sanitize internal framework references from deliverables' },
32
+ 'style-guard': { event: 'BeforeTool', description: 'Advisory: enforce em-dash and emoji standards' },
31
33
  };
32
34
 
33
35
  // ---------------------------------------------------------------------------
@@ -459,6 +461,145 @@ main();
459
461
  `;
460
462
  }
461
463
 
464
+ /**
465
+ * Generate the undercover guard hook for Gemini CLI.
466
+ * BeforeTool event -- advisory: sanitizes internal framework references from deliverables.
467
+ */
468
+ function generateUndercoverGuard() {
469
+ return `${HOOK_HEADER}
470
+ /**
471
+ * Undercover Guard -- BeforeTool
472
+ * Advisory: sanitizes internal chati.dev references from generated code,
473
+ * commits, and PRs so deliverables don't expose framework internals.
474
+ */
475
+ async function main() {
476
+ let input = '';
477
+ for await (const chunk of process.stdin) {
478
+ input += chunk;
479
+ }
480
+
481
+ try {
482
+ const event = JSON.parse(input);
483
+ const cwd = event.cwd || process.cwd();
484
+ const toolName = event.tool_name || '';
485
+ const toolInput = event.tool_input || {};
486
+
487
+ // Only process write/edit/bash operations
488
+ if (!['WriteFile', 'EditFile', 'Write', 'Edit', 'Bash', 'RunCommand'].includes(toolName)) {
489
+ console.log(JSON.stringify({}));
490
+ return;
491
+ }
492
+
493
+ // Delegate to shared undercover guard logic
494
+ const hookPath = join(cwd, 'chati.dev', 'hooks', 'undercover-guard.js');
495
+ if (!existsSync(hookPath)) {
496
+ console.log(JSON.stringify({}));
497
+ return;
498
+ }
499
+
500
+ const mod = await import(hookPath);
501
+ let scan = { found: false, matches: [] };
502
+
503
+ if (['Write', 'Edit', 'WriteFile', 'EditFile'].includes(toolName)) {
504
+ const content = toolInput.content || toolInput.new_string || '';
505
+ if (typeof mod.scanForInternals === 'function') {
506
+ scan = mod.scanForInternals(content);
507
+ }
508
+ } else if (['Bash', 'RunCommand'].includes(toolName)) {
509
+ const command = toolInput.command || '';
510
+ if (typeof mod.scanBashForInternals === 'function') {
511
+ scan = mod.scanBashForInternals(command);
512
+ }
513
+ }
514
+
515
+ if (scan.found) {
516
+ const terms = scan.matches.map(m => \`"\${m.term}" -> "\${m.replacement}"\`).join(', ');
517
+ console.log(JSON.stringify({
518
+ decision: 'allow',
519
+ reason: \`[Undercover] Internal references detected: \${terms}. Please sanitize before shipping.\`,
520
+ }));
521
+ return;
522
+ }
523
+
524
+ console.log(JSON.stringify({}));
525
+ } catch { /* expected: operation may fail gracefully */
526
+ console.log(JSON.stringify({}));
527
+ }
528
+ }
529
+
530
+ main();
531
+ `;
532
+ }
533
+
534
+ /**
535
+ * Generate the style guard hook for Gemini CLI.
536
+ * BeforeTool event -- advisory: enforces em-dash and emoji standards.
537
+ */
538
+ function generateStyleGuard() {
539
+ return `${HOOK_HEADER}
540
+ /**
541
+ * Style Guard -- BeforeTool
542
+ * Advisory: enforces Constitution Article V writing standards
543
+ * (no em-dashes, no emojis in generated content).
544
+ */
545
+ async function main() {
546
+ let input = '';
547
+ for await (const chunk of process.stdin) {
548
+ input += chunk;
549
+ }
550
+
551
+ try {
552
+ const event = JSON.parse(input);
553
+ const cwd = event.cwd || process.cwd();
554
+ const toolName = event.tool_name || '';
555
+ const toolInput = event.tool_input || {};
556
+
557
+ // Only process write/edit/bash operations
558
+ if (!['WriteFile', 'EditFile', 'Write', 'Edit', 'Bash', 'RunCommand'].includes(toolName)) {
559
+ console.log(JSON.stringify({}));
560
+ return;
561
+ }
562
+
563
+ // Delegate to shared style guard logic
564
+ const hookPath = join(cwd, 'chati.dev', 'hooks', 'style-guard.js');
565
+ if (!existsSync(hookPath)) {
566
+ console.log(JSON.stringify({}));
567
+ return;
568
+ }
569
+
570
+ const mod = await import(hookPath);
571
+ let result = { violations: [] };
572
+
573
+ if (['Write', 'Edit', 'WriteFile', 'EditFile'].includes(toolName)) {
574
+ const content = toolInput.content || toolInput.new_string || '';
575
+ if (typeof mod.checkStyle === 'function') {
576
+ result = mod.checkStyle(content);
577
+ }
578
+ } else if (['Bash', 'RunCommand'].includes(toolName)) {
579
+ const command = toolInput.command || '';
580
+ if (typeof mod.checkBashStyle === 'function') {
581
+ result = mod.checkBashStyle(command);
582
+ }
583
+ }
584
+
585
+ if (result.violations && result.violations.length > 0) {
586
+ console.log(JSON.stringify({
587
+ decision: 'allow',
588
+ reason: \`[Style Guard] \${result.violations.join(' ')}\`,
589
+ }));
590
+ return;
591
+ }
592
+
593
+ console.log(JSON.stringify({}));
594
+ } catch { /* expected: operation may fail gracefully */
595
+ console.log(JSON.stringify({}));
596
+ }
597
+ }
598
+
599
+ main();
600
+ `;
601
+ }
602
+
462
603
  // ---------------------------------------------------------------------------
463
604
  // Public API
464
605
  // ---------------------------------------------------------------------------
@@ -476,6 +617,8 @@ export function generateAllGeminiHooks() {
476
617
  'constitution-guard.js': generateConstitutionGuard(),
477
618
  'read-protection.js': generateReadProtection(),
478
619
  'session-digest.js': generateSessionDigest(),
620
+ 'undercover-guard.js': generateUndercoverGuard(),
621
+ 'style-guard.js': generateStyleGuard(),
479
622
  };
480
623
  }
481
624
 
@@ -8,7 +8,7 @@ import { validateSchema, CONFIG_SCHEMA } from '../utils/schema-validator.js';
8
8
 
9
9
  /**
10
10
  * Validate chati.dev installation
11
- * Checks all 13 agents, constitution, session, schemas, etc.
11
+ * Checks all primary agents, constitution, session, schemas, etc.
12
12
  */
13
13
  export async function validateInstallation(targetDir) {
14
14
  const results = {
@@ -28,7 +28,7 @@ export async function validateInstallation(targetDir) {
28
28
  passed: 0,
29
29
  };
30
30
 
31
- // Check all 13 agents (orchestrator + 12 specialized)
31
+ // Check all primary agents (orchestrator + 12 specialized, sub-agents validated by managers)
32
32
  const agentFiles = [
33
33
  'orchestrator/chati.md',
34
34
  'agents/discover/greenfield-wu.md',
@@ -9,6 +9,7 @@ import { buildHandoff, saveHandoff, loadHandoff } from '../tasks/handoff.js';
9
9
  import { readAgentMemory } from '../memory/agent-memory.js';
10
10
  import { getRelevantGotchas } from '../memory/gotchas.js';
11
11
  import { updateClaudeMd } from '../memory/magic-docs.js';
12
+ import { generateContextFiles } from '../config/context-file-generator.js';
12
13
  import { existsSync, readdirSync } from 'fs';
13
14
  import { join } from 'path';
14
15
 
@@ -83,6 +84,11 @@ export function executeHandoff(projectDir, params) {
83
84
  });
84
85
  } catch { /* Magic Docs update is non-critical */ }
85
86
 
87
+ // Sync GEMINI.md and AGENTS.md with updated CLAUDE.md (multi-CLI parity)
88
+ try {
89
+ generateContextFiles(projectDir);
90
+ } catch { /* Context file sync is non-critical */ }
91
+
86
92
  return {
87
93
  success: true,
88
94
  handoff,
@@ -35,7 +35,7 @@ const FALLBACK_EN = {
35
35
  quick_start_switch_hint: 'Switch CLIs anytime — your session continues from where you left off',
36
36
  created_overlays: 'Created provider overlay directories',
37
37
  will_install: 'Will install:',
38
- agents_count: '13 agent definitions (DISCOVER, PLAN, BUILD, DEPLOY phases)',
38
+ agents_count: 'Specialized agent definitions across DISCOVER, PLAN, BUILD, DEPLOY phases',
39
39
  workflows_count: '6 workflow blueprints',
40
40
  templates_count: '6 templates (PRD, Brownfield PRD, Architecture, Task, QA Gate, Quick Brief)',
41
41
  constitution: 'Constitution (19 Articles + Preamble)',
@@ -51,7 +51,7 @@ const FALLBACK_EN = {
51
51
  created_claude_md: 'Created CLAUDE.md',
52
52
  configured_mcps: 'Configured MCPs:',
53
53
  validating: 'Validating installation...',
54
- agents_valid: 'All 13 agents implement 8 protocols',
54
+ agents_valid: 'All agents implement 8 protocols',
55
55
  handoff_ok: 'Handoff protocol: OK',
56
56
  validation_ok: 'Self-validation criteria: OK',
57
57
  constitution_ok: 'Constitution: 19 articles verified',