@onlooker-community/ecosystem 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/beads/SKILL.md +80 -0
- package/.agents/skills/beads/agents/openai.yaml +4 -0
- package/.claude/settings.json +13 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.codex/config.toml +2 -0
- package/.codex/hooks.json +51 -0
- package/.markdownlint.json +3 -0
- package/.release-please-manifest.json +8 -8
- package/AGENTS.md +135 -0
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +56 -1
- package/docs/lesson-promotion-pipeline.md +210 -0
- package/docs/superpowers/plans/2026-08-09-lesson-transform.md +1537 -0
- package/docs/superpowers/specs/2026-08-09-lesson-transform-design.md +261 -0
- package/package.json +3 -2
- 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/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/config.json +4 -0
- package/plugins/librarian/schema/PROVENANCE.json +7 -0
- package/plugins/librarian/schema/lesson-applies-to.subschema.json +74 -0
- package/plugins/librarian/schema/lesson-evidence.subschema.json +36 -0
- package/plugins/librarian/scripts/hooks/librarian-session-end.sh +26 -0
- package/plugins/librarian/scripts/lib/librarian-config.sh +10 -34
- package/plugins/librarian/scripts/lib/librarian-lesson-storage.sh +135 -0
- package/plugins/librarian/scripts/lib/librarian-lesson-transform.sh +311 -0
- package/plugins/librarian/scripts/lib/librarian-lesson-validate.sh +140 -0
- 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 +8 -1
- package/scripts/lint/check-lesson-schema-drift.mjs +36 -0
- package/test/bats/librarian-lesson-transform.bats +609 -0
- package/test/node/lesson-schema-drift.test.mjs +28 -0
- package/test/node/lesson-validate-agreement.test.mjs +154 -0
|
@@ -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
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "curator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Maintenance layer for the user's typed auto-memory store. At every SessionStart, runs four cheap heuristic checks (date_decayed, path_broken, broken_index, orphaned_memory) against the memories at ~/.claude/projects/<encoded>/memory/ inside a wall-clock budget. Surfaces findings as a one-line pointer to /curator review; never edits the memory store directly. 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/curator-v0.2.1...curator-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/curator-v0.2.0...curator-v0.2.1) (2026-08-01)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,60 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Config resolution for
|
|
2
|
+
# Config resolution for curator.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/curator/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
|
-
# curator_config_load <repo_root> # populates
|
|
12
|
+
# curator_config_load <repo_root> # populates _curator_CONFIG (JSON)
|
|
11
13
|
# curator_config_get <jq-path> # echoes string value (empty if unset)
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
+
# curator_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"
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
_curator_CONFIG="{}"
|
|
16
20
|
|
|
17
21
|
curator_config_load() {
|
|
18
22
|
local repo_root="${1:-}"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
local merged="{}"
|
|
23
|
-
local file
|
|
24
|
-
|
|
25
|
-
file="${plugin_root}/config.json"
|
|
26
|
-
if [[ -f "$file" ]]; then
|
|
27
|
-
local defaults
|
|
28
|
-
defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
|
|
29
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
|
|
30
|
-
|| merged="$defaults"
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
for file in "${home_dir}/.claude/settings.json" "${repo_root}/.claude/settings.json"; do
|
|
34
|
-
[[ -n "$file" && -f "$file" ]] || continue
|
|
35
|
-
local overlay
|
|
36
|
-
overlay=$(jq '{ curator: (.curator // {}) }' "$file" 2>/dev/null) || continue
|
|
37
|
-
[[ -z "$overlay" ]] && continue
|
|
38
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
|
|
39
|
-
def deepmerge($a; $b):
|
|
40
|
-
if ($a|type) == "object" and ($b|type) == "object" then
|
|
41
|
-
reduce (($a|keys) + ($b|keys) | unique)[] as $k
|
|
42
|
-
({}; .[$k] = deepmerge($a[$k]; $b[$k]))
|
|
43
|
-
elif $b == null then $a
|
|
44
|
-
else $b end;
|
|
45
|
-
deepmerge($a; $b)
|
|
46
|
-
' 2>/dev/null) || true
|
|
47
|
-
done
|
|
48
|
-
|
|
49
|
-
_CURATOR_CONFIG="$merged"
|
|
23
|
+
config_load_plugin "curator" "$repo_root" "_curator_CONFIG"
|
|
24
|
+
return 0
|
|
50
25
|
}
|
|
51
26
|
|
|
52
27
|
curator_config_get() {
|
|
53
28
|
local path="$1"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
29
|
+
config_get "_curator_CONFIG" "${path}"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
curator_config_get_json() {
|
|
33
|
+
local path="$1"
|
|
34
|
+
config_get_json "_curator_CONFIG" "${path}"
|
|
60
35
|
}
|
|
@@ -1,100 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Config
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# Config resolution for echo.
|
|
3
|
+
#
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
|
+
# 1. plugins/echo/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
|
+
# echo_config_load <repo_root> # populates _echo_CONFIG (JSON)
|
|
13
|
+
# echo_config_get <jq-path> # echoes string value (empty if unset)
|
|
14
|
+
# echo_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
5
15
|
|
|
6
|
-
|
|
7
|
-
|
|
16
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
17
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
18
|
+
|
|
19
|
+
_echo_CONFIG="{}"
|
|
8
20
|
|
|
9
21
|
echo_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
|
-
_ECHO_PLUGIN_CONFIG_JSON=$(cat "$plugin_config" 2>/dev/null) || _ECHO_PLUGIN_CONFIG_JSON=""
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
_ECHO_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 echo_block
|
|
25
|
-
echo_block=$(printf '%s' "$settings" | jq -c '.echo // empty' 2>/dev/null) || echo_block=""
|
|
26
|
-
[[ -n "$echo_block" ]] && _ECHO_CONFIG_JSON="$echo_block"
|
|
27
|
-
fi
|
|
28
|
-
fi
|
|
23
|
+
config_load_plugin "echo" "$repo_root" "_echo_CONFIG"
|
|
24
|
+
return 0
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
# Get a single scalar value. Checks settings.json first, then plugin config.json.
|
|
32
27
|
echo_config_get() {
|
|
33
|
-
local
|
|
34
|
-
|
|
35
|
-
if [[ -n "$_ECHO_CONFIG_JSON" ]]; then
|
|
36
|
-
local val
|
|
37
|
-
val=$(printf '%s' "$_ECHO_CONFIG_JSON" | jq -r "${key} // empty" 2>/dev/null) || val=""
|
|
38
|
-
[[ -n "$val" && "$val" != "null" ]] && { printf '%s' "$val"; return 0; }
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
if [[ -n "$_ECHO_PLUGIN_CONFIG_JSON" ]]; then
|
|
42
|
-
local val
|
|
43
|
-
val=$(printf '%s' "$_ECHO_PLUGIN_CONFIG_JSON" | jq -r ".echo${key} // empty" 2>/dev/null) || val=""
|
|
44
|
-
[[ -n "$val" && "$val" != "null" ]] && { printf '%s' "$val"; return 0; }
|
|
45
|
-
fi
|
|
28
|
+
local path="$1"
|
|
29
|
+
config_get "_echo_CONFIG" "${path}"
|
|
46
30
|
}
|
|
47
31
|
|
|
48
32
|
echo_config_get_json() {
|
|
49
|
-
local
|
|
50
|
-
|
|
51
|
-
if [[ -n "$_ECHO_CONFIG_JSON" ]]; then
|
|
52
|
-
local val
|
|
53
|
-
val=$(printf '%s' "$_ECHO_CONFIG_JSON" | jq -c "${key} // empty" 2>/dev/null) || val=""
|
|
54
|
-
[[ -n "$val" && "$val" != "null" && "$val" != "empty" ]] && { printf '%s' "$val"; return 0; }
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
if [[ -n "$_ECHO_PLUGIN_CONFIG_JSON" ]]; then
|
|
58
|
-
local val
|
|
59
|
-
val=$(printf '%s' "$_ECHO_PLUGIN_CONFIG_JSON" | jq -c ".echo${key} // empty" 2>/dev/null) || val=""
|
|
60
|
-
[[ -n "$val" && "$val" != "null" && "$val" != "empty" ]] && { printf '%s' "$val"; return 0; }
|
|
61
|
-
fi
|
|
33
|
+
local path="$1"
|
|
34
|
+
config_get_json "_echo_CONFIG" "${path}"
|
|
62
35
|
}
|
|
63
36
|
|
|
64
37
|
echo_config_model() {
|
|
65
38
|
local val
|
|
66
|
-
val=$(echo_config_get '.evaluation.model')
|
|
39
|
+
val=$(echo_config_get '.echo.evaluation.model')
|
|
67
40
|
printf '%s' "${val:-claude-haiku-4-5-20251001}"
|
|
68
41
|
}
|
|
69
42
|
|
|
70
43
|
echo_config_timeout() {
|
|
71
44
|
local val
|
|
72
|
-
val=$(echo_config_get '.evaluation.timeout_seconds')
|
|
45
|
+
val=$(echo_config_get '.echo.evaluation.timeout_seconds')
|
|
73
46
|
printf '%s' "${val:-60}"
|
|
74
47
|
}
|
|
75
48
|
|
|
76
49
|
echo_config_drift_threshold() {
|
|
77
50
|
local val
|
|
78
|
-
val=$(echo_config_get '.drift_threshold')
|
|
51
|
+
val=$(echo_config_get '.echo.drift_threshold')
|
|
79
52
|
printf '%s' "${val:-0.05}"
|
|
80
53
|
}
|
|
81
54
|
|
|
82
|
-
# Prints newline-separated list of watch glob patterns.
|
|
83
55
|
echo_config_watch_paths() {
|
|
84
56
|
local raw
|
|
85
|
-
raw=$(echo_config_get_json '.watch_paths')
|
|
86
|
-
if [[ -n "$raw" ]]; then
|
|
57
|
+
raw=$(echo_config_get_json '.echo.watch_paths')
|
|
58
|
+
if [[ -n "$raw" && "$raw" != "null" ]]; then
|
|
87
59
|
printf '%s' "$raw" | jq -r '.[]' 2>/dev/null
|
|
88
60
|
else
|
|
89
61
|
printf 'plugins/*/agents/*.md\n'
|
|
90
62
|
fi
|
|
91
63
|
}
|
|
92
64
|
|
|
93
|
-
# Prints newline-separated list of exclude glob patterns.
|
|
94
65
|
echo_config_exclude_paths() {
|
|
95
66
|
local raw
|
|
96
|
-
raw=$(echo_config_get_json '.exclude_paths')
|
|
97
|
-
if [[ -n "$raw" ]]; then
|
|
67
|
+
raw=$(echo_config_get_json '.echo.exclude_paths')
|
|
68
|
+
if [[ -n "$raw" && "$raw" != "null" ]]; then
|
|
98
69
|
printf '%s' "$raw" | jq -r '.[]' 2>/dev/null
|
|
99
70
|
fi
|
|
100
71
|
# Always exclude Echo's own tree — hardcoded, not overridable.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Config resolution for Governor.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/governor/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
|
# governor_config_load <repo_root> # populates _GOVERNOR_CONFIG (JSON)
|
|
@@ -12,57 +14,25 @@
|
|
|
12
14
|
# governor_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
15
|
# governor_config_enforcement # echoes "soft" or "hard"
|
|
14
16
|
|
|
17
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
18
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
19
|
+
|
|
15
20
|
_GOVERNOR_CONFIG="{}"
|
|
16
21
|
|
|
17
22
|
governor_config_load() {
|
|
18
23
|
local repo_root="${1:-}"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
local merged="{}"
|
|
23
|
-
local file
|
|
24
|
-
|
|
25
|
-
file="${plugin_root}/config.json"
|
|
26
|
-
if [[ -f "$file" ]]; then
|
|
27
|
-
local defaults
|
|
28
|
-
defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
|
|
29
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
|
|
30
|
-
|| merged="$defaults"
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
local repo_settings=""
|
|
34
|
-
[[ -n "$repo_root" ]] && repo_settings="${repo_root}/.claude/settings.json"
|
|
35
|
-
|
|
36
|
-
for file in "${home_dir}/.claude/settings.json" "$repo_settings"; do
|
|
37
|
-
[[ -n "$file" && -f "$file" ]] || continue
|
|
38
|
-
local overlay
|
|
39
|
-
overlay=$(jq '{ governor: (.governor // {}) }' "$file" 2>/dev/null) || continue
|
|
40
|
-
[[ -z "$overlay" ]] && continue
|
|
41
|
-
local attempt
|
|
42
|
-
if attempt=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
|
|
43
|
-
def deepmerge($a; $b):
|
|
44
|
-
if ($a|type) == "object" and ($b|type) == "object" then
|
|
45
|
-
reduce (($a|keys) + ($b|keys) | unique)[] as $k
|
|
46
|
-
({}; .[$k] = deepmerge($a[$k]; $b[$k]))
|
|
47
|
-
elif $b == null then $a
|
|
48
|
-
else $b end;
|
|
49
|
-
deepmerge($a; $b)
|
|
50
|
-
' 2>/dev/null) && [[ -n "$attempt" ]]; then
|
|
51
|
-
merged="$attempt"
|
|
52
|
-
fi
|
|
53
|
-
done
|
|
54
|
-
|
|
55
|
-
_GOVERNOR_CONFIG="$merged"
|
|
24
|
+
config_load_plugin "governor" "$repo_root" "_GOVERNOR_CONFIG"
|
|
25
|
+
return 0
|
|
56
26
|
}
|
|
57
27
|
|
|
58
28
|
governor_config_get() {
|
|
59
29
|
local path="$1"
|
|
60
|
-
|
|
30
|
+
config_get "_GOVERNOR_CONFIG" "${path}"
|
|
61
31
|
}
|
|
62
32
|
|
|
63
33
|
governor_config_get_json() {
|
|
64
34
|
local path="$1"
|
|
65
|
-
|
|
35
|
+
config_get_json "_GOVERNOR_CONFIG" "${path}"
|
|
66
36
|
}
|
|
67
37
|
|
|
68
38
|
governor_config_enforcement() {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Config resolution for Historian.
|
|
3
3
|
#
|
|
4
|
-
# Reads
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
5
|
# 1. plugins/historian/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
|
# historian_config_load <repo_root> # populates _HISTORIAN_CONFIG (JSON)
|
|
@@ -12,41 +14,15 @@
|
|
|
12
14
|
#
|
|
13
15
|
# Settings overlay only touches the `historian.*` subtree of settings.json.
|
|
14
16
|
|
|
17
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
18
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
19
|
+
|
|
15
20
|
_HISTORIAN_CONFIG="{}"
|
|
16
21
|
|
|
17
22
|
historian_config_load() {
|
|
18
23
|
local repo_root="${1:-}"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
local merged="{}"
|
|
23
|
-
local file
|
|
24
|
-
|
|
25
|
-
file="${plugin_root}/config.json"
|
|
26
|
-
if [[ -f "$file" ]]; then
|
|
27
|
-
local defaults
|
|
28
|
-
defaults=$(jq '.' "$file" 2>/dev/null) || defaults="{}"
|
|
29
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$defaults" '$a * $b' 2>/dev/null) \
|
|
30
|
-
|| merged="$defaults"
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
for file in "${home_dir}/.claude/settings.json" "${repo_root}/.claude/settings.json"; do
|
|
34
|
-
[[ -n "$file" && -f "$file" ]] || continue
|
|
35
|
-
local overlay
|
|
36
|
-
overlay=$(jq '{ historian: (.historian // {}) }' "$file" 2>/dev/null) || continue
|
|
37
|
-
[[ -z "$overlay" ]] && continue
|
|
38
|
-
merged=$(jq -n --argjson a "$merged" --argjson b "$overlay" '
|
|
39
|
-
def deepmerge($a; $b):
|
|
40
|
-
if ($a|type) == "object" and ($b|type) == "object" then
|
|
41
|
-
reduce (($a|keys) + ($b|keys) | unique)[] as $k
|
|
42
|
-
({}; .[$k] = deepmerge($a[$k]; $b[$k]))
|
|
43
|
-
elif $b == null then $a
|
|
44
|
-
else $b end;
|
|
45
|
-
deepmerge($a; $b)
|
|
46
|
-
' 2>/dev/null) || true
|
|
47
|
-
done
|
|
48
|
-
|
|
49
|
-
_HISTORIAN_CONFIG="$merged"
|
|
24
|
+
config_load_plugin "historian" "$repo_root" "_HISTORIAN_CONFIG"
|
|
25
|
+
return 0
|
|
50
26
|
}
|
|
51
27
|
|
|
52
28
|
# Read a value from the loaded config. The explicit null check (instead of
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inspector",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Per-edit lint and typecheck gate. Runs the project's configured checks on just the touched file after every Write / Edit / MultiEdit, so the agent sees its own type errors before claiming success. Cheaper than proctor (which runs project-wide verification at Stop); complements assayer (which catches the agent lying about claims). 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.3.2](https://github.com/onlooker-community/ecosystem/compare/inspector-v0.3.1...inspector-v0.3.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.3.1](https://github.com/onlooker-community/ecosystem/compare/inspector-v0.3.0...inspector-v0.3.1) (2026-08-01)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,62 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# Config resolution for inspector.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# 1. plugins/inspector/config.json
|
|
6
|
-
# 2. ~/.claude/settings.json
|
|
7
|
-
# 3.
|
|
4
|
+
# Uses the shared config loader from ecosystem. Reads five layers, latest wins:
|
|
5
|
+
# 1. plugins/inspector/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)
|
|
8
10
|
#
|
|
9
|
-
#
|
|
10
|
-
# inspector_config_load <repo_root>
|
|
11
|
-
# inspector_config_get
|
|
12
|
-
# inspector_config_get_json
|
|
13
|
-
# inspector_config_checks_for_extension ".ts"
|
|
11
|
+
# Exposes:
|
|
12
|
+
# inspector_config_load <repo_root> # populates _inspector_CONFIG (JSON)
|
|
13
|
+
# inspector_config_get <jq-path> # echoes string value (empty if unset)
|
|
14
|
+
# inspector_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
# shellcheck source=../../../scripts/lib/config-loader.sh
|
|
17
|
+
source "${PLUGIN_ROOT}/../../scripts/lib/config-loader.sh"
|
|
18
|
+
|
|
19
|
+
_inspector_CONFIG="{}"
|
|
17
20
|
|
|
18
21
|
inspector_config_load() {
|
|
19
22
|
local repo_root="${1:-}"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
local plugin_config="$plugin_dir/config.json"
|
|
23
|
-
|
|
24
|
-
_INSPECTOR_PLUGIN_CONFIG="{}"
|
|
25
|
-
if [[ -f "$plugin_config" ]]; then
|
|
26
|
-
_INSPECTOR_PLUGIN_CONFIG=$(cat "$plugin_config")
|
|
27
|
-
fi
|
|
28
|
-
|
|
29
|
-
local home_settings="{}"
|
|
30
|
-
if [[ -f "$HOME/.claude/settings.json" ]]; then
|
|
31
|
-
home_settings=$(cat "$HOME/.claude/settings.json")
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
local repo_settings="{}"
|
|
35
|
-
if [[ -n "$repo_root" && -f "$repo_root/.claude/settings.json" ]]; then
|
|
36
|
-
repo_settings=$(cat "$repo_root/.claude/settings.json")
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
_INSPECTOR_CONFIG=$(jq -n \
|
|
40
|
-
--argjson plugin "$_INSPECTOR_PLUGIN_CONFIG" \
|
|
41
|
-
--argjson home "$home_settings" \
|
|
42
|
-
--argjson repo "$repo_settings" \
|
|
43
|
-
'$plugin * {"inspector": (($plugin.inspector // {}) * ($home.inspector // {}) * ($repo.inspector // {}))}')
|
|
23
|
+
config_load_plugin "inspector" "$repo_root" "_inspector_CONFIG"
|
|
24
|
+
return 0
|
|
44
25
|
}
|
|
45
26
|
|
|
46
27
|
inspector_config_get() {
|
|
47
|
-
local path="$
|
|
48
|
-
|
|
28
|
+
local path="$1"
|
|
29
|
+
config_get "_inspector_CONFIG" "${path}"
|
|
49
30
|
}
|
|
50
31
|
|
|
51
32
|
inspector_config_get_json() {
|
|
52
|
-
local path="$
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
inspector_config_show_clean_runs() {
|
|
57
|
-
local v
|
|
58
|
-
v=$(inspector_config_get '.inspector.show_clean_runs')
|
|
59
|
-
[[ "$v" == "true" ]]
|
|
33
|
+
local path="$1"
|
|
34
|
+
config_get_json "_inspector_CONFIG" "${path}"
|
|
60
35
|
}
|
|
61
36
|
|
|
62
37
|
inspector_config_timeout_per_check() {
|
|
@@ -77,25 +52,26 @@ inspector_config_output_excerpt_max_bytes() {
|
|
|
77
52
|
printf '%s' "${v:-4096}"
|
|
78
53
|
}
|
|
79
54
|
|
|
55
|
+
inspector_config_show_clean_runs() {
|
|
56
|
+
local v
|
|
57
|
+
v=$(inspector_config_get '.inspector.show_clean_runs')
|
|
58
|
+
[[ "$v" == "true" ]]
|
|
59
|
+
}
|
|
60
|
+
|
|
80
61
|
inspector_config_exclude_paths() {
|
|
81
|
-
inspector_config_get_json '.inspector.exclude_paths // []'
|
|
62
|
+
inspector_config_get_json '.inspector.exclude_paths // ["node_modules",".git","vendor",".venv","dist",".next",".nuxt","build","__pycache__","target","coverage"]'
|
|
82
63
|
}
|
|
83
64
|
|
|
84
|
-
# Emits a JSON array of {name, argv, kind} objects for the given file extension
|
|
85
|
-
# (including the leading dot). Returns an empty array when no checks are
|
|
86
|
-
# configured for the extension.
|
|
87
65
|
inspector_config_checks_for_extension() {
|
|
88
|
-
local ext="$
|
|
89
|
-
[[ -z "$ext" ]] && { printf '[]
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
)
|
|
100
|
-
' 2>/dev/null || printf '[]'
|
|
66
|
+
local ext="$1"
|
|
67
|
+
[[ -z "$ext" ]] && { printf '%s\n' "[]"; return 0; }
|
|
68
|
+
local raw
|
|
69
|
+
raw=$(inspector_config_get_json ".inspector.checks[\"$ext\"] // []")
|
|
70
|
+
[[ -z "$raw" ]] && { printf '%s\n' "[]"; return 0; }
|
|
71
|
+
# Normalize bare argv arrays into objects with name, kind, argv fields
|
|
72
|
+
printf '%s' "$raw" | jq -c 'map(
|
|
73
|
+
if type == "array" then
|
|
74
|
+
{name: .[0], kind: "lint", argv: .}
|
|
75
|
+
else . end
|
|
76
|
+
)'
|
|
101
77
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "librarian",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Consolidation layer between archivist's per-session artifacts and the user's durable typed memory store. Detects which session decisions, dead-ends, and open questions deserve to live across sessions, classifies them into the user/feedback/project/reference types, and queues them as proposals for explicit confirmation. Auto-promotion is opt-in. 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.7.0](https://github.com/onlooker-community/ecosystem/compare/librarian-v0.6.1...librarian-v0.7.0) (2026-08-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **librarian:** transform artifacts into shareable lesson candidates :microscope: ([#132](https://github.com/onlooker-community/ecosystem/issues/132)) ([48adbc7](https://github.com/onlooker-community/ecosystem/commit/48adbc7ec572b96b47f1be5f92810088c98702c6))
|
|
9
|
+
|
|
3
10
|
## [0.6.1](https://github.com/onlooker-community/ecosystem/compare/librarian-v0.6.0...librarian-v0.6.1) (2026-08-02)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source_repo": "https://github.com/onlooker-community/onlooker",
|
|
3
|
+
"source_path": "packages/lesson-contract/schema/lesson.schema.json",
|
|
4
|
+
"schema_version": 2,
|
|
5
|
+
"extracted": ["properties.evidence", "properties.applies_to"],
|
|
6
|
+
"note": "Vendored because ajv is unavailable at runtime (ADR-005). Runtime enforcement is jq in librarian-lesson-validate.sh; these files are the source of truth those rules mirror. Upgrade to a fetch-and-compare guard once lesson schemas are published — schema.onlooker.dev serves none today."
|
|
7
|
+
}
|