guardian-framework 0.1.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.
- package/LICENSE +21 -0
- package/README.md +463 -0
- package/dist/cli.js +12958 -0
- package/dist/exports.js +12765 -0
- package/package.json +61 -0
- package/templates/languages/go-patterns.md +411 -0
- package/templates/languages/java-patterns.md +545 -0
- package/templates/languages/python-patterns.md +312 -0
- package/templates/languages/rust-patterns.md +232 -0
- package/templates/languages/typescript-patterns.md +313 -0
- package/templates/pi/INDEX.md +437 -0
- package/templates/pi/agent/AGENTS.md +166 -0
- package/templates/pi/agents/architecture-coordinator.md +40 -0
- package/templates/pi/agents/architecture-validator.md +36 -0
- package/templates/pi/agents/bootstrap-implementer.md +37 -0
- package/templates/pi/agents/issue-factory.md +31 -0
- package/templates/pi/agents/operations-validator.md +32 -0
- package/templates/pi/agents/security-validator.md +33 -0
- package/templates/pi/architecture/CHANGELOG.md +78 -0
- package/templates/pi/architecture/decisions/ADR-template.md +76 -0
- package/templates/pi/architecture/diagrams/system-overview.md +159 -0
- package/templates/pi/architecture/modules/module-template.md +152 -0
- package/templates/pi/context/checklists.md +91 -0
- package/templates/pi/context/domain-workflow.md +180 -0
- package/templates/pi/context/output-formats.md +135 -0
- package/templates/pi/context/patterns-base.md +47 -0
- package/templates/pi/context/patterns.md +38 -0
- package/templates/pi/context/project.md +88 -0
- package/templates/pi/domain/exploration.md +93 -0
- package/templates/pi/domain/ubiquitous-language.md +24 -0
- package/templates/pi/extensions/architect-lib/generators.ts +528 -0
- package/templates/pi/extensions/architect-lib/helpers.ts +344 -0
- package/templates/pi/extensions/architect-lib/types.ts +117 -0
- package/templates/pi/extensions/architect.ts +1425 -0
- package/templates/pi/extensions/ask-user-question.ts +579 -0
- package/templates/pi/extensions/bash-guard.ts +556 -0
- package/templates/pi/extensions/config-reload.ts +115 -0
- package/templates/pi/extensions/coordinator.ts +304 -0
- package/templates/pi/extensions/curator.ts +543 -0
- package/templates/pi/extensions/domain-explorer.ts +990 -0
- package/templates/pi/extensions/filechanges.ts +656 -0
- package/templates/pi/extensions/goal-loop.ts +717 -0
- package/templates/pi/extensions/hooks.ts +452 -0
- package/templates/pi/extensions/kanban.ts +547 -0
- package/templates/pi/extensions/pipeline.ts +1246 -0
- package/templates/pi/extensions/plan-mode.ts +209 -0
- package/templates/pi/extensions/project-scaffolder.ts +284 -0
- package/templates/pi/extensions/read-only-mode.ts +192 -0
- package/templates/pi/extensions/redaction.ts +128 -0
- package/templates/pi/extensions/session-persistence.ts +174 -0
- package/templates/pi/extensions/slash-commands.ts +229 -0
- package/templates/pi/extensions/snippets.ts +201 -0
- package/templates/pi/extensions/validation-runner.ts +100 -0
- package/templates/pi/github/agents/architecture-coordinator.agent.md +27 -0
- package/templates/pi/github/agents/architecture-validator.agent.md +20 -0
- package/templates/pi/github/agents/bootstrap-implementer.agent.md +20 -0
- package/templates/pi/github/agents/epic-planner.agent.md +70 -0
- package/templates/pi/github/agents/issue-factory.agent.md +20 -0
- package/templates/pi/github/agents/operations-validator.agent.md +20 -0
- package/templates/pi/github/agents/security-validator.agent.md +20 -0
- package/templates/pi/github/copilot/settings.json +16 -0
- package/templates/pi/github/copilot-instructions.md +155 -0
- package/templates/pi/github/instructions/architecture.instructions.md +71 -0
- package/templates/pi/github/instructions/validation.instructions.md +69 -0
- package/templates/pi/github/workflows/01-planning-workflow.md +75 -0
- package/templates/pi/github/workflows/02-issue-generation-workflow.md +69 -0
- package/templates/pi/github/workflows/03-implementation-workflow.md +80 -0
- package/templates/pi/github/workflows/04-validation-workflow.md +68 -0
- package/templates/pi/preflight_report.json +99 -0
- package/templates/pi/prompts/blueprint-update.md +262 -0
- package/templates/pi/prompts/blueprint-validate.md +218 -0
- package/templates/pi/prompts/bug-fix.md +50 -0
- package/templates/pi/prompts/ci-blueprint.md +131 -0
- package/templates/pi/prompts/context-refresh.md +258 -0
- package/templates/pi/prompts/epic-plan.md +356 -0
- package/templates/pi/prompts/epic-template.md +186 -0
- package/templates/pi/prompts/feature-development.md +131 -0
- package/templates/pi/prompts/git-issues.md +243 -0
- package/templates/pi/prompts/hotfix.md +71 -0
- package/templates/pi/prompts/issue-closeout.md +342 -0
- package/templates/pi/prompts/issue-draft.md +218 -0
- package/templates/pi/prompts/issue-implementation-series.md +173 -0
- package/templates/pi/prompts/issue-merge.md +372 -0
- package/templates/pi/prompts/issue-template-set.md +392 -0
- package/templates/pi/prompts/issue-template.md +207 -0
- package/templates/pi/prompts/pattern-extract.md +269 -0
- package/templates/pi/prompts/plan-to-issues.md +430 -0
- package/templates/pi/prompts/refactoring.md +82 -0
- package/templates/pi/prompts/scope-analyzer.md +254 -0
- package/templates/pi/prompts/sync-check.md +230 -0
- package/templates/pi/scripts/categorize-issues.sh +171 -0
- package/templates/pi/scripts/ci/check_architecture_conformance.sh +748 -0
- package/templates/pi/scripts/ci/check_planning_packet.py +228 -0
- package/templates/pi/scripts/ci/run_hardening_stages.sh +264 -0
- package/templates/pi/scripts/ci/run_preflight.sh +649 -0
- package/templates/pi/scripts/ci/run_stage.sh +193 -0
- package/templates/pi/scripts/ci/stage_docs_policy.sh +82 -0
- package/templates/pi/scripts/ci/stage_integration.sh +3 -0
- package/templates/pi/scripts/ci/stage_lint.sh +130 -0
- package/templates/pi/scripts/ci/stage_migration_verify.sh +3 -0
- package/templates/pi/scripts/ci/stage_package_build.sh +3 -0
- package/templates/pi/scripts/ci/stage_release_readiness.sh +3 -0
- package/templates/pi/scripts/ci/stage_remaining.sh +242 -0
- package/templates/pi/scripts/ci/stage_security.sh +3 -0
- package/templates/pi/scripts/ci/stage_static_analysis.sh +114 -0
- package/templates/pi/scripts/ci/stage_unit.sh +119 -0
- package/templates/pi/scripts/ci/validate_agent_output.py +181 -0
- package/templates/pi/scripts/ci/validate_agent_output.sh +243 -0
- package/templates/pi/scripts/create-feature-branch.sh +136 -0
- package/templates/pi/scripts/create-mr.sh +117 -0
- package/templates/pi/scripts/fetch-issues.sh +131 -0
- package/templates/pi/scripts/generate-architecture.sh +161 -0
- package/templates/pi/scripts/git/close-epic.sh +69 -0
- package/templates/pi/scripts/git/close-issue.sh +35 -0
- package/templates/pi/scripts/git/create-tracking-issue.sh +174 -0
- package/templates/pi/scripts/git/link-issue-to-epic.sh +51 -0
- package/templates/pi/scripts/git/update-tracking-issue.sh +66 -0
- package/templates/pi/scripts/languages/go/validate-architecture.sh +139 -0
- package/templates/pi/scripts/languages/go/validate-canonical.sh +129 -0
- package/templates/pi/scripts/languages/go/validate-ci.sh +132 -0
- package/templates/pi/scripts/languages/go/validate-integration.sh +156 -0
- package/templates/pi/scripts/languages/go/validate-operations.sh +146 -0
- package/templates/pi/scripts/languages/go/validate-security.sh +135 -0
- package/templates/pi/scripts/languages/go/validate-tests.sh +125 -0
- package/templates/pi/scripts/languages/java/validate-annotations.sh +185 -0
- package/templates/pi/scripts/languages/java/validate-architecture.sh +159 -0
- package/templates/pi/scripts/languages/java/validate-canonical.sh +114 -0
- package/templates/pi/scripts/languages/java/validate-ci.sh +269 -0
- package/templates/pi/scripts/languages/java/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/java/validate-operations.sh +142 -0
- package/templates/pi/scripts/languages/java/validate-security.sh +174 -0
- package/templates/pi/scripts/languages/java/validate-spring-architecture.sh +227 -0
- package/templates/pi/scripts/languages/java/validate-tests.sh +159 -0
- package/templates/pi/scripts/languages/python/validate-architecture.sh +99 -0
- package/templates/pi/scripts/languages/python/validate-canonical.sh +124 -0
- package/templates/pi/scripts/languages/python/validate-ci.sh +130 -0
- package/templates/pi/scripts/languages/python/validate-integration.sh +119 -0
- package/templates/pi/scripts/languages/python/validate-operations.sh +107 -0
- package/templates/pi/scripts/languages/python/validate-security.sh +68 -0
- package/templates/pi/scripts/languages/python/validate-tests.sh +102 -0
- package/templates/pi/scripts/languages/rust/validate-architecture.sh +188 -0
- package/templates/pi/scripts/languages/rust/validate-canonical.sh +146 -0
- package/templates/pi/scripts/languages/rust/validate-ci.sh +147 -0
- package/templates/pi/scripts/languages/rust/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/rust/validate-operations.sh +154 -0
- package/templates/pi/scripts/languages/rust/validate-security.sh +153 -0
- package/templates/pi/scripts/languages/rust/validate-tests.sh +150 -0
- package/templates/pi/scripts/languages/typescript/validate-architecture.sh +157 -0
- package/templates/pi/scripts/languages/typescript/validate-canonical.sh +135 -0
- package/templates/pi/scripts/languages/typescript/validate-ci.sh +244 -0
- package/templates/pi/scripts/languages/typescript/validate-integration.sh +166 -0
- package/templates/pi/scripts/languages/typescript/validate-operations.sh +162 -0
- package/templates/pi/scripts/languages/typescript/validate-security.sh +169 -0
- package/templates/pi/scripts/languages/typescript/validate-tests.sh +158 -0
- package/templates/pi/scripts/merge-mr.sh +95 -0
- package/templates/pi/scripts/mr-validation.sh +228 -0
- package/templates/pi/scripts/validate-architecture-readiness.sh +153 -0
- package/templates/pi/scripts/validate-architecture.sh +22 -0
- package/templates/pi/scripts/validate-canonical.sh +22 -0
- package/templates/pi/scripts/validate-ci.sh +37 -0
- package/templates/pi/scripts/validate-integration.sh +22 -0
- package/templates/pi/scripts/validate-operations.sh +22 -0
- package/templates/pi/scripts/validate-security.sh +22 -0
- package/templates/pi/scripts/validate-tests.sh +22 -0
- package/templates/pi/scripts/validate-ubiquitous-language.sh +291 -0
- package/templates/pi/scripts/validation-cache.sh +139 -0
- package/templates/pi/skills/agents/architecture-coordinator.md +178 -0
- package/templates/pi/skills/agents/architecture-generator.md +79 -0
- package/templates/pi/skills/agents/architecture-validator.md +74 -0
- package/templates/pi/skills/agents/ci-mr-validator.md +46 -0
- package/templates/pi/skills/agents/code-developer.md +76 -0
- package/templates/pi/skills/agents/commit.md +46 -0
- package/templates/pi/skills/agents/curator.md +71 -0
- package/templates/pi/skills/agents/debug.md +59 -0
- package/templates/pi/skills/agents/documentation-maintainer.md +36 -0
- package/templates/pi/skills/agents/goal-loop.md +125 -0
- package/templates/pi/skills/agents/hooks.md +122 -0
- package/templates/pi/skills/agents/integration-validator.md +35 -0
- package/templates/pi/skills/agents/issue-creator.md +75 -0
- package/templates/pi/skills/agents/issue-factory.md +143 -0
- package/templates/pi/skills/agents/kanban.md +85 -0
- package/templates/pi/skills/agents/land.md +59 -0
- package/templates/pi/skills/agents/operations-validator.md +43 -0
- package/templates/pi/skills/agents/pipeline.md +113 -0
- package/templates/pi/skills/agents/plan-mode.md +77 -0
- package/templates/pi/skills/agents/pull.md +40 -0
- package/templates/pi/skills/agents/push.md +41 -0
- package/templates/pi/skills/agents/security-validator.md +85 -0
- package/templates/pi/skills/agents/session-persistence.md +119 -0
- package/templates/pi/skills/agents/slash-commands.md +117 -0
- package/templates/pi/skills/agents/snippets.md +99 -0
- package/templates/pi/skills/agents/subagent-registry.md +78 -0
- package/templates/pi/skills/agents/test-validator.md +42 -0
- package/templates/pi/skills/validators/architecture-validator.md +43 -0
- package/templates/pi/skills/validators/ci-validator.md +27 -0
- package/templates/pi/skills/validators/context-compaction.md +73 -0
- package/templates/pi/skills/validators/integration-validator.md +38 -0
- package/templates/pi/skills/validators/model-registry.md +96 -0
- package/templates/pi/skills/validators/operations-validator.md +34 -0
- package/templates/pi/skills/validators/security-guards.md +72 -0
- package/templates/pi/skills/validators/security-validator.md +41 -0
- package/templates/pi/skills/validators/system-prompt-tiers.md +69 -0
- package/templates/pi/skills/validators/test-validator.md +33 -0
- package/templates/pi/types.ts +62 -0
- package/templates/pi/validators/README.md +93 -0
- package/templates/pi/validators/default.toml +209 -0
- package/templates/pi/validators/spring.toml +142 -0
- package/templates/pi/workpad.md +53 -0
- package/templates/project/java/Dockerfile +14 -0
- package/templates/project/java/README.md +40 -0
- package/templates/project/java/pom.xml +132 -0
- package/templates/project/typescript/Dockerfile +15 -0
- package/templates/project/typescript/README.md +29 -0
- package/templates/project/typescript/package.json +23 -0
- package/templates/project/typescript/tsconfig.json +21 -0
- package/templates/workflow.md +123 -0
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Architecture Conformance Check Runner
|
|
3
|
+
#
|
|
4
|
+
# Validates that the current slice conforms to all architectural contracts
|
|
5
|
+
# defined in .pi/architecture/modules/*.md and .pi/architecture/decisions/*.md
|
|
6
|
+
#
|
|
7
|
+
# Usage: bash .pi/scripts/ci/check_architecture_conformance.sh [--module <name>]
|
|
8
|
+
#
|
|
9
|
+
# Exit codes:
|
|
10
|
+
# 0 — All conformance checks passed
|
|
11
|
+
# 1 — One or more conformance checks failed
|
|
12
|
+
# 2 — Architecture module not found or invalid
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
PI_DIR=".pi"
|
|
17
|
+
ARCH_DIR="${PI_DIR}/architecture"
|
|
18
|
+
MODULES_DIR="${ARCH_DIR}/modules"
|
|
19
|
+
DECISIONS_DIR="${ARCH_DIR}/decisions"
|
|
20
|
+
SCRIPTS_DIR="${PI_DIR}/scripts/ci"
|
|
21
|
+
|
|
22
|
+
# Color output
|
|
23
|
+
RED='\033[0;31m'
|
|
24
|
+
GREEN='\033[0;32m'
|
|
25
|
+
YELLOW='\033[1;33m'
|
|
26
|
+
NC='\033[0m'
|
|
27
|
+
|
|
28
|
+
PASS_COUNT=0
|
|
29
|
+
FAIL_COUNT=0
|
|
30
|
+
SKIP_COUNT=0
|
|
31
|
+
TOTAL_COUNT=0
|
|
32
|
+
|
|
33
|
+
# Track failures for summary
|
|
34
|
+
declare -a FAILURES=()
|
|
35
|
+
|
|
36
|
+
log_pass() {
|
|
37
|
+
echo -e " ${GREEN}✓ PASS${NC} $1"
|
|
38
|
+
((PASS_COUNT++))
|
|
39
|
+
((TOTAL_COUNT++))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
log_fail() {
|
|
43
|
+
echo -e " ${RED}✗ FAIL${NC} $1 — $2"
|
|
44
|
+
((FAIL_COUNT++))
|
|
45
|
+
((TOTAL_COUNT++))
|
|
46
|
+
FAILURES+=("$1: $2")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
log_skip() {
|
|
50
|
+
echo -e " ${YELLOW}⊘ SKIP${NC} $1 — $2"
|
|
51
|
+
((SKIP_COUNT++))
|
|
52
|
+
((TOTAL_COUNT++))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# ── Language Detection ──
|
|
56
|
+
|
|
57
|
+
detect_language() {
|
|
58
|
+
if [[ -f "pyproject.toml" || -f "requirements.txt" || -f "Pipfile" || -f "setup.py" ]]; then
|
|
59
|
+
echo "python"
|
|
60
|
+
elif [[ -f "package.json" || -f "tsconfig.json" ]]; then
|
|
61
|
+
echo "typescript"
|
|
62
|
+
elif [[ -f "Cargo.toml" ]]; then
|
|
63
|
+
echo "rust"
|
|
64
|
+
elif [[ -f "go.mod" ]]; then
|
|
65
|
+
echo "go"
|
|
66
|
+
elif [[ -f "pom.xml" || -f "build.gradle" || -f "build.gradle.kts" ]]; then
|
|
67
|
+
echo "java"
|
|
68
|
+
elif [[ -f "Gemfile" ]]; then
|
|
69
|
+
echo "ruby"
|
|
70
|
+
else
|
|
71
|
+
echo "unknown"
|
|
72
|
+
fi
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
PROJECT_LANG=$(detect_language)
|
|
76
|
+
|
|
77
|
+
# ── Module Discovery ──
|
|
78
|
+
|
|
79
|
+
discover_modules() {
|
|
80
|
+
if [[ ! -d "${MODULES_DIR}" ]]; then
|
|
81
|
+
echo "ERROR: Architecture modules directory not found: ${MODULES_DIR}"
|
|
82
|
+
echo "Run 'guardian init' or create ${MODULES_DIR}/ with module definitions."
|
|
83
|
+
exit 2
|
|
84
|
+
fi
|
|
85
|
+
ls "${MODULES_DIR}"/*.md 2>/dev/null || true
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
parse_module_status() {
|
|
89
|
+
local module_file="$1"
|
|
90
|
+
local status=""
|
|
91
|
+
if [[ -f "$module_file" ]]; then
|
|
92
|
+
status=$(grep -i "^status:" "$module_file" 2>/dev/null | head -1 | sed 's/^status:[[:space:]]*//' || echo "unknown")
|
|
93
|
+
fi
|
|
94
|
+
echo "$status"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# ── Conformance Checks ──
|
|
98
|
+
|
|
99
|
+
# Check 1: Tenant Isolation Conformance
|
|
100
|
+
# Verifies that tenant-scoped data never crosses tenant boundaries
|
|
101
|
+
check_tenant_isolation() {
|
|
102
|
+
local check_name="tenant_isolation_conformance"
|
|
103
|
+
local ext="$1"
|
|
104
|
+
local lang="$2"
|
|
105
|
+
|
|
106
|
+
# Try language-specific validator first
|
|
107
|
+
case "$lang" in
|
|
108
|
+
python)
|
|
109
|
+
if [[ -f "${SCRIPTS_DIR}/check_tenant_isolation.py" ]]; then
|
|
110
|
+
if python3 "${SCRIPTS_DIR}/check_tenant_isolation.py" 2>/dev/null; then
|
|
111
|
+
log_pass "Tenant isolation conformance (Python validator)"
|
|
112
|
+
return
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
;;
|
|
116
|
+
typescript)
|
|
117
|
+
if [[ -f "${SCRIPTS_DIR}/check_tenant_isolation.ts" ]]; then
|
|
118
|
+
if npx tsx "${SCRIPTS_DIR}/check_tenant_isolation.ts" 2>/dev/null; then
|
|
119
|
+
log_pass "Tenant isolation conformance (TypeScript validator)"
|
|
120
|
+
return
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
;;
|
|
124
|
+
rust)
|
|
125
|
+
if [[ -f "${SCRIPTS_DIR}/check_tenant_isolation.sh" ]]; then
|
|
126
|
+
if bash "${SCRIPTS_DIR}/check_tenant_isolation.sh" 2>/dev/null; then
|
|
127
|
+
log_pass "Tenant isolation conformance (Rust validator)"
|
|
128
|
+
return
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
131
|
+
;;
|
|
132
|
+
go)
|
|
133
|
+
if [[ -f "${SCRIPTS_DIR}/check_tenant_isolation.sh" ]]; then
|
|
134
|
+
if bash "${SCRIPTS_DIR}/check_tenant_isolation.sh" 2>/dev/null; then
|
|
135
|
+
log_pass "Tenant isolation conformance (Go validator)"
|
|
136
|
+
return
|
|
137
|
+
fi
|
|
138
|
+
fi
|
|
139
|
+
;;
|
|
140
|
+
esac
|
|
141
|
+
|
|
142
|
+
# Fallback: grep-based check for tenant_id propagation
|
|
143
|
+
local violations=0
|
|
144
|
+
if command -v grep &>/dev/null; then
|
|
145
|
+
while IFS= read -r model_file; do
|
|
146
|
+
if grep -q "tenant_id" "$model_file" 2>/dev/null; then
|
|
147
|
+
local has_tenant_filter=false
|
|
148
|
+
if grep -qE "tenant_id.*=|WHERE.*tenant|tenant_scoped" "$model_file" 2>/dev/null; then
|
|
149
|
+
has_tenant_filter=true
|
|
150
|
+
fi
|
|
151
|
+
if [[ "$has_tenant_filter" == "false" ]]; then
|
|
152
|
+
((violations++))
|
|
153
|
+
log_fail "$check_name" "Model $(basename "$model_file") has tenant_id but no tenant-scoped queries"
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
done < <(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -50)
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
if [[ $violations -eq 0 ]]; then
|
|
160
|
+
log_pass "Tenant isolation conformance (no tenant-scoped models without filtering)"
|
|
161
|
+
fi
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Check 2: Event Ordering Conformance
|
|
165
|
+
# Verifies that events are processed in correct order (causal, temporal)
|
|
166
|
+
check_event_ordering() {
|
|
167
|
+
local check_name="event_ordering_conformance"
|
|
168
|
+
local lang="$1"
|
|
169
|
+
|
|
170
|
+
case "$lang" in
|
|
171
|
+
python)
|
|
172
|
+
if [[ -f "${SCRIPTS_DIR}/check_event_ordering.py" ]]; then
|
|
173
|
+
if python3 "${SCRIPTS_DIR}/check_event_ordering.py" 2>/dev/null; then
|
|
174
|
+
log_pass "Event ordering conformance"
|
|
175
|
+
return
|
|
176
|
+
fi
|
|
177
|
+
fi
|
|
178
|
+
;;
|
|
179
|
+
typescript)
|
|
180
|
+
if [[ -f "${SCRIPTS_DIR}/check_event_ordering.ts" ]]; then
|
|
181
|
+
if npx tsx "${SCRIPTS_DIR}/check_event_ordering.ts" 2>/dev/null; then
|
|
182
|
+
log_pass "Event ordering conformance"
|
|
183
|
+
return
|
|
184
|
+
fi
|
|
185
|
+
fi
|
|
186
|
+
;;
|
|
187
|
+
esac
|
|
188
|
+
|
|
189
|
+
local has_ordering=false
|
|
190
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
191
|
+
if grep -qE "(sequence|sequence_num|causal|version|timestamp.*order)" "$f" 2>/dev/null; then
|
|
192
|
+
has_ordering=true
|
|
193
|
+
break
|
|
194
|
+
fi
|
|
195
|
+
done
|
|
196
|
+
|
|
197
|
+
if [[ "$has_ordering" == "true" ]]; then
|
|
198
|
+
log_pass "Event ordering conformance (ordering mechanism detected)"
|
|
199
|
+
else
|
|
200
|
+
log_skip "Event ordering conformance" "No event ordering mechanism found (may not apply to this slice)"
|
|
201
|
+
fi
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Check 3: Outbox / DLQ Conformance
|
|
205
|
+
# Verifies that outbox pattern and dead-letter queues are properly implemented
|
|
206
|
+
check_outbox_dlq() {
|
|
207
|
+
local check_name="outbox_dlq_conformance"
|
|
208
|
+
local lang="$1"
|
|
209
|
+
|
|
210
|
+
case "$lang" in
|
|
211
|
+
python)
|
|
212
|
+
if [[ -f "${SCRIPTS_DIR}/check_outbox_dlq.py" ]]; then
|
|
213
|
+
if python3 "${SCRIPTS_DIR}/check_outbox_dlq.py" 2>/dev/null; then
|
|
214
|
+
log_pass "Outbox/DLQ conformance"
|
|
215
|
+
return
|
|
216
|
+
fi
|
|
217
|
+
fi
|
|
218
|
+
;;
|
|
219
|
+
typescript)
|
|
220
|
+
if [[ -f "${SCRIPTS_DIR}/check_outbox_dlq.ts" ]]; then
|
|
221
|
+
if npx tsx "${SCRIPTS_DIR}/check_outbox_dlq.ts" 2>/dev/null; then
|
|
222
|
+
log_pass "Outbox/DLQ conformance"
|
|
223
|
+
return
|
|
224
|
+
fi
|
|
225
|
+
fi
|
|
226
|
+
;;
|
|
227
|
+
esac
|
|
228
|
+
|
|
229
|
+
local has_outbox=false
|
|
230
|
+
local has_dlq=false
|
|
231
|
+
|
|
232
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
233
|
+
grep -qi "outbox" "$f" 2>/dev/null && has_outbox=true
|
|
234
|
+
grep -qi "dead.letter\|dlq\|failed.queue" "$f" 2>/dev/null && has_dlq=true
|
|
235
|
+
done
|
|
236
|
+
|
|
237
|
+
if [[ "$has_outbox" == "true" || "$has_dlq" == "true" ]]; then
|
|
238
|
+
log_pass "Outbox/DLQ conformance (pattern detected)"
|
|
239
|
+
else
|
|
240
|
+
log_skip "Outbox/DLQ conformance" "No outbox/DLQ pattern in this slice"
|
|
241
|
+
fi
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
# Check 4: Replay / Upcaster Conformance
|
|
245
|
+
# Verifies that event replay and schema upcasting work correctly
|
|
246
|
+
check_replay_upcaster() {
|
|
247
|
+
local check_name="replay_upcaster_conformance"
|
|
248
|
+
local lang="$1"
|
|
249
|
+
|
|
250
|
+
case "$lang" in
|
|
251
|
+
python)
|
|
252
|
+
if [[ -f "${SCRIPTS_DIR}/check_replay_upcaster.py" ]]; then
|
|
253
|
+
if python3 "${SCRIPTS_DIR}/check_replay_upcaster.py" 2>/dev/null; then
|
|
254
|
+
log_pass "Replay/upcaster conformance"
|
|
255
|
+
return
|
|
256
|
+
fi
|
|
257
|
+
fi
|
|
258
|
+
;;
|
|
259
|
+
typescript)
|
|
260
|
+
if [[ -f "${SCRIPTS_DIR}/check_replay_upcaster.ts" ]]; then
|
|
261
|
+
if npx tsx "${SCRIPTS_DIR}/check_replay_upcaster.ts" 2>/dev/null; then
|
|
262
|
+
log_pass "Replay/upcaster conformance"
|
|
263
|
+
return
|
|
264
|
+
fi
|
|
265
|
+
fi
|
|
266
|
+
;;
|
|
267
|
+
esac
|
|
268
|
+
|
|
269
|
+
local has_replay=false
|
|
270
|
+
local has_upcaster=false
|
|
271
|
+
|
|
272
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
273
|
+
grep -qi "replay\|replay_from\|replay_events" "$f" 2>/dev/null && has_replay=true
|
|
274
|
+
grep -qi "upcast\|schema.*version\|migrate.*event" "$f" 2>/dev/null && has_upcaster=true
|
|
275
|
+
done
|
|
276
|
+
|
|
277
|
+
if [[ "$has_replay" == "true" || "$has_upcaster" == "true" ]]; then
|
|
278
|
+
log_pass "Replay/upcaster conformance (mechanism detected)"
|
|
279
|
+
else
|
|
280
|
+
log_skip "Replay/upcaster conformance" "No replay/upcaster mechanism in this slice"
|
|
281
|
+
fi
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
# Check 5: RunStarted Publication Conformance
|
|
285
|
+
# Verifies that run-started events are published correctly
|
|
286
|
+
check_runstarted_publication() {
|
|
287
|
+
local check_name="runstarted_publication_conformance"
|
|
288
|
+
local lang="$1"
|
|
289
|
+
|
|
290
|
+
case "$lang" in
|
|
291
|
+
python)
|
|
292
|
+
if [[ -f "${SCRIPTS_DIR}/check_runstarted_publication.py" ]]; then
|
|
293
|
+
if python3 "${SCRIPTS_DIR}/check_runstarted_publication.py" 2>/dev/null; then
|
|
294
|
+
log_pass "RunStarted publication conformance"
|
|
295
|
+
return
|
|
296
|
+
fi
|
|
297
|
+
fi
|
|
298
|
+
;;
|
|
299
|
+
typescript)
|
|
300
|
+
if [[ -f "${SCRIPTS_DIR}/check_runstarted_publication.ts" ]]; then
|
|
301
|
+
if npx tsx "${SCRIPTS_DIR}/check_runstarted_publication.ts" 2>/dev/null; then
|
|
302
|
+
log_pass "RunStarted publication conformance"
|
|
303
|
+
return
|
|
304
|
+
fi
|
|
305
|
+
fi
|
|
306
|
+
;;
|
|
307
|
+
esac
|
|
308
|
+
|
|
309
|
+
local has_publication=false
|
|
310
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
311
|
+
if grep -qi "run.started\|run_started\|RunStarted\|runstarted" "$f" 2>/dev/null; then
|
|
312
|
+
has_publication=true
|
|
313
|
+
break
|
|
314
|
+
fi
|
|
315
|
+
done
|
|
316
|
+
|
|
317
|
+
if [[ "$has_publication" == "true" ]]; then
|
|
318
|
+
log_pass "RunStarted publication conformance"
|
|
319
|
+
else
|
|
320
|
+
log_skip "RunStarted publication conformance" "No runstarted events in this slice"
|
|
321
|
+
fi
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
# Check 6: RunStarted Worker Activation Conformance
|
|
325
|
+
# Verifies that workers activate correctly on run-started events
|
|
326
|
+
check_runstarted_worker_activation() {
|
|
327
|
+
local check_name="runstarted_worker_activation_conformance"
|
|
328
|
+
local lang="$1"
|
|
329
|
+
|
|
330
|
+
case "$lang" in
|
|
331
|
+
python)
|
|
332
|
+
if [[ -f "${SCRIPTS_DIR}/check_runstarted_worker_activation.py" ]]; then
|
|
333
|
+
if python3 "${SCRIPTS_DIR}/check_runstarted_worker_activation.py" 2>/dev/null; then
|
|
334
|
+
log_pass "RunStarted worker activation conformance"
|
|
335
|
+
return
|
|
336
|
+
fi
|
|
337
|
+
fi
|
|
338
|
+
;;
|
|
339
|
+
typescript)
|
|
340
|
+
if [[ -f "${SCRIPTS_DIR}/check_runstarted_worker_activation.ts" ]]; then
|
|
341
|
+
if npx tsx "${SCRIPTS_DIR}/check_runstarted_worker_activation.ts" 2>/dev/null; then
|
|
342
|
+
log_pass "RunStarted worker activation conformance"
|
|
343
|
+
return
|
|
344
|
+
fi
|
|
345
|
+
fi
|
|
346
|
+
;;
|
|
347
|
+
esac
|
|
348
|
+
|
|
349
|
+
local has_worker_activation=false
|
|
350
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
351
|
+
if grep -qi "worker.*start\|activate.*worker\|on_run.*start" "$f" 2>/dev/null; then
|
|
352
|
+
has_worker_activation=true
|
|
353
|
+
break
|
|
354
|
+
fi
|
|
355
|
+
done
|
|
356
|
+
|
|
357
|
+
if [[ "$has_worker_activation" == "true" ]]; then
|
|
358
|
+
log_pass "RunStarted worker activation conformance"
|
|
359
|
+
else
|
|
360
|
+
log_skip "RunStarted worker activation conformance" "No worker activation in this slice"
|
|
361
|
+
fi
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
# Check 7: Bounded LangGraph Execution Conformance
|
|
365
|
+
# Verifies that LangGraph executions are bounded (timeout, token, step limits)
|
|
366
|
+
check_bounded_execution() {
|
|
367
|
+
local check_name="bounded_execution_conformance"
|
|
368
|
+
local lang="$1"
|
|
369
|
+
|
|
370
|
+
case "$lang" in
|
|
371
|
+
python)
|
|
372
|
+
if [[ -f "${SCRIPTS_DIR}/check_bounded_execution.py" ]]; then
|
|
373
|
+
if python3 "${SCRIPTS_DIR}/check_bounded_execution.py" 2>/dev/null; then
|
|
374
|
+
log_pass "Bounded execution conformance"
|
|
375
|
+
return
|
|
376
|
+
fi
|
|
377
|
+
fi
|
|
378
|
+
;;
|
|
379
|
+
typescript)
|
|
380
|
+
if [[ -f "${SCRIPTS_DIR}/check_bounded_execution.ts" ]]; then
|
|
381
|
+
if npx tsx "${SCRIPTS_DIR}/check_bounded_execution.ts" 2>/dev/null; then
|
|
382
|
+
log_pass "Bounded execution conformance"
|
|
383
|
+
return
|
|
384
|
+
fi
|
|
385
|
+
fi
|
|
386
|
+
;;
|
|
387
|
+
esac
|
|
388
|
+
|
|
389
|
+
local has_bounds=false
|
|
390
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
391
|
+
if grep -qiE "(timeout|max_steps|max_tokens|step_limit|bounded|circuit.breaker)" "$f" 2>/dev/null; then
|
|
392
|
+
has_bounds=true
|
|
393
|
+
break
|
|
394
|
+
fi
|
|
395
|
+
done
|
|
396
|
+
|
|
397
|
+
if [[ "$has_bounds" == "true" ]]; then
|
|
398
|
+
log_pass "Bounded execution conformance (bounds detected)"
|
|
399
|
+
else
|
|
400
|
+
log_skip "Bounded execution conformance" "No bounded execution pattern in this slice"
|
|
401
|
+
fi
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
# Check 8: Artifact Proof Surfaces Conformance
|
|
405
|
+
# Verifies that artifact proof surfaces are properly exposed
|
|
406
|
+
check_artifact_proof_surfaces() {
|
|
407
|
+
local check_name="artifact_proof_surfaces_conformance"
|
|
408
|
+
local lang="$1"
|
|
409
|
+
|
|
410
|
+
case "$lang" in
|
|
411
|
+
python)
|
|
412
|
+
if [[ -f "${SCRIPTS_DIR}/check_artifact_proof_surfaces.py" ]]; then
|
|
413
|
+
if python3 "${SCRIPTS_DIR}/check_artifact_proof_surfaces.py" 2>/dev/null; then
|
|
414
|
+
log_pass "Artifact proof surfaces conformance"
|
|
415
|
+
return
|
|
416
|
+
fi
|
|
417
|
+
fi
|
|
418
|
+
;;
|
|
419
|
+
typescript)
|
|
420
|
+
if [[ -f "${SCRIPTS_DIR}/check_artifact_proof_surfaces.ts" ]]; then
|
|
421
|
+
if npx tsx "${SCRIPTS_DIR}/check_artifact_proof_surfaces.ts" 2>/dev/null; then
|
|
422
|
+
log_pass "Artifact proof surfaces conformance"
|
|
423
|
+
return
|
|
424
|
+
fi
|
|
425
|
+
fi
|
|
426
|
+
;;
|
|
427
|
+
esac
|
|
428
|
+
|
|
429
|
+
local has_proof=false
|
|
430
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
431
|
+
if grep -qiE "(artifact.*proof|proof.*surface|verification.*artifact|artifact_hash)" "$f" 2>/dev/null; then
|
|
432
|
+
has_proof=true
|
|
433
|
+
break
|
|
434
|
+
fi
|
|
435
|
+
done
|
|
436
|
+
|
|
437
|
+
if [[ "$has_proof" == "true" ]]; then
|
|
438
|
+
log_pass "Artifact proof surfaces conformance"
|
|
439
|
+
else
|
|
440
|
+
log_skip "Artifact proof surfaces conformance" "No artifact proof surfaces in this slice"
|
|
441
|
+
fi
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
# Check 9: Runtime Baseline Conformance
|
|
445
|
+
# Verifies runtime environment meets baseline requirements
|
|
446
|
+
check_runtime_baseline() {
|
|
447
|
+
local check_name="runtime_baseline_conformance"
|
|
448
|
+
local lang="$1"
|
|
449
|
+
|
|
450
|
+
case "$lang" in
|
|
451
|
+
python)
|
|
452
|
+
if [[ -f "${SCRIPTS_DIR}/check_runtime_baseline.py" ]]; then
|
|
453
|
+
if python3 "${SCRIPTS_DIR}/check_runtime_baseline.py" 2>/dev/null; then
|
|
454
|
+
log_pass "Runtime baseline conformance"
|
|
455
|
+
return
|
|
456
|
+
fi
|
|
457
|
+
fi
|
|
458
|
+
# Python version check
|
|
459
|
+
if command -v python3 &>/dev/null; then
|
|
460
|
+
local version
|
|
461
|
+
version=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
|
462
|
+
local major minor
|
|
463
|
+
major=$(echo "$version" | cut -d. -f1)
|
|
464
|
+
minor=$(echo "$version" | cut -d. -f2)
|
|
465
|
+
if [[ $major -gt 3 ]] || [[ $major -eq 3 && $minor -ge 10 ]]; then
|
|
466
|
+
log_pass "Runtime baseline conformance (Python ${version} >= 3.10)"
|
|
467
|
+
else
|
|
468
|
+
log_fail "Runtime baseline conformance" "Python ${version} < 3.10"
|
|
469
|
+
return
|
|
470
|
+
fi
|
|
471
|
+
fi
|
|
472
|
+
;;
|
|
473
|
+
typescript)
|
|
474
|
+
if [[ -f "${SCRIPTS_DIR}/check_runtime_baseline.ts" ]]; then
|
|
475
|
+
if npx tsx "${SCRIPTS_DIR}/check_runtime_baseline.ts" 2>/dev/null; then
|
|
476
|
+
log_pass "Runtime baseline conformance"
|
|
477
|
+
return
|
|
478
|
+
fi
|
|
479
|
+
fi
|
|
480
|
+
# Node version check
|
|
481
|
+
if command -v node &>/dev/null; then
|
|
482
|
+
local version
|
|
483
|
+
version=$(node -v | sed 's/v//')
|
|
484
|
+
local major
|
|
485
|
+
major=$(echo "$version" | cut -d. -f1)
|
|
486
|
+
if [[ $major -ge 18 ]]; then
|
|
487
|
+
log_pass "Runtime baseline conformance (Node ${version} >= 18)"
|
|
488
|
+
else
|
|
489
|
+
log_fail "Runtime baseline conformance" "Node ${version} < 18"
|
|
490
|
+
return
|
|
491
|
+
fi
|
|
492
|
+
fi
|
|
493
|
+
;;
|
|
494
|
+
rust)
|
|
495
|
+
if [[ -f "${SCRIPTS_DIR}/check_runtime_baseline.sh" ]]; then
|
|
496
|
+
if bash "${SCRIPTS_DIR}/check_runtime_baseline.sh" 2>/dev/null; then
|
|
497
|
+
log_pass "Runtime baseline conformance"
|
|
498
|
+
return
|
|
499
|
+
fi
|
|
500
|
+
fi
|
|
501
|
+
if command -v rustc &>/dev/null; then
|
|
502
|
+
log_pass "Runtime baseline conformance (rustc available)"
|
|
503
|
+
fi
|
|
504
|
+
;;
|
|
505
|
+
go)
|
|
506
|
+
if [[ -f "${SCRIPTS_DIR}/check_runtime_baseline.sh" ]]; then
|
|
507
|
+
if bash "${SCRIPTS_DIR}/check_runtime_baseline.sh" 2>/dev/null; then
|
|
508
|
+
log_pass "Runtime baseline conformance"
|
|
509
|
+
return
|
|
510
|
+
fi
|
|
511
|
+
fi
|
|
512
|
+
if command -v go &>/dev/null; then
|
|
513
|
+
log_pass "Runtime baseline conformance (go available)"
|
|
514
|
+
fi
|
|
515
|
+
;;
|
|
516
|
+
esac
|
|
517
|
+
|
|
518
|
+
# Env var collision check
|
|
519
|
+
if [[ -f ".env.example" ]]; then
|
|
520
|
+
local unbound=0
|
|
521
|
+
while IFS= read -r var; do
|
|
522
|
+
var_name=$(echo "$var" | cut -d= -f1)
|
|
523
|
+
if [[ -z "${!var_name:-}" ]]; then
|
|
524
|
+
((unbound++))
|
|
525
|
+
fi
|
|
526
|
+
done < <(grep -v "^#" .env.example 2>/dev/null | grep "=" || true)
|
|
527
|
+
if [[ $unbound -eq 0 ]]; then
|
|
528
|
+
log_pass "Runtime baseline conformance (all env vars configured)"
|
|
529
|
+
else
|
|
530
|
+
log_fail "Runtime baseline conformance" "${unbound} env vars from .env.example not set"
|
|
531
|
+
fi
|
|
532
|
+
else
|
|
533
|
+
log_skip "Runtime baseline conformance" "No .env.example found"
|
|
534
|
+
fi
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
# Check 10: Controlled Stage Progression Conformance
|
|
538
|
+
# Verifies that state machines / workflows progress through defined stages only
|
|
539
|
+
check_controlled_stage_progression() {
|
|
540
|
+
local check_name="controlled_stage_progression_conformance"
|
|
541
|
+
local lang="$1"
|
|
542
|
+
|
|
543
|
+
case "$lang" in
|
|
544
|
+
python)
|
|
545
|
+
if [[ -f "${SCRIPTS_DIR}/check_controlled_stage_progression.py" ]]; then
|
|
546
|
+
if python3 "${SCRIPTS_DIR}/check_controlled_stage_progression.py" 2>/dev/null; then
|
|
547
|
+
log_pass "Controlled stage progression conformance"
|
|
548
|
+
return
|
|
549
|
+
fi
|
|
550
|
+
fi
|
|
551
|
+
;;
|
|
552
|
+
typescript)
|
|
553
|
+
if [[ -f "${SCRIPTS_DIR}/check_controlled_stage_progression.ts" ]]; then
|
|
554
|
+
if npx tsx "${SCRIPTS_DIR}/check_controlled_stage_progression.ts" 2>/dev/null; then
|
|
555
|
+
log_pass "Controlled stage progression conformance"
|
|
556
|
+
return
|
|
557
|
+
fi
|
|
558
|
+
fi
|
|
559
|
+
;;
|
|
560
|
+
esac
|
|
561
|
+
|
|
562
|
+
local has_state_machine=false
|
|
563
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
564
|
+
if grep -qiE "(state_machine|transition|Stage\(|step_to|next_stage|progression)" "$f" 2>/dev/null; then
|
|
565
|
+
has_state_machine=true
|
|
566
|
+
break
|
|
567
|
+
fi
|
|
568
|
+
done
|
|
569
|
+
|
|
570
|
+
if [[ "$has_state_machine" == "true" ]]; then
|
|
571
|
+
log_pass "Controlled stage progression conformance (state machine detected)"
|
|
572
|
+
else
|
|
573
|
+
log_skip "Controlled stage progression conformance" "No state machine in this slice"
|
|
574
|
+
fi
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
# ── Architecture Sanity Checks ──
|
|
578
|
+
|
|
579
|
+
check_arch_sanity() {
|
|
580
|
+
local check_name="architecture_sanity"
|
|
581
|
+
local lang="$1"
|
|
582
|
+
|
|
583
|
+
case "$lang" in
|
|
584
|
+
python)
|
|
585
|
+
if [[ -f "${SCRIPTS_DIR}/check_arch_sanity.py" ]]; then
|
|
586
|
+
if python3 "${SCRIPTS_DIR}/check_arch_sanity.py" 2>/dev/null; then
|
|
587
|
+
log_pass "Architecture sanity (Python validator)"
|
|
588
|
+
return
|
|
589
|
+
fi
|
|
590
|
+
fi
|
|
591
|
+
;;
|
|
592
|
+
typescript)
|
|
593
|
+
if [[ -f "${SCRIPTS_DIR}/check_arch_sanity.ts" ]]; then
|
|
594
|
+
if npx tsx "${SCRIPTS_DIR}/check_arch_sanity.ts" 2>/dev/null; then
|
|
595
|
+
log_pass "Architecture sanity (TypeScript validator)"
|
|
596
|
+
return
|
|
597
|
+
fi
|
|
598
|
+
fi
|
|
599
|
+
;;
|
|
600
|
+
esac
|
|
601
|
+
|
|
602
|
+
# Generic: no orphaned imports
|
|
603
|
+
local orphaned_imports=0
|
|
604
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
605
|
+
if grep -qE "^import.*UNUSED|^from.*UNUSED" "$f" 2>/dev/null; then
|
|
606
|
+
((orphaned_imports++))
|
|
607
|
+
fi
|
|
608
|
+
done
|
|
609
|
+
if [[ $orphaned_imports -gt 0 ]]; then
|
|
610
|
+
log_fail "$check_name" "${orphaned_imports} files have UNUSED import markers"
|
|
611
|
+
else
|
|
612
|
+
log_pass "Architecture sanity (no orphaned imports)"
|
|
613
|
+
fi
|
|
614
|
+
|
|
615
|
+
# Concurrency safety patterns
|
|
616
|
+
local has_concurrency_safety=false
|
|
617
|
+
for f in $(find . -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -30); do
|
|
618
|
+
if grep -qiE "(lock|mutex|atomic|transaction|isolation|concurrent\.)" "$f" 2>/dev/null; then
|
|
619
|
+
has_concurrency_safety=true
|
|
620
|
+
break
|
|
621
|
+
fi
|
|
622
|
+
done
|
|
623
|
+
if [[ "$has_concurrency_safety" == "true" ]]; then
|
|
624
|
+
log_pass "Architecture sanity (concurrency safety patterns detected)"
|
|
625
|
+
else
|
|
626
|
+
log_skip "Architecture sanity" "No concurrency-sensitive code in this slice"
|
|
627
|
+
fi
|
|
628
|
+
|
|
629
|
+
# Settings/env collision check
|
|
630
|
+
local collisions=0
|
|
631
|
+
if [[ -f ".env.example" ]] && [[ -f ".env" ]]; then
|
|
632
|
+
while IFS= read -r line; do
|
|
633
|
+
var_name=$(echo "$line" | cut -d= -f1)
|
|
634
|
+
if grep -q "^${var_name}=" ".env" 2>/dev/null; then
|
|
635
|
+
local example_val actual_val
|
|
636
|
+
example_val=$(grep "^${var_name}=" ".env.example" | cut -d= -f2-)
|
|
637
|
+
actual_val=$(grep "^${var_name}=" ".env" | cut -d= -f2-)
|
|
638
|
+
if [[ "$example_val" == "$actual_val" ]]; then
|
|
639
|
+
((collisions++))
|
|
640
|
+
fi
|
|
641
|
+
fi
|
|
642
|
+
done < <(grep -v "^#" .env.example 2>/dev/null | grep "=" || true)
|
|
643
|
+
fi
|
|
644
|
+
if [[ $collisions -gt 0 ]]; then
|
|
645
|
+
log_fail "$check_name" "${collisions} env vars in .env match .env.example (should be different)"
|
|
646
|
+
else
|
|
647
|
+
log_pass "Architecture sanity (no settings/env collisions)"
|
|
648
|
+
fi
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
# ── Import Boundary Check ──
|
|
652
|
+
|
|
653
|
+
check_import_boundaries() {
|
|
654
|
+
local check_name="import_boundaries"
|
|
655
|
+
local lang="$1"
|
|
656
|
+
|
|
657
|
+
case "$lang" in
|
|
658
|
+
python)
|
|
659
|
+
if [[ -f "${SCRIPTS_DIR}/check_import_boundaries.py" ]]; then
|
|
660
|
+
if python3 "${SCRIPTS_DIR}/check_import_boundaries.py" 2>/dev/null; then
|
|
661
|
+
log_pass "Import boundary conformance (Python validator)"
|
|
662
|
+
return
|
|
663
|
+
fi
|
|
664
|
+
fi
|
|
665
|
+
;;
|
|
666
|
+
typescript)
|
|
667
|
+
if [[ -f "${SCRIPTS_DIR}/check_import_boundaries.ts" ]]; then
|
|
668
|
+
if npx tsx "${SCRIPTS_DIR}/check_import_boundaries.ts" 2>/dev/null; then
|
|
669
|
+
log_pass "Import boundary conformance (TypeScript validator)"
|
|
670
|
+
return
|
|
671
|
+
fi
|
|
672
|
+
fi
|
|
673
|
+
;;
|
|
674
|
+
esac
|
|
675
|
+
|
|
676
|
+
# Basic check: no cross-layer violations
|
|
677
|
+
# Layer structure: app/domain → app/application → app/infrastructure → app/api
|
|
678
|
+
local violations=0
|
|
679
|
+
|
|
680
|
+
for layer_dir in app/domain app/application app/infrastructure app/api src/domain src/application src/infrastructure src/api; do
|
|
681
|
+
if [[ ! -d "$layer_dir" ]]; then continue; fi
|
|
682
|
+
while IFS= read -r file; do
|
|
683
|
+
[[ -f "$file" ]] || continue
|
|
684
|
+
if [[ "$layer_dir" == *"domain" ]]; then
|
|
685
|
+
if grep -qE "from.*infrastructure|from.*api|import.*infrastructure|import.*api" "$file" 2>/dev/null; then
|
|
686
|
+
((violations++))
|
|
687
|
+
log_fail "$check_name" "Domain layer imports from infrastructure/api in $(basename "$file")"
|
|
688
|
+
fi
|
|
689
|
+
fi
|
|
690
|
+
if [[ "$layer_dir" == *"application" ]]; then
|
|
691
|
+
if grep -qE "from.*api|import.*api" "$file" 2>/dev/null; then
|
|
692
|
+
((violations++))
|
|
693
|
+
log_fail "$check_name" "Application layer imports from api in $(basename "$file")"
|
|
694
|
+
fi
|
|
695
|
+
fi
|
|
696
|
+
done < <(find "$layer_dir" -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -20)
|
|
697
|
+
done
|
|
698
|
+
|
|
699
|
+
if [[ $violations -eq 0 ]]; then
|
|
700
|
+
log_pass "Import boundary conformance (no cross-layer violations)"
|
|
701
|
+
fi
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
# ── Main ──
|
|
705
|
+
|
|
706
|
+
echo "═══ Architecture Conformance Checks ═══"
|
|
707
|
+
echo ""
|
|
708
|
+
|
|
709
|
+
# Run all conformance checks
|
|
710
|
+
check_tenant_isolation "" "$PROJECT_LANG"
|
|
711
|
+
check_event_ordering "$PROJECT_LANG"
|
|
712
|
+
check_outbox_dlq "$PROJECT_LANG"
|
|
713
|
+
check_replay_upcaster "$PROJECT_LANG"
|
|
714
|
+
check_runstarted_publication "$PROJECT_LANG"
|
|
715
|
+
check_runstarted_worker_activation "$PROJECT_LANG"
|
|
716
|
+
check_bounded_execution "$PROJECT_LANG"
|
|
717
|
+
check_artifact_proof_surfaces "$PROJECT_LANG"
|
|
718
|
+
check_runtime_baseline "$PROJECT_LANG"
|
|
719
|
+
check_controlled_stage_progression "$PROJECT_LANG"
|
|
720
|
+
|
|
721
|
+
echo ""
|
|
722
|
+
echo "═══ Architecture Sanity Checks ═══"
|
|
723
|
+
echo ""
|
|
724
|
+
|
|
725
|
+
check_arch_sanity "" "$PROJECT_LANG"
|
|
726
|
+
check_import_boundaries "$PROJECT_LANG"
|
|
727
|
+
|
|
728
|
+
echo ""
|
|
729
|
+
echo "═══ Conformance Summary ═══"
|
|
730
|
+
echo -e " ${GREEN}Pass: ${PASS_COUNT}${NC}"
|
|
731
|
+
echo -e " ${RED}Fail: ${FAIL_COUNT}${NC}"
|
|
732
|
+
echo -e " ${YELLOW}Skip: ${SKIP_COUNT}${NC}"
|
|
733
|
+
echo " Total: ${TOTAL_COUNT}"
|
|
734
|
+
|
|
735
|
+
if [[ ${FAIL_COUNT} -gt 0 ]]; then
|
|
736
|
+
echo ""
|
|
737
|
+
echo "Failures:"
|
|
738
|
+
for f in "${FAILURES[@]}"; do
|
|
739
|
+
echo -e " ${RED}✗${NC} $f"
|
|
740
|
+
done
|
|
741
|
+
echo ""
|
|
742
|
+
echo "Architecture conformance FAILED. Fix the issues above before proceeding."
|
|
743
|
+
exit 1
|
|
744
|
+
fi
|
|
745
|
+
|
|
746
|
+
echo ""
|
|
747
|
+
echo -e "${GREEN}All architecture conformance checks passed.${NC}"
|
|
748
|
+
exit 0
|