@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.
- package/.claude-plugin/plugin.json +1 -1
- package/.release-please-manifest.json +9 -9
- package/CHANGELOG.md +19 -0
- package/package.json +1 -1
- package/plugins/archivist/scripts/lib/archivist-config.sh +10 -34
- package/plugins/assayer/.claude-plugin/plugin.json +1 -1
- package/plugins/assayer/CHANGELOG.md +7 -0
- package/plugins/assayer/scripts/lib/assayer-config.sh +39 -62
- package/plugins/bursar/.claude-plugin/plugin.json +1 -1
- package/plugins/bursar/CHANGELOG.md +12 -0
- package/plugins/bursar/scripts/hooks/bursar-session-end.sh +6 -5
- package/plugins/bursar/scripts/lib/bursar-config.sh +10 -43
- package/plugins/cartographer/scripts/lib/cartographer-config.sh +11 -29
- package/plugins/compass/scripts/lib/compass-config.sh +16 -46
- package/plugins/counsel/scripts/lib/counsel-config.sh +15 -46
- package/plugins/curator/.claude-plugin/plugin.json +1 -1
- package/plugins/curator/CHANGELOG.md +7 -0
- package/plugins/curator/scripts/lib/curator-config.sh +19 -44
- package/plugins/echo/scripts/lib/echo-config.sh +30 -59
- package/plugins/governor/scripts/lib/governor-config.sh +11 -41
- package/plugins/historian/scripts/lib/historian-config.sh +9 -33
- package/plugins/inspector/.claude-plugin/plugin.json +1 -1
- package/plugins/inspector/CHANGELOG.md +7 -0
- package/plugins/inspector/scripts/lib/inspector-config.sh +39 -63
- package/plugins/librarian/.claude-plugin/plugin.json +1 -1
- package/plugins/librarian/CHANGELOG.md +7 -0
- package/plugins/librarian/scripts/hooks/librarian-session-end.sh +38 -3
- package/plugins/librarian/scripts/lib/librarian-config.sh +10 -34
- package/plugins/lineage/.claude-plugin/plugin.json +1 -1
- package/plugins/lineage/CHANGELOG.md +7 -0
- package/plugins/lineage/scripts/lib/lineage-config.sh +17 -53
- package/plugins/scribe/.claude-plugin/plugin.json +1 -1
- package/plugins/scribe/CHANGELOG.md +7 -0
- package/plugins/scribe/scripts/lib/scribe-config.sh +17 -47
- package/plugins/tribunal/.claude-plugin/plugin.json +1 -1
- package/plugins/tribunal/CHANGELOG.md +7 -0
- package/plugins/tribunal/scripts/lib/tribunal-config.sh +25 -63
- package/plugins/warden/scripts/lib/warden-config.sh +17 -54
- package/scripts/lib/config-loader.sh +138 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ecosystem",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "Observability substrate for Claude Code. Provides the shared $ONLOOKER_DIR storage root (default $HOME/.onlooker), canonical schema-validated event emission, session and tool tracking hooks, and prompt rules. Required by all other Onlooker plugins.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Onlooker Community",
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
".": "0.
|
|
2
|
+
".": "0.33.1",
|
|
3
3
|
"plugins/archivist": "0.3.1",
|
|
4
|
-
"plugins/tribunal": "1.1.
|
|
4
|
+
"plugins/tribunal": "1.1.2",
|
|
5
5
|
"plugins/echo": "0.3.1",
|
|
6
6
|
"plugins/cartographer": "0.3.1",
|
|
7
7
|
"plugins/governor": "0.3.2",
|
|
8
8
|
"plugins/compass": "0.4.1",
|
|
9
|
-
"plugins/scribe": "0.4.
|
|
9
|
+
"plugins/scribe": "0.4.2",
|
|
10
10
|
"plugins/counsel": "0.5.1",
|
|
11
11
|
"plugins/warden": "0.3.1",
|
|
12
|
-
"plugins/librarian": "0.6.
|
|
13
|
-
"plugins/curator": "0.2.
|
|
12
|
+
"plugins/librarian": "0.6.1",
|
|
13
|
+
"plugins/curator": "0.2.2",
|
|
14
14
|
"plugins/historian": "0.3.2",
|
|
15
|
-
"plugins/assayer": "1.1.
|
|
16
|
-
"plugins/bursar": "0.
|
|
17
|
-
"plugins/lineage": "0.2.
|
|
18
|
-
"plugins/inspector": "0.3.
|
|
15
|
+
"plugins/assayer": "1.1.2",
|
|
16
|
+
"plugins/bursar": "0.3.0",
|
|
17
|
+
"plugins/lineage": "0.2.2",
|
|
18
|
+
"plugins/inspector": "0.3.2"
|
|
19
19
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.33.1](https://github.com/onlooker-community/ecosystem/compare/ecosystem-v0.33.0...ecosystem-v0.33.1) (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
|
+
|
|
10
|
+
## [0.33.0](https://github.com/onlooker-community/ecosystem/compare/ecosystem-v0.32.2...ecosystem-v0.33.0) (2026-08-02)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **config:** add shared config loader supporting all five settings layers :sparkles: ([#123](https://github.com/onlooker-community/ecosystem/issues/123)) ([c048b76](https://github.com/onlooker-community/ecosystem/commit/c048b76bee2b39abeb7f1af77181191dd48f9cf5))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **hooks:** prevent SessionEnd timeouts causing breadcrumb accumulation ([#121](https://github.com/onlooker-community/ecosystem/issues/121)) ([3c7a409](https://github.com/onlooker-community/ecosystem/commit/3c7a40937aa3ea8c1db85dd0bb3fcc22589bbb49))
|
|
21
|
+
|
|
3
22
|
## [0.32.2](https://github.com/onlooker-community/ecosystem/compare/ecosystem-v0.32.1...ecosystem-v0.32.2) (2026-08-02)
|
|
4
23
|
|
|
5
24
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Config resolution for Archivist.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/archivist/config.json (defaults shipped with the plugin)
|
|
6
6
|
# 2. ~/.claude/settings.json
|
|
7
|
-
# 3.
|
|
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
|
# archivist_config_load <repo_root> # populates _ARCHIVIST_CONFIG (JSON)
|
|
@@ -13,46 +15,20 @@
|
|
|
13
15
|
# Settings overlay only touches the `archivist.*` subtree of settings.json so it
|
|
14
16
|
# coexists with other plugins' configuration.
|
|
15
17
|
|
|
18
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
19
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
20
|
+
|
|
16
21
|
_ARCHIVIST_CONFIG="{}"
|
|
17
22
|
|
|
18
23
|
archivist_config_load() {
|
|
19
24
|
local repo_root="${1:-}"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
local merged="{}"
|
|
24
|
-
local file
|
|
25
|
-
|
|
26
|
-
file="${plugin_root}/config.json"
|
|
27
|
-
if [[ -f "$file" ]]; then
|
|
28
|
-
local defaults
|
|
29
|
-
defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
|
|
30
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
|
|
31
|
-
|| merged="$defaults"
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
for file in "${home_dir}/.claude/settings.json" "${repo_root}/.claude/settings.json"; do
|
|
35
|
-
[[ -n "$file" && -f "$file" ]] || continue
|
|
36
|
-
local overlay
|
|
37
|
-
overlay=$(jq '{ archivist: (.archivist // {}) }' "$file" 2>/dev/null) || continue
|
|
38
|
-
[[ -z "$overlay" ]] && continue
|
|
39
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
|
|
40
|
-
def deepmerge($a; $b):
|
|
41
|
-
if ($a|type) == "object" and ($b|type) == "object" then
|
|
42
|
-
reduce (($a|keys) + ($b|keys) | unique)[] as $k
|
|
43
|
-
({}; .[$k] = deepmerge($a[$k]; $b[$k]))
|
|
44
|
-
elif $b == null then $a
|
|
45
|
-
else $b end;
|
|
46
|
-
deepmerge($a; $b)
|
|
47
|
-
' 2>/dev/null) || true
|
|
48
|
-
done
|
|
49
|
-
|
|
50
|
-
_ARCHIVIST_CONFIG="$merged"
|
|
25
|
+
config_load_plugin "archivist" "$repo_root" "_ARCHIVIST_CONFIG"
|
|
26
|
+
return 0
|
|
51
27
|
}
|
|
52
28
|
|
|
53
29
|
# Read a value from the loaded config. Usage:
|
|
54
30
|
# archivist_config_get '.archivist.injection.max_items'
|
|
55
31
|
archivist_config_get() {
|
|
56
32
|
local path="$1"
|
|
57
|
-
|
|
33
|
+
config_get "_ARCHIVIST_CONFIG" "${path}"
|
|
58
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assayer",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Claim verification. At session end, parses the agent's final message for testable claims (\"I ran the tests, they pass\", \"the build is green\") and checks each against the actual command results in the session transcript, classifying it corroborated, contradicted, or unverifiable. Catches lying-without-malice. Advisory by default. 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/assayer-v1.1.1...assayer-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/assayer-v1.1.0...assayer-v1.1.1) (2026-08-01)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,82 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Config
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
# Config resolution for assayer.
|
|
3
|
+
#
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
|
+
# 1. plugins/assayer/config.json (defaults shipped with the plugin)
|
|
6
|
+
# 2. ~/.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)
|
|
10
|
+
#
|
|
11
|
+
# Exposes:
|
|
12
|
+
# assayer_config_load <repo_root> # populates _assayer_CONFIG (JSON)
|
|
13
|
+
# assayer_config_get <jq-path> # echoes string value (empty if unset)
|
|
14
|
+
# assayer_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"
|
|
18
|
+
|
|
19
|
+
_assayer_CONFIG="{}"
|
|
8
20
|
|
|
9
21
|
assayer_config_load() {
|
|
10
22
|
local repo_root="${1:-}"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
local plugin_config="${CLAUDE_PLUGIN_ROOT:-}/config.json"
|
|
14
|
-
if [[ -f "$plugin_config" ]]; then
|
|
15
|
-
_ASSAYER_PLUGIN_CONFIG_JSON=$(cat "$plugin_config" 2>/dev/null) || _ASSAYER_PLUGIN_CONFIG_JSON=""
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
_ASSAYER_CONFIG_JSON=""
|
|
19
|
-
if [[ -n "$repo_root" ]]; then
|
|
20
|
-
local settings_file="${repo_root}/.claude/settings.json"
|
|
21
|
-
if [[ -f "$settings_file" ]]; then
|
|
22
|
-
local settings
|
|
23
|
-
settings=$(cat "$settings_file" 2>/dev/null) || settings=""
|
|
24
|
-
local block
|
|
25
|
-
block=$(printf '%s' "$settings" | jq -c '.assayer // empty' 2>/dev/null) || block=""
|
|
26
|
-
[[ -n "$block" ]] && _ASSAYER_CONFIG_JSON="$block"
|
|
27
|
-
fi
|
|
28
|
-
fi
|
|
23
|
+
config_load_plugin "assayer" "$repo_root" "_assayer_CONFIG"
|
|
24
|
+
return 0
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
# Get a single scalar value. Checks settings.json first, then plugin config.json.
|
|
32
27
|
assayer_config_get() {
|
|
33
|
-
local
|
|
34
|
-
|
|
35
|
-
if [[ -n "$_ASSAYER_CONFIG_JSON" ]]; then
|
|
36
|
-
local val
|
|
37
|
-
val=$(printf '%s' "$_ASSAYER_CONFIG_JSON" | jq -r "${key} // empty" 2>/dev/null) || val=""
|
|
38
|
-
[[ -n "$val" && "$val" != "null" ]] && {
|
|
39
|
-
printf '%s' "$val"
|
|
40
|
-
return 0
|
|
41
|
-
}
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
if [[ -n "$_ASSAYER_PLUGIN_CONFIG_JSON" ]]; then
|
|
45
|
-
local val
|
|
46
|
-
val=$(printf '%s' "$_ASSAYER_PLUGIN_CONFIG_JSON" | jq -r ".assayer${key} // empty" 2>/dev/null) || val=""
|
|
47
|
-
[[ -n "$val" && "$val" != "null" ]] && {
|
|
48
|
-
printf '%s' "$val"
|
|
49
|
-
return 0
|
|
50
|
-
}
|
|
51
|
-
fi
|
|
28
|
+
local path="$1"
|
|
29
|
+
config_get "_assayer_CONFIG" "${path}"
|
|
52
30
|
}
|
|
53
31
|
|
|
54
|
-
|
|
55
|
-
local
|
|
56
|
-
|
|
57
|
-
printf '%s' "${val:-claude-haiku-4-5-20251001}"
|
|
32
|
+
assayer_config_get_json() {
|
|
33
|
+
local path="$1"
|
|
34
|
+
config_get_json "_assayer_CONFIG" "${path}"
|
|
58
35
|
}
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
local
|
|
62
|
-
|
|
63
|
-
printf '%s' "${
|
|
37
|
+
assayer_config_model() {
|
|
38
|
+
local v
|
|
39
|
+
v=$(assayer_config_get '.assayer.evaluation.model')
|
|
40
|
+
printf '%s' "${v:-claude-haiku-4-5-20251001}"
|
|
64
41
|
}
|
|
65
42
|
|
|
66
43
|
assayer_config_max_claims() {
|
|
67
|
-
local
|
|
68
|
-
|
|
69
|
-
printf '%s' "${
|
|
44
|
+
local v
|
|
45
|
+
v=$(assayer_config_get '.assayer.max_claims')
|
|
46
|
+
printf '%s' "${v:-12}"
|
|
70
47
|
}
|
|
71
48
|
|
|
72
49
|
assayer_config_min_confidence() {
|
|
73
|
-
local
|
|
74
|
-
|
|
75
|
-
printf '%s' "${
|
|
50
|
+
local v
|
|
51
|
+
v=$(assayer_config_get '.assayer.min_confidence')
|
|
52
|
+
printf '%s' "${v:-0.5}"
|
|
76
53
|
}
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
local
|
|
80
|
-
|
|
81
|
-
printf '%s' "${
|
|
55
|
+
assayer_config_timeout() {
|
|
56
|
+
local v
|
|
57
|
+
v=$(assayer_config_get '.assayer.evaluation.timeout_seconds')
|
|
58
|
+
printf '%s' "${v:-60}"
|
|
82
59
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bursar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Multi-session, per-project budget accounting for the Onlooker ecosystem. Rolls each session's spend into a per-project ledger on SessionEnd and surfaces \"this project burned $X this week\" at SessionStart. Where governor regulates a single session, bursar is the cross-session rollup: it reads governor.session.complete off the shared event bus and emits bursar.* events for audit. Named for the officer who keeps the accounts. Builds on the Onlooker ecosystem plugin.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Onlooker Community",
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0](https://github.com/onlooker-community/ecosystem/compare/bursar-v0.2.2...bursar-v0.3.0) (2026-08-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **config:** add shared config loader supporting all five settings layers :sparkles: ([#123](https://github.com/onlooker-community/ecosystem/issues/123)) ([c048b76](https://github.com/onlooker-community/ecosystem/commit/c048b76bee2b39abeb7f1af77181191dd48f9cf5))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **hooks:** prevent SessionEnd timeouts causing breadcrumb accumulation ([#121](https://github.com/onlooker-community/ecosystem/issues/121)) ([3c7a409](https://github.com/onlooker-community/ecosystem/commit/3c7a40937aa3ea8c1db85dd0bb3fcc22589bbb49))
|
|
14
|
+
|
|
3
15
|
## [0.2.2](https://github.com/onlooker-community/ecosystem/compare/bursar-v0.2.1...bursar-v0.2.2) (2026-08-02)
|
|
4
16
|
|
|
5
17
|
|
|
@@ -148,12 +148,13 @@ MODEL=""
|
|
|
148
148
|
# must keep the breadcrumb so the session→project attribution survives for a
|
|
149
149
|
# later attempt rather than being lost behind a false "recorded" event.
|
|
150
150
|
#
|
|
151
|
-
# Use a
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
151
|
+
# Use a short lock timeout (1s) to ensure the hook completes within the CLI's
|
|
152
|
+
# 1.5s SessionEnd budget. If the lock is contended, fail fast and retain the
|
|
153
|
+
# breadcrumb for retry on a future session. Retries on subsequent SessionStart
|
|
154
|
+
# will eventually succeed when contention subsides; this prevents the hook from
|
|
155
|
+
# being cancelled mid-execution by the CLI timeout.
|
|
155
156
|
if [[ -n "$RECORD" ]]; then
|
|
156
|
-
if bursar_ledger_record "$PROJECT_KEY" "$RECORD"
|
|
157
|
+
if bursar_ledger_record "$PROJECT_KEY" "$RECORD" 1; then
|
|
157
158
|
[[ -n "$EV" ]] && bursar_emit_event "bursar.session.recorded" "$EV" "$SESSION_ID" || true
|
|
158
159
|
rm -f "$BREADCRUMB" 2>/dev/null || true
|
|
159
160
|
else
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Config resolution for bursar.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/bursar/config.json (defaults shipped with the plugin)
|
|
6
6
|
# 2. ~/.claude/settings.json
|
|
7
|
-
# 3.
|
|
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
|
# bursar_config_load <repo_root> # populates _BURSAR_CONFIG (JSON)
|
|
@@ -14,60 +16,25 @@
|
|
|
14
16
|
# bursar_config_surface_enabled # 0 if bursar.surface_at_session_start is true
|
|
15
17
|
# bursar_config_week_start # echoes "monday" or "sunday"
|
|
16
18
|
|
|
19
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
20
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
21
|
+
|
|
17
22
|
_BURSAR_CONFIG="{}"
|
|
18
23
|
|
|
19
24
|
bursar_config_load() {
|
|
20
25
|
local repo_root="${1:-}"
|
|
21
|
-
|
|
22
|
-
local home_dir="${HOME:-}"
|
|
23
|
-
|
|
24
|
-
# Read each layer's raw text with the no-fork `$(<file)` builtin (NOT `cat`),
|
|
25
|
-
# then deep-merge all three layers in a SINGLE jq invocation. The dominant
|
|
26
|
-
# cost in the SessionEnd hook is jq process startup, not the merge itself, so
|
|
27
|
-
# this collapses what was one-jq-per-file (up to 6 forks) down to one.
|
|
28
|
-
local default_txt="" home_txt="" repo_txt=""
|
|
29
|
-
local default_file="${plugin_root}/config.json"
|
|
30
|
-
local home_file="${home_dir}/.claude/settings.json"
|
|
31
|
-
local repo_file=""
|
|
32
|
-
[[ -n "$repo_root" ]] && repo_file="${repo_root}/.claude/settings.json"
|
|
33
|
-
|
|
34
|
-
[[ -f "$default_file" ]] && default_txt="$(<"$default_file")"
|
|
35
|
-
[[ -f "$home_file" ]] && home_txt="$(<"$home_file")"
|
|
36
|
-
[[ -n "$repo_file" && -f "$repo_file" ]] && repo_txt="$(<"$repo_file")"
|
|
37
|
-
|
|
38
|
-
# Precedence (latest wins): defaults < home settings < repo settings. The
|
|
39
|
-
# defaults file is merged whole; settings files contribute only their .bursar
|
|
40
|
-
# key. `fromjson? // {}` parses each layer defensively — a missing or malformed
|
|
41
|
-
# file degrades to {} rather than aborting the merge (matches the prior
|
|
42
|
-
# per-file fallback).
|
|
43
|
-
_BURSAR_CONFIG=$(jq -n \
|
|
44
|
-
--arg d "$default_txt" \
|
|
45
|
-
--arg h "$home_txt" \
|
|
46
|
-
--arg r "$repo_txt" \
|
|
47
|
-
'
|
|
48
|
-
def deepmerge($a; $b):
|
|
49
|
-
if ($a|type) == "object" and ($b|type) == "object" then
|
|
50
|
-
reduce (($a|keys) + ($b|keys) | unique)[] as $k
|
|
51
|
-
({}; .[$k] = deepmerge($a[$k]; $b[$k]))
|
|
52
|
-
elif $b == null then $a
|
|
53
|
-
else $b end;
|
|
54
|
-
($d | fromjson? // {}) as $defaults
|
|
55
|
-
| (($h | fromjson? // {}) | {bursar: (.bursar // {})}) as $home
|
|
56
|
-
| (($r | fromjson? // {}) | {bursar: (.bursar // {})}) as $repo
|
|
57
|
-
| deepmerge(deepmerge($defaults; $home); $repo)
|
|
58
|
-
' 2>/dev/null) || _BURSAR_CONFIG="{}"
|
|
59
|
-
[[ -z "$_BURSAR_CONFIG" ]] && _BURSAR_CONFIG="{}"
|
|
26
|
+
config_load_plugin "bursar" "$repo_root" "_BURSAR_CONFIG"
|
|
60
27
|
return 0
|
|
61
28
|
}
|
|
62
29
|
|
|
63
30
|
bursar_config_get() {
|
|
64
31
|
local path="$1"
|
|
65
|
-
|
|
32
|
+
config_get "_BURSAR_CONFIG" "${path}"
|
|
66
33
|
}
|
|
67
34
|
|
|
68
35
|
bursar_config_get_json() {
|
|
69
36
|
local path="$1"
|
|
70
|
-
|
|
37
|
+
config_get_json "_BURSAR_CONFIG" "${path}"
|
|
71
38
|
}
|
|
72
39
|
|
|
73
40
|
bursar_config_surface_enabled() {
|
|
@@ -1,54 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# cartographer-config.sh — load and query Cartographer configuration.
|
|
3
3
|
#
|
|
4
|
-
# Merges
|
|
4
|
+
# Uses the shared config loader from ecosystem. Merges five layers in precedence order:
|
|
5
5
|
# 1. plugins/cartographer/config.json (plugin defaults)
|
|
6
6
|
# 2. ~/.claude/settings.json (.cartographer subtree)
|
|
7
|
-
# 3.
|
|
7
|
+
# 3. ~/.claude/settings.local.json (.cartographer subtree, local overrides user)
|
|
8
|
+
# 4. <repo>/.claude/settings.json (.cartographer subtree)
|
|
9
|
+
# 5. <repo>/.claude/settings.local.json (.cartographer subtree, local overrides project)
|
|
8
10
|
#
|
|
9
11
|
# Usage:
|
|
10
12
|
# cartographer_config_load <repo_root>
|
|
11
13
|
# cartographer_config_get_json ".cartographer.exclude_paths"
|
|
12
14
|
|
|
15
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
16
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
17
|
+
|
|
13
18
|
_CARTOGRAPHER_CONFIG=""
|
|
14
|
-
_CARTOGRAPHER_PLUGIN_CONFIG=""
|
|
15
19
|
|
|
16
20
|
cartographer_config_load() {
|
|
17
21
|
local repo_root="${1:-}"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
local plugin_config="$plugin_dir/config.json"
|
|
21
|
-
|
|
22
|
-
_CARTOGRAPHER_PLUGIN_CONFIG="{}"
|
|
23
|
-
if [[ -f "$plugin_config" ]]; then
|
|
24
|
-
_CARTOGRAPHER_PLUGIN_CONFIG=$(cat "$plugin_config")
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
local home_settings="{}"
|
|
28
|
-
if [[ -f "$HOME/.claude/settings.json" ]]; then
|
|
29
|
-
home_settings=$(cat "$HOME/.claude/settings.json")
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
local repo_settings="{}"
|
|
33
|
-
if [[ -n "$repo_root" && -f "$repo_root/.claude/settings.json" ]]; then
|
|
34
|
-
repo_settings=$(cat "$repo_root/.claude/settings.json")
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
_CARTOGRAPHER_CONFIG=$(jq -n \
|
|
38
|
-
--argjson plugin "$_CARTOGRAPHER_PLUGIN_CONFIG" \
|
|
39
|
-
--argjson home "$home_settings" \
|
|
40
|
-
--argjson repo "$repo_settings" \
|
|
41
|
-
'$plugin * {"cartographer": (($plugin.cartographer // {}) * ($home.cartographer // {}) * ($repo.cartographer // {}))}')
|
|
22
|
+
config_load_plugin "cartographer" "$repo_root" "_CARTOGRAPHER_CONFIG"
|
|
23
|
+
return 0
|
|
42
24
|
}
|
|
43
25
|
|
|
44
26
|
cartographer_config_get() {
|
|
45
27
|
local path="${1:-}"
|
|
46
|
-
|
|
28
|
+
config_get "_CARTOGRAPHER_CONFIG" "${path}"
|
|
47
29
|
}
|
|
48
30
|
|
|
49
31
|
cartographer_config_get_json() {
|
|
50
32
|
local path="${1:-}"
|
|
51
|
-
|
|
33
|
+
config_get_json "_CARTOGRAPHER_CONFIG" "${path}"
|
|
52
34
|
}
|
|
53
35
|
|
|
54
36
|
cartographer_config_model_extraction() {
|
|
@@ -1,65 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Config resolution for
|
|
2
|
+
# Config resolution for compass.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/compass/config.json (defaults shipped with the plugin)
|
|
6
6
|
# 2. ~/.claude/settings.json
|
|
7
|
-
# 3.
|
|
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
|
-
# compass_config_load <repo_root>
|
|
11
|
-
# compass_config_get <jq-path>
|
|
12
|
-
# compass_config_get_json <jq-path>
|
|
12
|
+
# compass_config_load <repo_root> # populates _compass_CONFIG (JSON)
|
|
13
|
+
# compass_config_get <jq-path> # echoes string value (empty if unset)
|
|
14
|
+
# compass_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
17
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
18
|
+
|
|
19
|
+
_compass_CONFIG="{}"
|
|
15
20
|
|
|
16
21
|
compass_config_load() {
|
|
17
22
|
local repo_root="${1:-}"
|
|
18
|
-
|
|
19
|
-
|
|
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 '{ compass: (.compass // {}) }' "$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
|
-
_COMPASS_CONFIG="$merged"
|
|
23
|
+
config_load_plugin "compass" "$repo_root" "_compass_CONFIG"
|
|
24
|
+
return 0
|
|
55
25
|
}
|
|
56
26
|
|
|
57
27
|
compass_config_get() {
|
|
58
28
|
local path="$1"
|
|
59
|
-
|
|
29
|
+
config_get "_compass_CONFIG" "${path}"
|
|
60
30
|
}
|
|
61
31
|
|
|
62
32
|
compass_config_get_json() {
|
|
63
33
|
local path="$1"
|
|
64
|
-
|
|
34
|
+
config_get_json "_compass_CONFIG" "${path}"
|
|
65
35
|
}
|
|
@@ -1,66 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Config resolution for
|
|
2
|
+
# Config resolution for counsel.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# 1. plugins/counsel/config.json
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
|
+
# 1. plugins/counsel/config.json (defaults shipped with the plugin)
|
|
6
6
|
# 2. ~/.claude/settings.json
|
|
7
|
-
# 3.
|
|
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
|
-
# counsel_config_load <repo_root> # populates
|
|
12
|
+
# counsel_config_load <repo_root> # populates _counsel_CONFIG (JSON)
|
|
11
13
|
# counsel_config_get <jq-path> # echoes string value (empty if unset)
|
|
12
14
|
# counsel_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
17
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
18
|
+
|
|
19
|
+
_counsel_CONFIG="{}"
|
|
15
20
|
|
|
16
21
|
counsel_config_load() {
|
|
17
22
|
local repo_root="${1:-}"
|
|
18
|
-
|
|
19
|
-
|
|
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 '{ counsel: (.counsel // {}) }' "$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
|
-
_COUNSEL_CONFIG="$merged"
|
|
23
|
+
config_load_plugin "counsel" "$repo_root" "_counsel_CONFIG"
|
|
24
|
+
return 0
|
|
55
25
|
}
|
|
56
26
|
|
|
57
27
|
counsel_config_get() {
|
|
58
28
|
local path="$1"
|
|
59
|
-
|
|
29
|
+
config_get "_counsel_CONFIG" "${path}"
|
|
60
30
|
}
|
|
61
31
|
|
|
62
32
|
counsel_config_get_json() {
|
|
63
33
|
local path="$1"
|
|
64
|
-
|
|
34
|
+
config_get_json "_counsel_CONFIG" "${path}"
|
|
65
35
|
}
|
|
66
|
-
|