clckernel 1.2.19 → 2.0.0

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 (78) hide show
  1. package/.agents/skills/clckernel_cli/SKILL.md +23 -6
  2. package/.agents/skills/clckernel_cli/reference/audit.md +13 -3
  3. package/.agents/skills/clckernel_cli/reference/commit.md +1 -1
  4. package/.agents/skills/clckernel_cli/reference/doctor.md +5 -3
  5. package/.agents/skills/clckernel_cli/reference/feature.md +3 -3
  6. package/.agents/skills/clckernel_cli/reference/guard.md +48 -12
  7. package/.agents/skills/clckernel_cli/reference/phase.md +6 -3
  8. package/.agents/skills/clckernel_cli/reference/start.md +14 -4
  9. package/.agents/skills/clckernel_cli/reference/test.md +1 -1
  10. package/.agents/skills/clckernel_cli/reference/update.md +19 -19
  11. package/CHANGELOG.md +244 -0
  12. package/LICENSE +21 -0
  13. package/README.es.md +280 -51
  14. package/README.md +274 -50
  15. package/bin/cli.js +8 -0
  16. package/package.json +12 -2
  17. package/src/adapters/agent-os.js +161 -84
  18. package/src/adapters/astro.js +8 -6
  19. package/src/adapters/base.js +23 -38
  20. package/src/adapters/django.js +14 -13
  21. package/src/adapters/fastapi.js +16 -15
  22. package/src/adapters/go.js +11 -9
  23. package/src/adapters/laravel.js +12 -10
  24. package/src/adapters/nextjs.js +7 -5
  25. package/src/adapters/rails.js +13 -11
  26. package/src/adapters/rust.js +11 -9
  27. package/src/catalog.js +58 -49
  28. package/src/config.js +38 -240
  29. package/src/detector.js +243 -44
  30. package/src/doctor.js +18 -9
  31. package/src/generator.js +734 -302
  32. package/src/gitignore.js +60 -14
  33. package/src/index.js +257 -18
  34. package/src/io.js +409 -0
  35. package/src/known-hashes.json +309 -0
  36. package/src/onboarding.js +15 -0
  37. package/src/technologies/detector.js +1 -1
  38. package/src/technologies/guards/_shared.js +1 -1
  39. package/src/ui.js +233 -40
  40. package/src/updater.js +271 -38
  41. package/tools/_changes.js +279 -0
  42. package/tools/_changes.py +233 -0
  43. package/tools/_config.js +294 -0
  44. package/tools/_config.py +271 -0
  45. package/tools/_yaml.py +489 -0
  46. package/tools/audit.js +511 -111
  47. package/tools/audit.py +506 -128
  48. package/tools/celery_guard.py +13 -35
  49. package/tools/check_a11y.js +8 -28
  50. package/tools/check_api_contracts.js +13 -39
  51. package/tools/check_architecture.js +35 -44
  52. package/tools/check_architecture.py +172 -105
  53. package/tools/check_custom.js +108 -61
  54. package/tools/check_custom.py +108 -271
  55. package/tools/check_data_files.js +88 -0
  56. package/tools/check_db_efficiency.py +80 -65
  57. package/tools/check_hitl.js +112 -69
  58. package/tools/check_links.js +138 -0
  59. package/tools/check_migrations.py +143 -94
  60. package/tools/check_performance.js +35 -44
  61. package/tools/check_placeholders.js +104 -0
  62. package/tools/check_responsive.js +8 -28
  63. package/tools/check_scope.py +40 -31
  64. package/tools/check_seo.js +8 -28
  65. package/tools/check_skills.js +158 -0
  66. package/tools/check_storybook.js +8 -21
  67. package/tools/check_symlinks.js +40 -22
  68. package/tools/check_ui_reuse.js +17 -29
  69. package/tools/docker_guard.py +19 -41
  70. package/tools/postgres_guard.py +15 -36
  71. package/tools/redis_guard.py +13 -35
  72. package/tools/scan_secrets.js +134 -67
  73. package/tools/scan_secrets.py +163 -72
  74. package/tools/verify_tdd.js +867 -0
  75. package/tools/verify_tdd.py +407 -165
  76. package/tools/yaml.js +404 -132
  77. package/tools/check_domain_data.js +0 -100
  78. package/tools/check_test_calendar_sync.js +0 -111
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * CLC Kernel — Go Stack Adapter
3
- * Supports Golang apps, `go test`, golangci-lint AST, and Domain/UseCase Clean Architecture.
3
+ * Supports Golang apps, `go test`, golangci-lint, and Domain/UseCase Clean Architecture.
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -18,27 +18,29 @@ class GoAdapter extends BaseAdapter {
18
18
 
19
19
  getSafeguards() {
20
20
  return [
21
- 'golangci-lint Code Quality & AST Linter',
21
+ 'golangci-lint Code Quality Linter (external CLI)',
22
22
  'Go Clean Architecture Guard (Domain -> UseCase -> Handler)',
23
- 'go test Red-to-Green TDD Validator',
23
+ 'Red→Green TDD Verifier (runs changed tests with go test)',
24
24
  'Secret & Private Key Leak Scanner',
25
25
  'Educational Audit Gate (05-audit-report.md)',
26
- 'Memory Guard (Engram / Graphify ADR Sync)'
26
+ 'Memory protocol (agent-enforced; Engram / Graphify optional, not checked by a guard)'
27
27
  ];
28
28
  }
29
29
 
30
30
  /**
31
31
  * Returns the tool manifest for Go projects.
32
- * External CLIs only — no custom guard scripts bundled.
32
+ * External CLIs plus the bundled JS guards (secret scan, TDD verifier, custom rules).
33
33
  * @returns {Array<{name: string, language: string, path: string, command: string, description: string, extCLI?: string}>}
34
34
  */
35
35
  getTools() {
36
36
  const baseTools = [
37
- { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clc-forge.yml' },
38
- { name: 'golangci-lint', language: 'external', path: '', command: 'golangci-lint run', description: 'Go linter and static analysis', extCLI: 'golangci-lint' },
39
- { name: 'go_test', language: 'external', path: '', command: 'go test ./...', description: 'Go test runner', extCLI: 'go' },
37
+ { name: 'scan_secrets', language: 'js', path: 'scan_secrets.js', command: 'node tools/scan_secrets.js', description: 'Scans for leaked secrets and API keys' },
38
+ { name: 'verify_tdd', language: 'js', path: 'verify_tdd.js', command: 'node tools/verify_tdd.js', description: 'Runs changed tests (go test) against BASE (must fail) and the staged code (must pass)' },
39
+ { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clckernel.yaml' },
40
+ { name: 'golangci-lint', language: 'external', path: '', command: 'golangci-lint run', description: 'Go linter and static analysis', extCLI: 'golangci-lint', availableIf: 'command -v golangci-lint' },
41
+ { name: 'go_test', language: 'external', path: '', command: 'go test ./...', description: 'Go test runner', extCLI: 'go', availableIf: 'command -v go' },
40
42
  ];
41
- return this._mergeTechTools(baseTools);
43
+ return baseTools;
42
44
  }
43
45
 
44
46
  provision(targetDir, config) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * CLC Kernel — PHP / Laravel Stack Adapter
3
- * Supports Laravel, Pest / PHPUnit, PHPStan AST, and Eloquent migration idempotency.
3
+ * Supports Laravel, Pest / PHPUnit, and PHPStan static analysis.
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -20,27 +20,29 @@ class LaravelAdapter extends BaseAdapter {
20
20
 
21
21
  getSafeguards() {
22
22
  return [
23
- 'PHPStan / PHP_CodeSniffer AST Code Quality Linter',
24
- 'Laravel Migration Idempotency & Schema Guard',
25
- 'Pest / PHPUnit Red-to-Green TDD Validator',
23
+ 'PHPStan Static Analysis (external CLI)',
24
+ 'Laravel Migration Reversibility protocol (agent-enforced; no migration guard installed for this stack)',
25
+ 'Red→Green TDD Verifier (runs changed tests with PHPUnit or Pest)',
26
26
  'Secret & Private Key Leak Scanner',
27
27
  'Educational Audit Gate (05-audit-report.md)',
28
- 'Memory Guard (Engram / Graphify ADR Sync)'
28
+ 'Memory protocol (agent-enforced; Engram / Graphify optional, not checked by a guard)'
29
29
  ];
30
30
  }
31
31
 
32
32
  /**
33
33
  * Returns the tool manifest for Laravel projects.
34
- * External CLIs only — no custom guard scripts bundled.
34
+ * External CLIs plus the bundled JS guards (secret scan, TDD verifier, custom rules).
35
35
  * @returns {Array<{name: string, language: string, path: string, command: string, description: string, extCLI?: string}>}
36
36
  */
37
37
  getTools() {
38
38
  const baseTools = [
39
- { name: 'check_custom', language: 'python', path: 'check_custom.py', command: 'python3 tools/check_custom.py', description: 'Runs user-defined custom rules from .clc-forge.yml' },
40
- { name: 'phpstan', language: 'external', path: '', command: './vendor/bin/phpstan analyse', description: 'PHP static analysis', extCLI: 'phpstan' },
41
- { name: 'artisan', language: 'external', path: '', command: 'php artisan test', description: 'Laravel test runner', extCLI: 'artisan' },
39
+ { name: 'scan_secrets', language: 'js', path: 'scan_secrets.js', command: 'node tools/scan_secrets.js', description: 'Scans for leaked secrets and API keys' },
40
+ { name: 'verify_tdd', language: 'js', path: 'verify_tdd.js', command: 'node tools/verify_tdd.js', description: 'Runs changed tests (Pest / PHPUnit) against BASE (must fail) and the staged code (must pass)' },
41
+ { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clckernel.yaml' },
42
+ { name: 'phpstan', language: 'external', path: '', command: './vendor/bin/phpstan analyse', description: 'PHP static analysis', extCLI: 'phpstan', availableIf: '[ -x vendor/bin/phpstan ]' },
43
+ { name: 'artisan', language: 'external', path: '', command: 'php artisan test', description: 'Laravel test runner', extCLI: 'artisan', availableIf: '[ -f artisan ] && command -v php' },
42
44
  ];
43
- return this._mergeTechTools(baseTools);
45
+ return baseTools;
44
46
  }
45
47
 
46
48
  provision(targetDir, config) {
@@ -37,8 +37,9 @@ class NextjsAdapter extends BaseAdapter {
37
37
  'Zod API Contract Guard (services response schema parsing)',
38
38
  'Performance & Next/Image Guard (next/image & tree-shaking)',
39
39
  'Storybook Story Coverage Guard (.stories.tsx)',
40
+ 'Red→Green TDD Verifier (runs changed tests with vitest / jest / node:test)',
40
41
  'Educational Audit Gate (05-audit-report.md)',
41
- 'Memory Guard & PR Generator (.github/pull_request_body.md)'
42
+ 'Memory protocol (agent-enforced; Engram / Graphify optional, not checked by a guard)'
42
43
  ];
43
44
  }
44
45
 
@@ -56,11 +57,12 @@ class NextjsAdapter extends BaseAdapter {
56
57
  { name: 'check_ui_reuse', language: 'js', path: 'check_ui_reuse.js', command: 'node tools/check_ui_reuse.js', description: 'Enforces UI primitive reuse from components/ui/' },
57
58
  { name: 'check_architecture', language: 'js', path: 'check_architecture.js', command: 'node tools/check_architecture.js', description: 'Validates Next.js Server Component boundaries' },
58
59
  { name: 'check_performance', language: 'js', path: 'check_performance.js', command: 'node tools/check_performance.js', description: 'Checks next/image and bundle optimization' },
59
- { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clc-forge.yml' },
60
- { name: 'tsc', language: 'external', path: '', command: 'npx tsc --noEmit', description: 'TypeScript type checking', extCLI: 'tsc' },
61
- { name: 'lint', language: 'external', path: '', command: 'npx lint-staged', description: 'Lint staged files', extCLI: 'lint-staged' },
60
+ { name: 'verify_tdd', language: 'js', path: 'verify_tdd.js', command: 'node tools/verify_tdd.js', description: 'Runs changed tests (vitest / jest / node:test) against BASE (must fail) and the staged code (must pass)' },
61
+ { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clckernel.yaml' },
62
+ { name: 'tsc', language: 'external', path: '', command: 'npx tsc --noEmit', description: 'TypeScript type checking', extCLI: 'tsc', availableIf: '[ -x node_modules/.bin/tsc ]' },
63
+ { name: 'lint', language: 'external', path: '', command: 'npx lint-staged', description: 'Lint staged files', extCLI: 'lint-staged', availableIf: '[ -x node_modules/.bin/lint-staged ]' },
62
64
  ];
63
- return this._mergeTechTools(baseTools);
65
+ return baseTools;
64
66
  }
65
67
 
66
68
  provision(targetDir, config) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * CLC Kernel — Ruby on Rails Stack Adapter
3
- * Supports Rails, RSpec, RuboCop AST, Brakeman Security, and migration idempotency.
3
+ * Supports Rails, RSpec, RuboCop, and Brakeman security scanning.
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -20,29 +20,31 @@ class RailsAdapter extends BaseAdapter {
20
20
 
21
21
  getSafeguards() {
22
22
  return [
23
- 'RuboCop Code Style & AST Security Guard',
23
+ 'RuboCop Code Style Linter (external CLI)',
24
24
  'Brakeman Rails Vulnerability Scanner',
25
- 'Rails Migration Idempotency Guard (schema drift protection)',
26
- 'RSpec / Minitest Red-to-Green TDD Validator',
25
+ 'Rails Migration Reversibility protocol (agent-enforced; no migration guard installed for this stack)',
26
+ 'Red→Green TDD Verifier (runs changed tests with RSpec or Minitest)',
27
27
  'Secret & Private Credential Leak Scanner',
28
28
  'Educational Audit Gate (05-audit-report.md)',
29
- 'Memory Guard (Engram / Graphify ADR Sync)'
29
+ 'Memory protocol (agent-enforced; Engram / Graphify optional, not checked by a guard)'
30
30
  ];
31
31
  }
32
32
 
33
33
  /**
34
34
  * Returns the tool manifest for Rails projects.
35
- * External CLIs only — no custom guard scripts bundled.
35
+ * External CLIs plus the bundled JS guards (secret scan, TDD verifier, custom rules).
36
36
  * @returns {Array<{name: string, language: string, path: string, command: string, description: string, extCLI?: string}>}
37
37
  */
38
38
  getTools() {
39
39
  const baseTools = [
40
- { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clc-forge.yml' },
41
- { name: 'rubocop', language: 'external', path: '', command: 'bundle exec rubocop --parallel', description: 'Ruby linter', extCLI: 'rubocop' },
42
- { name: 'brakeman', language: 'external', path: '', command: 'bundle exec brakeman -q', description: 'Rails vulnerability scanner', extCLI: 'brakeman' },
43
- { name: 'rspec', language: 'external', path: '', command: 'bundle exec rspec', description: 'Test runner', extCLI: 'rspec' },
40
+ { name: 'scan_secrets', language: 'js', path: 'scan_secrets.js', command: 'node tools/scan_secrets.js', description: 'Scans for leaked secrets and API keys' },
41
+ { name: 'verify_tdd', language: 'js', path: 'verify_tdd.js', command: 'node tools/verify_tdd.js', description: 'Runs changed tests (RSpec / Minitest) against BASE (must fail) and the staged code (must pass)' },
42
+ { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clckernel.yaml' },
43
+ { name: 'rubocop', language: 'external', path: '', command: 'bundle exec rubocop --parallel', description: 'Ruby linter', extCLI: 'rubocop', availableIf: "grep -q '^ rubocop ' Gemfile.lock" },
44
+ { name: 'brakeman', language: 'external', path: '', command: 'bundle exec brakeman -q', description: 'Rails vulnerability scanner', extCLI: 'brakeman', availableIf: "grep -q '^ brakeman ' Gemfile.lock" },
45
+ { name: 'rspec', language: 'external', path: '', command: 'bundle exec rspec', description: 'Test runner', extCLI: 'rspec', availableIf: "grep -q '^ rspec-core ' Gemfile.lock" },
44
46
  ];
45
- return this._mergeTechTools(baseTools);
47
+ return baseTools;
46
48
  }
47
49
 
48
50
  provision(targetDir, config) {
@@ -18,28 +18,30 @@ class RustAdapter extends BaseAdapter {
18
18
 
19
19
  getSafeguards() {
20
20
  return [
21
- 'cargo clippy AST Code Quality Linter',
21
+ 'cargo clippy Linter (external CLI)',
22
22
  'cargo audit Security Vulnerability Scanner',
23
- 'cargo test Red-to-Green TDD Validator',
23
+ 'Red→Green TDD Verifier (runs changed tests with cargo test)',
24
24
  'Secret & Private Key Leak Scanner',
25
25
  'Educational Audit Gate (05-audit-report.md)',
26
- 'Memory Guard (Engram / Graphify ADR Sync)'
26
+ 'Memory protocol (agent-enforced; Engram / Graphify optional, not checked by a guard)'
27
27
  ];
28
28
  }
29
29
 
30
30
  /**
31
31
  * Returns the tool manifest for Rust projects.
32
- * External CLIs only — no custom guard scripts bundled.
32
+ * External CLIs plus the bundled JS guards (secret scan, TDD verifier, custom rules).
33
33
  * @returns {Array<{name: string, language: string, path: string, command: string, description: string, extCLI?: string}>}
34
34
  */
35
35
  getTools() {
36
36
  const baseTools = [
37
- { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clc-forge.yml' },
38
- { name: 'cargo_clippy', language: 'external', path: '', command: 'cargo clippy -- -D warnings', description: 'Rust linter and static analysis', extCLI: 'clippy' },
39
- { name: 'cargo_audit', language: 'external', path: '', command: 'cargo audit', description: 'Security vulnerability scanner', extCLI: 'cargo-audit' },
40
- { name: 'cargo_test', language: 'external', path: '', command: 'cargo test', description: 'Rust test runner', extCLI: 'cargo' },
37
+ { name: 'scan_secrets', language: 'js', path: 'scan_secrets.js', command: 'node tools/scan_secrets.js', description: 'Scans for leaked secrets and API keys' },
38
+ { name: 'verify_tdd', language: 'js', path: 'verify_tdd.js', command: 'node tools/verify_tdd.js', description: 'Runs changed tests (cargo test integration tests) against BASE (must fail) and the staged code (must pass)' },
39
+ { name: 'check_custom', language: 'js', path: 'check_custom.js', command: 'node tools/check_custom.js', description: 'Runs user-defined custom rules from .clckernel.yaml' },
40
+ { name: 'cargo_clippy', language: 'external', path: '', command: 'cargo clippy -- -D warnings', description: 'Rust linter and static analysis', extCLI: 'clippy', availableIf: 'cargo clippy --version' },
41
+ { name: 'cargo_audit', language: 'external', path: '', command: 'cargo audit', description: 'Security vulnerability scanner', extCLI: 'cargo-audit', availableIf: 'command -v cargo-audit' },
42
+ { name: 'cargo_test', language: 'external', path: '', command: 'cargo test', description: 'Rust test runner', extCLI: 'cargo', availableIf: 'command -v cargo' },
41
43
  ];
42
- return this._mergeTechTools(baseTools);
44
+ return baseTools;
43
45
  }
44
46
 
45
47
  provision(targetDir, config) {
package/src/catalog.js CHANGED
@@ -2,9 +2,11 @@
2
2
  * CLC Kernel — Central Safeguard Catalog
3
3
  *
4
4
  * Single source of truth describing every safeguard/guard the clckernel
5
- * framework knows about. Drives config validation (src/config.js),
6
- * config-driven harness generation (src/generator.js), doctor checks, and
7
- * the future safeguard audit.
5
+ * framework knows about: descriptions and audit lenses (tools/audit.js).
6
+ * It does not choose what install puts in a project (the
7
+ * adapters' manifests do) and its severity/gate_mode fields are not
8
+ * configurable here: the audit honours the guard's own `level` and the
9
+ * `severities` key of .clckernel.yaml instead (sdds/audit-cli).
8
10
  *
9
11
  * Entry shape (design §1.2, additive fields noted):
10
12
  * name {string} guard script basename WITHOUT extension
@@ -14,124 +16,131 @@
14
16
  * applies_when{string} applicability predicate key (stack/project conditions)
15
17
  * severity {string} 'error' | 'warning' | 'advisory' (catalog default)
16
18
  * gate_mode {string} 'hard' | 'advisory' (catalog default)
17
- * config_keys {string[]} .clc-forge.yml keys this safeguard consumes
19
+ * config_keys {string[]} .clckernel.yaml keys this safeguard reads (tools/_config.js)
18
20
  * phase {string} 10-phase harness phase: 'audit' | 'test' | 'review' | 'handover'
19
21
  * file {string|null} bundled tools/ file(s), '+' separated; null = external CLI
20
22
  * manifest {boolean} true = declared by >=1 adapter manifest (design §1.2)
21
23
  * planned {boolean} true = tool file not yet materialized (future slice)
22
- *
23
- * The catalog is a JOIN, not a rewrite: the no-config adapter path never
24
- * consults it; only the config-driven generation path does.
25
24
  */
26
25
 
27
26
  const SAFEGUARD_CATALOG = [
28
27
  { name: 'scan_secrets', labels: ['scan_secrets', 'scan_secrets.js', 'scan_secrets.py'],
29
28
  checks: 'Secret & private-key leak scan', verify: ['verify_secret_leaks', 'verify_no_hardcoded_secrets'],
30
- applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
29
+ applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
31
30
  phase: 'audit', file: 'scan_secrets.js+scan_secrets.py', manifest: true, planned: false, lens: 'security' },
32
31
 
33
32
  { name: 'check_architecture', labels: ['check_architecture', 'check_architecture.js', 'check_architecture.py'],
34
33
  checks: 'Clean Architecture layer / server-component boundaries', verify: ['verify_architecture_layers', 'verify_server_component_boundaries'],
35
- applies_when: 'frontend,backend', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
34
+ applies_when: 'frontend,backend', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
36
35
  phase: 'audit', file: 'check_architecture.js+check_architecture.py', manifest: true, planned: false, lens: 'architecture' },
37
36
 
38
37
  { name: 'check_custom', labels: ['check_custom', 'check_custom.js', 'check_custom.py'],
39
- checks: 'User-defined regex rules from `.clc-forge.yml`', verify: ['verify_custom_rules', 'verify_user_defined_regex_rules'],
40
- applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
38
+ checks: 'User-defined regex rules from `.clckernel.yaml`', verify: ['verify_custom_rules', 'verify_user_defined_regex_rules'],
39
+ applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['rules', 'exclude_paths'],
41
40
  phase: 'audit', file: 'check_custom.js+check_custom.py', manifest: true, planned: false, lens: 'architecture' },
42
41
 
43
42
  { name: 'check_a11y', labels: ['check_a11y', 'check_a11y.js'],
44
43
  checks: 'ARIA + alt accessibility', verify: ['verify_a11y', 'verify_accessibility'],
45
- applies_when: 'frontend', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
44
+ applies_when: 'frontend', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
46
45
  phase: 'audit', file: 'check_a11y.js', manifest: true, planned: false, lens: 'correctness' },
47
46
 
48
47
  { name: 'check_ui_reuse', labels: ['check_ui_reuse', 'check_ui_reuse.js'],
49
48
  checks: 'UI primitive reuse from components/ui/', verify: ['verify_ui_reuse', 'verify_component_reuse'],
50
- applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
49
+ applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
51
50
  phase: 'audit', file: 'check_ui_reuse.js', manifest: true, planned: false, lens: 'architecture' },
52
51
 
53
52
  { name: 'check_performance', labels: ['check_performance', 'check_performance.js'],
54
53
  checks: 'next/image + tree-shaking', verify: ['verify_performance', 'verify_image_optimization'],
55
- applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
54
+ applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
56
55
  phase: 'audit', file: 'check_performance.js', manifest: true, planned: false, lens: 'performance' },
57
56
 
58
57
  { name: 'check_responsive', labels: ['check_responsive', 'check_responsive.js'],
59
58
  checks: 'Mobile-first responsiveness, fixed-width overflow & touch target size', verify: ['verify_responsive', 'verify_mobile_adaptability'],
60
- applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
59
+ applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
61
60
  phase: 'audit', file: 'check_responsive.js', manifest: true, planned: false, lens: 'performance' },
62
61
 
63
62
  { name: 'check_seo', labels: ['check_seo', 'check_seo.js'],
64
63
  checks: 'SEO metadata, OpenGraph, GEO tags, semantic HTML & LCP priority', verify: ['verify_seo', 'verify_geo_metadata', 'verify_core_web_vitals'],
65
- applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
64
+ applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
66
65
  phase: 'audit', file: 'check_seo.js', manifest: true, planned: false, lens: 'performance' },
67
66
 
68
67
  { name: 'check_storybook', labels: ['check_storybook', 'check_storybook.js'],
69
68
  checks: 'Storybook coverage (`.stories.tsx`)', verify: ['verify_storybook_coverage'],
70
- applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
69
+ applies_when: 'frontend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
71
70
  phase: 'audit', file: 'check_storybook.js', manifest: true, planned: false, lens: 'performance' },
72
71
 
73
72
  { name: 'check_api_contracts', labels: ['check_api_contracts', 'check_api_contracts.js'],
74
73
  checks: 'Zod response-schema parsing', verify: ['verify_api_contracts', 'verify_response_schemas'],
75
- applies_when: 'frontend', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
74
+ applies_when: 'frontend', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
76
75
  phase: 'audit', file: 'check_api_contracts.js', manifest: true, planned: false, lens: 'correctness' },
77
76
 
78
77
  { name: 'check_migrations', labels: ['check_migrations', 'check_migrations.py'],
79
- checks: 'Alembic/Django migration idempotency', verify: ['verify_migration_idempotency'],
80
- applies_when: 'backend,fastapi,django', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
78
+ checks: 'Alembic/Django migration reversibility (upgrade/downgrade, destructive operations)', verify: ['verify_migration_idempotency'],
79
+ applies_when: 'backend,fastapi,django', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
81
80
  phase: 'audit', file: 'check_migrations.py', manifest: true, planned: false, lens: 'architecture' },
82
81
 
83
- { name: 'verify_tdd', labels: ['verify_tdd', 'verify_tdd.py'],
84
- checks: 'Real red→green TDD validation', verify: ['verify_tdd_red_green', 'verify_tdd_evidence'],
85
- applies_when: 'backend', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
86
- phase: 'audit', file: 'verify_tdd.py', manifest: false, planned: false, lens: 'correctness' },
82
+ { name: 'verify_tdd', labels: ['verify_tdd', 'verify_tdd.js', 'verify_tdd.py'],
83
+ checks: 'red→green (pytest / vitest / jest / node:test / go test / cargo test / RSpec / Minitest / PHPUnit / Pest): changed tests fail on BASE and pass on the staged code', verify: ['verify_tdd_red_green', 'verify_tdd_evidence'],
84
+ applies_when: 'frontend,backend,agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['tdd', 'exclude_paths'],
85
+ phase: 'audit', file: 'verify_tdd.js+verify_tdd.py', manifest: true, planned: false, lens: 'correctness' },
87
86
 
88
87
  { name: 'check_scope', labels: ['check_scope', 'check_scope.py'],
89
88
  checks: 'git-diff vs SDD-authorization scope guardrail', verify: ['verify_scope_authorization', 'verify_sdd_scope'],
90
- applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
89
+ applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
91
90
  phase: 'audit', file: 'check_scope.py', manifest: false, planned: false, lens: 'correctness' },
92
91
 
93
92
  { name: 'celery_guard', labels: ['celery_guard', 'celery_guard.py'],
94
93
  checks: 'Broker URL exposure, ignore_result, result backend', verify: ['verify_celery_broker_config'],
95
- applies_when: 'celery', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
94
+ applies_when: 'celery', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
96
95
  phase: 'audit', file: 'celery_guard.py', manifest: true, planned: false, lens: 'security' },
97
96
 
98
97
  { name: 'redis_guard', labels: ['redis_guard', 'redis_guard.py'],
99
98
  checks: 'decode_responses, connect timeout, hardcoded URLs', verify: ['verify_redis_config'],
100
- applies_when: 'redis', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
99
+ applies_when: 'redis', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
101
100
  phase: 'audit', file: 'redis_guard.py', manifest: true, planned: false, lens: 'security' },
102
101
 
103
102
  { name: 'postgres_guard', labels: ['postgres_guard', 'postgres_guard.py'],
104
103
  checks: 'Raw SQL string formatting, hstore misuse', verify: ['verify_postgres_sql_usage'],
105
- applies_when: 'postgresql', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
104
+ applies_when: 'postgresql', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
106
105
  phase: 'audit', file: 'postgres_guard.py', manifest: true, planned: false, lens: 'security' },
107
106
 
108
107
  { name: 'docker_guard', labels: ['docker_guard', 'docker_guard.py'],
109
108
  checks: 'Non-root USER, ENV secrets, missing HEALTHCHECK', verify: ['verify_dockerfile_security'],
110
- applies_when: 'docker', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
109
+ applies_when: 'docker', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
111
110
  phase: 'audit', file: 'docker_guard.py', manifest: true, planned: false, lens: 'security' },
112
111
 
113
112
  { 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'],
113
+ checks: 'AI IDE rule mirrors (CLAUDE.md, GEMINI.md, .cursorrules, .windsurfrules) point to AGENTS.md: symlink or identical copy', verify: ['verify_symlinks', 'verify_rule_mirrors'],
114
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['mirrors'],
116
115
  phase: 'audit', file: 'check_symlinks.js', manifest: true, planned: false, lens: 'architecture' },
117
116
 
118
117
  { 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'],
118
+ checks: 'Explicit Human-in-the-Loop marker (`HITL:` line or `## Human checkpoint` section) in changed skills and playbooks', verify: ['verify_hitl', 'verify_human_review_checkpoints'],
119
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['hitl', 'exclude_paths'],
121
120
  phase: 'audit', file: 'check_hitl.js', manifest: true, planned: false, lens: 'architecture' },
122
121
 
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, lens: 'architecture' },
122
+ { name: 'check_data_files', labels: ['check_data_files', 'check_data_files.js'],
123
+ checks: 'Every changed .json file parses (snapshot content, any folder); reports the file and the parse error', verify: ['verify_data_files_parse'],
124
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [],
125
+ phase: 'audit', file: 'check_data_files.js', manifest: true, planned: false, lens: 'correctness' },
126
+
127
+ { name: 'check_skills', labels: ['check_skills', 'check_skills.js'],
128
+ checks: 'SKILL.md frontmatter: non-empty lowercase `name` unique in the repository, non-empty `description` of at most 1024 characters', verify: ['verify_skill_frontmatter'],
129
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [],
130
+ phase: 'audit', file: 'check_skills.js', manifest: true, planned: false, lens: 'correctness' },
131
+
132
+ { name: 'check_links', labels: ['check_links', 'check_links.js'],
133
+ checks: 'Relative links in changed Markdown point to files present in the commit', verify: ['verify_relative_links'],
134
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [],
135
+ phase: 'audit', file: 'check_links.js', manifest: true, planned: false, lens: 'correctness' },
127
136
 
128
- { name: 'check_test_calendar_sync', labels: ['check_test_calendar_sync', 'check_test_calendar_sync.js'],
129
- checks: 'Test calendar harness synchronization and parity check', verify: ['verify_calendar_sync', 'verify_test_calendar_sync'],
130
- applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['scope'],
131
- phase: 'audit', file: 'check_test_calendar_sync.js', manifest: true, planned: false, lens: 'performance' },
137
+ { name: 'check_placeholders', labels: ['check_placeholders', 'check_placeholders.js'],
138
+ checks: 'Forgotten draft placeholders in changed Markdown, YAML and JSON (double-brace slots allowed in templates/)', verify: ['verify_no_placeholders'],
139
+ applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [],
140
+ phase: 'audit', file: 'check_placeholders.js', manifest: true, planned: false, lens: 'correctness' },
132
141
 
133
142
  { name: 'ruff', labels: ['ruff'],
134
- checks: 'Python AST linter (external CLI)', verify: ['verify_python_lint'],
143
+ checks: 'Python linter (external CLI)', verify: ['verify_python_lint'],
135
144
  applies_when: 'backend', severity: 'warning', gate_mode: 'advisory', config_keys: [],
136
145
  phase: 'test', file: null, manifest: true, planned: false, lens: 'correctness' },
137
146
 
@@ -162,17 +171,17 @@ const SAFEGUARD_CATALOG = [
162
171
 
163
172
  { name: 'check_openapi_drift', labels: ['check_openapi_drift', 'check_openapi_drift.py'],
164
173
  checks: 'FastAPI OpenAPI schema drift vs app routes', verify: ['verify_openapi_drift'],
165
- applies_when: 'fastapi', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
174
+ applies_when: 'fastapi', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
166
175
  phase: 'audit', file: 'check_openapi_drift.py', manifest: true, planned: true, lens: 'correctness' },
167
176
 
168
177
  { name: 'check_db_efficiency', labels: ['check_db_efficiency', 'check_db_efficiency.py'],
169
- checks: 'ORM N+1 / select_related / prefetch_related', verify: ['verify_db_efficiency', 'verify_no_n_plus_1'],
170
- applies_when: 'django|sqlalchemy', severity: 'error', gate_mode: 'hard', config_keys: ['scope', 'exclude_paths'],
178
+ checks: 'N+1 heuristic: ORM-like calls inside loops (Python AST)', verify: ['verify_db_efficiency', 'verify_no_n_plus_1'],
179
+ applies_when: 'django|sqlalchemy', severity: 'error', gate_mode: 'hard', config_keys: ['exclude_paths'],
171
180
  phase: 'audit', file: 'check_db_efficiency.py', manifest: true, planned: false, lens: 'performance' },
172
181
 
173
182
  { name: 'check_observability', labels: ['check_observability', 'check_observability.py'],
174
183
  checks: 'structlog structured logging; bare print/logger ban', verify: ['verify_structured_logging'],
175
- applies_when: 'backend', severity: 'warning', gate_mode: 'advisory', config_keys: ['scope', 'exclude_paths'],
184
+ applies_when: 'backend', severity: 'warning', gate_mode: 'advisory', config_keys: ['exclude_paths'],
176
185
  phase: 'audit', file: 'check_observability.py', manifest: true, planned: true, lens: 'performance' },
177
186
  ];
178
187
 
@@ -192,10 +201,10 @@ const VALID_PHASES = ['audit', 'test', 'review', 'handover'];
192
201
  const VALID_APPLIES_WHEN = [
193
202
  'always', 'frontend', 'backend', 'fastapi', 'django', 'django|sqlalchemy',
194
203
  'celery', 'redis', 'postgresql', 'docker', 'frontend,backend', 'backend,fastapi,django',
195
- 'agent-os',
204
+ 'agent-os', 'frontend,backend,agent-os',
196
205
  ];
197
206
 
198
- /** Canonical 4 RDD Lenses */
207
+ /** The 4 RDD lenses guard results are grouped into */
199
208
  const VALID_LENSES = ['correctness', 'security', 'architecture', 'performance'];
200
209
 
201
210
  /** Normalize an input label for catalog lookup. */
@@ -229,7 +238,7 @@ function gateFor(name) {
229
238
  return entry ? entry.gate_mode : null;
230
239
  }
231
240
 
232
- /** Canonical RDD review lens for a guard name/label; null when unknown. */
241
+ /** RDD review lens a guard's results are grouped into; null when unknown. */
233
242
  function lensFor(name) {
234
243
  const entry = applyTo(name);
235
244
  return entry ? entry.lens : null;