@onlooker-community/ecosystem 0.30.0 → 0.31.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 (150) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.gitattributes +18 -0
  3. package/.release-please-manifest.json +17 -17
  4. package/CHANGELOG.md +19 -0
  5. package/CLAUDE.md +10 -0
  6. package/package.json +2 -3
  7. package/plugins/archivist/.claude-plugin/plugin.json +1 -1
  8. package/plugins/archivist/CHANGELOG.md +7 -0
  9. package/plugins/archivist/README.md +4 -10
  10. package/plugins/archivist/config.json +0 -1
  11. package/plugins/archivist/scripts/hooks/archivist-extract.sh +0 -6
  12. package/plugins/archivist/scripts/hooks/archivist-inject.sh +2 -7
  13. package/plugins/archivist/scripts/lib/archivist-config.sh +0 -8
  14. package/plugins/assayer/.claude-plugin/plugin.json +1 -1
  15. package/plugins/assayer/CHANGELOG.md +7 -0
  16. package/plugins/assayer/README.md +4 -10
  17. package/plugins/assayer/config.json +0 -1
  18. package/plugins/assayer/scripts/hooks/assayer-stop.sh +1 -3
  19. package/plugins/assayer/scripts/lib/assayer-config.sh +0 -6
  20. package/plugins/bursar/.claude-plugin/plugin.json +1 -1
  21. package/plugins/bursar/CHANGELOG.md +7 -0
  22. package/plugins/bursar/README.md +3 -11
  23. package/plugins/bursar/config.json +0 -1
  24. package/plugins/bursar/scripts/hooks/bursar-session-end.sh +4 -6
  25. package/plugins/bursar/scripts/hooks/bursar-session-start.sh +3 -5
  26. package/plugins/bursar/scripts/lib/bursar-config.sh +1 -7
  27. package/plugins/cartographer/.claude-plugin/plugin.json +1 -1
  28. package/plugins/cartographer/CHANGELOG.md +7 -0
  29. package/plugins/cartographer/README.md +3 -10
  30. package/plugins/cartographer/config.json +0 -1
  31. package/plugins/cartographer/scripts/hooks/cartographer-post-write.sh +0 -2
  32. package/plugins/cartographer/scripts/hooks/cartographer-session-start.sh +0 -2
  33. package/plugins/cartographer/scripts/lib/cartographer-config.sh +0 -7
  34. package/plugins/cartographer/skills/cartographer/SKILL.md +0 -5
  35. package/plugins/compass/.claude-plugin/plugin.json +1 -1
  36. package/plugins/compass/CHANGELOG.md +7 -0
  37. package/plugins/compass/README.md +4 -10
  38. package/plugins/compass/config.json +0 -1
  39. package/plugins/compass/scripts/hooks/compass-bash-gate.sh +0 -4
  40. package/plugins/compass/scripts/hooks/compass-pre-tool-use.sh +0 -4
  41. package/plugins/compass/scripts/hooks/compass-record-write.sh +0 -4
  42. package/plugins/compass/scripts/hooks/compass-session-start.sh +1 -6
  43. package/plugins/compass/scripts/lib/compass-config.sh +0 -7
  44. package/plugins/counsel/.claude-plugin/plugin.json +1 -1
  45. package/plugins/counsel/CHANGELOG.md +7 -0
  46. package/plugins/counsel/README.md +6 -10
  47. package/plugins/counsel/config.json +0 -1
  48. package/plugins/counsel/scripts/hooks/counsel-session-start.sh +1 -7
  49. package/plugins/counsel/scripts/lib/counsel-config.sh +0 -6
  50. package/plugins/counsel/skills/counsel/SKILL.md +0 -5
  51. package/plugins/curator/.claude-plugin/plugin.json +1 -1
  52. package/plugins/curator/CHANGELOG.md +7 -0
  53. package/plugins/curator/README.md +1 -11
  54. package/plugins/curator/config.json +0 -1
  55. package/plugins/curator/scripts/hooks/curator-session-start.sh +0 -6
  56. package/plugins/curator/scripts/lib/curator-config.sh +0 -7
  57. package/plugins/echo/.claude-plugin/plugin.json +1 -1
  58. package/plugins/echo/CHANGELOG.md +7 -0
  59. package/plugins/echo/README.md +3 -9
  60. package/plugins/echo/config.json +0 -1
  61. package/plugins/echo/scripts/hooks/echo-stop-gate.sh +1 -3
  62. package/plugins/echo/scripts/lib/echo-config.sh +0 -6
  63. package/plugins/governor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/governor/CHANGELOG.md +7 -0
  65. package/plugins/governor/README.md +4 -10
  66. package/plugins/governor/config.json +0 -1
  67. package/plugins/governor/scripts/hooks/governor-post-tool-use.sh +0 -5
  68. package/plugins/governor/scripts/hooks/governor-pre-tool-use.sh +0 -5
  69. package/plugins/governor/scripts/hooks/governor-session-start.sh +4 -9
  70. package/plugins/governor/scripts/hooks/governor-stop.sh +0 -5
  71. package/plugins/governor/scripts/lib/governor-config.sh +0 -7
  72. package/plugins/historian/.claude-plugin/plugin.json +1 -1
  73. package/plugins/historian/CHANGELOG.md +14 -0
  74. package/plugins/historian/README.md +3 -7
  75. package/plugins/historian/config.json +0 -1
  76. package/plugins/historian/scripts/hooks/historian-prompt-submit.sh +1 -6
  77. package/plugins/historian/scripts/hooks/historian-session-end.sh +2 -6
  78. package/plugins/historian/scripts/lib/historian-config.sh +0 -6
  79. package/plugins/historian/scripts/lib/historian-embedder.sh +10 -6
  80. package/plugins/inspector/.claude-plugin/plugin.json +1 -1
  81. package/plugins/inspector/CHANGELOG.md +7 -0
  82. package/plugins/inspector/README.md +9 -5
  83. package/plugins/inspector/config.json +0 -1
  84. package/plugins/inspector/scripts/hooks/inspector-post-write.sh +0 -7
  85. package/plugins/inspector/scripts/lib/inspector-config.sh +0 -7
  86. package/plugins/librarian/.claude-plugin/plugin.json +1 -1
  87. package/plugins/librarian/CHANGELOG.md +7 -0
  88. package/plugins/librarian/README.md +5 -9
  89. package/plugins/librarian/config.json +0 -1
  90. package/plugins/librarian/scripts/hooks/librarian-session-end.sh +0 -2
  91. package/plugins/librarian/scripts/hooks/librarian-session-start.sh +0 -6
  92. package/plugins/librarian/scripts/lib/librarian-config.sh +0 -8
  93. package/plugins/lineage/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lineage/CHANGELOG.md +7 -1
  95. package/plugins/lineage/README.md +3 -12
  96. package/plugins/lineage/config.json +0 -1
  97. package/plugins/lineage/scripts/hooks/lineage-post-tool-use.sh +0 -1
  98. package/plugins/lineage/scripts/lib/lineage-config.sh +0 -7
  99. package/plugins/lineage/skills/lineage/SKILL.md +1 -4
  100. package/plugins/scribe/.claude-plugin/plugin.json +1 -1
  101. package/plugins/scribe/CHANGELOG.md +7 -0
  102. package/plugins/scribe/README.md +4 -12
  103. package/plugins/scribe/config.json +0 -1
  104. package/plugins/scribe/scripts/hooks/scribe-capture.sh +0 -4
  105. package/plugins/scribe/scripts/hooks/scribe-session-start.sh +2 -7
  106. package/plugins/scribe/scripts/hooks/scribe-stop.sh +0 -5
  107. package/plugins/scribe/scripts/lib/scribe-config.sh +1 -8
  108. package/plugins/scribe/scripts/lib/scribe-extract.sh +16 -12
  109. package/plugins/tribunal/.claude-plugin/plugin.json +1 -1
  110. package/plugins/tribunal/CHANGELOG.md +7 -0
  111. package/plugins/tribunal/README.md +7 -1
  112. package/plugins/tribunal/config.json +0 -1
  113. package/plugins/tribunal/scripts/hooks/tribunal-stop-gate.sh +3 -14
  114. package/plugins/tribunal/scripts/lib/tribunal-config.sh +0 -8
  115. package/plugins/warden/.claude-plugin/plugin.json +1 -1
  116. package/plugins/warden/CHANGELOG.md +7 -0
  117. package/plugins/warden/README.md +3 -12
  118. package/plugins/warden/config.json +0 -1
  119. package/plugins/warden/scripts/hooks/warden-post-tool-use.sh +0 -4
  120. package/plugins/warden/scripts/hooks/warden-pre-tool-use.sh +0 -4
  121. package/plugins/warden/scripts/hooks/warden-session-start.sh +1 -6
  122. package/plugins/warden/scripts/lib/warden-config.sh +1 -8
  123. package/renovate.json +34 -0
  124. package/test/bats/archivist-config-files.bats +2 -2
  125. package/test/bats/archivist-config.bats +0 -25
  126. package/test/bats/archivist-inject.bats +1 -13
  127. package/test/bats/assayer-config.bats +0 -13
  128. package/test/bats/assayer-stop-hook.bats +3 -17
  129. package/test/bats/bursar-config.bats +0 -25
  130. package/test/bats/bursar-session-end.bats +0 -20
  131. package/test/bats/bursar-session-start.bats +1 -18
  132. package/test/bats/cartographer-config.bats +0 -25
  133. package/test/bats/compass-config.bats +1 -26
  134. package/test/bats/compass-gate.bats +1 -3
  135. package/test/bats/curator-session-start.bats +2 -12
  136. package/test/bats/echo-config.bats +0 -24
  137. package/test/bats/echo-stop-hook.bats +3 -15
  138. package/test/bats/governor-config.bats +0 -36
  139. package/test/bats/historian-prompt-submit.bats +2 -8
  140. package/test/bats/historian-session-end.bats +4 -14
  141. package/test/bats/inspector-config.bats +0 -13
  142. package/test/bats/inspector-post-write-hook.bats +10 -17
  143. package/test/bats/librarian-session-end.bats +0 -11
  144. package/test/bats/librarian-session-start.bats +1 -11
  145. package/test/bats/lineage-config.bats +0 -25
  146. package/test/bats/lineage-post-tool-use.bats +1 -7
  147. package/test/bats/scribe-extract.bats +6 -6
  148. package/test/bats/tribunal-config.bats +0 -25
  149. package/test/bats/warden-config.bats +0 -25
  150. package/test/bats/warden-scanner.bats +1 -1
@@ -25,11 +25,6 @@ setup() {
25
25
  SID="bats-start-001"
26
26
  }
27
27
 
28
- _enable() {
29
- mkdir -p "${HOME}/.claude"
30
- printf '%s\n' '{"bursar":{"enabled":true}}' > "${HOME}/.claude/settings.json"
31
- }
32
-
33
28
  _seed_ledger() {
34
29
  # One recent recorded session with cost.
35
30
  local dir="${ONLOOKER_DIR}/bursar/projects/${KEY}"
@@ -48,14 +43,7 @@ _run_hook() {
48
43
  run bash "$HOOK" < "${BATS_TEST_TMPDIR}/in.json"
49
44
  }
50
45
 
51
- @test "produces no output when bursar is disabled" {
52
- _run_hook
53
- [ "$status" -eq 0 ]
54
- [ -z "$output" ]
55
- }
56
-
57
46
  @test "writes a breadcrumb carrying the project key" {
58
- _enable
59
47
  _run_hook
60
48
  [ "$status" -eq 0 ]
61
49
  local bc="${ONLOOKER_DIR}/bursar/sessions/${SID}.json"
@@ -64,14 +52,12 @@ _run_hook() {
64
52
  }
65
53
 
66
54
  @test "surfaces no additionalContext when the window is empty" {
67
- _enable
68
55
  _run_hook
69
56
  [ "$status" -eq 0 ]
70
57
  [[ "$output" != *"hookSpecificOutput"* ]]
71
58
  }
72
59
 
73
60
  @test "emits bursar.rollup.skipped when there is no data" {
74
- _enable
75
61
  _run_hook
76
62
  run grep -c '"event_type":"bursar.rollup.skipped"' "$ONLOOKER_EVENTS_LOG"
77
63
  [ "$status" -eq 0 ]
@@ -79,7 +65,6 @@ _run_hook() {
79
65
  }
80
66
 
81
67
  @test "surfaces the burned total as SessionStart additionalContext" {
82
- _enable
83
68
  _seed_ledger
84
69
  _run_hook
85
70
  [ "$status" -eq 0 ]
@@ -89,7 +74,6 @@ _run_hook() {
89
74
  }
90
75
 
91
76
  @test "reports a tracked \$0.00 total without nudging to enable governor" {
92
- _enable
93
77
  # governor present, but the window's cost is legitimately zero
94
78
  local dir="${ONLOOKER_DIR}/bursar/projects/${KEY}"
95
79
  mkdir -p "$dir"
@@ -106,7 +90,6 @@ _run_hook() {
106
90
  }
107
91
 
108
92
  @test "emits bursar.rollup.surfaced when data exists" {
109
- _enable
110
93
  _seed_ledger
111
94
  _run_hook
112
95
  run grep -c '"event_type":"bursar.rollup.surfaced"' "$ONLOOKER_EVENTS_LOG"
@@ -116,7 +99,7 @@ _run_hook() {
116
99
 
117
100
  @test "stays silent at the surface step but still records the breadcrumb when surfacing is disabled" {
118
101
  mkdir -p "${HOME}/.claude"
119
- printf '%s\n' '{"bursar":{"enabled":true,"surface_at_session_start":false}}' \
102
+ printf '%s\n' '{"bursar":{"surface_at_session_start":false}}' \
120
103
  > "${HOME}/.claude/settings.json"
121
104
  _seed_ledger
122
105
  _run_hook
@@ -10,31 +10,6 @@ setup() {
10
10
  source "${PLUGIN_ROOT}/scripts/lib/cartographer-config.sh"
11
11
  }
12
12
 
13
- @test "config defaults: disabled by default" {
14
- cartographer_config_load ""
15
- run cartographer_config_enabled
16
- [ "$status" -ne 0 ]
17
- }
18
-
19
- @test "user-level settings.json can enable cartographer" {
20
- mkdir -p "${HOME}/.claude"
21
- printf '%s\n' '{"cartographer":{"enabled":true}}' > "${HOME}/.claude/settings.json"
22
- cartographer_config_load ""
23
- run cartographer_config_enabled
24
- [ "$status" -eq 0 ]
25
- }
26
-
27
- @test "repo-level settings.json overrides user-level enabled" {
28
- mkdir -p "${HOME}/.claude"
29
- printf '%s\n' '{"cartographer":{"enabled":true}}' > "${HOME}/.claude/settings.json"
30
- local repo="${BATS_TEST_TMPDIR}/repo"
31
- mkdir -p "${repo}/.claude"
32
- printf '%s\n' '{"cartographer":{"enabled":false}}' > "${repo}/.claude/settings.json"
33
- cartographer_config_load "$repo"
34
- run cartographer_config_enabled
35
- [ "$status" -ne 0 ]
36
- }
37
-
38
13
  @test "deep merge: user-level partial override preserves plugin defaults" {
39
14
  mkdir -p "${HOME}/.claude"
40
15
  printf '%s\n' '{"cartographer":{"audit_interval_hours":12}}' > "${HOME}/.claude/settings.json"
@@ -10,35 +10,10 @@ setup() {
10
10
  source "${PLUGIN_ROOT}/scripts/lib/compass-config.sh"
11
11
  }
12
12
 
13
- @test "compass is disabled by default" {
14
- compass_config_load ""
15
- run compass_config_enabled
16
- [ "$status" -ne 0 ]
17
- }
18
-
19
- @test "user-level settings.json can enable compass" {
20
- mkdir -p "${HOME}/.claude"
21
- printf '%s\n' '{"compass":{"enabled":true}}' > "${HOME}/.claude/settings.json"
22
- compass_config_load ""
23
- run compass_config_enabled
24
- [ "$status" -eq 0 ]
25
- }
26
-
27
- @test "repo-level settings.json overrides user-level" {
28
- mkdir -p "${HOME}/.claude"
29
- printf '%s\n' '{"compass":{"enabled":true}}' > "${HOME}/.claude/settings.json"
30
- local repo="${BATS_TEST_TMPDIR}/repo"
31
- mkdir -p "${repo}/.claude"
32
- printf '%s\n' '{"compass":{"enabled":false}}' > "${repo}/.claude/settings.json"
33
- compass_config_load "$repo"
34
- run compass_config_enabled
35
- [ "$status" -ne 0 ]
36
- }
37
-
38
13
  @test "shipped defaults survive a partial overlay" {
39
14
  mkdir -p "${HOME}/.claude"
40
15
  printf '%s\n' \
41
- '{"compass":{"enabled":true,"evaluator":{"n":7}}}' \
16
+ '{"compass":{"evaluator":{"n":7}}}' \
42
17
  > "${HOME}/.claude/settings.json"
43
18
  compass_config_load ""
44
19
  # Overlay key is picked up.
@@ -25,9 +25,7 @@ setup() {
25
25
  # shellcheck disable=SC1091
26
26
  source "${PLUGIN_ROOT}/scripts/lib/compass-gate.sh"
27
27
 
28
- # Enable compass and load config.
29
- mkdir -p "${HOME}/.claude"
30
- printf '%s\n' '{"compass":{"enabled":true}}' > "${HOME}/.claude/settings.json"
28
+ # Load config.
31
29
  compass_config_load ""
32
30
 
33
31
  # Seed a session-state file so the gate's state lookups succeed.
@@ -38,7 +38,6 @@ setup() {
38
38
  jq -n --arg path "$MEM_DIR" \
39
39
  '{
40
40
  curator: {
41
- enabled: true,
42
41
  memory_store_path: $path,
43
42
  date_check: { date_grace_period_days: 7 }
44
43
  }
@@ -64,15 +63,6 @@ _write_index() {
64
63
  printf '%b\n' "$entries" > "${MEM_DIR}/MEMORY.md"
65
64
  }
66
65
 
67
- @test "session-start no-ops when curator is disabled" {
68
- rm -f "${PROJECT_REPO}/.claude/settings.json"
69
- _seed_memory "feedback_stale.md" "feedback" "Decayed 2025-01-01 reference."
70
-
71
- run bash -c "printf '%s' '$(_input)' | '$HOOK'"
72
- [ "$status" -eq 0 ]
73
- echo "$output" | jq -e '.hookSpecificOutput.additionalContext == ""' >/dev/null
74
- [ ! -f "$ONLOOKER_EVENTS_LOG" ] || ! grep -q 'curator' "$ONLOOKER_EVENTS_LOG"
75
- }
76
66
 
77
67
  @test "session-start emits scan events with empty memory store" {
78
68
  run bash -c "printf '%s' '$(_input)' | '$HOOK'"
@@ -273,7 +263,7 @@ BODY
273
263
 
274
264
  @test "cheap_checks.enabled=false skips the scan and emits skip_reason disabled" {
275
265
  printf '%s\n' \
276
- '{"curator":{"enabled":true,"memory_store_path":"'"$MEM_DIR"'","cheap_checks":{"enabled":false}}}' \
266
+ '{"curator":{"memory_store_path":"'"$MEM_DIR"'","cheap_checks":{"enabled":false}}}' \
277
267
  > "${PROJECT_REPO}/.claude/settings.json"
278
268
 
279
269
  _seed_memory "project_stale.md" "project" "Decayed 2025-01-01"
@@ -295,7 +285,7 @@ BODY
295
285
 
296
286
  @test "surfacer truncates context past max_pointer_chars" {
297
287
  printf '%s\n' \
298
- '{"curator":{"enabled":true,"memory_store_path":"'"$MEM_DIR"'","surfacer":{"max_pointer_chars":40}}}' \
288
+ '{"curator":{"memory_store_path":"'"$MEM_DIR"'","surfacer":{"max_pointer_chars":40}}}' \
299
289
  > "${PROJECT_REPO}/.claude/settings.json"
300
290
 
301
291
  _seed_memory "project_a.md" "project" "Date 2025-01-01"
@@ -10,30 +10,6 @@ setup() {
10
10
  source "${PLUGIN_ROOT}/scripts/lib/echo-config.sh"
11
11
  }
12
12
 
13
- @test "echo is disabled by default" {
14
- CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" echo_config_load ""
15
- run echo_config_enabled
16
- [ "$status" -ne 0 ]
17
- }
18
-
19
- @test "settings.json echo.enabled=true enables echo" {
20
- local repo="${BATS_TEST_TMPDIR}/repo"
21
- mkdir -p "${repo}/.claude"
22
- printf '%s\n' '{"echo":{"enabled":true}}' > "${repo}/.claude/settings.json"
23
- CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" echo_config_load "$repo"
24
- run echo_config_enabled
25
- [ "$status" -eq 0 ]
26
- }
27
-
28
- @test "settings.json echo.enabled=false overrides plugin default" {
29
- local repo="${BATS_TEST_TMPDIR}/repo"
30
- mkdir -p "${repo}/.claude"
31
- printf '%s\n' '{"echo":{"enabled":false}}' > "${repo}/.claude/settings.json"
32
- CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" echo_config_load "$repo"
33
- run echo_config_enabled
34
- [ "$status" -ne 0 ]
35
- }
36
-
37
13
  @test "default model is claude-haiku-4-5-20251001" {
38
14
  CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" echo_config_load ""
39
15
  local m
@@ -26,14 +26,6 @@ _make_input() {
26
26
  jq -n --arg cwd "$cwd" --arg sid "$sid" '{cwd: $cwd, session_id: $sid}'
27
27
  }
28
28
 
29
- @test "hook exits 0 silently when echo.enabled is false (default)" {
30
- local input
31
- input=$(_make_input)
32
- run bash -c "printf '%s' '$input' | ONLOOKER_DIR='$ONLOOKER_DIR' '$HOOK'"
33
- [ "$status" -eq 0 ]
34
- [ -z "$output" ]
35
- }
36
-
37
29
  @test "hook exits 0 when cwd is not a git repo" {
38
30
  local non_repo="${BATS_TEST_TMPDIR}/not-a-repo"
39
31
  mkdir -p "$non_repo"
@@ -43,9 +35,7 @@ _make_input() {
43
35
  [ "$status" -eq 0 ]
44
36
  }
45
37
 
46
- @test "hook exits 0 when enabled but no watched files changed" {
47
- mkdir -p "${REPO}/.claude"
48
- printf '%s\n' '{"echo":{"enabled":true}}' > "${REPO}/.claude/settings.json"
38
+ @test "hook exits 0 when no watched files changed" {
49
39
  local input
50
40
  input=$(_make_input)
51
41
  run bash -c "printf '%s' '$input' | ONLOOKER_DIR='$ONLOOKER_DIR' '$HOOK'"
@@ -54,8 +44,6 @@ _make_input() {
54
44
  }
55
45
 
56
46
  @test "recursion guard: ECHO_NESTED=1 causes immediate exit 0" {
57
- mkdir -p "${REPO}/.claude"
58
- printf '%s\n' '{"echo":{"enabled":true}}' > "${REPO}/.claude/settings.json"
59
47
  local input
60
48
  input=$(_make_input)
61
49
  # Export ECHO_NESTED into the subshell that runs the hook.
@@ -74,7 +62,7 @@ _make_input() {
74
62
 
75
63
  @test "untracked watched file is detected when enabled and claude missing" {
76
64
  mkdir -p "${REPO}/.claude" "${REPO}/plugins/myplugin/agents"
77
- printf '%s\n' '{"echo":{"enabled":true,"watch_paths":["plugins/*/agents/*.md"]}}' \
65
+ printf '%s\n' '{"echo":{"watch_paths":["plugins/*/agents/*.md"]}}' \
78
66
  > "${REPO}/.claude/settings.json"
79
67
  printf '%s\n' '# New agent' > "${REPO}/plugins/myplugin/agents/new-agent.md"
80
68
  local input
@@ -88,7 +76,7 @@ _make_input() {
88
76
 
89
77
  @test "files under plugins/echo are excluded even if they match watch_paths" {
90
78
  mkdir -p "${REPO}/.claude" "${REPO}/plugins/echo/agents"
91
- printf '%s\n' '{"echo":{"enabled":true,"watch_paths":["plugins/*/agents/*.md"]}}' \
79
+ printf '%s\n' '{"echo":{"watch_paths":["plugins/*/agents/*.md"]}}' \
92
80
  > "${REPO}/.claude/settings.json"
93
81
  printf '%s\n' '# Echo self' > "${REPO}/plugins/echo/agents/self.md"
94
82
  local input
@@ -10,31 +10,6 @@ setup() {
10
10
  source "${PLUGIN_ROOT}/scripts/lib/governor-config.sh"
11
11
  }
12
12
 
13
- @test "governor is disabled by default" {
14
- governor_config_load ""
15
- run governor_config_enabled
16
- [ "$status" -ne 0 ]
17
- }
18
-
19
- @test "user-level settings.json can enable governor" {
20
- mkdir -p "${HOME}/.claude"
21
- printf '%s\n' '{"governor":{"enabled":true}}' > "${HOME}/.claude/settings.json"
22
- governor_config_load ""
23
- run governor_config_enabled
24
- [ "$status" -eq 0 ]
25
- }
26
-
27
- @test "repo-level settings.json overrides user-level" {
28
- mkdir -p "${HOME}/.claude"
29
- printf '%s\n' '{"governor":{"enabled":true}}' > "${HOME}/.claude/settings.json"
30
- local repo="${BATS_TEST_TMPDIR}/repo"
31
- mkdir -p "${repo}/.claude"
32
- printf '%s\n' '{"governor":{"enabled":false}}' > "${repo}/.claude/settings.json"
33
- governor_config_load "$repo"
34
- run governor_config_enabled
35
- [ "$status" -ne 0 ]
36
- }
37
-
38
13
  @test "default enforcement is soft" {
39
14
  governor_config_load ""
40
15
  local v
@@ -93,14 +68,3 @@ setup() {
93
68
  [ -z "$v" ]
94
69
  }
95
70
 
96
- @test "empty repo_root does not load /.claude/settings.json" {
97
- # Place a settings.json at the absolute root path that an empty repo_root would produce.
98
- # On a real machine this won't exist, but in CI it might; the guard should skip it.
99
- # We verify that a file at / does not influence config by confirming the default holds.
100
- governor_config_load ""
101
- run governor_config_enabled
102
- # Default is disabled — if /.claude/settings.json were loaded with {enabled:true}
103
- # this would fail. We can't plant a file at / in tests, so we assert the default
104
- # is intact (regression guard rather than direct injection test).
105
- [ "$status" -ne 0 ]
106
- }
@@ -65,6 +65,7 @@ if [[ "${HISTORIAN_STUB_OLLAMA_AVAILABLE:-1}" == "0" ]]; then
65
65
  fi
66
66
 
67
67
  if [[ "$url" == */api/tags ]]; then
68
+ printf '{"models":[{"name":"nomic-embed-text"}]}'
68
69
  exit 0
69
70
  fi
70
71
 
@@ -89,7 +90,7 @@ STUB
89
90
 
90
91
  mkdir -p "${PROJECT_REPO}/.claude"
91
92
  printf '%s\n' \
92
- '{"historian":{"enabled":true,"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"retrieval":{"cooldown_seconds":60,"max_retrievals_per_session":5,"min_prompt_chars":40,"min_similarity":0.55,"max_age_days":365}}}' \
93
+ '{"historian":{"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"retrieval":{"cooldown_seconds":60,"max_retrievals_per_session":5,"min_prompt_chars":40,"min_similarity":0.55,"max_age_days":365}}}' \
93
94
  > "${PROJECT_REPO}/.claude/settings.json"
94
95
 
95
96
  INDEX_HOOK="${PLUGIN_ROOT}/scripts/hooks/historian-session-end.sh"
@@ -125,13 +126,6 @@ _index_session() {
125
126
  bash -c "printf '%s' '$(_index_input "$sid")' | '$INDEX_HOOK'" >/dev/null
126
127
  }
127
128
 
128
- @test "retrieval no-op when historian is disabled" {
129
- rm -f "${PROJECT_REPO}/.claude/settings.json"
130
- run bash -c "printf '%s' '$(_retrieve_input "a prompt long enough to clear the floor and trigger retrieval but historian is off")' | '$RETRIEVE_HOOK'"
131
- [ "$status" -eq 0 ]
132
- echo "$output" | jq -e '.hookSpecificOutput.additionalContext == ""' >/dev/null
133
- [ ! -f "$ONLOOKER_EVENTS_LOG" ] || ! grep -q '"historian.retrieval' "$ONLOOKER_EVENTS_LOG"
134
- }
135
129
 
136
130
  @test "retrieval skipped when prompt is shorter than min_prompt_chars" {
137
131
  run bash -c "printf '%s' '$(_retrieve_input "tiny")' | '$RETRIEVE_HOOK'"
@@ -34,7 +34,7 @@ setup() {
34
34
  SESSION_ID="sess-hist-test"
35
35
 
36
36
  mkdir -p "${PROJECT_REPO}/.claude"
37
- printf '%s\n' '{"historian":{"enabled":true,"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50}}}' \
37
+ printf '%s\n' '{"historian":{"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50}}}' \
38
38
  > "${PROJECT_REPO}/.claude/settings.json"
39
39
 
40
40
  HOOK="${PLUGIN_ROOT}/scripts/hooks/historian-session-end.sh"
@@ -67,16 +67,6 @@ _chunk_count() {
67
67
  wc -l < "$file" | tr -d ' '
68
68
  }
69
69
 
70
- @test "session-end is a no-op when historian is disabled" {
71
- rm -f "${PROJECT_REPO}/.claude/settings.json"
72
- _append_text_turn "user" "$(printf 'long enough %.0s' {1..30})"
73
- _append_text_turn "assistant" "ok"
74
-
75
- run bash -c "printf '%s' '$(_input)' | '$HOOK'"
76
- [ "$status" -eq 0 ]
77
- [ ! -f "${HIST_DIR}/sessions/${SESSION_ID}.jsonl" ]
78
- [ ! -f "$ONLOOKER_EVENTS_LOG" ] || ! grep -q 'historian' "$ONLOOKER_EVENTS_LOG"
79
- }
80
70
 
81
71
  @test "session-end emits skip_reason transcript_unavailable when path missing" {
82
72
  run bash -c "printf '%s' '$(_input)' | '$HOOK'"
@@ -164,7 +154,7 @@ _chunk_count() {
164
154
 
165
155
  @test "session-end drops chunks referencing never_index_paths" {
166
156
  printf '%s\n' \
167
- '{"historian":{"enabled":true,"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"never_index_paths":["restricted/notes.md"]}}}' \
157
+ '{"historian":{"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"never_index_paths":["restricted/notes.md"]}}}' \
168
158
  > "${PROJECT_REPO}/.claude/settings.json"
169
159
 
170
160
  _append_text_turn "user" "$(printf 'first chunk %.0s' {1..30})"
@@ -235,7 +225,7 @@ _chunk_count() {
235
225
 
236
226
  @test "redact_secret_patterns=false leaves secret-shaped strings untouched" {
237
227
  printf '%s\n' \
238
- '{"historian":{"enabled":true,"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"redact_secret_patterns":false}}}' \
228
+ '{"historian":{"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"redact_secret_patterns":false}}}' \
239
229
  > "${PROJECT_REPO}/.claude/settings.json"
240
230
 
241
231
  # Synthetic AWS-shaped string. Without redaction it should pass through
@@ -254,7 +244,7 @@ _chunk_count() {
254
244
 
255
245
  @test "drop_skip_marker=false keeps chunks containing the marker" {
256
246
  printf '%s\n' \
257
- '{"historian":{"enabled":true,"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"drop_skip_marker":false}}}' \
247
+ '{"historian":{"indexing":{"min_transcript_chars_to_index":50,"chunk_target_chars":400,"chunk_overlap_chars":50},"sanitization":{"drop_skip_marker":false}}}' \
258
248
  > "${PROJECT_REPO}/.claude/settings.json"
259
249
 
260
250
  local marker
@@ -15,19 +15,6 @@ setup() {
15
15
  mkdir -p "${REPO}/.claude"
16
16
  }
17
17
 
18
- @test "disabled by default" {
19
- inspector_config_load "$REPO"
20
- run inspector_config_enabled
21
- [ "$status" -ne 0 ]
22
- }
23
-
24
- @test "enabled when settings opt in" {
25
- printf '%s\n' '{"inspector":{"enabled":true}}' >"${REPO}/.claude/settings.json"
26
- inspector_config_load "$REPO"
27
- run inspector_config_enabled
28
- [ "$status" -eq 0 ]
29
- }
30
-
31
18
  @test "default timeout_seconds_per_check is 10" {
32
19
  inspector_config_load "$REPO"
33
20
  [ "$(inspector_config_timeout_per_check)" = "10" ]
@@ -52,15 +52,8 @@ _run_hook() {
52
52
  printf '%s' "$input" | ONLOOKER_DIR="$ONLOOKER_DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
53
53
  }
54
54
 
55
- @test "exits 0 silently when inspector.enabled is false (default)" {
56
- run _run_hook "$(_input)"
57
- [ "$status" -eq 0 ]
58
- [ -z "$output" ]
59
- [ ! -f "$ONLOOKER_EVENTS_LOG" ] || [ "$(_event_count inspector.run.completed)" = "0" ]
60
- }
61
-
62
55
  @test "exits 0 when tool_name is not Write/Edit/MultiEdit" {
63
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
56
+ echo '{"inspector":{"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
64
57
  run _run_hook "$(_input "$REPO" "Bash")"
65
58
  [ "$status" -eq 0 ]
66
59
  [ -z "$output" ]
@@ -68,7 +61,7 @@ _run_hook() {
68
61
  }
69
62
 
70
63
  @test "recursion guard: INSPECTOR_NESTED=1 causes immediate exit 0" {
71
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
64
+ echo '{"inspector":{"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
72
65
  run bash -c "printf '%s' '$(_input)' | INSPECTOR_NESTED=1 ONLOOKER_DIR='$ONLOOKER_DIR' CLAUDE_PLUGIN_ROOT='$PLUGIN_ROOT' '$HOOK'"
73
66
  [ "$status" -eq 0 ]
74
67
  [ -z "$output" ]
@@ -76,7 +69,7 @@ _run_hook() {
76
69
  }
77
70
 
78
71
  @test "files in excluded_paths emit a single .skipped event and produce no agent output" {
79
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
72
+ echo '{"inspector":{"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
80
73
  run _run_hook "$(_input "$REPO" "Write" "${REPO}/node_modules/foo/index.ts")"
81
74
  [ "$status" -eq 0 ]
82
75
  [ -z "$output" ]
@@ -87,7 +80,7 @@ _run_hook() {
87
80
  }
88
81
 
89
82
  @test "extensions with no configured checks emit a single .skipped with no_extension_match" {
90
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
83
+ echo '{"inspector":{"checks":{".ts":[{"name":"t","kind":"lint","argv":["true"]}]}}}' | _settings
91
84
  run _run_hook "$(_input "$REPO" "Edit" "${REPO}/src/sample.py")"
92
85
  [ "$status" -eq 0 ]
93
86
  [ "$(_event_count inspector.check.skipped)" = "1" ]
@@ -95,7 +88,7 @@ _run_hook() {
95
88
  }
96
89
 
97
90
  @test "a passing check emits .passed and silences agent-facing stdout by default" {
98
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"clean","kind":"lint","argv":["true"]}]}}}' | _settings
91
+ echo '{"inspector":{"checks":{".ts":[{"name":"clean","kind":"lint","argv":["true"]}]}}}' | _settings
99
92
  run _run_hook "$(_input)"
100
93
  [ "$status" -eq 0 ]
101
94
  [ -z "$output" ]
@@ -104,7 +97,7 @@ _run_hook() {
104
97
  }
105
98
 
106
99
  @test "show_clean_runs surfaces the file header for passing checks" {
107
- echo '{"inspector":{"enabled":true,"show_clean_runs":true,"checks":{".ts":[{"name":"clean","kind":"lint","argv":["true"]}]}}}' | _settings
100
+ echo '{"inspector":{"show_clean_runs":true,"checks":{".ts":[{"name":"clean","kind":"lint","argv":["true"]}]}}}' | _settings
108
101
  run _run_hook "$(_input)"
109
102
  [ "$status" -eq 0 ]
110
103
  [[ "$output" == *"inspector: src/sample.ts"* ]]
@@ -113,7 +106,7 @@ _run_hook() {
113
106
 
114
107
  @test "a failing check emits .failed with exit_code and surfaces issue lines to the agent" {
115
108
  cat <<'EOF' | _settings
116
- {"inspector":{"enabled":true,"checks":{".ts":[
109
+ {"inspector":{"checks":{".ts":[
117
110
  {"name":"broken","kind":"lint","argv":["sh","-c","echo 'src/sample.ts:1:1 - Bad'; exit 2"]}
118
111
  ]}}}
119
112
  EOF
@@ -127,7 +120,7 @@ EOF
127
120
  }
128
121
 
129
122
  @test "a missing tool emits .skipped with tool_missing and produces no agent output" {
130
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"ghost","kind":"lint","argv":["this-tool-does-not-exist"]}]}}}' | _settings
123
+ echo '{"inspector":{"checks":{".ts":[{"name":"ghost","kind":"lint","argv":["this-tool-does-not-exist"]}]}}}' | _settings
131
124
  run _run_hook "$(_input)"
132
125
  [ "$status" -eq 0 ]
133
126
  [ -z "$output" ]
@@ -137,7 +130,7 @@ EOF
137
130
 
138
131
  @test "run.completed aggregates pass/fail/skip counts" {
139
132
  cat <<'EOF' | _settings
140
- {"inspector":{"enabled":true,"checks":{".ts":[
133
+ {"inspector":{"checks":{".ts":[
141
134
  {"name":"clean", "kind":"lint", "argv":["true"]},
142
135
  {"name":"broken","kind":"typecheck", "argv":["sh","-c","echo 'oops'; exit 1"]},
143
136
  {"name":"ghost", "kind":"lint", "argv":["this-tool-does-not-exist"]}
@@ -154,7 +147,7 @@ EOF
154
147
  }
155
148
 
156
149
  @test "argv is expanded with the touched file path" {
157
- echo '{"inspector":{"enabled":true,"checks":{".ts":[{"name":"echo-file","kind":"lint","argv":["sh","-c","echo $1; test -n \"$1\"","--","${file}"]}]}}}' | _settings
150
+ echo '{"inspector":{"checks":{".ts":[{"name":"echo-file","kind":"lint","argv":["sh","-c","echo $1; test -n \"$1\"","--","${file}"]}]}}}' | _settings
158
151
  run _run_hook "$(_input)"
159
152
  [ "$status" -eq 0 ]
160
153
  local argv
@@ -36,9 +36,7 @@ setup() {
36
36
  LIBRARIAN_DIR="${ONLOOKER_DIR}/librarian/${PROJECT_KEY}"
37
37
  ONLOOKER_EVENTS_LOG="${ONLOOKER_DIR}/logs/onlooker-events.jsonl"
38
38
 
39
- # Project-scoped settings.json that enables librarian.
40
39
  mkdir -p "${PROJECT_REPO}/.claude"
41
- printf '%s\n' '{"librarian":{"enabled":true}}' > "${PROJECT_REPO}/.claude/settings.json"
42
40
 
43
41
  # Stub `claude` CLI on PATH. Returns a deterministic classifier response
44
42
  # based on the artifact's summary contents.
@@ -92,15 +90,6 @@ _hook_input() {
92
90
  '{cwd: $cwd, session_id: $sid, hook_event_name: "SessionEnd"}'
93
91
  }
94
92
 
95
- @test "session-end is a no-op when librarian is disabled" {
96
- rm -f "${PROJECT_REPO}/.claude/settings.json"
97
- run bash -c "printf '%s' '$(_hook_input)' | '$HOOK'"
98
- [ "$status" -eq 0 ]
99
- # No proposals written.
100
- [ ! -d "${LIBRARIAN_DIR}/proposals" ] || [ -z "$(ls -A "${LIBRARIAN_DIR}/proposals" 2>/dev/null)" ]
101
- # No events emitted.
102
- [ ! -f "$ONLOOKER_EVENTS_LOG" ] || ! grep -q 'librarian' "$ONLOOKER_EVENTS_LOG"
103
- }
104
93
 
105
94
  @test "session-end emits empty scan when archivist has nothing" {
106
95
  run bash -c "printf '%s' '$(_hook_input)' | '$HOOK'"
@@ -29,7 +29,6 @@ setup() {
29
29
  LIBRARIAN_DIR="${ONLOOKER_DIR}/librarian/${PROJECT_KEY}"
30
30
 
31
31
  mkdir -p "${PROJECT_REPO}/.claude"
32
- printf '%s\n' '{"librarian":{"enabled":true}}' > "${PROJECT_REPO}/.claude/settings.json"
33
32
 
34
33
  HOOK="${PLUGIN_ROOT}/scripts/hooks/librarian-session-start.sh"
35
34
  }
@@ -57,15 +56,6 @@ _seed_proposal() {
57
56
  }' > "${LIBRARIAN_DIR}/proposals/${id}.json"
58
57
  }
59
58
 
60
- @test "surfacer emits empty context when librarian is disabled" {
61
- rm -f "${PROJECT_REPO}/.claude/settings.json"
62
- _seed_proposal "01PROPOSALA000000000000000"
63
-
64
- run bash -c "printf '%s' '$(_input)' | '$HOOK'"
65
- [ "$status" -eq 0 ]
66
- echo "$output" | jq -e '.hookSpecificOutput.additionalContext == ""' >/dev/null
67
- echo "$output" | jq -e '.hookSpecificOutput.hookEventName == "SessionStart"' >/dev/null
68
- }
69
59
 
70
60
  @test "surfacer emits empty context when there is no git context" {
71
61
  local non_git="${BATS_TEST_TMPDIR}/no-git"
@@ -122,7 +112,7 @@ _seed_proposal() {
122
112
 
123
113
  @test "surfacer caps display at max_pending_for_inject + '+'" {
124
114
  # Override max to 3 via a project settings overlay.
125
- printf '%s\n' '{"librarian":{"enabled":true,"surfacer":{"max_pending_for_inject":3}}}' \
115
+ printf '%s\n' '{"librarian":{"surfacer":{"max_pending_for_inject":3}}}' \
126
116
  > "${PROJECT_REPO}/.claude/settings.json"
127
117
  for i in A B C D E; do
128
118
  _seed_proposal "01PROPOSALCAP$i$i$i$i$i$i$i$i$i$i$i$i"
@@ -10,31 +10,6 @@ setup() {
10
10
  source "${PLUGIN_ROOT}/scripts/lib/lineage-config.sh"
11
11
  }
12
12
 
13
- @test "lineage is disabled by default" {
14
- lineage_config_load ""
15
- run lineage_config_enabled
16
- [ "$status" -ne 0 ]
17
- }
18
-
19
- @test "user-level settings.json can enable lineage" {
20
- mkdir -p "${HOME}/.claude"
21
- printf '%s\n' '{"lineage":{"enabled":true}}' > "${HOME}/.claude/settings.json"
22
- lineage_config_load ""
23
- run lineage_config_enabled
24
- [ "$status" -eq 0 ]
25
- }
26
-
27
- @test "repo-level settings.json overrides user-level" {
28
- mkdir -p "${HOME}/.claude"
29
- printf '%s\n' '{"lineage":{"enabled":true}}' > "${HOME}/.claude/settings.json"
30
- local repo="${BATS_TEST_TMPDIR}/repo"
31
- mkdir -p "${repo}/.claude"
32
- printf '%s\n' '{"lineage":{"enabled":false}}' > "${repo}/.claude/settings.json"
33
- lineage_config_load "$repo"
34
- run lineage_config_enabled
35
- [ "$status" -ne 0 ]
36
- }
37
-
38
13
  @test "default max_snippet_chars is 4000" {
39
14
  lineage_config_load ""
40
15
  [ "$(lineage_config_max_snippet_chars)" = "4000" ]
@@ -24,8 +24,7 @@ setup() {
24
24
  }
25
25
 
26
26
  _enable() {
27
- mkdir -p "${HOME}/.claude"
28
- printf '%s\n' '{"lineage":{"enabled":true}}' > "${HOME}/.claude/settings.json"
27
+ :
29
28
  }
30
29
 
31
30
  _ledger() { printf '%s/lineage/%s/changes.jsonl' "$ONLOOKER_DIR" "$KEY"; }
@@ -77,11 +76,6 @@ _run() {
77
76
  [ "$(jq -rs '.[0].turn' "$(_ledger)")" = "7" ]
78
77
  }
79
78
 
80
- @test "writes nothing when lineage is disabled" {
81
- _run Edit "${REPO}/foo.py" "$(jq -nc --arg f "${REPO}/foo.py" '{file_path:$f, old_string:"a", new_string:"b"}')"
82
- [ "$status" -eq 0 ]
83
- [ ! -d "${ONLOOKER_DIR}/lineage" ]
84
- }
85
79
 
86
80
  @test "skips paths matching ignore_globs" {
87
81
  _enable