phasegate 0.161.0 → 0.162.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/docs/contracts/requirement-test-matrix.schema.json +1 -1
  3. package/package.json +6 -3
  4. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +91 -23
  5. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +4 -0
  6. package/scripts/harness/agent-integration/infrastructure/adapters/ci-governance-baseline-grandfather-adapter.ts +25 -2
  7. package/scripts/harness/agent-integration/infrastructure/adapters/phase-gate-query-adapter.ts +17 -2
  8. package/scripts/harness/biome-ast-engine/domain/value-objects/import-graph.ts +28 -1
  9. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +1 -0
  10. package/scripts/harness/config-foundation/domain/harness-config.ts +1 -0
  11. package/scripts/harness/config-foundation/domain/value-objects/l3-config.ts +4 -0
  12. package/scripts/harness/config-foundation/domain/value-objects/layers-config.ts +1 -1
  13. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +2 -1
  14. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +2 -1
  15. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +2 -1
  16. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +14 -9
  17. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +14 -9
  18. package/scripts/harness/harness-api/infrastructure/adapters/phase-dependency-model-query-adapter.ts +18 -4
  19. package/scripts/harness/harness-api/infrastructure/adapters/validator-system-execution-adapter.ts +27 -4
  20. package/scripts/harness/installation/application/ports/model-delegation-port.ts +10 -0
  21. package/scripts/harness/installation/application/usecases/run-install.ts +56 -7
  22. package/scripts/harness/installation/application/usecases/run-reconcile.ts +12 -7
  23. package/scripts/harness/installation/composition-root.ts +4 -2
  24. package/scripts/harness/installation/infrastructure/adapters/skill-deployer-model-delegation-adapter.ts +16 -0
  25. package/scripts/harness/installation/presentation/cli/install-handler.ts +2 -1
  26. package/scripts/harness/main.ts +68 -12
  27. package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +9 -7
  28. package/scripts/harness/nyquist-validation/domain/services/matrix-validation-service.ts +27 -2
  29. package/scripts/harness/nyquist-validation/domain/services/requirement-intent-coverage-service.ts +4 -4
  30. package/scripts/harness/nyquist-validation/domain/value-objects/intent-coverage.ts +33 -0
  31. package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +3 -1
  32. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +8 -3
  33. package/scripts/harness/quick-mode/composition-root.ts +3 -0
  34. package/scripts/harness/quick-mode/infrastructure/adapters/validator-system-quick-mode-execution-adapter.ts +18 -0
  35. package/scripts/harness/quick-mode/presentation/handlers/ci-check-quick-mode-handler.ts +51 -5
  36. package/scripts/harness/skill-quality/infrastructure/adapters/l1-biome-validator-adapter.ts +12 -2
  37. package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts +12 -2
  38. package/scripts/harness/traceability-model/application/usecases/apply-work-item-status-usecase.ts +6 -1
  39. package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +28 -9
  40. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +65 -27
  41. package/scripts/harness/validator-system/application/use-cases/run-l4-validators-usecase.ts +6 -7
  42. package/scripts/harness/validator-system/composition-root.ts +8 -1
  43. package/scripts/harness/validator-system/infrastructure/adapters/file-system-security-pattern-scanner-adapter.ts +16 -6
  44. package/scripts/harness/validator-system/infrastructure/adapters/file-system-work-item-reflection-adapter.ts +10 -1
  45. package/scripts/harness/validator-system/infrastructure/adapters/import-graph-source-analysis-adapter.ts +35 -3
  46. package/scripts/harness/validator-system/infrastructure/adapters/nyquist-ac-coverage-policy-adapter.ts +86 -14
  47. package/scripts/harness/validator-system/infrastructure/adapters/phase-dependency-phase-gate-policy-adapter.ts +29 -3
  48. package/templates/.claude/scripts/deny-check.sh +73 -12
@@ -51,9 +51,35 @@ export class PhaseDependencyPhaseGatePolicyAdapter implements PhaseGatePolicyPor
51
51
  };
52
52
  }
53
53
 
54
- return { satisfied: true, violations: [] };
55
- } catch {
56
- return { satisfied: true, violations: [] };
54
+ // Fail-closed: an unexpected exit code means prerequisites could not be confirmed.
55
+ console.error(`[validator-system] phase gate check returned unexpected exit code ${result.exitCode}`);
56
+ return {
57
+ satisfied: false,
58
+ violations: [
59
+ {
60
+ code: { value: 'L2-002', toString: () => 'L2-002' },
61
+ severity: { value: 'error', toString: () => 'error' },
62
+ message: `phase gate check returned unexpected exit code ${result.exitCode}; prerequisites cannot be confirmed`,
63
+ suggestion: 'phase gate prerequisites could not be evaluated; treating as NOT satisfied (fail-closed)',
64
+ },
65
+ ],
66
+ };
67
+ } catch (err) {
68
+ // Fail-closed: if the phase-dependency-model could not be loaded/executed we cannot
69
+ // confirm prerequisites are met, so treat them as NOT satisfied rather than opening the gate.
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ console.error(`[validator-system] phase gate prerequisite check failed to run: ${message}`);
72
+ return {
73
+ satisfied: false,
74
+ violations: [
75
+ {
76
+ code: { value: 'L2-002', toString: () => 'L2-002' },
77
+ severity: { value: 'error', toString: () => 'error' },
78
+ message: `phase gate prerequisite check could not be evaluated: ${message}`,
79
+ suggestion: 'phase gate prerequisites could not be evaluated; treating as NOT satisfied (fail-closed)',
80
+ },
81
+ ],
82
+ };
57
83
  }
58
84
  }
59
85
  }
@@ -4,14 +4,33 @@
4
4
  # Reads JSON from stdin, exits with code 2 to block dangerous commands.
5
5
  # Deny patterns are read from .claude/settings.json permissions.deny.
6
6
 
7
- DEBUG_LOG="/tmp/claude_deny_check_debug.log"
8
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] deny-check.sh started" >> "$DEBUG_LOG"
7
+ # Debug logging is OFF by default to avoid leaking command contents to a
8
+ # world-readable file. Set CLAUDE_DENY_CHECK_DEBUG=1 to enable. When enabled,
9
+ # the log is created with restrictive (owner-only) permissions.
10
+ DEBUG_LOG="${CLAUDE_DENY_CHECK_DEBUG_LOG:-$HOME/.cache/claude/deny-check-debug.log}"
11
+
12
+ debug_log() {
13
+ if [[ "$CLAUDE_DENY_CHECK_DEBUG" == "1" ]]; then
14
+ local dir
15
+ dir=$(dirname "$DEBUG_LOG")
16
+ mkdir -p "$dir" 2>/dev/null || return 0
17
+ # Restrict permissions before writing anything sensitive.
18
+ ( umask 077; touch "$DEBUG_LOG" 2>/dev/null ) || return 0
19
+ chmod 600 "$DEBUG_LOG" 2>/dev/null || true
20
+ printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" >> "$DEBUG_LOG" 2>/dev/null || true
21
+ fi
22
+ }
23
+
24
+ debug_log "deny-check.sh started"
9
25
 
10
26
  INPUT_JSON=$(cat)
11
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] Input JSON: $INPUT_JSON" >> "$DEBUG_LOG"
27
+ debug_log "input received (${#INPUT_JSON} bytes)"
12
28
 
29
+ # Fail CLOSED: without jq we cannot parse the deny policy, so deny the command
30
+ # rather than silently allowing it.
13
31
  if ! command -v jq &> /dev/null; then
14
- exit 0
32
+ echo "Security policy: jq is required to evaluate the deny policy but was not found; command blocked." >&2
33
+ exit 2
15
34
  fi
16
35
 
17
36
  TOOL_NAME=$(echo "$INPUT_JSON" | jq -r '.tool_name // empty')
@@ -43,13 +62,55 @@ if [[ ${#DENY_PATTERNS[@]} -eq 0 ]]; then
43
62
  exit 0
44
63
  fi
45
64
 
46
- for pattern in "${DENY_PATTERNS[@]}"; do
47
- regex_pattern=$(echo "$pattern" | sed 's/\*/.*/')
48
- if echo "$COMMAND" | grep -E "^$regex_pattern" &>/dev/null; then
49
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] BLOCKED: '$COMMAND' matches '$pattern'" >> "$DEBUG_LOG"
50
- echo "Security policy violation: command '$COMMAND' is denied by pattern '$pattern'" >&2
51
- exit 2
52
- fi
53
- done
65
+ # Split a shell command line into individual command segments so that denied
66
+ # commands smuggled behind chaining/grouping/substitution operators are still
67
+ # inspected. Operators handled: ; && || | & newline $( ) ` { } ( )
68
+ # We replace each operator with a newline, then treat each line as a segment.
69
+ split_command_segments() {
70
+ local cmd="$1"
71
+ # Order matters: multi-char operators first.
72
+ cmd=${cmd//&&/$'\n'}
73
+ cmd=${cmd//||/$'\n'}
74
+ cmd=${cmd//|/$'\n'}
75
+ cmd=${cmd//;/$'\n'}
76
+ cmd=${cmd//&/$'\n'}
77
+ cmd=${cmd//\$(/$'\n'}
78
+ cmd=${cmd//\`/$'\n'}
79
+ cmd=${cmd//(/$'\n'}
80
+ cmd=${cmd//)/$'\n'}
81
+ cmd=${cmd//\{/$'\n'}
82
+ cmd=${cmd//\}/$'\n'}
83
+ # Trailing newline ensures the final segment is emitted as a complete line
84
+ # so that `while read` does not drop an unterminated last segment.
85
+ printf '%s\n' "$cmd"
86
+ }
87
+
88
+ # Convert a settings glob pattern to an anchored regex. ALL '*' become '.*'.
89
+ glob_to_regex() {
90
+ printf '%s' "$1" | sed 's/\*/.*/g'
91
+ }
92
+
93
+ check_segment() {
94
+ local segment="$1"
95
+ # Strip leading whitespace so "^pattern" anchors match after operators.
96
+ segment="${segment#"${segment%%[![:space:]]*}"}"
97
+ [[ -z "$segment" ]] && return 0
98
+ for pattern in "${DENY_PATTERNS[@]}"; do
99
+ local regex_pattern
100
+ regex_pattern=$(glob_to_regex "$pattern")
101
+ if printf '%s' "$segment" | grep -E "^$regex_pattern" &>/dev/null; then
102
+ debug_log "BLOCKED segment '$segment' matches '$pattern'"
103
+ echo "Security policy violation: command segment '$segment' is denied by pattern '$pattern'" >&2
104
+ exit 2
105
+ fi
106
+ done
107
+ return 0
108
+ }
109
+
110
+ # Inspect the whole command AND each chained/substituted segment.
111
+ check_segment "$COMMAND"
112
+ while IFS= read -r segment; do
113
+ check_segment "$segment"
114
+ done < <(split_command_segments "$COMMAND")
54
115
 
55
116
  exit 0