guardian-framework 0.1.104 → 0.1.109
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/README.md +11 -2
- package/dist/cli.js +232 -16
- package/dist/exports.js +232 -16
- package/package.json +1 -1
- package/templates/languages/rust-patterns.md +5 -2
- package/templates/pi/context/checklists.md +15 -1
- package/templates/pi/domain/exploration.md +9 -0
- package/templates/pi/domain/ubiquitous-language.md +12 -0
- package/templates/pi/extensions/architect-lib/generators.ts +163 -12
- package/templates/pi/extensions/architect-lib/helpers.ts +49 -0
- package/templates/pi/extensions/architect-lib/tdd-generator.ts +1 -1
- package/templates/pi/extensions/architect-lib/types.ts +44 -2
- package/templates/pi/extensions/architect.ts +105 -41
- package/templates/pi/extensions/ask-user-question.ts +2 -2
- package/templates/pi/extensions/bash-guard.ts +2 -2
- package/templates/pi/extensions/config-reload.ts +12 -5
- package/templates/pi/extensions/coordinator.ts +2 -2
- package/templates/pi/extensions/curator.ts +1 -1
- package/templates/pi/extensions/domain-explorer.ts +50 -3
- package/templates/pi/extensions/filechanges.ts +2 -2
- package/templates/pi/extensions/goal-loop.ts +3 -3
- package/templates/pi/extensions/hooks.ts +1 -1
- package/templates/pi/extensions/pi-env.d.ts +96 -0
- package/templates/pi/extensions/pipeline.ts +1 -1
- package/templates/pi/extensions/project-scaffolder.ts +1 -1
- package/templates/pi/extensions/read-only-mode.ts +5 -1
- package/templates/pi/extensions/tsconfig.json +9 -2
- package/templates/pi/preflight_report.json +1 -1
- package/templates/pi/prompts/ci-blueprint.md +2 -2
- package/templates/pi/scripts/check_model_judgment.sh +28 -0
- package/templates/pi/scripts/ci/check_judgment_contracts.sh +93 -0
- package/templates/pi/scripts/ci/run_preflight.sh +3 -3
- package/templates/pi/scripts/ci/run_stage.sh +1 -1
- package/templates/pi/scripts/ci/stage_lint.sh +1 -1
- package/templates/pi/scripts/coverage.sh +58 -0
- package/templates/pi/scripts/install_coverage_tools.sh +43 -0
- package/templates/pi/scripts/languages/go/check_model_judgment.sh +70 -0
- package/templates/pi/scripts/languages/go/check_runtime_reachability.sh +34 -0
- package/templates/pi/scripts/languages/go/coverage.sh +78 -0
- package/templates/pi/scripts/languages/go/install_coverage_tools.sh +17 -0
- package/templates/pi/scripts/languages/java/check_model_judgment.sh +142 -0
- package/templates/pi/scripts/languages/java/check_runtime_reachability.sh +31 -0
- package/templates/pi/scripts/languages/java/coverage.sh +103 -0
- package/templates/pi/scripts/languages/java/install_coverage_tools.sh +40 -0
- package/templates/pi/scripts/languages/java/validate-architecture.sh +20 -0
- package/templates/pi/scripts/languages/python/check_model_judgment.sh +67 -0
- package/templates/pi/scripts/languages/python/check_runtime_reachability.sh +34 -0
- package/templates/pi/scripts/languages/python/coverage.sh +88 -0
- package/templates/pi/scripts/languages/python/install_coverage_tools.sh +22 -0
- package/templates/pi/scripts/languages/rust/check_model_judgment.sh +61 -0
- package/templates/pi/scripts/languages/rust/check_runtime_reachability.sh +40 -0
- package/templates/pi/scripts/languages/rust/coverage.sh +79 -0
- package/templates/pi/scripts/languages/rust/install_coverage_tools.sh +20 -0
- package/templates/pi/scripts/languages/rust/validate-tests.sh +9 -6
- package/templates/pi/scripts/languages/typescript/check_model_judgment.sh +81 -0
- package/templates/pi/scripts/languages/typescript/check_runtime_reachability.sh +41 -0
- package/templates/pi/scripts/languages/typescript/coverage.sh +154 -0
- package/templates/pi/scripts/languages/typescript/install_coverage_tools.sh +41 -0
- package/templates/pi/scripts/languages/typescript/validate-canonical.sh +6 -2
- package/templates/pi/scripts/languages/typescript/validate-ci.sh +2 -2
- package/templates/pi/scripts/validate-architecture-readiness.sh +29 -0
- package/templates/pi/scripts/validate-exploration-depth.sh +112 -0
- package/templates/pi/scripts/validate-runtime-wiring.sh +35 -0
- package/templates/pi/skills/agents/architecture-validator.md +28 -0
- package/templates/pi/skills/agents/test-validator.md +1 -1
- package/templates/pi/skills/go-enterprise-codegen.md +46 -0
- package/templates/pi/skills/java-spring-enterprise-codegen.md +50 -0
- package/templates/pi/skills/python-enterprise-codegen.md +46 -0
- package/templates/pi/skills/rust-enterprise-codegen.md +46 -0
- package/templates/pi/skills/tdd-practice.md +17 -9
- package/templates/pi/skills/typescript-enterprise-codegen.md +46 -0
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
const COMMAND_NAME = "read-only";
|
|
26
26
|
const STATUS_KEY = "read-only-mode";
|
|
27
27
|
const WIDGET_KEY = "read-only-mode";
|
|
28
|
+
let readOnlyActive = false;
|
|
29
|
+
|
|
28
30
|
const READ_ONLY_TOOL_NAMES = ["read", "grep", "find", "ls"] as const;
|
|
29
31
|
|
|
30
32
|
function getReadOnlyToolNames(pi: ExtensionAPI): string[] {
|
|
@@ -95,6 +97,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
function enable(ctx: ExtensionContext): void {
|
|
100
|
+
readOnlyActive = true;
|
|
98
101
|
if (enabled) {
|
|
99
102
|
updateUi(pi, ctx, enabled);
|
|
100
103
|
ctx.ui.notify("Read-only mode is already enabled.", "info");
|
|
@@ -111,6 +114,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
function disable(ctx: ExtensionContext): void {
|
|
117
|
+
readOnlyActive = false;
|
|
114
118
|
if (!enabled) {
|
|
115
119
|
updateUi(pi, ctx, enabled);
|
|
116
120
|
ctx.ui.notify("Read-only mode is already disabled.", "info");
|
|
@@ -130,7 +134,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
130
134
|
switch (action) {
|
|
131
135
|
case "":
|
|
132
136
|
case "toggle":
|
|
133
|
-
|
|
137
|
+
if (readOnlyActive) disable(ctx); else enable(ctx);
|
|
134
138
|
return;
|
|
135
139
|
case "on":
|
|
136
140
|
case "enable":
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"types": [
|
|
3
|
+
"types": [
|
|
4
|
+
"bun-types"
|
|
5
|
+
],
|
|
4
6
|
"strict": true,
|
|
7
|
+
"noImplicitAny": false,
|
|
8
|
+
"strictNullChecks": false,
|
|
5
9
|
"target": "ES2022",
|
|
6
10
|
"module": "ESNext",
|
|
7
11
|
"moduleResolution": "bundler",
|
|
@@ -11,5 +15,8 @@
|
|
|
11
15
|
"isolatedModules": true,
|
|
12
16
|
"allowImportingTsExtensions": true
|
|
13
17
|
},
|
|
14
|
-
"include": [
|
|
18
|
+
"include": [
|
|
19
|
+
"**/*.ts",
|
|
20
|
+
"**/*.d.ts"
|
|
21
|
+
]
|
|
15
22
|
}
|
|
@@ -72,7 +72,7 @@ Language-specific linting.
|
|
|
72
72
|
| `unit_application` | `pytest tests/unit/application` | No |
|
|
73
73
|
| `unit_contract` | `pytest tests/contract` | No |
|
|
74
74
|
| `unit_verification` | `pytest tests/verification` | No |
|
|
75
|
-
| `
|
|
75
|
+
| `coverage_gate` | `bash .pi/scripts/install_coverage_tools.sh && bash .pi/scripts/coverage.sh --gate --lcov` | No |
|
|
76
76
|
|
|
77
77
|
## Stage 6: Integration
|
|
78
78
|
|
|
@@ -119,7 +119,7 @@ Language-specific linting.
|
|
|
119
119
|
| Rule | Jobs Using It |
|
|
120
120
|
|------|---------------|
|
|
121
121
|
| `rules_default` (MRs or main branch) | Most jobs |
|
|
122
|
-
| `rules_sonar` (requires `$SONAR_TOKEN` + `$SONAR_HOST_URL`) |
|
|
122
|
+
| `rules_sonar` (requires `$SONAR_TOKEN` + `$SONAR_HOST_URL`) | coverage_gate (uploads lcov artifact), sonar_quality_gate |
|
|
123
123
|
| `rules_main_only` | `package_build` |
|
|
124
124
|
| `rules_migration_changes` (migration file changes only) | `migration_verify` stage |
|
|
125
125
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# check_model_judgment.sh — ADR-008/009 dispatcher
|
|
4
|
+
# Runs the language-scoped model-judgment hard gates (dip-domain,
|
|
5
|
+
# interface-ownership, adapter-purity, transaction placement per language).
|
|
6
|
+
# Usage: bash .pi/scripts/check_model_judgment.sh [--root <dir>]
|
|
7
|
+
# ============================================================================
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
ROOT="$(pwd)"
|
|
11
|
+
if [ "${1:-}" = "--root" ] && [ -n "${2:-}" ]; then ROOT="$2"; fi
|
|
12
|
+
cd "$ROOT" || exit 1
|
|
13
|
+
|
|
14
|
+
detect_language() {
|
|
15
|
+
if [ -f "Cargo.lock" ] || [ -f "Cargo.toml" ]; then echo "rust"
|
|
16
|
+
elif [ -f "package.json" ]; then echo "typescript"
|
|
17
|
+
elif [ -f "go.mod" ]; then echo "go"
|
|
18
|
+
elif [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then echo "python"
|
|
19
|
+
elif [ -f "pom.xml" ] || [ -f "build.gradle" ]; then echo "java"
|
|
20
|
+
else echo "unknown"; fi
|
|
21
|
+
}
|
|
22
|
+
LANG="$(detect_language)"
|
|
23
|
+
SCRIPT="${SCRIPT_DIR}/languages/${LANG}/check_model_judgment.sh"
|
|
24
|
+
if [ -f "$SCRIPT" ]; then
|
|
25
|
+
exec bash "$SCRIPT" --root "$ROOT"
|
|
26
|
+
fi
|
|
27
|
+
echo "model-judgment: no gate script for language '${LANG}'"
|
|
28
|
+
exit 0
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# check_judgment_contracts.sh — proofing for ADR-008 P1 (judgment-aware
|
|
4
|
+
# modeling). Deterministic proof that each frozen contract (§1–§7 of
|
|
5
|
+
# .pi/architecture/contracts/judgment-aware-modeling-p1.md) is implemented
|
|
6
|
+
# in the framework sources.
|
|
7
|
+
#
|
|
8
|
+
# Checks:
|
|
9
|
+
# 1. exploration prompt emits ADR-008 schema markers (src)
|
|
10
|
+
# 2. validate-exploration-depth.sh exists + executable
|
|
11
|
+
# 3. java model-judgment gate exists + executable
|
|
12
|
+
# 4. module-doc scaffold emits 'Modeling Depth' header (src)
|
|
13
|
+
# 5. java-spring codegen skill carries 'Judgment Tables (ADR-008)'
|
|
14
|
+
# 6. architecture-validator skill carries Model Judgment Review R1-R4
|
|
15
|
+
# 7. modeling contracts: ModuleComponent type carries the ADR-008 fields
|
|
16
|
+
# 8. exploration.md template carries the Modeling Judgment section
|
|
17
|
+
#
|
|
18
|
+
# Exit 0 = all contracts proven; 1 = at least one missing.
|
|
19
|
+
# ============================================================================
|
|
20
|
+
set -uo pipefail
|
|
21
|
+
|
|
22
|
+
ROOT="$(pwd)"
|
|
23
|
+
if [ "${1:-}" = "--root" ] && [ -n "${2:-}" ]; then ROOT="$2"; fi
|
|
24
|
+
cd "$ROOT" || exit 1
|
|
25
|
+
|
|
26
|
+
FAILED=0
|
|
27
|
+
PASSED=0
|
|
28
|
+
|
|
29
|
+
check() { # label, file-or-dir, grep pattern
|
|
30
|
+
local label="$1" path="$2" pattern="$3"
|
|
31
|
+
if [ -n "$path" ] && [ -e "$path" ] && grep -qE "$pattern" "$path" 2>/dev/null; then
|
|
32
|
+
echo " PASS: $label"
|
|
33
|
+
PASSED=$((PASSED + 1))
|
|
34
|
+
else
|
|
35
|
+
echo " FAIL: $label (missing: $path / $pattern)" >&2
|
|
36
|
+
FAILED=$((FAILED + 1))
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
check_file() { # label file
|
|
41
|
+
if [ -f "$2" ] && [ -x "$2" ]; then
|
|
42
|
+
echo " PASS: $1"
|
|
43
|
+
PASSED=$((PASSED + 1))
|
|
44
|
+
else
|
|
45
|
+
echo " FAIL: $1 (not found/executable: $2)" >&2
|
|
46
|
+
FAILED=$((FAILED + 1))
|
|
47
|
+
fi
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
echo "Judgment contracts proofing (ADR-008 P1)"
|
|
51
|
+
echo "----------------------------------------"
|
|
52
|
+
|
|
53
|
+
# 1. exploration prompt schema markers
|
|
54
|
+
check "exploration prompt: subdomainType/invariants/triage/contextMap/conflicts" \
|
|
55
|
+
"src/lib/domain-explorer.ts" 'subdomainType|"invariants"|"triage"|"contextMap"|"conflicts"'
|
|
56
|
+
|
|
57
|
+
# 2. depth validator present + executable
|
|
58
|
+
check_file "validate-exploration-depth.sh executable" ".pi/scripts/validate-exploration-depth.sh"
|
|
59
|
+
check_file "validate-exploration-depth.sh (templates copy)" "templates/pi/scripts/validate-exploration-depth.sh"
|
|
60
|
+
|
|
61
|
+
# 3. java model-judgment gate present + executable
|
|
62
|
+
check_file "java model-judgment gate" ".pi/scripts/languages/java/check_model_judgment.sh"
|
|
63
|
+
check_file "java model-judgment gate (templates copy)" "templates/pi/scripts/languages/java/check_model_judgment.sh"
|
|
64
|
+
|
|
65
|
+
# 4. scaffold emits Modeling Depth header + invariants + depth note
|
|
66
|
+
check "scaffold: Modeling Depth header" "src/lib/domain-explorer.ts" 'Modeling Depth'
|
|
67
|
+
check "scaffold: depth note for service/adapter" "src/lib/domain-explorer.ts" 'Modeling Depth Note \(ADR-008\)'
|
|
68
|
+
|
|
69
|
+
# 5. java-spring codegen skill: judgment tables
|
|
70
|
+
check "java-spring skill: Judgment Tables (ADR-008)" \
|
|
71
|
+
".pi/skills/java-spring-enterprise-codegen.md" 'Judgment Tables \(ADR-008\)'
|
|
72
|
+
|
|
73
|
+
# 6. architecture-validator skill: R1-R4 review questions
|
|
74
|
+
check "architecture-validator skill: Model Judgment Review" \
|
|
75
|
+
".pi/skills/agents/architecture-validator.md" 'Model Judgment Review'
|
|
76
|
+
|
|
77
|
+
# 7. ModuleComponent modeling-contract fields
|
|
78
|
+
check "architect-lib types: modelingDepth/aggregateRoot/invariants/events" \
|
|
79
|
+
".pi/extensions/architect-lib/types.ts" 'modelingDepth|aggregateRoot|invariants|publishes'
|
|
80
|
+
check "generators: Modeling Contract emission" \
|
|
81
|
+
".pi/extensions/architect-lib/generators.ts" 'Modeling Contract \(ADR-008\)'
|
|
82
|
+
|
|
83
|
+
# 8. exploration.md template: Modeling Judgment section
|
|
84
|
+
check "exploration.md template: Modeling Judgment section" \
|
|
85
|
+
"templates/pi/domain/exploration.md" 'Modeling Judgment \(ADR-008\)'
|
|
86
|
+
|
|
87
|
+
echo ""
|
|
88
|
+
echo " Passed: $PASSED Failed: $FAILED"
|
|
89
|
+
if [ "$FAILED" -gt 0 ]; then
|
|
90
|
+
exit 1
|
|
91
|
+
fi
|
|
92
|
+
echo "All judgment contracts proven."
|
|
93
|
+
exit 0
|
|
@@ -255,10 +255,10 @@ run_stage_lint() {
|
|
|
255
255
|
log_fail "biome check" "lint errors found" "$(( $(date +%s) - t ))"
|
|
256
256
|
fi
|
|
257
257
|
t=$(date +%s)
|
|
258
|
-
if biome
|
|
259
|
-
log_pass "biome
|
|
258
|
+
if biome ci . >/dev/null 2>&1; then
|
|
259
|
+
log_pass "biome ci" "$(( $(date +%s) - t ))"
|
|
260
260
|
else
|
|
261
|
-
log_fail "biome
|
|
261
|
+
log_fail "biome ci" "format errors found" "$(( $(date +%s) - t ))"
|
|
262
262
|
fi
|
|
263
263
|
else
|
|
264
264
|
log_skip "biome" "not installed"
|
|
@@ -76,7 +76,7 @@ case "$STAGE" in
|
|
|
76
76
|
ruff check . && ruff format --check .
|
|
77
77
|
elif [[ -f "package.json" ]]; then
|
|
78
78
|
echo "TypeScript project detected"
|
|
79
|
-
biome check . && biome
|
|
79
|
+
biome check . && biome ci .
|
|
80
80
|
elif [[ -f "Cargo.toml" ]]; then
|
|
81
81
|
echo "Rust project detected"
|
|
82
82
|
cargo clippy -- -D warnings && cargo fmt --check
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# coverage.sh — Real project coverage measurement + gate (dispatcher)
|
|
4
|
+
#
|
|
5
|
+
# Runs the project's REAL coverage tool for the detected language and reports
|
|
6
|
+
# line coverage. This is the honest replacement for the old per-module
|
|
7
|
+
# heuristic `*_coverage.sh` checks (coverage-theater — they counted test
|
|
8
|
+
# functions via grep, never a real percentage).
|
|
9
|
+
#
|
|
10
|
+
# Delegates to languages/<lang>/coverage.sh. Real coverage tool per language:
|
|
11
|
+
# rust — cargo llvm-cov (workspace line coverage, lcov artifact)
|
|
12
|
+
# python — coverage.py (pytest/unittest)
|
|
13
|
+
# typescript — vitest / jest / bun test --coverage (istanbul text)
|
|
14
|
+
# go — go test -coverprofile + go tool cover
|
|
15
|
+
# java — JaCoCo (maven/gradle)
|
|
16
|
+
#
|
|
17
|
+
# Usage:
|
|
18
|
+
# bash .pi/scripts/coverage.sh # measure + print summary
|
|
19
|
+
# bash .pi/scripts/coverage.sh --gate # exit 1 if lines < COVERAGE_THRESHOLD
|
|
20
|
+
# bash .pi/scripts/coverage.sh --lcov # also emit the tool's report artifact
|
|
21
|
+
#
|
|
22
|
+
# Env:
|
|
23
|
+
# COVERAGE_THRESHOLD minimum line-coverage % (default: 60 — a conservative
|
|
24
|
+
# floor; set it to the threshold your CI actually enforces)
|
|
25
|
+
#
|
|
26
|
+
# Exit codes:
|
|
27
|
+
# 0 — measured and (with --gate) meets threshold, or language not applicable
|
|
28
|
+
# 1 — coverage tool missing / below threshold / could not measure (honest
|
|
29
|
+
# fail — never fake-pass)
|
|
30
|
+
# 2 — unknown argument
|
|
31
|
+
# ============================================================================
|
|
32
|
+
set -uo pipefail
|
|
33
|
+
|
|
34
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
35
|
+
|
|
36
|
+
detect_language() {
|
|
37
|
+
if [ -f "Cargo.lock" ] || [ -f "Cargo.toml" ]; then echo "rust"
|
|
38
|
+
elif [ -f "poetry.lock" ] || [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then echo "python"
|
|
39
|
+
elif [ -f "go.mod" ]; then echo "go"
|
|
40
|
+
elif [ -f "package.json" ]; then echo "typescript"
|
|
41
|
+
elif [ -f "pom.xml" ] || [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then echo "java"
|
|
42
|
+
else echo "unknown"; fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
LANG="$(detect_language)"
|
|
46
|
+
|
|
47
|
+
if [ "$LANG" = "unknown" ]; then
|
|
48
|
+
echo "⚠️ No project language detected — no real coverage gate applies." >&2
|
|
49
|
+
exit 0
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
LANG_SCRIPT="${SCRIPT_DIR}/languages/${LANG}/coverage.sh"
|
|
53
|
+
if [ ! -f "$LANG_SCRIPT" ]; then
|
|
54
|
+
echo "⚠️ No coverage gate script for '${LANG}' yet (${LANG_SCRIPT})." >&2
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
exec bash "$LANG_SCRIPT" "$@"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# install_coverage_tools.sh — Install the project's real coverage tooling
|
|
4
|
+
# (dispatcher)
|
|
5
|
+
#
|
|
6
|
+
# Delegates to languages/<lang>/install_coverage_tools.sh based on the
|
|
7
|
+
# detected language. Run this before `.pi/scripts/coverage.sh --gate` in CI
|
|
8
|
+
# or on a fresh checkout.
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# bash .pi/scripts/install_coverage_tools.sh
|
|
12
|
+
#
|
|
13
|
+
# Exit codes:
|
|
14
|
+
# 0 — tooling available / installed / not required
|
|
15
|
+
# 1 — install failed
|
|
16
|
+
# ============================================================================
|
|
17
|
+
set -uo pipefail
|
|
18
|
+
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
20
|
+
|
|
21
|
+
detect_language() {
|
|
22
|
+
if [ -f "Cargo.lock" ] || [ -f "Cargo.toml" ]; then echo "rust"
|
|
23
|
+
elif [ -f "poetry.lock" ] || [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then echo "python"
|
|
24
|
+
elif [ -f "go.mod" ]; then echo "go"
|
|
25
|
+
elif [ -f "package.json" ]; then echo "typescript"
|
|
26
|
+
elif [ -f "pom.xml" ] || [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then echo "java"
|
|
27
|
+
else echo "unknown"; fi
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
LANG="$(detect_language)"
|
|
31
|
+
|
|
32
|
+
if [ "$LANG" = "unknown" ]; then
|
|
33
|
+
echo "⚠️ No project language detected — nothing to install." >&2
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
LANG_SCRIPT="${SCRIPT_DIR}/languages/${LANG}/install_coverage_tools.sh"
|
|
38
|
+
if [ ! -f "$LANG_SCRIPT" ]; then
|
|
39
|
+
echo "⚠️ No coverage installer for '${LANG}' yet (${LANG_SCRIPT})." >&2
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
exec bash "$LANG_SCRIPT" "$@"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# check_model_judgment.sh — Go (ADR-008/009)
|
|
4
|
+
# Deterministic hard gates:
|
|
5
|
+
# dip-domain domain/ imports gorm/sqlx/gin/echo
|
|
6
|
+
# txn-placement sql.Tx / BeginTx outside application/
|
|
7
|
+
# interface-ownership (tactical) infra adapters without a domain interface
|
|
8
|
+
# adapter-purity (adapter modules) model code in generic subdomains
|
|
9
|
+
# Usage: bash check_model_judgment.sh [--root <dir>]
|
|
10
|
+
# ============================================================================
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
ROOT="$(pwd)"
|
|
13
|
+
if [ "${1:-}" = "--root" ] && [ -n "${2:-}" ]; then ROOT="$2"; fi
|
|
14
|
+
cd "$ROOT" || exit 1
|
|
15
|
+
VIOLATIONS=0
|
|
16
|
+
report() { echo "$1:$2: [$3] $4"; VIOLATIONS=$((VIOLATIONS + 1)); }
|
|
17
|
+
[ -d src ] || { echo "model-judgment (go): no src/"; exit 0; }
|
|
18
|
+
|
|
19
|
+
while IFS= read -r f; do
|
|
20
|
+
[ -n "$f" ] || continue
|
|
21
|
+
case "$f" in */domain/*)
|
|
22
|
+
while IFS=: read -r ln rest; do
|
|
23
|
+
case "$rest" in
|
|
24
|
+
*gorm.io*|*database/sql*|*sqlx*|*gin-gonic*|*labstack*|*uptrace/bun*)
|
|
25
|
+
report "$f" "$ln" "dip-domain" "domain imports persistence/web framework: $rest" ;;
|
|
26
|
+
esac
|
|
27
|
+
done < <(grep -nE '^\s*("|_ "|import )' "$f" | grep -E 'gorm|sqlx|database/sql|gin-gonic|labstack|bun' || true) ;;
|
|
28
|
+
esac
|
|
29
|
+
case "$f" in */application/*) ;; *)
|
|
30
|
+
if grep -qE "sql\.Tx|BeginTx|\.Commit\(\)" "$f" 2>/dev/null; then
|
|
31
|
+
report "$f" "1" "txn-placement" "transaction handling outside application layer"
|
|
32
|
+
fi ;;
|
|
33
|
+
esac
|
|
34
|
+
done < <(find src -type f -name "*.go" 2>/dev/null | grep -vE "_test\.go$|/tests?/" || true)
|
|
35
|
+
|
|
36
|
+
if [ -d ".pi/architecture/modules" ]; then
|
|
37
|
+
for doc in .pi/architecture/modules/*.md; do
|
|
38
|
+
[ -f "$doc" ] || continue
|
|
39
|
+
doc_name="$(basename "$doc" .md)"
|
|
40
|
+
depth="$(grep -m1 '^\*\*Modeling Depth:\*\*' "$doc" | sed 's/.*\*\*Modeling Depth:\*\* *//' | cut -d' ' -f1 || true)"
|
|
41
|
+
docnorm="$(echo "$doc_name" | sed 's/^module[-_]//' | tr '[:upper:]' '[:lower:]' | tr '-' '_')"
|
|
42
|
+
match_dir=""
|
|
43
|
+
while IFS= read -r d; do
|
|
44
|
+
norm="$(basename "$d" | tr '[:upper:]' '[:lower:]' | tr '-' '_')"
|
|
45
|
+
if [ "$norm" = "$docnorm" ]; then match_dir="$d"; break; fi
|
|
46
|
+
done < <(find src -mindepth 1 -maxdepth 1 -type d 2>/dev/null || true)
|
|
47
|
+
[ -n "$match_dir" ] || continue
|
|
48
|
+
if [ "$depth" = "adapter" ]; then
|
|
49
|
+
for layer in domain application; do
|
|
50
|
+
while IFS= read -r f; do [ -n "$f" ] || continue; report "$f" "1" "adapter-purity" "generic subdomain '${doc_name}' must not contain ${layer}/ model code (ADR-008)"; done < <(find "$match_dir/$layer" -type f -name "*.go" 2>/dev/null || true)
|
|
51
|
+
done
|
|
52
|
+
elif [ "$depth" = "tactical" ]; then
|
|
53
|
+
while IFS= read -r impl; do
|
|
54
|
+
[ -n "$impl" ] || continue
|
|
55
|
+
simple="$(basename "$impl" .go)"
|
|
56
|
+
stem="$(echo "$simple" | sed -E 's/Impl$//;s/impl$//')"
|
|
57
|
+
if ! grep -rqiE "type ${stem} interface|type ${simple} interface|${stem}" "$match_dir/domain" 2>/dev/null; then
|
|
58
|
+
compact="$(printf '%s' "$simple" | tr -d '_-')"
|
|
59
|
+
if [ -z "$compact" ] || ! grep -rqil "$compact" "$match_dir/domain" 2>/dev/null; then
|
|
60
|
+
report "$impl" "1" "interface-ownership" "adapter without a domain/-owned interface (${simple})"
|
|
61
|
+
fi
|
|
62
|
+
fi
|
|
63
|
+
done < <(find "$match_dir/infrastructure" -type f -name "*.go" 2>/dev/null || true)
|
|
64
|
+
fi
|
|
65
|
+
done
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if [ "$VIOLATIONS" -gt 0 ]; then echo "model-judgment (go): ${VIOLATIONS} violation(s)" >&2; exit 1; fi
|
|
69
|
+
echo "model-judgment (go): all gates passed (dip-domain, txn-placement, interface-ownership, adapter-purity)"
|
|
70
|
+
exit 0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# check_runtime_reachability.sh — Go (ADR-009)
|
|
4
|
+
#
|
|
5
|
+
# Every service file under src/<module>/application/ must be referenced from
|
|
6
|
+
# production code OUTSIDE its own module and OUTSIDE tests. Candidates: the
|
|
7
|
+
# file stem (snake), its PascalCase type name, and the separator-stripped
|
|
8
|
+
# form (case-insensitive).
|
|
9
|
+
# Usage: bash check_runtime_reachability.sh [--root <dir>]
|
|
10
|
+
# Exit: 0 all reachable ; 1 dead service(s)
|
|
11
|
+
# ============================================================================
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
ROOT="$(pwd)"
|
|
14
|
+
if [ "${1:-}" = "--root" ] && [ -n "${2:-}" ]; then ROOT="$2"; fi
|
|
15
|
+
cd "$ROOT" || exit 1
|
|
16
|
+
VIOLATIONS=0
|
|
17
|
+
[ -d src ] || { echo "runtime-reachability (go): no src/"; exit 0; }
|
|
18
|
+
|
|
19
|
+
while IFS= read -r svc; do
|
|
20
|
+
[ -n "$svc" ] || continue
|
|
21
|
+
mod="$(echo "$svc" | sed 's|^src/||; s|/application/.*||')"
|
|
22
|
+
stem="$(basename "$svc" .go)"
|
|
23
|
+
pascal="$(echo "$stem" | python3 -c 'import sys; s=sys.stdin.read().strip(); print("".join(w.capitalize() for w in s.split("_")) if s else "")' 2>/dev/null || echo "$stem")"
|
|
24
|
+
compact="$(echo "$stem" | tr -d '_-')"
|
|
25
|
+
refs="$(grep -rliE "\b(${pascal}|${stem}|${compact})\b" src 2>/dev/null | grep -vE "_test\.go$|/tests?/|/test/" | grep -v "^src/${mod}/" | grep -v "^${svc}$" | grep -cv '^$' || true)"
|
|
26
|
+
if [ "${refs:-0}" -eq 0 ]; then
|
|
27
|
+
echo "$svc: [runtime-reachability] application service has no production caller outside its module (tests-only callers don't count — ADR-009)"
|
|
28
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
29
|
+
fi
|
|
30
|
+
done < <(find src -path "*/application/*.go" -type f 2>/dev/null | grep -vE "_test\.go$" || true)
|
|
31
|
+
|
|
32
|
+
if [ "$VIOLATIONS" -gt 0 ]; then echo "runtime-wiring (go): ${VIOLATIONS} unwired service(s)" >&2; exit 1; fi
|
|
33
|
+
echo "runtime-reachability (go): all application services reachable from production code"
|
|
34
|
+
exit 0
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# coverage.sh — Go: real line coverage via `go test -coverprofile`
|
|
4
|
+
#
|
|
5
|
+
# Runs the full test suite with a coverage profile and reports total line
|
|
6
|
+
# coverage from `go tool cover -func`.
|
|
7
|
+
#
|
|
8
|
+
# Usage (normally via the .pi/scripts/coverage.sh dispatcher):
|
|
9
|
+
# bash coverage.sh # measure coverage
|
|
10
|
+
# bash coverage.sh --gate # fail if lines < COVERAGE_THRESHOLD
|
|
11
|
+
# bash coverage.sh --lcov # keep coverage.out profile artifact
|
|
12
|
+
#
|
|
13
|
+
# Env:
|
|
14
|
+
# COVERAGE_THRESHOLD minimum line-coverage % (default: 60)
|
|
15
|
+
# ============================================================================
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
COVERAGE_THRESHOLD="${COVERAGE_THRESHOLD:-60}"
|
|
19
|
+
GATE=0
|
|
20
|
+
LCOV=0
|
|
21
|
+
|
|
22
|
+
for arg in "$@"; do
|
|
23
|
+
case "$arg" in
|
|
24
|
+
--gate) GATE=1 ;;
|
|
25
|
+
--lcov) LCOV=1 ;;
|
|
26
|
+
*) echo "unknown arg: $arg" >&2; exit 2 ;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
# Walk up from CWD to the module root (go.mod).
|
|
31
|
+
ROOT="$(pwd)"
|
|
32
|
+
while [ "$ROOT" != "/" ] && [ ! -f "$ROOT/go.mod" ]; do
|
|
33
|
+
ROOT="$(dirname "$ROOT")"
|
|
34
|
+
done
|
|
35
|
+
if [ ! -f "$ROOT/go.mod" ]; then
|
|
36
|
+
echo "✗ No go.mod found in this directory tree" >&2
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
cd "$ROOT" || exit 1
|
|
40
|
+
|
|
41
|
+
if ! command -v go >/dev/null 2>&1; then
|
|
42
|
+
echo "✗ go toolchain not found on PATH" >&2
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo "═══ Coverage (go test -coverprofile) ═══"
|
|
47
|
+
go test -coverprofile=coverage.out ./... 2>&1 | tail -10
|
|
48
|
+
|
|
49
|
+
if [ ! -f "coverage.out" ]; then
|
|
50
|
+
echo "✗ No coverage profile generated (go test -coverprofile failed)" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
FUNC_OUT="$(go tool cover -func=coverage.out 2>/dev/null || true)"
|
|
55
|
+
COVERAGE="$(echo "$FUNC_OUT" | awk '/^total:/{print $NF}' | tr -d '%')"
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Line coverage: ${COVERAGE:-unavailable}% (threshold: ${COVERAGE_THRESHOLD}%)"
|
|
58
|
+
|
|
59
|
+
if [ -z "$COVERAGE" ]; then
|
|
60
|
+
echo "✗ Could not extract total coverage from coverage profile" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
if [ "$LCOV" -eq 1 ]; then
|
|
65
|
+
echo "coverage profile artifact kept: coverage.out"
|
|
66
|
+
else
|
|
67
|
+
rm -f coverage.out
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ "$GATE" -eq 1 ]; then
|
|
71
|
+
if awk "BEGIN { exit !($COVERAGE >= $COVERAGE_THRESHOLD) }"; then
|
|
72
|
+
echo "✓ Coverage gate passed"
|
|
73
|
+
else
|
|
74
|
+
echo "✗ Coverage below threshold (${COVERAGE}% < ${COVERAGE_THRESHOLD}%)" >&2
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
exit 0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# install_coverage_tools.sh — Go: no extra install required
|
|
4
|
+
#
|
|
5
|
+
# `go test -coverprofile` is built into the Go toolchain. This script exists
|
|
6
|
+
# so the language dispatcher is uniform; it only verifies the toolchain is
|
|
7
|
+
# present.
|
|
8
|
+
# ============================================================================
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
if command -v go >/dev/null 2>&1; then
|
|
12
|
+
echo "Go coverage tooling is built-in (go version $(go version | awk '{print $3}'))."
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "✗ go toolchain not found — install Go (https://go.dev/dl/) to use the coverage gate." >&2
|
|
17
|
+
exit 1
|