Skip to content

fix(selfhost): redact agent disposition metric repo labels#3946

Merged
JSONbored merged 1 commit into
mainfrom
codex/fix-unauthenticated-metrics-access-vulnerability
Jul 7, 2026
Merged

fix(selfhost): redact agent disposition metric repo labels#3946
JSONbored merged 1 commit into
mainfrom
codex/fix-unauthenticated-metrics-access-vulnerability

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Motivation

  • Prevent unauthenticated /metrics scrapes on self-hosted deployments from exposing private repository full names in the new disposition metric.
  • Maintain the prior public/private boundary for sensitive metrics while keeping lower-risk counters sliceable by repo for operators where appropriate.

Description

  • Move gittensory_agent_disposition_total out of the self-host opt-out set and into the always-redact set in src/selfhost/metrics.ts so its repo label is never emitted verbatim.
  • Adjust publicLabelsForMetric behavior implicitly by updating the metric classification sets so disposition metrics are redacted even when setSelfHostedMetricsMode(true) is called.
  • Update test/unit/selfhost-metrics.test.ts to assert that disposition metrics use stable redacted repo labels in both default and self-hosted modes and to remove the previous expectation that disposition repos become visible in self-host mode.
  • Commit message: fix(selfhost): redact disposition metric repos.

Testing

  • Ran unit metric tests with npx vitest run test/unit/selfhost-metrics.test.ts, which passed (36 tests passed).
  • Ran static checks with git diff --check and npm run typecheck, both succeeded locally.
  • Attempted coverage generation with npm run test:coverage -- test/unit/selfhost-metrics.test.ts; tests passed but coverage report generation failed locally due to TypeError: jsTokens is not a function in ast-v8-to-istanbul (environment-specific tooling error, tests themselves passed).
  • npm audit --audit-level=moderate could not complete in the environment (npm audit endpoint returned HTTP 403).

Codex Task

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

❌ 56 Tests Failed:

Tests completed Failed Passed Skipped
10410 56 10354 7
View the top 3 failed test(s) by shortest run time
test/integration/api.test.ts > test/integration/api.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/maintainer-activation.test.ts > test/integration/maintainer-activation.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-broker.test.ts > test/integration/orb-broker.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-ingest.test.ts > test/integration/orb-ingest.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-oauth.test.ts > test/integration/orb-oauth.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-onboarding.test.ts > test/integration/orb-onboarding.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-relay.test.ts > test/integration/orb-relay.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/orb-webhook.test.ts > test/integration/orb-webhook.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/public-quality-metrics-route-error.test.ts > test/integration/public-quality-metrics-route-error.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/public-stats-route-error.test.ts > test/integration/public-stats-route-error.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/public-stats-route.test.ts > test/integration/public-stats-route.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/routes-errors.test.ts > test/integration/routes-errors.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/integration/subnet-interface.test.ts > test/integration/subnet-interface.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/access-boundary.test.ts > test/unit/access-boundary.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/ai-key-byok.test.ts > test/unit/ai-key-byok.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/docs-examples-schema.test.ts > test/unit/docs-examples-schema.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/draft.test.ts > test/unit/draft.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/index.test.ts > test/unit/index.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/issue-watch.test.ts > test/unit/issue-watch.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/linear-key.test.ts > test/unit/linear-key.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-automation-state.test.ts > test/unit/mcp-automation-state.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-check-slop-risk.test.ts > test/unit/mcp-check-slop-risk.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-fleet-analytics.test.ts > test/unit/mcp-fleet-analytics.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-miner-prompts.test.ts > test/unit/mcp-miner-prompts.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-notifications.test.ts > test/unit/mcp-notifications.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-output-schemas.test.ts > test/unit/mcp-output-schemas.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-plan-dag.test.ts > test/unit/mcp-plan-dag.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-planning-elicitation.test.ts > test/unit/mcp-planning-elicitation.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-predict-gate.test.ts > test/unit/mcp-predict-gate.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-refresh-repo-docs.test.ts > test/unit/mcp-refresh-repo-docs.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-run-local-scorer.test.ts > test/unit/mcp-run-local-scorer.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-suggest-boundary-tests.test.ts > test/unit/mcp-suggest-boundary-tests.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-upstream.test.ts > test/unit/mcp-upstream.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-write-tools.test.ts > test/unit/mcp-write-tools.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/ops-wire.test.ts > test/unit/ops-wire.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/parity-wire.test.ts > test/unit/parity-wire.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/plan-templates.test.ts > test/unit/plan-templates.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/retention.test.ts > test/unit/retention.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-agent-approval.test.ts > test/unit/routes-agent-approval.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-ai-byok.test.ts > test/unit/routes-ai-byok.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-check-before-start.test.ts > test/unit/routes-check-before-start.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-contributor-issue-draft.test.ts > test/unit/routes-contributor-issue-draft.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-extension.test.ts > test/unit/routes-extension.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-focus-manifest.test.ts > test/unit/routes-focus-manifest.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-kill-switch.test.ts > test/unit/routes-kill-switch.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-remediation-plan.test.ts > test/unit/routes-remediation-plan.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-self-dogfood-registration-pack.test.ts > test/unit/routes-self-dogfood-registration-pack.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/routes-selfhost-dead-letter-queue.test.ts > test/unit/routes-selfhost-dead-letter-queue.test.ts
Stack Traces | 0s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/config-templates.test.ts > config/examples review templates (#1682) > gittensory.full.yml body matches .gittensory.yml.example from WHERE IT LIVES onward
Stack Traces | 0.023s run time
AssertionError: expected '# WHERE IT LIVES (first match wins):\…' to be '# WHERE IT LIVES (first match wins):\…' // Object.is equality

- Expected
+ Received

@@ -326,17 +326,10 @@
  # All values shown are the safe defaults; delete any line to inherit it.
  #
  # Review output controls. These tune review output without changing the
  # deterministic gate policy above. Omit the block to keep the byte-identical
  # defaults.
- #
- # SELF-HOST ONLY (`review.shared_config`, #2046): when `GITTENSORY_REPO_CONFIG_DIR` is mounted,
- # place a shared review base at `${GITTENSORY_REPO_CONFIG_DIR}/_shared/.gittensory.yml` (see
- # `config/examples/shared.gittensory.yml`). Per-repo `review:` keys overlay it field-by-field —
- # repo value wins when set, shared fills gaps, defaults stay byte-identical. Absent shared base is
- # the common case and changes nothing. A malformed shared base warns and is ignored (never blocks a
- # review). The loader records provenance at runtime in `review.sharedConfigSource` (not a YAML key).
  review:
    # Deterministic AI review eligibility filters (`review.auto_review`, #1954 / #2038–#2065). Each knob quietly
    # skips the advisory AI review for matching PRs — never a gate failure. When the Orb review check is enabled,
    # skipped PRs complete as "skipped" with a human-readable reason (see `evaluateAutoReviewSkipReason` in
    # `src/signals/focus-manifest.ts` and the public-surface `SKIP_SUMMARY.ignored_author` mapping in

 ❯ test/unit/config-templates.test.ts:36:57
test/unit/mcp-server-telemetry.test.ts > MCP server telemetry > falls back when Hono does not expose an execution context
Stack Traces | 0.0344s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-server-telemetry.test.ts > MCP server telemetry > records session-scoped MCP request errors without a tool name
Stack Traces | 0.063s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/mcp-server-telemetry.test.ts > MCP server telemetry > records sanitized error telemetry when the MCP transport handler throws
Stack Traces | 0.215s run time
Error: Failed to resolve entry for package "@jsonbored/gittensory-engine". The package may have incorrect main/module/exports specified in its package.json.
 ❯ .../gittensory-miner/lib/opportunity-fanout.js:2:1
 ❯ src/mcp/find-opportunities.ts:11:1
test/unit/queue.test.ts > auto-action convergence: end-to-end plan+execute for the general heuristic path (#selfhost-auto-action-convergence) > a guardrail-path hold (neutral gate conclusion) records blocker_class=guardrail_hold, not 'none'
Stack Traces | 0.702s run time
AssertionError: expected '# HELP gittensory_github_response_cac…' to contain 'gittensory_agent_disposition_total{ac…'

- Expected
+ Received

- gittensory_agent_disposition_total{action_class="hold",autonomy_level="auto",blocker_class="guardrail_hold"} 1
+ # HELP gittensory_github_response_cache_total GitHub response cache outcomes by response class.
+ # TYPE gittensory_github_response_cache_total counter
+ gittensory_github_response_cache_total{class="disabled",result="bypassed"} 11
+ gittensory_github_pull_request_files_fetch_total{caller="live_review"} 1
+ gittensory_github_response_cache_total{class="sensitive",result="bypassed"} 17
+ # HELP gittensory_pr_state_cache_total Pull-request state cache outcomes.
+ # TYPE gittensory_pr_state_cache_total counter
+ gittensory_pr_state_cache_total{field="mergeable_state",result="miss"} 1
+ gittensory_pr_state_cache_total{field="write",result="set"} 1
+ # HELP gittensory_ci_state_cache_total CI-state snapshot cache outcomes.
+ # TYPE gittensory_ci_state_cache_total counter
+ gittensory_ci_state_cache_total{field="aggregate",result="miss"} 1
+ gittensory_ci_state_cache_total{field="write",result="set"} 2
+ # HELP gittensory_github_graphql_cache_total GitHub GraphQL cache outcomes by response class.
+ # TYPE gittensory_github_graphql_cache_total counter
+ gittensory_github_graphql_cache_total{class="sensitive",result="bypassed"} 2
+ gittensory_ci_state_cache_total{field="aggregate",result="forced"} 1
+ # HELP gittensory_agent_disposition_total Final agent disposition per PR pass (merge/close/hold), by repo, action class, blocker-code class, and autonomy level.
+ # TYPE gittensory_agent_disposition_total counter
+ gittensory_agent_disposition_total{action_class="hold",autonomy_level="auto",blocker_class="guardrail_hold",repo="redacted-1"} 1
+

 ❯ test/unit/queue.test.ts:27176:35
test/unit/queue.test.ts > auto-action convergence: end-to-end plan+execute for the general heuristic path (#selfhost-auto-action-convergence) > REGRESSION (#selfhost-backlog-convergence): a CI-pending PR defers, then merges once check_suite.completed reports CI green (convergence chain)
Stack Traces | 0.799s run time
AssertionError: expected '# HELP gittensory_github_response_cac…' to contain 'gittensory_agent_disposition_total{ac…'

- Expected
+ Received

- gittensory_agent_disposition_total{action_class="merge",autonomy_level="auto",blocker_class="none"} 1
+ # HELP gittensory_github_response_cache_total GitHub response cache outcomes by response class.
+ # TYPE gittensory_github_response_cache_total counter
+ gittensory_github_response_cache_total{class="sensitive",result="bypassed"} 16
+ # HELP gittensory_pr_state_cache_total Pull-request state cache outcomes.
+ # TYPE gittensory_pr_state_cache_total counter
+ gittensory_pr_state_cache_total{field="write",result="set"} 1
+ # HELP gittensory_ci_state_cache_total CI-state snapshot cache outcomes.
+ # TYPE gittensory_ci_state_cache_total counter
+ gittensory_ci_state_cache_total{field="aggregate",result="miss"} 1
+ gittensory_ci_state_cache_total{field="write",result="set"} 2
+ gittensory_github_response_cache_total{class="disabled",result="bypassed"} 9
+ # HELP gittensory_github_graphql_cache_total GitHub GraphQL cache outcomes by response class.
+ # TYPE gittensory_github_graphql_cache_total counter
+ gittensory_github_graphql_cache_total{class="sensitive",result="bypassed"} 2
+ gittensory_ci_state_cache_total{field="aggregate",result="forced"} 1
+ # HELP gittensory_agent_disposition_total Final agent disposition per PR pass (merge/close/hold), by repo, action class, blocker-code class, and autonomy level.
+ # TYPE gittensory_agent_disposition_total counter
+ gittensory_agent_disposition_total{action_class="merge",autonomy_level="auto",blocker_class="none",repo="redacted-1"} 1
+

 ❯ test/unit/queue.test.ts:27304:35
test/unit/queue.test.ts > auto-action convergence: end-to-end plan+execute for the general heuristic path (#selfhost-auto-action-convergence) > REGRESSION (#terminal-outcome-audit): an engaged holdonly breaker withholds a real would-merge AND increments the downgrade counter
Stack Traces | 0.856s run time
AssertionError: expected '# HELP gittensory_github_response_cac…' to contain 'gittensory_agent_disposition_total{ac…'

- Expected
+ Received

- gittensory_agent_disposition_total{action_class="hold",autonomy_level="observe",blocker_class="none"} 1
+ # HELP gittensory_github_response_cache_total GitHub response cache outcomes by response class.
+ # TYPE gittensory_github_response_cache_total counter
+ gittensory_github_response_cache_total{class="sensitive",result="bypassed"} 14
+ # HELP gittensory_pr_state_cache_total Pull-request state cache outcomes.
+ # TYPE gittensory_pr_state_cache_total counter
+ gittensory_pr_state_cache_total{field="write",result="set"} 1
+ # HELP gittensory_ci_state_cache_total CI-state snapshot cache outcomes.
+ # TYPE gittensory_ci_state_cache_total counter
+ gittensory_ci_state_cache_total{field="aggregate",result="miss"} 1
+ gittensory_ci_state_cache_total{field="write",result="set"} 2
+ gittensory_github_response_cache_total{class="disabled",result="bypassed"} 10
+ # HELP gittensory_github_graphql_cache_total GitHub GraphQL cache outcomes by response class.
+ # TYPE gittensory_github_graphql_cache_total counter
+ gittensory_github_graphql_cache_total{class="sensitive",result="bypassed"} 2
+ gittensory_ci_state_cache_total{field="aggregate",result="forced"} 1
+ # HELP gittensory_precision_breaker_downgrades_total Would-merge/would-close actions downgraded to a human hold by an accuracy circuit-breaker, by breaker direction.
+ # TYPE gittensory_precision_breaker_downgrades_total counter
+ gittensory_precision_breaker_downgrades_total{direction="merge"} 1
+ # HELP gittensory_agent_disposition_total Final agent disposition per PR pass (merge/close/hold), by repo, action class, blocker-code class, and autonomy level.
+ # TYPE gittensory_agent_disposition_total counter
+ gittensory_agent_disposition_total{action_class="hold",autonomy_level="observe",blocker_class="none",repo="redacted-1"} 1
+

 ❯ test/unit/queue.test.ts:27378:35
test/unit/queue.test.ts > auto-action convergence: end-to-end plan+execute for the general heuristic path (#selfhost-auto-action-convergence) > REGRESSION: a blocked contributor PR (plain gate failure) with close=auto is actually closed via the general heuristic-close path
Stack Traces | 1.12s run time
AssertionError: expected '# HELP gittensory_github_response_cac…' to contain 'gittensory_agent_disposition_total{ac…'

- Expected
+ Received

- gittensory_agent_disposition_total{action_class="close",autonomy_level="auto",blocker_class="missing_linked_issue"} 1
+ # HELP gittensory_github_response_cache_total GitHub response cache outcomes by response class.
+ # TYPE gittensory_github_response_cache_total counter
+ gittensory_github_response_cache_total{class="disabled",result="bypassed"} 11
+ gittensory_github_pull_request_files_fetch_total{caller="live_review"} 3
+ gittensory_github_response_cache_total{class="sensitive",result="bypassed"} 18
+ # HELP gittensory_pr_state_cache_total Pull-request state cache outcomes.
+ # TYPE gittensory_pr_state_cache_total counter
+ gittensory_pr_state_cache_total{field="mergeable_state",result="miss"} 1
+ gittensory_pr_state_cache_total{field="write",result="set"} 1
+ # HELP gittensory_ci_state_cache_total CI-state snapshot cache outcomes.
+ # TYPE gittensory_ci_state_cache_total counter
+ gittensory_ci_state_cache_total{field="aggregate",result="miss"} 1
+ gittensory_ci_state_cache_total{field="write",result="set"} 2
+ # HELP gittensory_github_graphql_cache_total GitHub GraphQL cache outcomes by response class.
+ # TYPE gittensory_github_graphql_cache_total counter
+ gittensory_github_graphql_cache_total{class="sensitive",result="bypassed"} 2
+ gittensory_ci_state_cache_total{field="aggregate",result="forced"} 1
+ # HELP gittensory_agent_disposition_total Final agent disposition per PR pass (merge/close/hold), by repo, action class, blocker-code class, and autonomy level.
+ # TYPE gittensory_agent_disposition_total counter
+ gittensory_agent_disposition_total{action_class="close",autonomy_level="auto",blocker_class="missing_linked_issue",repo="redacted-1"} 1
+

 ❯ test/unit/queue.test.ts:27133:35

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 7, 2026
@loopover-orb

loopover-orb Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - fixes required

Review updated: 2026-07-07 09:02:03 UTC

2 files · 1 AI reviewer · 3 blockers · readiness 93/100 · CI failing · blocked

🛑 Suggested Action - Manual Review

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.
  • AI reviewers agree on a likely critical defect: The PR description does not close or link any open issue in this repo, which this repo's contribution convention requires even for maintainer-adjacent fixes like this one — please add a `Closes #NNN` reference or confirm this was pre-authorized before merge. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
This PR moves gittensory_agent_disposition_total from the self-host opt-out set (PRIVATE_REPO_LABEL_METRICS) into the always-redact set (ALWAYS_REDACT_REPO_LABEL_METRICS) in src/selfhost/metrics.ts, closing a real privacy gap where self-hosted operators previously got verbatim repo names on this metric. The code change is correct and minimal: publicLabelsForMetric checks ALWAYS_REDACT_REPO_LABEL_METRICS before the selfHostedMetricsMode branch, so disposition labels are redacted in both modes, matching the two new/updated tests that exercise default mode and setSelfHostedMetricsMode(true) mode with real private-looking repo strings. The diff is narrow, the tests hit the actual publicLabelsForMetric path (not a fabricated scenario), and no schema/migration is implicated.

Blockers

  • The PR description does not close or link any open issue in this repo, which this repo's contribution convention requires even for maintainer-adjacent fixes like this one — please add a `Closes #NNN` reference or confirm this was pre-authorized before merge.
Nits — 5 non-blocking
  • The comment above `selfHostedMetricsMode` (src/selfhost/metrics.ts) still describes it only as letting self-host 'opt out for established per-repo counters' without noting that gittensory_agent_disposition_total is now permanently excluded from that opt-out — worth a one-line update so a future reader doesn't assume it's still governed by that flag.
  • The test comment tagged `#terminal-outcome-audit` above the `setSelfHostedMetricsMode(true) stops redacting...` test (test/unit/selfhost-metrics.test.ts) only mentions gate_decisions/reviews_published now, which is fine, but double check no other doc or comment elsewhere still lists agent_disposition_total as self-host-visible.
  • Link the motivating issue in the PR description per repo convention.
  • Update the selfHostedMetricsMode doc comment in src/selfhost/metrics.ts to explicitly call out that ALWAYS_REDACT_REPO_LABEL_METRICS members (including the disposition metric) are never affected by this flag.
  • If any operator-facing docs describe which counters are per-repo sliceable in self-host mode, update them to reflect that agent_disposition_total is no longer one of them.

Why this is blocked

  • The PR description does not close or link any open issue in this repo, which this repo's contribution convention requires even for maintainer-adjacent fixes like this one — please add a `Closes #NNN` reference or confirm this was pre-authorized before merge.
  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

CI checks failing

  • validate
  • validate-code
Signal Result Evidence
Code review ❌ 3 blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 51 registered-repo PR(s), 43 merged, 569 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 51 PR(s), 569 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 51 PR(s), 569 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 7, 2026
@JSONbored
JSONbored force-pushed the codex/fix-unauthenticated-metrics-access-vulnerability branch from 6853c01 to a3ac40f Compare July 7, 2026 09:47
@JSONbored
JSONbored merged commit 40569b4 into main Jul 7, 2026
6 of 8 checks passed
@JSONbored
JSONbored deleted the codex/fix-unauthenticated-metrics-access-vulnerability branch July 7, 2026 09:50
JSONbored added a commit that referenced this pull request Jul 7, 2026
Three independent test/doc mismatches accumulated on main from recently
merged PRs, each blocking every subsequent PR's validate-code:

- queue.test.ts: 4 disposition-metric assertions predated #3946's repo
  label redaction and still expected the unredacted literal repo name.
- predicted-gate-engine-coverage.test.ts: 3 duplicate-winner assertions
  predated #3956's anti-backdating fix and asserted the old createdAt-
  based ordering instead of the new claim-time-only, fail-closed one.
- gittensory.full.yml: missing the review.shared_config (#2046) doc
  section that .gittensory.yml.example already had, breaking their
  required byte-identical-from-marker sync.
JSONbored added a commit that referenced this pull request Jul 7, 2026
Three independent test/doc mismatches accumulated on main from recently
merged PRs, each blocking every subsequent PR's validate-code:

- queue.test.ts: 4 disposition-metric assertions predated #3946's repo
  label redaction and still expected the unredacted literal repo name.
- predicted-gate-engine-coverage.test.ts: 3 duplicate-winner assertions
  predated #3956's anti-backdating fix and asserted the old createdAt-
  based ordering instead of the new claim-time-only, fail-closed one.
- gittensory.full.yml: missing the review.shared_config (#2046) doc
  section that .gittensory.yml.example already had, breaking their
  required byte-identical-from-marker sync.
JSONbored added a commit that referenced this pull request Jul 7, 2026
…4019)

Three independent test/doc mismatches accumulated on main from recently
merged PRs, each blocking every subsequent PR's validate-code:

- queue.test.ts: 4 disposition-metric assertions predated #3946's repo
  label redaction and still expected the unredacted literal repo name.
- predicted-gate-engine-coverage.test.ts: 3 duplicate-winner assertions
  predated #3956's anti-backdating fix and asserted the old createdAt-
  based ordering instead of the new claim-time-only, fail-closed one.
- gittensory.full.yml: missing the review.shared_config (#2046) doc
  section that .gittensory.yml.example already had, breaking their
  required byte-identical-from-marker sync.
JSONbored added a commit that referenced this pull request Jul 7, 2026
Three independent test/doc mismatches accumulated on main from recently
merged PRs, each blocking every subsequent PR's validate-code:

- queue.test.ts: 4 disposition-metric assertions predated #3946's repo
  label redaction and still expected the unredacted literal repo name.
- predicted-gate-engine-coverage.test.ts: 3 duplicate-winner assertions
  predated #3956's anti-backdating fix and asserted the old createdAt-
  based ordering instead of the new claim-time-only, fail-closed one.
- gittensory.full.yml: missing the review.shared_config (#2046) doc
  section that .gittensory.yml.example already had, breaking their
  required byte-identical-from-marker sync.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant