@onlooker-community/ecosystem 0.32.2 → 0.33.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.
Files changed (39) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.release-please-manifest.json +9 -9
  3. package/CHANGELOG.md +19 -0
  4. package/package.json +1 -1
  5. package/plugins/archivist/scripts/lib/archivist-config.sh +10 -34
  6. package/plugins/assayer/.claude-plugin/plugin.json +1 -1
  7. package/plugins/assayer/CHANGELOG.md +7 -0
  8. package/plugins/assayer/scripts/lib/assayer-config.sh +39 -62
  9. package/plugins/bursar/.claude-plugin/plugin.json +1 -1
  10. package/plugins/bursar/CHANGELOG.md +12 -0
  11. package/plugins/bursar/scripts/hooks/bursar-session-end.sh +6 -5
  12. package/plugins/bursar/scripts/lib/bursar-config.sh +10 -43
  13. package/plugins/cartographer/scripts/lib/cartographer-config.sh +11 -29
  14. package/plugins/compass/scripts/lib/compass-config.sh +16 -46
  15. package/plugins/counsel/scripts/lib/counsel-config.sh +15 -46
  16. package/plugins/curator/.claude-plugin/plugin.json +1 -1
  17. package/plugins/curator/CHANGELOG.md +7 -0
  18. package/plugins/curator/scripts/lib/curator-config.sh +19 -44
  19. package/plugins/echo/scripts/lib/echo-config.sh +30 -59
  20. package/plugins/governor/scripts/lib/governor-config.sh +11 -41
  21. package/plugins/historian/scripts/lib/historian-config.sh +9 -33
  22. package/plugins/inspector/.claude-plugin/plugin.json +1 -1
  23. package/plugins/inspector/CHANGELOG.md +7 -0
  24. package/plugins/inspector/scripts/lib/inspector-config.sh +39 -63
  25. package/plugins/librarian/.claude-plugin/plugin.json +1 -1
  26. package/plugins/librarian/CHANGELOG.md +7 -0
  27. package/plugins/librarian/scripts/hooks/librarian-session-end.sh +38 -3
  28. package/plugins/librarian/scripts/lib/librarian-config.sh +10 -34
  29. package/plugins/lineage/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lineage/CHANGELOG.md +7 -0
  31. package/plugins/lineage/scripts/lib/lineage-config.sh +17 -53
  32. package/plugins/scribe/.claude-plugin/plugin.json +1 -1
  33. package/plugins/scribe/CHANGELOG.md +7 -0
  34. package/plugins/scribe/scripts/lib/scribe-config.sh +17 -47
  35. package/plugins/tribunal/.claude-plugin/plugin.json +1 -1
  36. package/plugins/tribunal/CHANGELOG.md +7 -0
  37. package/plugins/tribunal/scripts/lib/tribunal-config.sh +25 -63
  38. package/plugins/warden/scripts/lib/warden-config.sh +17 -54
  39. package/scripts/lib/config-loader.sh +138 -0
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env bash
2
2
  # Config resolution for Librarian.
3
3
  #
4
- # Reads three layers, latest wins:
4
+ # Uses the shared config loader from ecosystem. Reads five layers, latest wins:
5
5
  # 1. plugins/librarian/config.json (defaults shipped with the plugin)
6
6
  # 2. ~/.claude/settings.json
7
- # 3. <repo>/.claude/settings.json
7
+ # 3. ~/.claude/settings.local.json (local overrides user)
8
+ # 4. <repo>/.claude/settings.json
9
+ # 5. <repo>/.claude/settings.local.json (local overrides project)
8
10
  #
9
11
  # Exposes:
10
12
  # librarian_config_load <repo_root> # populates _LIBRARIAN_CONFIG (JSON)
@@ -14,48 +16,22 @@
14
16
  # Settings overlay only touches the `librarian.*` subtree of settings.json so
15
17
  # it coexists with other plugins' configuration.
16
18
 
19
+ # shellcheck source=../../../scripts/lib/config-loader.sh
20
+ source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
21
+
17
22
  _LIBRARIAN_CONFIG="{}"
18
23
 
19
24
  librarian_config_load() {
20
25
  local repo_root="${1:-}"
21
- local plugin_root="${CLAUDE_PLUGIN_ROOT:-}"
22
- local home_dir="${HOME:-}"
23
-
24
- local merged="{}"
25
- local file
26
-
27
- file="${plugin_root}/config.json"
28
- if [[ -f "$file" ]]; then
29
- local defaults
30
- defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
31
- merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
32
- || merged="$defaults"
33
- fi
34
-
35
- for file in "${home_dir}/.claude/settings.json" "${repo_root}/.claude/settings.json"; do
36
- [[ -n "$file" && -f "$file" ]] || continue
37
- local overlay
38
- overlay=$(jq '{ librarian: (.librarian // {}) }' "$file" 2>/dev/null) || continue
39
- [[ -z "$overlay" ]] && continue
40
- merged=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
41
- def deepmerge($a; $b):
42
- if ($a|type) == "object" and ($b|type) == "object" then
43
- reduce (($a|keys) + ($b|keys) | unique)[] as $k
44
- ({}; .[$k] = deepmerge($a[$k]; $b[$k]))
45
- elif $b == null then $a
46
- else $b end;
47
- deepmerge($a; $b)
48
- ' 2>/dev/null) || true
49
- done
50
-
51
- _LIBRARIAN_CONFIG="$merged"
26
+ config_load_plugin "librarian" "$repo_root" "_LIBRARIAN_CONFIG"
27
+ return 0
52
28
  }
53
29
 
54
30
  # Read a value from the loaded config. Usage:
55
31
  # librarian_config_get '.librarian.surfacer.max_pending_for_inject'
56
32
  librarian_config_get() {
57
33
  local path="$1"
58
- printf '%s' "$_LIBRARIAN_CONFIG" | jq -r "${path} // empty" 2>/dev/null
34
+ config_get "_LIBRARIAN_CONFIG" "${path}"
59
35
  }
60
36
 
61
37
  # Returns 0 if librarian.auto_promote is true, 1 otherwise.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lineage",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Per-change provenance for the Onlooker ecosystem. Records session/turn metadata plus a secret-redacted, size-capped snippet for every Edit/Write/MultiEdit at PostToolUse, then answers \"why does this line exist?\" via /lineage by joining change records to historian-preserved transcripts. Emits lineage.* events for audit. Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.2](https://github.com/onlooker-community/ecosystem/compare/lineage-v0.2.1...lineage-v0.2.2) (2026-08-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * restore config convenience functions & refactor execution plugins to shared loader ([#128](https://github.com/onlooker-community/ecosystem/issues/128)) ([4b3660c](https://github.com/onlooker-community/ecosystem/commit/4b3660c5a8b234187ec1e71c37b63e6a3d305c98))
9
+
3
10
  ## [0.2.1](https://github.com/onlooker-community/ecosystem/compare/lineage-v0.2.0...lineage-v0.2.1) (2026-08-01)
4
11
 
5
12
 
@@ -1,71 +1,37 @@
1
1
  #!/usr/bin/env bash
2
2
  # Config resolution for lineage.
3
3
  #
4
- # Reads three layers, latest wins:
4
+ # Uses the shared config loader from ecosystem. Reads five layers, latest wins:
5
5
  # 1. plugins/lineage/config.json (defaults shipped with the plugin)
6
6
  # 2. ~/.claude/settings.json
7
- # 3. <repo>/.claude/settings.json
7
+ # 3. ~/.claude/settings.local.json (local overrides user)
8
+ # 4. <repo>/.claude/settings.json
9
+ # 5. <repo>/.claude/settings.local.json (local overrides project)
8
10
  #
9
11
  # Exposes:
10
- # lineage_config_load <repo_root> # populates _LINEAGE_CONFIG (JSON)
11
- # lineage_config_get <jq-path> # echoes string value (empty if unset)
12
- # lineage_config_get_json <jq-path> # echoes JSON value (null if unset)
13
- # lineage_config_max_snippet_chars # echoes the snippet cap (default 4000)
14
- # lineage_config_redact_enabled # 0 unless redact_secrets is false
15
- # lineage_config_prompt_source # echoes the prompt-source strategy
16
- # lineage_config_ignore_globs # echoes ignore globs, one per line
12
+ # lineage_config_load <repo_root> # populates _lineage_CONFIG (JSON)
13
+ # lineage_config_get <jq-path> # echoes string value (empty if unset)
14
+ # lineage_config_get_json <jq-path> # echoes JSON value (null if unset)
17
15
 
18
- _LINEAGE_CONFIG="{}"
16
+ # shellcheck source=../../../scripts/lib/config-loader.sh
17
+ source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
18
+
19
+ _lineage_CONFIG="{}"
19
20
 
20
21
  lineage_config_load() {
21
22
  local repo_root="${1:-}"
22
- local plugin_root="${CLAUDE_PLUGIN_ROOT:-}"
23
- local home_dir="${HOME:-}"
24
-
25
- local merged="{}"
26
- local file
27
-
28
- file="${plugin_root}/config.json"
29
- if [[ -f "$file" ]]; then
30
- local defaults
31
- defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
32
- merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
33
- || merged="$defaults"
34
- fi
35
-
36
- local repo_settings=""
37
- [[ -n "$repo_root" ]] && repo_settings="${repo_root}/.claude/settings.json"
38
-
39
- for file in "${home_dir}/.claude/settings.json" "$repo_settings"; do
40
- [[ -n "$file" && -f "$file" ]] || continue
41
- local overlay
42
- overlay=$(jq '{ lineage: (.lineage // {}) }' "$file" 2>/dev/null) || continue
43
- [[ -z "$overlay" ]] && continue
44
- local attempt
45
- if attempt=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
46
- def deepmerge($a; $b):
47
- if ($a|type) == "object" and ($b|type) == "object" then
48
- reduce (($a|keys) + ($b|keys) | unique)[] as $k
49
- ({}; .[$k] = deepmerge($a[$k]; $b[$k]))
50
- elif $b == null then $a
51
- else $b end;
52
- deepmerge($a; $b)
53
- ' 2>/dev/null) && [[ -n "$attempt" ]]; then
54
- merged="$attempt"
55
- fi
56
- done
57
-
58
- _LINEAGE_CONFIG="$merged"
23
+ config_load_plugin "lineage" "$repo_root" "_lineage_CONFIG"
24
+ return 0
59
25
  }
60
26
 
61
27
  lineage_config_get() {
62
28
  local path="$1"
63
- printf '%s' "$_LINEAGE_CONFIG" | jq -r "${path} // empty" 2>/dev/null
29
+ config_get "_lineage_CONFIG" "${path}"
64
30
  }
65
31
 
66
32
  lineage_config_get_json() {
67
33
  local path="$1"
68
- printf '%s' "$_LINEAGE_CONFIG" | jq -c "${path}" 2>/dev/null
34
+ config_get_json "_lineage_CONFIG" "${path}"
69
35
  }
70
36
 
71
37
  lineage_config_max_snippet_chars() {
@@ -75,10 +41,8 @@ lineage_config_max_snippet_chars() {
75
41
  }
76
42
 
77
43
  lineage_config_redact_enabled() {
78
- # Default on. jq's `//` treats a literal `false` as empty, so read the raw
79
- # JSON value and only disable on an explicit false.
80
44
  local v
81
- v=$(lineage_config_get_json '.lineage.redact_secrets')
45
+ v=$(lineage_config_get '.lineage.redact_secrets')
82
46
  [[ "$v" != "false" ]]
83
47
  }
84
48
 
@@ -89,5 +53,5 @@ lineage_config_prompt_source() {
89
53
  }
90
54
 
91
55
  lineage_config_ignore_globs() {
92
- printf '%s' "$_LINEAGE_CONFIG" | jq -r '.lineage.ignore_globs[]? // empty' 2>/dev/null
56
+ lineage_config_get_json '.lineage.ignore_globs // ["**/.git/**","**/node_modules/**","**/dist/**","**/*.lock"]' | jq -r '.[]'
93
57
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scribe",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Intent documentation from agent activity. Captures why changes were made — problem context, decisions, tradeoffs — and distills them into readable artifacts at session end.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.2](https://github.com/onlooker-community/ecosystem/compare/scribe-v0.4.1...scribe-v0.4.2) (2026-08-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * restore config convenience functions & refactor execution plugins to shared loader ([#128](https://github.com/onlooker-community/ecosystem/issues/128)) ([4b3660c](https://github.com/onlooker-community/ecosystem/commit/4b3660c5a8b234187ec1e71c37b63e6a3d305c98))
9
+
3
10
  ## [0.4.1](https://github.com/onlooker-community/ecosystem/compare/scribe-v0.4.0...scribe-v0.4.1) (2026-08-01)
4
11
 
5
12
 
@@ -1,65 +1,35 @@
1
1
  #!/usr/bin/env bash
2
- # Config resolution for Scribe.
2
+ # Config resolution for scribe.
3
3
  #
4
- # Reads three layers, latest wins:
4
+ # Uses the shared config loader from ecosystem. Reads five layers, latest wins:
5
5
  # 1. plugins/scribe/config.json (defaults shipped with the plugin)
6
6
  # 2. ~/.claude/settings.json
7
- # 3. <repo>/.claude/settings.json
7
+ # 3. ~/.claude/settings.local.json (local overrides user)
8
+ # 4. <repo>/.claude/settings.json
9
+ # 5. <repo>/.claude/settings.local.json (local overrides project)
8
10
  #
9
11
  # Exposes:
10
- # scribe_config_load <repo_root> # populates _SCRIBE_CONFIG (JSON)
11
- # scribe_config_get <jq-path> # echoes string value (empty if unset)
12
- # scribe_config_get_json <jq-path> # echoes JSON value (null if unset)
12
+ # scribe_config_load <repo_root> # populates _scribe_CONFIG (JSON)
13
+ # scribe_config_get <jq-path> # echoes string value (empty if unset)
14
+ # scribe_config_get_json <jq-path> # echoes JSON value (null if unset)
13
15
 
14
- _SCRIBE_CONFIG="{}"
16
+ # shellcheck source=../../../scripts/lib/config-loader.sh
17
+ source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
18
+
19
+ _scribe_CONFIG="{}"
15
20
 
16
21
  scribe_config_load() {
17
22
  local repo_root="${1:-}"
18
- local plugin_root="${CLAUDE_PLUGIN_ROOT:-}"
19
- local home_dir="${HOME:-}"
20
-
21
- local merged="{}"
22
- local file
23
-
24
- file="${plugin_root}/config.json"
25
- if [[ -f "$file" ]]; then
26
- local defaults
27
- defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
28
- merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
29
- || merged="$defaults"
30
- fi
31
-
32
- local repo_settings=""
33
- [[ -n "$repo_root" ]] && repo_settings="${repo_root}/.claude/settings.json"
34
-
35
- for file in "${home_dir}/.claude/settings.json" "$repo_settings"; do
36
- [[ -n "$file" && -f "$file" ]] || continue
37
- local overlay
38
- overlay=$(jq '{ scribe: (.scribe // {}) }' "$file" 2>/dev/null) || continue
39
- [[ -z "$overlay" ]] && continue
40
- local attempt
41
- if attempt=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
42
- def deepmerge($a; $b):
43
- if ($a|type) == "object" and ($b|type) == "object" then
44
- reduce (($a|keys) + ($b|keys) | unique)[] as $k
45
- ({}; .[$k] = deepmerge($a[$k]; $b[$k]))
46
- elif $b == null then $a
47
- else $b end;
48
- deepmerge($a; $b)
49
- ' 2>/dev/null) && [[ -n "$attempt" ]]; then
50
- merged="$attempt"
51
- fi
52
- done
53
-
54
- _SCRIBE_CONFIG="$merged"
23
+ config_load_plugin "scribe" "$repo_root" "_scribe_CONFIG"
24
+ return 0
55
25
  }
56
26
 
57
27
  scribe_config_get() {
58
28
  local path="$1"
59
- printf '%s' "$_SCRIBE_CONFIG" | jq -r "${path} // empty" 2>/dev/null
29
+ config_get "_scribe_CONFIG" "${path}"
60
30
  }
61
31
 
62
32
  scribe_config_get_json() {
63
33
  local path="$1"
64
- printf '%s' "$_SCRIBE_CONFIG" | jq -c "${path}" 2>/dev/null
65
- }
34
+ config_get_json "_scribe_CONFIG" "${path}"
35
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tribunal",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Multi-agent execution with LLM-as-a-Judge quality gates. An Actor performs work; a jury of typed Judges scores it against a project-overridable rubric; a Meta-Judge reviews the jury for bias; the gate decides accept, retry, or exhaust. Grounded in LLM-as-a-Judge (Zheng et al. 2023) and LLM-as-a-Meta-Judge (Wu et al. 2024). Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.2](https://github.com/onlooker-community/ecosystem/compare/tribunal-v1.1.1...tribunal-v1.1.2) (2026-08-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * restore config convenience functions & refactor execution plugins to shared loader ([#128](https://github.com/onlooker-community/ecosystem/issues/128)) ([4b3660c](https://github.com/onlooker-community/ecosystem/commit/4b3660c5a8b234187ec1e71c37b63e6a3d305c98))
9
+
3
10
  ## [1.1.1](https://github.com/onlooker-community/ecosystem/compare/tribunal-v1.1.0...tribunal-v1.1.1) (2026-08-01)
4
11
 
5
12
 
@@ -1,93 +1,55 @@
1
1
  #!/usr/bin/env bash
2
- # Config resolution for Tribunal.
2
+ # Config resolution for tribunal.
3
3
  #
4
- # Reads three layers, latest wins:
4
+ # Uses the shared config loader from ecosystem. Reads five layers, latest wins:
5
5
  # 1. plugins/tribunal/config.json (defaults shipped with the plugin)
6
6
  # 2. ~/.claude/settings.json
7
- # 3. <repo>/.claude/settings.json
7
+ # 3. ~/.claude/settings.local.json (local overrides user)
8
+ # 4. <repo>/.claude/settings.json
9
+ # 5. <repo>/.claude/settings.local.json (local overrides project)
8
10
  #
9
11
  # Exposes:
10
- # tribunal_config_load <repo_root> # populates _TRIBUNAL_CONFIG (JSON)
11
- # tribunal_config_get <jq-path> # echoes string value (empty if unset)
12
- # tribunal_config_get_json <jq-path> # echoes JSON value (null if unset)
13
- # tribunal_config_stop_hook_enabled # 0 if tribunal.stop_hook.enabled is true
14
- # tribunal_config_judge_model <judge_type>
15
- # # echoes per-judge-type model override,
16
- # # falling back to tribunal.judges.model
17
- #
18
- # Settings overlay only touches the `tribunal.*` subtree so this plugin coexists
19
- # with other plugins' configuration.
12
+ # tribunal_config_load <repo_root> # populates _tribunal_CONFIG (JSON)
13
+ # tribunal_config_get <jq-path> # echoes string value (empty if unset)
14
+ # tribunal_config_get_json <jq-path> # echoes JSON value (null if unset)
15
+
16
+ # shellcheck source=../../../scripts/lib/config-loader.sh
17
+ source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
20
18
 
21
19
  _TRIBUNAL_CONFIG="{}"
22
20
 
23
21
  tribunal_config_load() {
24
22
  local repo_root="${1:-}"
25
- local plugin_root="${CLAUDE_PLUGIN_ROOT:-}"
26
- local home_dir="${HOME:-}"
27
-
28
- local merged="{}"
29
- local file
30
-
31
- file="${plugin_root}/config.json"
32
- if [[ -f "$file" ]]; then
33
- local defaults
34
- defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
35
- merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
36
- || merged="$defaults"
37
- fi
38
-
39
- for file in "${home_dir}/.claude/settings.json" "${repo_root}/.claude/settings.json"; do
40
- [[ -n "$file" && -f "$file" ]] || continue
41
- local overlay
42
- overlay=$(jq '{ tribunal: (.tribunal // {}) }' "$file" 2>/dev/null) || continue
43
- [[ -z "$overlay" ]] && continue
44
- local attempt
45
- if attempt=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
46
- def deepmerge($a; $b):
47
- if ($a|type) == "object" and ($b|type) == "object" then
48
- reduce (($a|keys) + ($b|keys) | unique)[] as $k
49
- ({}; .[$k] = deepmerge($a[$k]; $b[$k]))
50
- elif $b == null then $a
51
- else $b end;
52
- deepmerge($a; $b)
53
- ' 2>/dev/null) && [[ -n "$attempt" ]]; then
54
- merged="$attempt"
55
- fi
56
- done
57
-
58
- _TRIBUNAL_CONFIG="$merged"
23
+ config_load_plugin "tribunal" "$repo_root" "_TRIBUNAL_CONFIG"
24
+ return 0
59
25
  }
60
26
 
61
- # Read a string value from the loaded config.
62
- # Usage: tribunal_config_get '.tribunal.session.gate_policy'
63
27
  tribunal_config_get() {
64
28
  local path="$1"
65
- printf '%s' "$_TRIBUNAL_CONFIG" | jq -r "${path} // empty" 2>/dev/null
29
+ config_get "_TRIBUNAL_CONFIG" "${path}"
66
30
  }
67
31
 
68
- # Read a JSON value (arrays, objects, numbers) from the loaded config.
69
- # Usage: tribunal_config_get_json '.tribunal.session.judge_types'
70
32
  tribunal_config_get_json() {
71
33
  local path="$1"
72
- printf '%s' "$_TRIBUNAL_CONFIG" | jq -c "${path}" 2>/dev/null
34
+ config_get_json "_TRIBUNAL_CONFIG" "${path}"
73
35
  }
74
36
 
75
- # Returns 0 if tribunal.stop_hook.enabled is true. Default is false.
76
37
  tribunal_config_stop_hook_enabled() {
77
38
  local v
78
39
  v=$(tribunal_config_get '.tribunal.stop_hook.enabled')
79
40
  [[ "$v" == "true" ]]
80
41
  }
81
42
 
82
- # Resolve the model id for a given judge_type.
83
- # Precedence: tribunal.judges.<type>.model > tribunal.judges.model
84
43
  tribunal_config_judge_model() {
85
- local judge_type="$1"
86
- local override
87
- override=$(tribunal_config_get ".tribunal.judges.\"${judge_type}\".model")
88
- if [[ -n "$override" ]]; then
89
- printf '%s' "$override"
90
- return 0
44
+ local judge_type="${1:-}"
45
+ local v
46
+ if [[ -n "$judge_type" ]]; then
47
+ v=$(tribunal_config_get ".tribunal.judges.\"$judge_type\".model")
48
+ if [[ -n "$v" ]]; then
49
+ printf '%s' "$v"
50
+ return 0
51
+ fi
91
52
  fi
92
- tribunal_config_get '.tribunal.judges.model'
53
+ v=$(tribunal_config_get '.tribunal.judges.model')
54
+ printf '%s' "${v:-claude-opus-4-7}"
93
55
  }
@@ -1,72 +1,35 @@
1
1
  #!/usr/bin/env bash
2
- # Config resolution for Warden.
2
+ # Config resolution for warden.
3
3
  #
4
- # Reads three layers, latest wins:
4
+ # Uses the shared config loader from ecosystem. Reads five layers, latest wins:
5
5
  # 1. plugins/warden/config.json (defaults shipped with the plugin)
6
6
  # 2. ~/.claude/settings.json
7
- # 3. <repo>/.claude/settings.json
7
+ # 3. ~/.claude/settings.local.json (local overrides user)
8
+ # 4. <repo>/.claude/settings.json
9
+ # 5. <repo>/.claude/settings.local.json (local overrides project)
8
10
  #
9
11
  # Exposes:
10
- # warden_config_load <repo_root> # populates _WARDEN_CONFIG (JSON)
11
- # warden_config_get <jq-path> # echoes string value (empty if unset)
12
- # warden_config_get_json <jq-path> # echoes JSON value (null if unset)
12
+ # warden_config_load <repo_root> # populates _warden_CONFIG (JSON)
13
+ # warden_config_get <jq-path> # echoes string value (empty if unset)
14
+ # warden_config_get_json <jq-path> # echoes JSON value (null if unset)
13
15
 
14
- _WARDEN_CONFIG="{}"
16
+ # shellcheck source=../../../scripts/lib/config-loader.sh
17
+ source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
18
+
19
+ _warden_CONFIG="{}"
15
20
 
16
21
  warden_config_load() {
17
22
  local repo_root="${1:-}"
18
- local plugin_root="${CLAUDE_PLUGIN_ROOT:-}"
19
- local home_dir="${HOME:-}"
20
-
21
- local merged="{}"
22
- local file
23
-
24
- file="${plugin_root}/config.json"
25
- if [[ -f "$file" ]]; then
26
- local defaults
27
- defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
28
- merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
29
- || merged="$defaults"
30
- fi
31
-
32
- local repo_settings=""
33
- [[ -n "$repo_root" ]] && repo_settings="${repo_root}/.claude/settings.json"
34
-
35
- for file in "${home_dir}/.claude/settings.json" "$repo_settings"; do
36
- [[ -n "$file" && -f "$file" ]] || continue
37
- local overlay
38
- overlay=$(jq '{ warden: (.warden // {}) }' "$file" 2>/dev/null) || continue
39
- [[ -z "$overlay" ]] && continue
40
- local attempt
41
- if attempt=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
42
- def deepmerge($a; $b):
43
- if ($a|type) == "object" and ($b|type) == "object" then
44
- reduce (($a|keys) + ($b|keys) | unique)[] as $k
45
- ({}; .[$k] = deepmerge($a[$k]; $b[$k]))
46
- elif $b == null then $a
47
- else $b end;
48
- deepmerge($a; $b)
49
- ' 2>/dev/null) && [[ -n "$attempt" ]]; then
50
- merged="$attempt"
51
- fi
52
- done
53
-
54
- _WARDEN_CONFIG="$merged"
23
+ config_load_plugin "warden" "$repo_root" "_warden_CONFIG"
24
+ return 0
55
25
  }
56
26
 
57
27
  warden_config_get() {
58
28
  local path="$1"
59
- # NB: do NOT use `${path} // empty` — jq's `//` treats `false` and `0` as
60
- # empty, so a `false` boolean would read back as "" and a `${v:-true}`
61
- # default would silently flip it to true. Emit the raw value and map only a
62
- # literal JSON null to the empty string.
63
- local v
64
- v=$(printf '%s' "$_WARDEN_CONFIG" | jq -r "${path}" 2>/dev/null) || return 1
65
- [[ "$v" == "null" ]] && v=""
66
- printf '%s' "$v"
29
+ config_get "_warden_CONFIG" "${path}"
67
30
  }
68
31
 
69
32
  warden_config_get_json() {
70
33
  local path="$1"
71
- printf '%s' "$_WARDEN_CONFIG" | jq -c "${path}" 2>/dev/null
72
- }
34
+ config_get_json "_warden_CONFIG" "${path}"
35
+ }