@onlooker-community/ecosystem 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.github/workflows/release.yml +8 -4
  3. package/.release-please-manifest.json +3 -2
  4. package/CHANGELOG.md +14 -0
  5. package/README.md +1 -0
  6. package/docs/architecture.md +28 -22
  7. package/package.json +1 -1
  8. package/plugins/cartographer/.claude-plugin/plugin.json +14 -0
  9. package/plugins/cartographer/CHANGELOG.md +27 -0
  10. package/plugins/cartographer/README.md +113 -0
  11. package/plugins/cartographer/config.json +21 -0
  12. package/plugins/cartographer/docs/adr/001-background-audit-launch.md +28 -0
  13. package/plugins/cartographer/docs/adr/002-flock-pid-file-fallback.md +30 -0
  14. package/plugins/cartographer/docs/adr/003-at-least-once-event-delivery.md +32 -0
  15. package/plugins/cartographer/docs/adr/004-exclude-paths-replace-semantics.md +27 -0
  16. package/plugins/cartographer/hooks/hooks.json +44 -0
  17. package/plugins/cartographer/scripts/hooks/cartographer-post-write.sh +87 -0
  18. package/plugins/cartographer/scripts/hooks/cartographer-session-start.sh +89 -0
  19. package/plugins/cartographer/scripts/lib/cartographer-analyze.sh +286 -0
  20. package/plugins/cartographer/scripts/lib/cartographer-collect.sh +59 -0
  21. package/plugins/cartographer/scripts/lib/cartographer-config.sh +105 -0
  22. package/plugins/cartographer/scripts/lib/cartographer-events.sh +82 -0
  23. package/plugins/cartographer/scripts/lib/cartographer-lock.sh +38 -0
  24. package/plugins/cartographer/scripts/lib/cartographer-project-key.sh +55 -0
  25. package/plugins/cartographer/scripts/lib/cartographer-ulid.sh +47 -0
  26. package/plugins/cartographer/scripts/run-audit.sh +309 -0
  27. package/plugins/cartographer/skills/cartographer/SKILL.md +154 -0
  28. package/release-please-config.json +16 -0
  29. package/test/bats/cartographer-config.bats +107 -0
  30. package/test/bats/cartographer-lock.bats +77 -0
  31. package/test/bats/cartographer-ulid.bats +56 -0
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ source "${BATS_TEST_DIRNAME}/../helpers/setup.bash"
5
+ setup_test_env
6
+
7
+ PLUGIN_ROOT="${REPO_ROOT}/plugins/cartographer"
8
+ export CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT"
9
+ # shellcheck disable=SC1091
10
+ source "${PLUGIN_ROOT}/scripts/lib/cartographer-config.sh"
11
+ }
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
+ @test "deep merge: user-level partial override preserves plugin defaults" {
39
+ mkdir -p "${HOME}/.claude"
40
+ printf '%s\n' '{"cartographer":{"audit_interval_hours":12}}' > "${HOME}/.claude/settings.json"
41
+ cartographer_config_load ""
42
+ local interval model
43
+ interval=$(cartographer_config_audit_interval_hours)
44
+ model=$(cartographer_config_model_extraction)
45
+ [ "$interval" = "12" ]
46
+ [ "$model" = "claude-haiku-4-5-20251001" ]
47
+ }
48
+
49
+ @test "deep merge: repo overrides user but preserves user keys not in repo" {
50
+ mkdir -p "${HOME}/.claude"
51
+ printf '%s\n' '{"cartographer":{"audit_interval_hours":6,"phase_timeout_seconds":30}}' > "${HOME}/.claude/settings.json"
52
+ local repo="${BATS_TEST_TMPDIR}/repo2"
53
+ mkdir -p "${repo}/.claude"
54
+ printf '%s\n' '{"cartographer":{"audit_interval_hours":48}}' > "${repo}/.claude/settings.json"
55
+ cartographer_config_load "$repo"
56
+ local interval timeout_s
57
+ interval=$(cartographer_config_audit_interval_hours)
58
+ timeout_s=$(cartographer_config_phase_timeout)
59
+ [ "$interval" = "48" ]
60
+ [ "$timeout_s" = "30" ]
61
+ }
62
+
63
+ @test "model_extraction falls back to default when not configured" {
64
+ cartographer_config_load ""
65
+ local v
66
+ v=$(cartographer_config_model_extraction)
67
+ [ "$v" = "claude-haiku-4-5-20251001" ]
68
+ }
69
+
70
+ @test "model_synthesis falls back to default when not configured" {
71
+ cartographer_config_load ""
72
+ local v
73
+ v=$(cartographer_config_model_synthesis)
74
+ [ "$v" = "claude-haiku-4-5-20251001" ]
75
+ }
76
+
77
+ @test "model_extraction respects user-level override" {
78
+ mkdir -p "${HOME}/.claude"
79
+ printf '%s\n' '{"cartographer":{"extraction":{"model":"claude-sonnet-4-6"}}}' > "${HOME}/.claude/settings.json"
80
+ cartographer_config_load ""
81
+ local v
82
+ v=$(cartographer_config_model_extraction)
83
+ [ "$v" = "claude-sonnet-4-6" ]
84
+ }
85
+
86
+ @test "phase_timeout_seconds defaults to 60" {
87
+ cartographer_config_load ""
88
+ local v
89
+ v=$(cartographer_config_phase_timeout)
90
+ [ "$v" = "60" ]
91
+ }
92
+
93
+ @test "audit_interval_hours defaults to 24" {
94
+ cartographer_config_load ""
95
+ local v
96
+ v=$(cartographer_config_audit_interval_hours)
97
+ [ "$v" = "24" ]
98
+ }
99
+
100
+ @test "exclude_paths defaults are non-empty JSON array" {
101
+ cartographer_config_load ""
102
+ local v
103
+ v=$(cartographer_config_exclude_paths)
104
+ # Must be a non-empty JSON array containing node_modules
105
+ echo "$v" | jq -e 'type == "array" and length > 0' >/dev/null
106
+ echo "$v" | jq -e 'any(. == "node_modules")' >/dev/null
107
+ }
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ source "${BATS_TEST_DIRNAME}/../helpers/setup.bash"
5
+ setup_test_env
6
+ # shellcheck disable=SC1091
7
+ source "${REPO_ROOT}/plugins/cartographer/scripts/lib/cartographer-lock.sh"
8
+
9
+ LOCK_FILE="${BATS_TEST_TMPDIR}/test.lock"
10
+ }
11
+
12
+ teardown() {
13
+ cartographer_lock_release "$LOCK_FILE" 2>/dev/null || true
14
+ }
15
+
16
+ @test "acquire succeeds when lock is free" {
17
+ run cartographer_lock_acquire "$LOCK_FILE"
18
+ [ "$status" -eq 0 ]
19
+ }
20
+
21
+ @test "acquire fails immediately when lock is already held" {
22
+ cartographer_lock_acquire "$LOCK_FILE"
23
+ run cartographer_lock_acquire "$LOCK_FILE"
24
+ [ "$status" -ne 0 ]
25
+ }
26
+
27
+ @test "release allows re-acquire" {
28
+ cartographer_lock_acquire "$LOCK_FILE"
29
+ cartographer_lock_release "$LOCK_FILE"
30
+ run cartographer_lock_acquire "$LOCK_FILE"
31
+ [ "$status" -eq 0 ]
32
+ }
33
+
34
+ @test "is_held returns true while lock is held" {
35
+ cartographer_lock_acquire "$LOCK_FILE"
36
+ run cartographer_lock_is_held "$LOCK_FILE"
37
+ [ "$status" -eq 0 ]
38
+ }
39
+
40
+ @test "is_held returns false after release" {
41
+ cartographer_lock_acquire "$LOCK_FILE"
42
+ cartographer_lock_release "$LOCK_FILE"
43
+ run cartographer_lock_is_held "$LOCK_FILE"
44
+ [ "$status" -ne 0 ]
45
+ }
46
+
47
+ @test "release is idempotent (safe to call when not held)" {
48
+ run cartographer_lock_release "$LOCK_FILE"
49
+ [ "$status" -eq 0 ]
50
+ }
51
+
52
+ @test "two independent lock paths do not interfere" {
53
+ local lock_a="${BATS_TEST_TMPDIR}/a.lock"
54
+ local lock_b="${BATS_TEST_TMPDIR}/b.lock"
55
+ cartographer_lock_acquire "$lock_a"
56
+ run cartographer_lock_acquire "$lock_b"
57
+ [ "$status" -eq 0 ]
58
+ cartographer_lock_release "$lock_a"
59
+ cartographer_lock_release "$lock_b"
60
+ }
61
+
62
+ @test "background child holds lock after parent releases its reference" {
63
+ # Acquire in a background subprocess, then verify is_held from this process.
64
+ bash -c "
65
+ source '${REPO_ROOT}/plugins/cartographer/scripts/lib/cartographer-lock.sh'
66
+ cartographer_lock_acquire '${LOCK_FILE}'
67
+ sleep 2
68
+ cartographer_lock_release '${LOCK_FILE}'
69
+ " &
70
+ sleep 0.1
71
+ run cartographer_lock_is_held "$LOCK_FILE"
72
+ [ "$status" -eq 0 ]
73
+ # Second acquire from this process must fail while child holds it
74
+ run cartographer_lock_acquire "$LOCK_FILE"
75
+ [ "$status" -ne 0 ]
76
+ wait
77
+ }
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ source "${BATS_TEST_DIRNAME}/../helpers/setup.bash"
5
+ setup_test_env
6
+ # shellcheck disable=SC1091
7
+ source "${REPO_ROOT}/plugins/cartographer/scripts/lib/cartographer-ulid.sh"
8
+ }
9
+
10
+ @test "cartographer_ulid returns a 26-char Crockford Base32 string" {
11
+ local id
12
+ id=$(cartographer_ulid)
13
+ [ "${#id}" -eq 26 ]
14
+ [[ "$id" =~ ^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$ ]]
15
+ }
16
+
17
+ @test "two ULIDs minted apart are lexicographically ordered" {
18
+ local a b
19
+ a=$(cartographer_ulid)
20
+ sleep 0.01
21
+ b=$(cartographer_ulid)
22
+ [[ "$a" < "$b" ]] || [ "$a" = "$b" ]
23
+ }
24
+
25
+ @test "many ULIDs are unique" {
26
+ local seen="${BATS_TEST_TMPDIR}/ulids.txt"
27
+ : > "$seen"
28
+ local i
29
+ for ((i = 0; i < 50; i++)); do
30
+ printf '%s\n' "$(cartographer_ulid)" >> "$seen"
31
+ done
32
+ local total unique
33
+ total=$(wc -l < "$seen" | tr -d ' ')
34
+ unique=$(sort -u "$seen" | wc -l | tr -d ' ')
35
+ [ "$total" = "$unique" ]
36
+ }
37
+
38
+ @test "random component is 16 chars (full 80-bit coverage)" {
39
+ local id
40
+ id=$(cartographer_ulid)
41
+ # Characters 10-25 (0-indexed) are the random component
42
+ local rand_part="${id:10:16}"
43
+ [ "${#rand_part}" -eq 16 ]
44
+ }
45
+
46
+ @test "timestamp component sorts ULIDs correctly across 10+ calls" {
47
+ local prev=""
48
+ local id
49
+ for _ in 1 2 3 4 5 6 7 8 9 10; do
50
+ id=$(cartographer_ulid)
51
+ if [[ -n "$prev" ]]; then
52
+ [[ "$prev" < "$id" ]] || [ "$prev" = "$id" ]
53
+ fi
54
+ prev="$id"
55
+ done
56
+ }