clckernel 1.2.19 → 2.0.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/skills/clckernel_cli/SKILL.md +23 -6
- package/.agents/skills/clckernel_cli/reference/audit.md +13 -3
- package/.agents/skills/clckernel_cli/reference/commit.md +1 -1
- package/.agents/skills/clckernel_cli/reference/doctor.md +5 -3
- package/.agents/skills/clckernel_cli/reference/feature.md +3 -3
- package/.agents/skills/clckernel_cli/reference/guard.md +48 -12
- package/.agents/skills/clckernel_cli/reference/phase.md +6 -3
- package/.agents/skills/clckernel_cli/reference/start.md +14 -4
- package/.agents/skills/clckernel_cli/reference/test.md +1 -1
- package/.agents/skills/clckernel_cli/reference/update.md +19 -19
- package/CHANGELOG.md +250 -0
- package/LICENSE +21 -0
- package/README.es.md +280 -51
- package/README.md +274 -50
- package/bin/deprecated.js +13 -0
- package/package.json +14 -4
- package/src/adapters/agent-os.js +161 -84
- package/src/adapters/astro.js +8 -6
- package/src/adapters/base.js +23 -38
- package/src/adapters/django.js +14 -13
- package/src/adapters/fastapi.js +16 -15
- package/src/adapters/go.js +11 -9
- package/src/adapters/laravel.js +12 -10
- package/src/adapters/nextjs.js +7 -5
- package/src/adapters/rails.js +13 -11
- package/src/adapters/rust.js +11 -9
- package/src/catalog.js +58 -49
- package/src/config.js +38 -240
- package/src/detector.js +243 -44
- package/src/doctor.js +18 -9
- package/src/generator.js +734 -302
- package/src/gitignore.js +60 -14
- package/src/index.js +257 -18
- package/src/io.js +409 -0
- package/src/known-hashes.json +309 -0
- package/src/onboarding.js +15 -0
- package/src/technologies/detector.js +1 -1
- package/src/technologies/guards/_shared.js +1 -1
- package/src/ui.js +233 -40
- package/src/updater.js +271 -38
- package/tools/_changes.js +279 -0
- package/tools/_changes.py +233 -0
- package/tools/_config.js +294 -0
- package/tools/_config.py +271 -0
- package/tools/_yaml.py +489 -0
- package/tools/audit.js +511 -111
- package/tools/audit.py +506 -128
- package/tools/celery_guard.py +13 -35
- package/tools/check_a11y.js +8 -28
- package/tools/check_api_contracts.js +13 -39
- package/tools/check_architecture.js +35 -44
- package/tools/check_architecture.py +172 -105
- package/tools/check_custom.js +108 -61
- package/tools/check_custom.py +108 -271
- package/tools/check_data_files.js +88 -0
- package/tools/check_db_efficiency.py +80 -65
- package/tools/check_hitl.js +112 -69
- package/tools/check_links.js +138 -0
- package/tools/check_migrations.py +143 -94
- package/tools/check_performance.js +35 -44
- package/tools/check_placeholders.js +104 -0
- package/tools/check_responsive.js +8 -28
- package/tools/check_scope.py +40 -31
- package/tools/check_seo.js +8 -28
- package/tools/check_skills.js +158 -0
- package/tools/check_storybook.js +8 -21
- package/tools/check_symlinks.js +40 -22
- package/tools/check_ui_reuse.js +17 -29
- package/tools/docker_guard.py +19 -41
- package/tools/postgres_guard.py +15 -36
- package/tools/redis_guard.py +13 -35
- package/tools/scan_secrets.js +134 -67
- package/tools/scan_secrets.py +163 -72
- package/tools/verify_tdd.js +867 -0
- package/tools/verify_tdd.py +407 -165
- package/tools/yaml.js +404 -132
- package/tools/check_domain_data.js +0 -100
- package/tools/check_test_calendar_sync.js +0 -111
package/src/adapters/go.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLC Kernel — Go Stack Adapter
|
|
3
|
-
* Supports Golang apps, `go test`, golangci-lint
|
|
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
|
|
21
|
+
'golangci-lint Code Quality Linter (external CLI)',
|
|
22
22
|
'Go Clean Architecture Guard (Domain -> UseCase -> Handler)',
|
|
23
|
-
'
|
|
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
|
|
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
|
|
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: '
|
|
38
|
-
{ name: '
|
|
39
|
-
{ name: '
|
|
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
|
|
43
|
+
return baseTools;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
provision(targetDir, config) {
|
package/src/adapters/laravel.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLC Kernel — PHP / Laravel Stack Adapter
|
|
3
|
-
* Supports Laravel, Pest / PHPUnit,
|
|
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
|
|
24
|
-
'Laravel Migration
|
|
25
|
-
'
|
|
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
|
|
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
|
|
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: '
|
|
40
|
-
{ name: '
|
|
41
|
-
{ name: '
|
|
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
|
|
45
|
+
return baseTools;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
provision(targetDir, config) {
|
package/src/adapters/nextjs.js
CHANGED
|
@@ -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
|
|
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: '
|
|
60
|
-
{ name: '
|
|
61
|
-
{ name: '
|
|
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
|
|
65
|
+
return baseTools;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
provision(targetDir, config) {
|
package/src/adapters/rails.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLC Kernel — Ruby on Rails Stack Adapter
|
|
3
|
-
* Supports Rails, RSpec, RuboCop
|
|
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
|
|
23
|
+
'RuboCop Code Style Linter (external CLI)',
|
|
24
24
|
'Brakeman Rails Vulnerability Scanner',
|
|
25
|
-
'Rails Migration
|
|
26
|
-
'
|
|
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
|
|
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
|
|
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: '
|
|
41
|
-
{ name: '
|
|
42
|
-
{ name: '
|
|
43
|
-
{ name: '
|
|
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
|
|
47
|
+
return baseTools;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
provision(targetDir, config) {
|
package/src/adapters/rust.js
CHANGED
|
@@ -18,28 +18,30 @@ class RustAdapter extends BaseAdapter {
|
|
|
18
18
|
|
|
19
19
|
getSafeguards() {
|
|
20
20
|
return [
|
|
21
|
-
'cargo clippy
|
|
21
|
+
'cargo clippy Linter (external CLI)',
|
|
22
22
|
'cargo audit Security Vulnerability Scanner',
|
|
23
|
-
'
|
|
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
|
|
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
|
|
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: '
|
|
38
|
-
{ name: '
|
|
39
|
-
{ name: '
|
|
40
|
-
{ name: '
|
|
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
|
|
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
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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[]} .
|
|
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: ['
|
|
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: ['
|
|
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 `.
|
|
40
|
-
applies_when: 'always', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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
|
|
80
|
-
applies_when: 'backend,fastapi,django', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
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: '
|
|
85
|
-
applies_when: 'backend', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
86
|
-
phase: 'audit', file: 'verify_tdd.py', manifest:
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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
|
|
115
|
-
applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
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
|
|
120
|
-
applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
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: '
|
|
124
|
-
checks: '
|
|
125
|
-
applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [
|
|
126
|
-
phase: 'audit', file: '
|
|
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: '
|
|
129
|
-
checks: '
|
|
130
|
-
applies_when: 'agent-os', severity: 'error', gate_mode: 'hard', config_keys: [
|
|
131
|
-
phase: 'audit', file: '
|
|
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
|
|
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: ['
|
|
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: '
|
|
170
|
-
applies_when: 'django|sqlalchemy', severity: 'error', gate_mode: 'hard', config_keys: ['
|
|
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: ['
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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;
|