@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.
- package/.claude-plugin/plugin.json +1 -1
- package/.gitattributes +18 -0
- package/.release-please-manifest.json +17 -17
- package/CHANGELOG.md +19 -0
- package/CLAUDE.md +10 -0
- package/package.json +2 -3
- package/plugins/archivist/.claude-plugin/plugin.json +1 -1
- package/plugins/archivist/CHANGELOG.md +7 -0
- package/plugins/archivist/README.md +4 -10
- package/plugins/archivist/config.json +0 -1
- package/plugins/archivist/scripts/hooks/archivist-extract.sh +0 -6
- package/plugins/archivist/scripts/hooks/archivist-inject.sh +2 -7
- package/plugins/archivist/scripts/lib/archivist-config.sh +0 -8
- package/plugins/assayer/.claude-plugin/plugin.json +1 -1
- package/plugins/assayer/CHANGELOG.md +7 -0
- package/plugins/assayer/README.md +4 -10
- package/plugins/assayer/config.json +0 -1
- package/plugins/assayer/scripts/hooks/assayer-stop.sh +1 -3
- package/plugins/assayer/scripts/lib/assayer-config.sh +0 -6
- package/plugins/bursar/.claude-plugin/plugin.json +1 -1
- package/plugins/bursar/CHANGELOG.md +7 -0
- package/plugins/bursar/README.md +3 -11
- package/plugins/bursar/config.json +0 -1
- package/plugins/bursar/scripts/hooks/bursar-session-end.sh +4 -6
- package/plugins/bursar/scripts/hooks/bursar-session-start.sh +3 -5
- package/plugins/bursar/scripts/lib/bursar-config.sh +1 -7
- package/plugins/cartographer/.claude-plugin/plugin.json +1 -1
- package/plugins/cartographer/CHANGELOG.md +7 -0
- package/plugins/cartographer/README.md +3 -10
- package/plugins/cartographer/config.json +0 -1
- package/plugins/cartographer/scripts/hooks/cartographer-post-write.sh +0 -2
- package/plugins/cartographer/scripts/hooks/cartographer-session-start.sh +0 -2
- package/plugins/cartographer/scripts/lib/cartographer-config.sh +0 -7
- package/plugins/cartographer/skills/cartographer/SKILL.md +0 -5
- package/plugins/compass/.claude-plugin/plugin.json +1 -1
- package/plugins/compass/CHANGELOG.md +7 -0
- package/plugins/compass/README.md +4 -10
- package/plugins/compass/config.json +0 -1
- package/plugins/compass/scripts/hooks/compass-bash-gate.sh +0 -4
- package/plugins/compass/scripts/hooks/compass-pre-tool-use.sh +0 -4
- package/plugins/compass/scripts/hooks/compass-record-write.sh +0 -4
- package/plugins/compass/scripts/hooks/compass-session-start.sh +1 -6
- package/plugins/compass/scripts/lib/compass-config.sh +0 -7
- package/plugins/counsel/.claude-plugin/plugin.json +1 -1
- package/plugins/counsel/CHANGELOG.md +7 -0
- package/plugins/counsel/README.md +6 -10
- package/plugins/counsel/config.json +0 -1
- package/plugins/counsel/scripts/hooks/counsel-session-start.sh +1 -7
- package/plugins/counsel/scripts/lib/counsel-config.sh +0 -6
- package/plugins/counsel/skills/counsel/SKILL.md +0 -5
- package/plugins/curator/.claude-plugin/plugin.json +1 -1
- package/plugins/curator/CHANGELOG.md +7 -0
- package/plugins/curator/README.md +1 -11
- package/plugins/curator/config.json +0 -1
- package/plugins/curator/scripts/hooks/curator-session-start.sh +0 -6
- package/plugins/curator/scripts/lib/curator-config.sh +0 -7
- package/plugins/echo/.claude-plugin/plugin.json +1 -1
- package/plugins/echo/CHANGELOG.md +7 -0
- package/plugins/echo/README.md +3 -9
- package/plugins/echo/config.json +0 -1
- package/plugins/echo/scripts/hooks/echo-stop-gate.sh +1 -3
- package/plugins/echo/scripts/lib/echo-config.sh +0 -6
- package/plugins/governor/.claude-plugin/plugin.json +1 -1
- package/plugins/governor/CHANGELOG.md +7 -0
- package/plugins/governor/README.md +4 -10
- package/plugins/governor/config.json +0 -1
- package/plugins/governor/scripts/hooks/governor-post-tool-use.sh +0 -5
- package/plugins/governor/scripts/hooks/governor-pre-tool-use.sh +0 -5
- package/plugins/governor/scripts/hooks/governor-session-start.sh +4 -9
- package/plugins/governor/scripts/hooks/governor-stop.sh +0 -5
- package/plugins/governor/scripts/lib/governor-config.sh +0 -7
- package/plugins/historian/.claude-plugin/plugin.json +1 -1
- package/plugins/historian/CHANGELOG.md +14 -0
- package/plugins/historian/README.md +3 -7
- package/plugins/historian/config.json +0 -1
- package/plugins/historian/scripts/hooks/historian-prompt-submit.sh +1 -6
- package/plugins/historian/scripts/hooks/historian-session-end.sh +2 -6
- package/plugins/historian/scripts/lib/historian-config.sh +0 -6
- package/plugins/historian/scripts/lib/historian-embedder.sh +10 -6
- package/plugins/inspector/.claude-plugin/plugin.json +1 -1
- package/plugins/inspector/CHANGELOG.md +7 -0
- package/plugins/inspector/README.md +9 -5
- package/plugins/inspector/config.json +0 -1
- package/plugins/inspector/scripts/hooks/inspector-post-write.sh +0 -7
- package/plugins/inspector/scripts/lib/inspector-config.sh +0 -7
- package/plugins/librarian/.claude-plugin/plugin.json +1 -1
- package/plugins/librarian/CHANGELOG.md +7 -0
- package/plugins/librarian/README.md +5 -9
- package/plugins/librarian/config.json +0 -1
- package/plugins/librarian/scripts/hooks/librarian-session-end.sh +0 -2
- package/plugins/librarian/scripts/hooks/librarian-session-start.sh +0 -6
- package/plugins/librarian/scripts/lib/librarian-config.sh +0 -8
- package/plugins/lineage/.claude-plugin/plugin.json +1 -1
- package/plugins/lineage/CHANGELOG.md +7 -1
- package/plugins/lineage/README.md +3 -12
- package/plugins/lineage/config.json +0 -1
- package/plugins/lineage/scripts/hooks/lineage-post-tool-use.sh +0 -1
- package/plugins/lineage/scripts/lib/lineage-config.sh +0 -7
- package/plugins/lineage/skills/lineage/SKILL.md +1 -4
- package/plugins/scribe/.claude-plugin/plugin.json +1 -1
- package/plugins/scribe/CHANGELOG.md +7 -0
- package/plugins/scribe/README.md +4 -12
- package/plugins/scribe/config.json +0 -1
- package/plugins/scribe/scripts/hooks/scribe-capture.sh +0 -4
- package/plugins/scribe/scripts/hooks/scribe-session-start.sh +2 -7
- package/plugins/scribe/scripts/hooks/scribe-stop.sh +0 -5
- package/plugins/scribe/scripts/lib/scribe-config.sh +1 -8
- package/plugins/scribe/scripts/lib/scribe-extract.sh +16 -12
- package/plugins/tribunal/.claude-plugin/plugin.json +1 -1
- package/plugins/tribunal/CHANGELOG.md +7 -0
- package/plugins/tribunal/README.md +7 -1
- package/plugins/tribunal/config.json +0 -1
- package/plugins/tribunal/scripts/hooks/tribunal-stop-gate.sh +3 -14
- package/plugins/tribunal/scripts/lib/tribunal-config.sh +0 -8
- package/plugins/warden/.claude-plugin/plugin.json +1 -1
- package/plugins/warden/CHANGELOG.md +7 -0
- package/plugins/warden/README.md +3 -12
- package/plugins/warden/config.json +0 -1
- package/plugins/warden/scripts/hooks/warden-post-tool-use.sh +0 -4
- package/plugins/warden/scripts/hooks/warden-pre-tool-use.sh +0 -4
- package/plugins/warden/scripts/hooks/warden-session-start.sh +1 -6
- package/plugins/warden/scripts/lib/warden-config.sh +1 -8
- package/renovate.json +34 -0
- package/test/bats/archivist-config-files.bats +2 -2
- package/test/bats/archivist-config.bats +0 -25
- package/test/bats/archivist-inject.bats +1 -13
- package/test/bats/assayer-config.bats +0 -13
- package/test/bats/assayer-stop-hook.bats +3 -17
- package/test/bats/bursar-config.bats +0 -25
- package/test/bats/bursar-session-end.bats +0 -20
- package/test/bats/bursar-session-start.bats +1 -18
- package/test/bats/cartographer-config.bats +0 -25
- package/test/bats/compass-config.bats +1 -26
- package/test/bats/compass-gate.bats +1 -3
- package/test/bats/curator-session-start.bats +2 -12
- package/test/bats/echo-config.bats +0 -24
- package/test/bats/echo-stop-hook.bats +3 -15
- package/test/bats/governor-config.bats +0 -36
- package/test/bats/historian-prompt-submit.bats +2 -8
- package/test/bats/historian-session-end.bats +4 -14
- package/test/bats/inspector-config.bats +0 -13
- package/test/bats/inspector-post-write-hook.bats +10 -17
- package/test/bats/librarian-session-end.bats +0 -11
- package/test/bats/librarian-session-start.bats +1 -11
- package/test/bats/lineage-config.bats +0 -25
- package/test/bats/lineage-post-tool-use.bats +1 -7
- package/test/bats/scribe-extract.bats +6 -6
- package/test/bats/tribunal-config.bats +0 -25
- package/test/bats/warden-config.bats +0 -25
- package/test/bats/warden-scanner.bats +1 -1
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
# Scribe SessionStart hook.
|
|
3
3
|
#
|
|
4
4
|
# Fires at every session start. Responsibilities:
|
|
5
|
-
# 1.
|
|
6
|
-
# 2.
|
|
7
|
-
# 3. Initialize session state file:
|
|
5
|
+
# 1. Create storage directories.
|
|
6
|
+
# 2. Initialize session state file:
|
|
8
7
|
# - captured_prompt: null (populated by scribe-capture.sh on first turn)
|
|
9
8
|
# - captured_at: null
|
|
10
9
|
#
|
|
@@ -30,10 +29,6 @@ _done() { exit 0; }
|
|
|
30
29
|
|
|
31
30
|
scribe_config_load "$CWD"
|
|
32
31
|
|
|
33
|
-
if ! scribe_config_enabled; then
|
|
34
|
-
_done
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
32
|
export _HOOK_SESSION_ID="$SESSION_ID"
|
|
38
33
|
|
|
39
34
|
ONLOOKER_DIR="${ONLOOKER_DIR:-${HOME}/.onlooker}"
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
# ~/.onlooker/scribe/<project_key>/<date>-<session>.md.
|
|
8
8
|
#
|
|
9
9
|
# Skip conditions (all silent):
|
|
10
|
-
# - scribe.enabled is false
|
|
11
10
|
# - no transcript_path in hook input, or file is unreadable
|
|
12
11
|
# - session has fewer turns than scribe.capture.min_turns
|
|
13
12
|
#
|
|
@@ -46,10 +45,6 @@ _done() { exit 0; }
|
|
|
46
45
|
|
|
47
46
|
scribe_config_load "$CWD"
|
|
48
47
|
|
|
49
|
-
if ! scribe_config_enabled; then
|
|
50
|
-
_done
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
48
|
if [[ -z "$TRANSCRIPT_PATH" || ! -f "$TRANSCRIPT_PATH" ]]; then
|
|
54
49
|
_done
|
|
55
50
|
fi
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
# scribe_config_load <repo_root> # populates _SCRIBE_CONFIG (JSON)
|
|
11
11
|
# scribe_config_get <jq-path> # echoes string value (empty if unset)
|
|
12
12
|
# scribe_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
|
-
# scribe_config_enabled # 0 if scribe.enabled is true
|
|
14
13
|
|
|
15
14
|
_SCRIBE_CONFIG="{}"
|
|
16
15
|
|
|
@@ -63,10 +62,4 @@ scribe_config_get() {
|
|
|
63
62
|
scribe_config_get_json() {
|
|
64
63
|
local path="$1"
|
|
65
64
|
printf '%s' "$_SCRIBE_CONFIG" | jq -c "${path}" 2>/dev/null
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
scribe_config_enabled() {
|
|
69
|
-
local v
|
|
70
|
-
v=$(scribe_config_get '.scribe.enabled')
|
|
71
|
-
[[ "$v" == "true" ]]
|
|
72
|
-
}
|
|
65
|
+
}
|
|
@@ -59,9 +59,13 @@ scribe_count_turns() {
|
|
|
59
59
|
local line
|
|
60
60
|
while IFS= read -r line; do
|
|
61
61
|
[[ -z "$line" ]] && continue
|
|
62
|
-
local
|
|
63
|
-
|
|
64
|
-
[[ "$
|
|
62
|
+
local entry_type
|
|
63
|
+
entry_type=$(printf '%s' "$line" | jq -r '.type // empty' 2>/dev/null) || continue
|
|
64
|
+
[[ "$entry_type" == "user" ]] || continue
|
|
65
|
+
# Only count real user prompts (string content), not tool results (array content)
|
|
66
|
+
local content_type
|
|
67
|
+
content_type=$(printf '%s' "$line" | jq -r '.message.content | type' 2>/dev/null) || continue
|
|
68
|
+
[[ "$content_type" == "string" ]] && count=$((count + 1))
|
|
65
69
|
done < "$transcript_path"
|
|
66
70
|
|
|
67
71
|
printf '%s' "$count"
|
|
@@ -79,21 +83,21 @@ scribe_extract_intent() {
|
|
|
79
83
|
|
|
80
84
|
local transcript_content
|
|
81
85
|
transcript_content=$(jq -r '
|
|
82
|
-
select(.
|
|
83
|
-
if .
|
|
86
|
+
select(.type == "user" or .type == "assistant") |
|
|
87
|
+
if .type == "user" then
|
|
84
88
|
"[User]\n" + (
|
|
85
|
-
if (.content | type) == "array" then
|
|
86
|
-
[.content[] | select(.type == "text") | .text] | join("\n")
|
|
89
|
+
if (.message.content | type) == "array" then
|
|
90
|
+
[.message.content[] | select(.type == "text") | .text] | join("\n")
|
|
87
91
|
else
|
|
88
|
-
(.content // "")
|
|
92
|
+
(.message.content // "")
|
|
89
93
|
end
|
|
90
94
|
)
|
|
91
|
-
elif .
|
|
95
|
+
elif .type == "assistant" then
|
|
92
96
|
"[Assistant]\n" + (
|
|
93
|
-
if (.content | type) == "array" then
|
|
94
|
-
[.content[] | select(.type == "text") | .text] | join("\n")
|
|
97
|
+
if (.message.content | type) == "array" then
|
|
98
|
+
[.message.content[] | select(.type == "text") | .text] | join("\n")
|
|
95
99
|
else
|
|
96
|
-
(.content // "")
|
|
100
|
+
(.message.content // "")
|
|
97
101
|
end
|
|
98
102
|
)
|
|
99
103
|
else empty end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tribunal",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Multi-agent execution with LLM-as-a-Judge quality gates. An Actor performs work; a jury of typed Judges scores it against a project-overridable rubric; a Meta-Judge reviews the jury for bias; the gate decides accept, retry, or exhaust. Grounded in LLM-as-a-Judge (Zheng et al. 2023) and LLM-as-a-Meta-Judge (Wu et al. 2024). Builds on the Onlooker ecosystem plugin.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Onlooker Community",
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0](https://github.com/onlooker-community/ecosystem/compare/tribunal-v1.0.1...tribunal-v1.1.0) (2026-07-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
|
|
9
|
+
|
|
3
10
|
## [1.0.1](https://github.com/onlooker-community/ecosystem/compare/tribunal-v1.0.0...tribunal-v1.0.1) (2026-05-25)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -34,7 +34,13 @@ The gate uses `majority` policy with `weighted_mean` aggregation, so one strong
|
|
|
34
34
|
|
|
35
35
|
## Configuration
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Install the plugin in Claude from the marketplace with:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
/plugin install tribunal@onlooker-community
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The Stop hook is opt-in. Override per-project in your project's `.claude/settings.json`:
|
|
38
44
|
|
|
39
45
|
```json
|
|
40
46
|
{
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Tribunal Stop-gate hook.
|
|
3
3
|
#
|
|
4
|
-
# Triggered by Stop.
|
|
5
|
-
#
|
|
6
|
-
# session's last turn and writes a verdict for review on the next session.
|
|
7
|
-
#
|
|
8
|
-
# Why advisory only: by the time Stop fires the main agent loop has already
|
|
9
|
-
# ended. We cannot retry the Actor or re-run the work. The hook records what
|
|
10
|
-
# the Standard Judge would have said so a human (or a follow-up SessionStart
|
|
11
|
-
# hook in v0.2) can see whether the turn would have passed the gate.
|
|
4
|
+
# Triggered by Stop.
|
|
5
|
+
# runs a single-judge advisory pass on the just-finished session's last turn and writes a verdict for review on the next session.
|
|
12
6
|
#
|
|
13
7
|
# Hook contract:
|
|
14
8
|
# - Always exits 0. Never blocks Stop.
|
|
@@ -64,10 +58,6 @@ _done() {
|
|
|
64
58
|
REPO_ROOT=$(tribunal_project_repo_root "$CWD")
|
|
65
59
|
tribunal_config_load "$REPO_ROOT"
|
|
66
60
|
|
|
67
|
-
if ! tribunal_config_stop_hook_enabled; then
|
|
68
|
-
_done
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
61
|
PROJECT_KEY=$(tribunal_project_key "$CWD")
|
|
72
62
|
if [[ -z "$PROJECT_KEY" || -z "$REPO_ROOT" ]]; then
|
|
73
63
|
_done
|
|
@@ -77,8 +67,7 @@ if [[ -z "$TRANSCRIPT_PATH" || ! -f "$TRANSCRIPT_PATH" ]]; then
|
|
|
77
67
|
_done
|
|
78
68
|
fi
|
|
79
69
|
|
|
80
|
-
# Skip if no files were modified since the last commit AND
|
|
81
|
-
# skip_if_no_file_changes (default true).
|
|
70
|
+
# Skip if no files were modified since the last commit AND skip_if_no_file_changes is true.
|
|
82
71
|
SKIP_IF_CLEAN=$(tribunal_config_get '.tribunal.stop_hook.skip_if_no_file_changes')
|
|
83
72
|
if [[ "$SKIP_IF_CLEAN" == "true" ]]; then
|
|
84
73
|
if git -C "$REPO_ROOT" diff --quiet 2>/dev/null && git -C "$REPO_ROOT" diff --cached --quiet 2>/dev/null; then
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
# tribunal_config_load <repo_root> # populates _TRIBUNAL_CONFIG (JSON)
|
|
11
11
|
# tribunal_config_get <jq-path> # echoes string value (empty if unset)
|
|
12
12
|
# tribunal_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
|
-
# tribunal_config_enabled # 0 if tribunal.enabled is true
|
|
14
13
|
# tribunal_config_stop_hook_enabled # 0 if tribunal.stop_hook.enabled is true
|
|
15
14
|
# tribunal_config_judge_model <judge_type>
|
|
16
15
|
# # echoes per-judge-type model override,
|
|
@@ -73,13 +72,6 @@ tribunal_config_get_json() {
|
|
|
73
72
|
printf '%s' "$_TRIBUNAL_CONFIG" | jq -c "${path}" 2>/dev/null
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
# Returns 0 if tribunal.enabled is true.
|
|
77
|
-
tribunal_config_enabled() {
|
|
78
|
-
local v
|
|
79
|
-
v=$(tribunal_config_get '.tribunal.enabled')
|
|
80
|
-
[[ "$v" == "true" ]]
|
|
81
|
-
}
|
|
82
|
-
|
|
83
75
|
# Returns 0 if tribunal.stop_hook.enabled is true. Default is false.
|
|
84
76
|
tribunal_config_stop_hook_enabled() {
|
|
85
77
|
local v
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "warden",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Untrusted-content gate. Scans content flowing in through WebFetch and Read for prompt-injection patterns, and when a threat is detected closes a session-scoped gate that blocks Write, Edit, and Bash until the user explicitly clears it. Grounded in Meta's Agents Rule of Two: an agent should hold no more than two of {private data, external actions, untrusted content} at once — warden removes the external-actions property while untrusted content is in play. 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.0](https://github.com/onlooker-community/ecosystem/compare/warden-v0.2.0...warden-v0.3.0) (2026-07-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
|
|
9
|
+
|
|
3
10
|
## [0.2.0](https://github.com/onlooker-community/ecosystem/compare/warden-v0.1.0...warden-v0.2.0) (2026-06-02)
|
|
4
11
|
|
|
5
12
|
|
package/plugins/warden/README.md
CHANGED
|
@@ -36,18 +36,11 @@ Clean content (no signature) never reaches the model. Set `escalation.enabled: f
|
|
|
36
36
|
|
|
37
37
|
## Activation
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Install the plugin in Claude from the marketplace with:
|
|
40
40
|
|
|
41
|
-
```json
|
|
42
|
-
{
|
|
43
|
-
"warden": {
|
|
44
|
-
"enabled": true
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
41
|
```
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
/plugin install warden@onlooker-community
|
|
43
|
+
```
|
|
51
44
|
## Configuration
|
|
52
45
|
|
|
53
46
|
All keys are optional. Unset keys fall back to the plugin's `config.json` defaults.
|
|
@@ -55,7 +48,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
|
|
|
55
48
|
```json
|
|
56
49
|
{
|
|
57
50
|
"warden": {
|
|
58
|
-
"enabled": false,
|
|
59
51
|
"scan": {
|
|
60
52
|
"sources": ["web_fetch", "file_read"],
|
|
61
53
|
"max_content_chars": 20000,
|
|
@@ -88,7 +80,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
|
|
|
88
80
|
|
|
89
81
|
| Key | Default | Description |
|
|
90
82
|
|-----|---------|-------------|
|
|
91
|
-
| `enabled` | `false` | Must be `true` for any scanning or gating to run. |
|
|
92
83
|
| `scan.sources` | `["web_fetch", "file_read"]` | Which ingestion sources to scan. Matches the schema's `source_type` enum. |
|
|
93
84
|
| `scan.max_content_chars` | `20000` | Length cap on the content fed into detection. |
|
|
94
85
|
| `scan.skip_globs` | lockfiles, `node_modules`, `.git`, `dist`, `build`, … | Globs whose reads are not scanned. |
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
# Warden SessionStart hook.
|
|
3
3
|
#
|
|
4
4
|
# Fires at every session start. Responsibilities:
|
|
5
|
-
# 1.
|
|
6
|
-
# 2. Ensure the session gate directory exists.
|
|
5
|
+
# 1. Ensure the session gate directory exists.
|
|
7
6
|
#
|
|
8
7
|
# A new session starts with the gate OPEN — the gate is session-scoped because
|
|
9
8
|
# the threat model is untrusted content ingested into THIS session's context.
|
|
@@ -34,10 +33,6 @@ _done() { exit 0; }
|
|
|
34
33
|
|
|
35
34
|
warden_config_load "$CWD"
|
|
36
35
|
|
|
37
|
-
if ! warden_config_enabled; then
|
|
38
|
-
_done
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
36
|
[[ -z "$SESSION_ID" ]] && {
|
|
42
37
|
printf 'warden-session-start: no session_id in hook input\n' >&2
|
|
43
38
|
_done
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
# warden_config_load <repo_root> # populates _WARDEN_CONFIG (JSON)
|
|
11
11
|
# warden_config_get <jq-path> # echoes string value (empty if unset)
|
|
12
12
|
# warden_config_get_json <jq-path> # echoes JSON value (null if unset)
|
|
13
|
-
# warden_config_enabled # 0 if warden.enabled is true
|
|
14
13
|
|
|
15
14
|
_WARDEN_CONFIG="{}"
|
|
16
15
|
|
|
@@ -70,10 +69,4 @@ warden_config_get() {
|
|
|
70
69
|
warden_config_get_json() {
|
|
71
70
|
local path="$1"
|
|
72
71
|
printf '%s' "$_WARDEN_CONFIG" | jq -c "${path}" 2>/dev/null
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
warden_config_enabled() {
|
|
76
|
-
local v
|
|
77
|
-
v=$(warden_config_get '.warden.enabled')
|
|
78
|
-
[[ "$v" == "true" ]]
|
|
79
|
-
}
|
|
72
|
+
}
|
package/renovate.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"extends": ["config:recommended", ":dependencyDashboard"],
|
|
4
|
+
"labels": ["dependencies"],
|
|
5
|
+
"schedule": ["before 5am on monday"],
|
|
6
|
+
"timezone": "UTC",
|
|
7
|
+
"lockFileMaintenance": {
|
|
8
|
+
"enabled": true,
|
|
9
|
+
"schedule": ["before 5am on the first day of the month"]
|
|
10
|
+
},
|
|
11
|
+
"packageRules": [
|
|
12
|
+
{
|
|
13
|
+
"description": "Group GitHub Actions updates",
|
|
14
|
+
"matchManagers": ["github-actions"],
|
|
15
|
+
"groupName": "GitHub Actions"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Group mise tool version updates",
|
|
19
|
+
"matchManagers": ["mise"],
|
|
20
|
+
"groupName": "mise tools"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"description": "Group npm devDependency updates",
|
|
24
|
+
"matchDepTypes": ["devDependencies"],
|
|
25
|
+
"groupName": "npm devDependencies"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"description": "Require dashboard approval for major devDependency bumps",
|
|
29
|
+
"matchDepTypes": ["devDependencies"],
|
|
30
|
+
"matchUpdateTypes": ["major"],
|
|
31
|
+
"dependencyDashboardApproval": true
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -11,8 +11,8 @@ setup_file() {
|
|
|
11
11
|
[ "$status" -eq 0 ]
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
@test "archivist config.json has plugin_name
|
|
15
|
-
run jq -e '.plugin_name == "archivist"
|
|
14
|
+
@test "archivist config.json has plugin_name field" {
|
|
15
|
+
run jq -e '.plugin_name == "archivist"' \
|
|
16
16
|
"${REPO_ROOT}/plugins/archivist/config.json"
|
|
17
17
|
[ "$status" -eq 0 ]
|
|
18
18
|
}
|
|
@@ -10,31 +10,6 @@ setup() {
|
|
|
10
10
|
source "${PLUGIN_ROOT}/scripts/lib/archivist-config.sh"
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
@test "config defaults from plugin config.json: disabled" {
|
|
14
|
-
archivist_config_load ""
|
|
15
|
-
run archivist_config_enabled
|
|
16
|
-
[ "$status" -ne 0 ]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@test "user-level settings.json overlay can enable archivist" {
|
|
20
|
-
mkdir -p "${HOME}/.claude"
|
|
21
|
-
printf '%s\n' '{"archivist":{"enabled":true}}' > "${HOME}/.claude/settings.json"
|
|
22
|
-
archivist_config_load ""
|
|
23
|
-
run archivist_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' '{"archivist":{"enabled":true}}' > "${HOME}/.claude/settings.json"
|
|
30
|
-
local repo="${BATS_TEST_TMPDIR}/repo"
|
|
31
|
-
mkdir -p "${repo}/.claude"
|
|
32
|
-
printf '%s\n' '{"archivist":{"enabled":false}}' > "${repo}/.claude/settings.json"
|
|
33
|
-
archivist_config_load "$repo"
|
|
34
|
-
run archivist_config_enabled
|
|
35
|
-
[ "$status" -ne 0 ]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
13
|
@test "injection.max_items defaults from config.json" {
|
|
39
14
|
archivist_config_load ""
|
|
40
15
|
local v
|
|
@@ -35,21 +35,9 @@ setup() {
|
|
|
35
35
|
"updated_at": "2026-05-22T10:00:00Z"
|
|
36
36
|
}' > "${kind_dir}/01TESTTESTTESTTESTTESTTEST.json"
|
|
37
37
|
|
|
38
|
-
# Project-scoped settings.json that enables archivist.
|
|
39
|
-
mkdir -p "${PROJECT_REPO}/.claude"
|
|
40
|
-
printf '%s\n' '{"archivist":{"enabled":true}}' > "${PROJECT_REPO}/.claude/settings.json"
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
@test "inject hook
|
|
44
|
-
rm -f "${PROJECT_REPO}/.claude/settings.json"
|
|
45
|
-
local input
|
|
46
|
-
input=$(jq -n --arg cwd "$PROJECT_REPO" '{cwd: $cwd, source: "startup", session_id: "s"}')
|
|
47
|
-
run bash -c "printf '%s' '$input' | '${PLUGIN_ROOT}/scripts/hooks/archivist-inject.sh'"
|
|
48
|
-
[ "$status" -eq 0 ]
|
|
49
|
-
echo "$output" | jq -e '.hookSpecificOutput.additionalContext == ""' >/dev/null
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@test "inject hook emits seeded artifact when enabled" {
|
|
40
|
+
@test "inject hook emits seeded artifact" {
|
|
53
41
|
local input
|
|
54
42
|
input=$(jq -n --arg cwd "$PROJECT_REPO" '{cwd: $cwd, source: "startup", session_id: "s"}')
|
|
55
43
|
run bash -c "printf '%s' '$input' | '${PLUGIN_ROOT}/scripts/hooks/archivist-inject.sh'"
|
|
@@ -14,19 +14,6 @@ setup() {
|
|
|
14
14
|
mkdir -p "${REPO}/.claude"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
@test "disabled by default (no settings)" {
|
|
18
|
-
assayer_config_load "$REPO"
|
|
19
|
-
run assayer_config_enabled
|
|
20
|
-
[ "$status" -ne 0 ]
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@test "enabled when settings opt in" {
|
|
24
|
-
printf '%s\n' '{"assayer":{"enabled":true}}' >"${REPO}/.claude/settings.json"
|
|
25
|
-
assayer_config_load "$REPO"
|
|
26
|
-
run assayer_config_enabled
|
|
27
|
-
[ "$status" -eq 0 ]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
17
|
@test "default model is haiku" {
|
|
31
18
|
assayer_config_load "$REPO"
|
|
32
19
|
[ "$(assayer_config_model)" = "claude-haiku-4-5-20251001" ]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Exercises the Assayer Stop hook's gating behavior. Does not invoke claude -p
|
|
4
4
|
# (the hook bails before the extraction step when preconditions fail).
|
|
5
|
-
# Verifies:
|
|
5
|
+
# Verifies: no-git, recursion guard, no-transcript, and
|
|
6
6
|
# stdout silence (advisory hook must never block Stop).
|
|
7
7
|
|
|
8
8
|
setup() {
|
|
@@ -30,14 +30,6 @@ _make_input() {
|
|
|
30
30
|
'{cwd: $cwd, session_id: $sid, transcript_path: $tp}'
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
@test "exits 0 silently when assayer.enabled is false (default)" {
|
|
34
|
-
local input
|
|
35
|
-
input=$(_make_input)
|
|
36
|
-
run bash -c "printf '%s' '$input' | ONLOOKER_DIR='$ONLOOKER_DIR' '$HOOK'"
|
|
37
|
-
[ "$status" -eq 0 ]
|
|
38
|
-
[ -z "$output" ]
|
|
39
|
-
}
|
|
40
|
-
|
|
41
33
|
@test "exits 0 when cwd is not a git repo" {
|
|
42
34
|
local non_repo="${BATS_TEST_TMPDIR}/not-a-repo"
|
|
43
35
|
mkdir -p "$non_repo"
|
|
@@ -48,8 +40,6 @@ _make_input() {
|
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
@test "recursion guard: ASSAYER_NESTED=1 causes immediate exit 0" {
|
|
51
|
-
mkdir -p "${REPO}/.claude"
|
|
52
|
-
printf '%s\n' '{"assayer":{"enabled":true}}' >"${REPO}/.claude/settings.json"
|
|
53
43
|
local input
|
|
54
44
|
input=$(_make_input)
|
|
55
45
|
run bash -c "printf '%s' '$input' | ASSAYER_NESTED=1 ONLOOKER_DIR='$ONLOOKER_DIR' '$HOOK'"
|
|
@@ -57,9 +47,7 @@ _make_input() {
|
|
|
57
47
|
[ -z "$output" ]
|
|
58
48
|
}
|
|
59
49
|
|
|
60
|
-
@test "exits 0 when
|
|
61
|
-
mkdir -p "${REPO}/.claude"
|
|
62
|
-
printf '%s\n' '{"assayer":{"enabled":true}}' >"${REPO}/.claude/settings.json"
|
|
50
|
+
@test "exits 0 when transcript is missing" {
|
|
63
51
|
local input
|
|
64
52
|
input=$(_make_input "$REPO" "test-session" "${BATS_TEST_TMPDIR}/nope.jsonl")
|
|
65
53
|
run bash -c "printf '%s' '$input' | ONLOOKER_DIR='$ONLOOKER_DIR' '$HOOK'"
|
|
@@ -67,9 +55,7 @@ _make_input() {
|
|
|
67
55
|
[ -z "$output" ]
|
|
68
56
|
}
|
|
69
57
|
|
|
70
|
-
@test "exits 0 when
|
|
71
|
-
mkdir -p "${REPO}/.claude"
|
|
72
|
-
printf '%s\n' '{"assayer":{"enabled":true}}' >"${REPO}/.claude/settings.json"
|
|
58
|
+
@test "exits 0 when final message is empty" {
|
|
73
59
|
# Transcript with no assistant text turn.
|
|
74
60
|
local empty_transcript="${BATS_TEST_TMPDIR}/empty.jsonl"
|
|
75
61
|
printf '%s\n' '{"type":"user","message":{"content":[{"type":"text","text":"hi"}]}}' >"$empty_transcript"
|
|
@@ -10,31 +10,6 @@ setup() {
|
|
|
10
10
|
source "${PLUGIN_ROOT}/scripts/lib/bursar-config.sh"
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
@test "bursar is disabled by default" {
|
|
14
|
-
bursar_config_load ""
|
|
15
|
-
run bursar_config_enabled
|
|
16
|
-
[ "$status" -ne 0 ]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@test "user-level settings.json can enable bursar" {
|
|
20
|
-
mkdir -p "${HOME}/.claude"
|
|
21
|
-
printf '%s\n' '{"bursar":{"enabled":true}}' > "${HOME}/.claude/settings.json"
|
|
22
|
-
bursar_config_load ""
|
|
23
|
-
run bursar_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' '{"bursar":{"enabled":true}}' > "${HOME}/.claude/settings.json"
|
|
30
|
-
local repo="${BATS_TEST_TMPDIR}/repo"
|
|
31
|
-
mkdir -p "${repo}/.claude"
|
|
32
|
-
printf '%s\n' '{"bursar":{"enabled":false}}' > "${repo}/.claude/settings.json"
|
|
33
|
-
bursar_config_load "$repo"
|
|
34
|
-
run bursar_config_enabled
|
|
35
|
-
[ "$status" -ne 0 ]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
13
|
@test "default window is rolling_7d" {
|
|
39
14
|
bursar_config_load ""
|
|
40
15
|
[ "$(bursar_config_window)" = "rolling_7d" ]
|
|
@@ -16,11 +16,6 @@ setup() {
|
|
|
16
16
|
PK="projendabcd12"
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
_enable() {
|
|
20
|
-
mkdir -p "${HOME}/.claude"
|
|
21
|
-
printf '%s\n' '{"bursar":{"enabled":true}}' > "${HOME}/.claude/settings.json"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
19
|
_breadcrumb() {
|
|
25
20
|
local dir="${ONLOOKER_DIR}/bursar/sessions"
|
|
26
21
|
mkdir -p "$dir"
|
|
@@ -44,7 +39,6 @@ _run_hook() {
|
|
|
44
39
|
}
|
|
45
40
|
|
|
46
41
|
@test "records a session's spend from governor.session.complete" {
|
|
47
|
-
_enable
|
|
48
42
|
_breadcrumb
|
|
49
43
|
_seed_governor_event
|
|
50
44
|
_run_hook
|
|
@@ -62,7 +56,6 @@ _run_hook() {
|
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
@test "removes the breadcrumb after recording" {
|
|
65
|
-
_enable
|
|
66
59
|
_breadcrumb
|
|
67
60
|
_seed_governor_event
|
|
68
61
|
_run_hook
|
|
@@ -70,7 +63,6 @@ _run_hook() {
|
|
|
70
63
|
}
|
|
71
64
|
|
|
72
65
|
@test "degrades to governor_present:false when no governor event exists" {
|
|
73
|
-
_enable
|
|
74
66
|
_breadcrumb
|
|
75
67
|
# no governor.session.complete seeded
|
|
76
68
|
_run_hook
|
|
@@ -84,7 +76,6 @@ _run_hook() {
|
|
|
84
76
|
}
|
|
85
77
|
|
|
86
78
|
@test "is idempotent across a repeated SessionEnd" {
|
|
87
|
-
_enable
|
|
88
79
|
_breadcrumb
|
|
89
80
|
_seed_governor_event
|
|
90
81
|
_run_hook
|
|
@@ -94,17 +85,7 @@ _run_hook() {
|
|
|
94
85
|
[ "$(wc -l < "$(_ledger_path)")" -eq 1 ]
|
|
95
86
|
}
|
|
96
87
|
|
|
97
|
-
@test "writes nothing when bursar is disabled" {
|
|
98
|
-
# bursar disabled (no settings written)
|
|
99
|
-
_breadcrumb
|
|
100
|
-
_seed_governor_event
|
|
101
|
-
_run_hook
|
|
102
|
-
[ "$status" -eq 0 ]
|
|
103
|
-
[ ! -d "${ONLOOKER_DIR}/bursar/projects" ]
|
|
104
|
-
}
|
|
105
|
-
|
|
106
88
|
@test "keeps the breadcrumb and emits nothing when the ledger write fails" {
|
|
107
|
-
_enable
|
|
108
89
|
_breadcrumb
|
|
109
90
|
_seed_governor_event
|
|
110
91
|
# Force bursar_ledger_record to fail: a file where the projects dir must go,
|
|
@@ -121,7 +102,6 @@ _run_hook() {
|
|
|
121
102
|
}
|
|
122
103
|
|
|
123
104
|
@test "emits bursar.session.recorded" {
|
|
124
|
-
_enable
|
|
125
105
|
_breadcrumb
|
|
126
106
|
_seed_governor_event
|
|
127
107
|
_run_hook
|