@onlooker-community/ecosystem 0.43.6 → 0.43.7

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecosystem",
3
- "version": "0.43.6",
3
+ "version": "0.43.7",
4
4
  "description": "Observability substrate for Claude Code. Provides the shared $ONLOOKER_DIR storage root (default $HOME/.onlooker), canonical schema-validated event emission, session and tool tracking hooks, and prompt rules. Required by all other Onlooker plugins.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,9 +1,9 @@
1
1
  {
2
- ".": "0.43.6",
2
+ ".": "0.43.7",
3
3
  "plugins/archivist": "0.3.2",
4
4
  "plugins/tribunal": "1.2.8",
5
5
  "plugins/echo": "0.3.2",
6
- "plugins/cartographer": "0.6.1",
6
+ "plugins/cartographer": "0.6.2",
7
7
  "plugins/governor": "0.3.3",
8
8
  "plugins/compass": "0.4.2",
9
9
  "plugins/scribe": "0.4.3",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.43.7](https://github.com/onlooker-community/ecosystem/compare/ecosystem-v0.43.6...ecosystem-v0.43.7) (2026-08-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **cartographer:** drop a typeless finding instead of hashing it as "unknown" :broom: ([#203](https://github.com/onlooker-community/ecosystem/issues/203)) ([a949d5d](https://github.com/onlooker-community/ecosystem/commit/a949d5d43f3ae3515ac6278b35d1be5cc468cb0e))
9
+
3
10
  ## [0.43.6](https://github.com/onlooker-community/ecosystem/compare/ecosystem-v0.43.5...ecosystem-v0.43.6) (2026-08-22)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlooker-community/ecosystem",
3
- "version": "0.43.6",
3
+ "version": "0.43.7",
4
4
  "description": "Agents, skills, hooks, commands, rules, and MCP configurations that power [Onlooker](https://onlooker.dev)",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cartographer",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Proactive periodic auditor of the persistent instruction layer (CLAUDE.md, AGENTS.md, .claude/rules/). Discovers all instruction files in the repo, extracts semantic maps, and surfaces contradictions, shadowing, gaps, and drift before they cause expensive agent misbehavior. Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to the Cartographer plugin are documented here.
4
4
 
5
+ ## [0.6.2](https://github.com/onlooker-community/ecosystem/compare/cartographer-v0.6.1...cartographer-v0.6.2) (2026-08-23)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **cartographer:** drop a typeless finding instead of hashing it as "unknown" :broom: ([#203](https://github.com/onlooker-community/ecosystem/issues/203)) ([a949d5d](https://github.com/onlooker-community/ecosystem/commit/a949d5d43f3ae3515ac6278b35d1be5cc468cb0e))
11
+
5
12
  ## [0.6.1](https://github.com/onlooker-community/ecosystem/compare/cartographer-v0.6.0...cartographer-v0.6.1) (2026-08-22)
6
13
 
7
14
 
@@ -247,7 +247,29 @@ run_synthesize() {
247
247
  while IFS= read -r finding; do
248
248
  [[ -z "$finding" ]] && continue
249
249
  local ftype ffile_a fexcerpt_a ffile_b fexcerpt_b
250
- ftype=$(printf '%s' "$finding" | jq -r '.type // "unknown"')
250
+ # `// ""` collapses absent, null and empty into one check, the same way
251
+ # cartographer_issue_found_payload does — jq's `//` treats "" as
252
+ # present, so an empty type would otherwise slip past.
253
+ ftype=$(printf '%s' "$finding" | jq -r '.type // ""')
254
+
255
+ # A finding with no type is malformed: every analyzer writes a literal
256
+ # type, so this means the phase that produced it has a bug. Drop it here
257
+ # rather than hashing it.
258
+ #
259
+ # This used to default to "unknown". The emit path already refused to
260
+ # announce such a finding (ecosystem-ci0), but the orchestrator stored
261
+ # it anyway under a hash derived from a type it does not have, and then
262
+ # touched its dedup sentinel. That sentinel made the silence permanent:
263
+ # every later audit saw "known", took the refresh path, and emitted
264
+ # nothing — so the finding sat on disk forever, counted in
265
+ # new_finding_count, and could never be announced. Dropping it keeps the
266
+ # stored corpus honest and leaves the hash of every well-formed finding
267
+ # untouched, so no existing dedup sentinel is orphaned (ecosystem-0ty).
268
+ if [[ -z "$ftype" ]]; then
269
+ log "synthesize: dropped a finding that carries no type — the analyzer that produced it has a bug"
270
+ continue
271
+ fi
272
+
251
273
  ffile_a=$(printf '%s' "$finding" | jq -r '.file_a // ""')
252
274
  fexcerpt_a=$(printf '%s' "$finding" | jq -r '.excerpt_a // ""')
253
275
  ffile_b=$(printf '%s' "$finding" | jq -r '.file_b // ""')
@@ -268,10 +268,12 @@ _run_audit() {
268
268
  [ "$output" = "session_start_first_run" ]
269
269
  }
270
270
 
271
- # A typeless finding must not vanish. The builder refuses it (ecosystem-ci0),
272
- # but refusing is only half the fix: if the orchestrator discards that refusal
273
- # the event is still silently absent, one layer further up. The audit log is
274
- # where an operator would go looking for it.
271
+ # A typeless finding must not vanish. Since ecosystem-0ty the synthesize phase
272
+ # drops it before it is hashed, so this line now comes from there rather than
273
+ # from the emit-phase builder refusal that ecosystem-ci0 added. Both write
274
+ # "carries no type" on purpose: what matters to an operator is that the audit
275
+ # log says a finding was discarded and why, not which layer discarded it. The
276
+ # builder's own refusal is still covered directly in cartographer-events.bats.
275
277
  @test "a finding with no type is reported in the audit log" {
276
278
  cat > "${STUB_BIN}/claude" <<'STUB'
277
279
  #!/usr/bin/env bash
@@ -286,6 +288,50 @@ STUB
286
288
  grep -q 'carries no type' "$AUDIT_LOG"
287
289
  }
288
290
 
291
+ # Refusing to announce a typeless finding was only half of ecosystem-ci0. The
292
+ # orchestrator still stored it under a hash computed from a type it does not
293
+ # have, then touched its dedup sentinel — so on every later audit the sentinel
294
+ # said "known", the refresh path ran, and no bus event ever fired again. The
295
+ # finding sat on disk forever, counted in new_finding_count, and was
296
+ # permanently unannounceable. These three assert it is dropped instead
297
+ # (ecosystem-0ty).
298
+
299
+ _typeless_stub() {
300
+ cat > "${STUB_BIN}/claude" <<'STUB'
301
+ #!/usr/bin/env bash
302
+ cat >/dev/null
303
+ echo call >> "$CLAUDE_CALL_LOG"
304
+ printf '[{"severity":"warning","file_a":"CLAUDE.md","excerpt_a":"Always prefer tabs.","description":"typeless"}]'
305
+ STUB
306
+ chmod +x "${STUB_BIN}/claude"
307
+ }
308
+
309
+ @test "a finding with no type is never written to findings/" {
310
+ _typeless_stub
311
+ run _run_audit
312
+ [ "$status" -eq 0 ] || return 1
313
+ [ "$(find "${CARTOGRAPHER_DIR}/findings" -name '*.json' 2>/dev/null | wc -l | tr -d ' ')" = "0" ]
314
+ }
315
+
316
+ @test "a finding with no type leaves no dedup sentinel" {
317
+ # The sentinel is what made this permanent: with one on disk, a corrected
318
+ # finding that later hashes the same way would be seen as already known and
319
+ # silently refreshed instead of announced.
320
+ _typeless_stub
321
+ run _run_audit
322
+ [ "$status" -eq 0 ] || return 1
323
+ [ "$(find "${CARTOGRAPHER_DIR}/dedup" -type f 2>/dev/null | wc -l | tr -d ' ')" = "0" ]
324
+ }
325
+
326
+ @test "a finding with no type is not counted as a new finding" {
327
+ # audit.complete used to report a finding that produced no issue.found,
328
+ # so a consumer reading only the bus saw counts that its own event stream
329
+ # could not account for.
330
+ _typeless_stub
331
+ _run_audit
332
+ _last_audit_complete | jq -e '.payload.new_finding_count == 0' >/dev/null
333
+ }
334
+
289
335
 
290
336
  # ── Resolution reaching the bus (ecosystem-w2i) ──────────────────────────────
291
337
  #