stacktrace-cli 0.2.1__tar.gz → 0.2.3__tar.gz
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.
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/PKG-INFO +5 -4
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/README.md +4 -3
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0004-three-stage-detector.md +2 -0
- stacktrace_cli-0.2.3/docs/adrs/0028-the-console-shows-what-it-placed.md +108 -0
- stacktrace_cli-0.2.3/docs/adrs/0029-stage-three-returns-to-opt-in.md +115 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/INDEX.md +2 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/007-detection-upload.md +2 -2
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/008-monitor.md +1 -1
- stacktrace_cli-0.2.3/docs/releases/v0.2.2.md +76 -0
- stacktrace_cli-0.2.3/docs/releases/v0.2.3.md +102 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/detection-upload.md +1 -1
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/detector.md +5 -5
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/monitor.md +25 -9
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/pyproject.toml +1 -1
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/__init__.py +1 -1
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/cli.py +25 -17
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/acquire.py +154 -2
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/render.py +9 -12
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/render.py +6 -2
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/app.js +48 -46
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/index.html +1 -7
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/styles.css +0 -5
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/cli.py +3 -4
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/sync_detect.py +7 -1
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/feed_harness.mjs +62 -12
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_feed_model.py +55 -31
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_render.py +19 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_site_assets.py +8 -4
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_cli.py +3 -3
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_sync_detect.py +89 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_acquire.py +299 -2
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_cli.py +57 -17
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_render.py +29 -12
- stacktrace_cli-0.2.3/tests/test_no_live_document_states_the_old_escalate_default.py +158 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_openaca_contract.py +7 -1
- stacktrace_cli-0.2.3/tests/test_stored_verdicts_are_never_gated_on_escalate.py +74 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/uv.lock +1 -1
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.agents/skills/release-stacktrace/SKILL.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.claude/settings.json +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.claude/skills/release-stacktrace/SKILL.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.codex/hooks.json +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.github/workflows/autofix.yml +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.github/workflows/ci.yml +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.github/workflows/claude.yml +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.github/workflows/publish-pypi.yml +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/.gitignore +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/AGENTS.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/CLAUDE.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0001-session-telemetry-as-input.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0002-session-collection-in-openaidr.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0003-runtime-edges.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0005-detection-family-and-report-assembly.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0006-trust-boundary-and-detection-upload.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0007-proprietary-package-on-open-dependencies.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0008-console-in-separate-demo-package.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0010-detection-severity-and-confidence-ladders.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0011-verdict-cache.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0012-observation-evidence-kinds-and-transport.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0013-rule-catalogue-triage-and-per-rule-context.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0014-declared-project-mapping.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0015-narrow-the-security-catalogue.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0016-stall-grouping-is-session-wide.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0017-a-declined-repeat-is-a-stall.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0018-remote-sync-config-and-facade-consumption.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0019-delegated-commands-are-openaca-objects.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0020-openaca-consumption-boundary.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0021-two-command-kinds.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0022-detection-scope-is-a-catalogue-column.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0023-sync-detect-collects-and-does-not-escalate.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0024-the-upload-carries-observations.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0025-a-denied-call-is-activity-never-an-invocation.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0026-the-console-becomes-a-product-surface.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/0027-a-finding-may-name-what-it-could-not-place.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/HOOK-PROMPT.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/adrs/TEMPLATE.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/cutover-openaca-remote.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/002-session-input.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/003-correlation.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/004-detector.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/005-remote-sync.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/plans/006-cli-composition.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/releases/v0.0.1.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/releases/v0.1.0.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/releases/v0.2.0.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/releases/v0.2.1.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/aidr.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/cli-composition.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/correlation.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/remote-sync.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/docs/specs/session-input.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/scripts/git-hooks/pre-push +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/scripts/install-hooks.sh +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/__main__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/analysis.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/composition.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/join.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/observed.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/orchestrate.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/project_map.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/record.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/correlate/render.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/analyzer.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/cache.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/deterministic.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/finding.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/markers.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/priors.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/v1/exclusions.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/v1/framing.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/v1/stacktrace-deceptive-completion.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/v1/stacktrace-injected-instruction-followed.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/prompts/v1/stacktrace-intent-drift.md +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/reasoning.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/rules.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/run.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/secrets.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/detector/verdict.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/escalate.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/server.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/fonts/OFL.txt +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/fonts/dm-mono-400-latin.woff2 +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/fonts/dm-mono-500-latin.woff2 +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/site/fonts/dm-sans-latin.woff2 +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/state.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/verdicts.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/monitor/watch.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/client.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/config.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/detect_payload.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/payload.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/policy.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/redact.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/spool.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/sync.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/remote/upload_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/sessions/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/sessions/access.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/sessions/outcome.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/sessions/protocols.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/src/stacktrace_cli/sessions/render.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/agent_bom_fixture.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/detector_session_fixture.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_escalation_gates.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_server.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_state.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_verdicts.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/monitor/test_watch.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/__init__.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/helpers.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_cli.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_client.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_config.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_activity.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_client.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_contract_is_exhaustive.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_gate_matches_the_cloud.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_layers_compose.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_payload_reaches_the_cloud_model.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_redaction.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_spool.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_upload_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_detect_wire_payload.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_facade_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_payload.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_policy.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_redact_payload.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_seam.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_spool.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_sync.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/remote/test_upload_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_agent_instance_id.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_analysis.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_bom_shape.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_call_status_conventions.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_composition.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_correlate_orchestrate.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_correlate_render.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_correlated_session.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detection_components.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detection_subject.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_analyzer_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_analyzer_live.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_cache.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_deterministic.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_end_to_end.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_finding.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_liveness.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_markers.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_priors.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_reasoning.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_run.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_secrets.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_detector_verdict.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_fingerprint_covers_what_the_analyzer_reads.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_help_sections.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_join.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_monitor_cli.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_observed.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_openaidr_contract.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_option_arity_matches_the_binary.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_project_map.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_readme_examples_are_real_output.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_release_readiness.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_seam_boundary.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_sessions_access.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_sessions_end_to_end.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_sessions_protocol_typing.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_sessions_protocols.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_sessions_render.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_shell_separators_match_the_shell.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_untrusted_content_never_travels.py +0 -0
- {stacktrace_cli-0.2.1 → stacktrace_cli-0.2.3}/tests/test_verification_subcommands_match_the_binary.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: stacktrace-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: CLI for Stacktrace — Detection and Response platform for AI Agents.
|
|
5
5
|
Project-URL: Homepage, https://stacktrace.ai
|
|
6
6
|
Author-email: "Stacktrace AI, Inc" <founders@stacktrace.ai>
|
|
@@ -126,9 +126,10 @@ because it is installed.
|
|
|
126
126
|
## What leaves your machine
|
|
127
127
|
|
|
128
128
|
Two of `detect`'s three stages run entirely locally and need no model or
|
|
129
|
-
credential
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
credential, and they are the two a bare `detect` runs. The third sends flagged
|
|
130
|
+
sessions to the agent's *own* CLI — the provider that produced the transcript,
|
|
131
|
+
never a different one — and runs only when you pass `--escalate`, capped by
|
|
132
|
+
`--budget`.
|
|
132
133
|
|
|
133
134
|
`sessions` omits prompts, tool arguments and results unless you pass
|
|
134
135
|
`--include-content`. `monitor` binds to loopback only, refuses a non-loopback
|
|
@@ -101,9 +101,10 @@ because it is installed.
|
|
|
101
101
|
## What leaves your machine
|
|
102
102
|
|
|
103
103
|
Two of `detect`'s three stages run entirely locally and need no model or
|
|
104
|
-
credential
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
credential, and they are the two a bare `detect` runs. The third sends flagged
|
|
105
|
+
sessions to the agent's *own* CLI — the provider that produced the transcript,
|
|
106
|
+
never a different one — and runs only when you pass `--escalate`, capped by
|
|
107
|
+
`--budget`.
|
|
107
108
|
|
|
108
109
|
`sessions` omits prompts, tool arguments and results unless you pass
|
|
109
110
|
`--include-content`. `monitor` binds to loopback only, refuses a non-loopback
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 0028
|
|
3
|
+
title: The console shows what it placed, and states no coverage
|
|
4
|
+
status: accepted
|
|
5
|
+
date: 2026-09-08
|
|
6
|
+
supersedes: null
|
|
7
|
+
superseded-by: null
|
|
8
|
+
amends: null
|
|
9
|
+
amended-by: null
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Context
|
|
13
|
+
|
|
14
|
+
A reader opened `stacktrace monitor` on their own machine and asked why the
|
|
15
|
+
busiest row on the page was red. The row was the grouped built-in row for one
|
|
16
|
+
project — 4,467 calls over five days — and it carried `⚠ 16 refusals`. All 16
|
|
17
|
+
were `user-rejected` in the transcript, and their recorded reasons were the
|
|
18
|
+
Bash gate rather than a person: 29 `contains multiple operations`, 28 `requires
|
|
19
|
+
approval`, 6 `changes directory before running git`, 3 `brace with quote
|
|
20
|
+
character (expansion obfuscation)`, 2 `parser aborted`, 1 `contains
|
|
21
|
+
for_statement` across the project's 70 denials. Nothing reached a tool.
|
|
22
|
+
|
|
23
|
+
`sessions/outcome.py` already states the rule: *a denied call reached nothing,
|
|
24
|
+
so it is evidence of nothing* — written after six sites had each grown their own
|
|
25
|
+
`status == "rejected"` test. The page took that rule for its counters and then
|
|
26
|
+
painted the row red anyway, which reports the permission prompt as the
|
|
27
|
+
incident. ADR-0025 left this open deliberately: its Consequences name "a second
|
|
28
|
+
counter every activity read surface must decide whether to show".
|
|
29
|
+
|
|
30
|
+
The same page led with `⚠ unresolved` rows, an `Unresolved` row in the overview
|
|
31
|
+
table, a legend line, and a `6,867/7,055 placed` header fraction. `unresolved`
|
|
32
|
+
is a fact about the *record*, with four causes the reader cannot distinguish and
|
|
33
|
+
none of which they can act on: absent from the composition, no composition for
|
|
34
|
+
that agent kind, an ambiguous match, or a matched component whose type the
|
|
35
|
+
category map does not know. The row names no component — `classify_call`
|
|
36
|
+
returns no name for it by design (ADR-0027 admits a name at one position, and an
|
|
37
|
+
activity row is not one) — so what reached the reader was "something happened
|
|
38
|
+
and nothing here claims it", set in the page's warning colour.
|
|
39
|
+
|
|
40
|
+
The rule that would have made such a call actionable, `unsanctioned-mcp-tool-use`,
|
|
41
|
+
was withdrawn by ADR-0015. So no live rule is about an unplaceable call, and the
|
|
42
|
+
page was warning about something it could not then explain.
|
|
43
|
+
|
|
44
|
+
## Decision
|
|
45
|
+
|
|
46
|
+
The console renders only activity it could place, and states no coverage
|
|
47
|
+
figure. Rows whose category is `unresolved` are dropped at the page boundary;
|
|
48
|
+
the `N/M placed` fraction and its `placing…` placeholder are gone from the
|
|
49
|
+
header, which now counts sessions and the actions it actually shows; a refusal
|
|
50
|
+
is counted in a row's `×N` and carries no badge and no colour; the
|
|
51
|
+
no-composition banner is gone, leaving the two banners that report a *reader*
|
|
52
|
+
which came back with nothing.
|
|
53
|
+
|
|
54
|
+
The snapshot contract does not change. `_activity` still emits unresolved rows,
|
|
55
|
+
`summary.coverage` and each session's `coverage` are still computed and still
|
|
56
|
+
sent, `activity_for_upload` and the `denied` counter are untouched, and every
|
|
57
|
+
detector rule reads what it always read. `stacktrace correlate` remains the
|
|
58
|
+
surface where coverage and unplaceability are the subject; ADR-0026's clause
|
|
59
|
+
holds, because a page that shows less has still invented nothing.
|
|
60
|
+
|
|
61
|
+
## Alternatives considered
|
|
62
|
+
|
|
63
|
+
- **Filter in `_activity`, server-side** — rejected. The snapshot is also the
|
|
64
|
+
`/api/state` contract and the thing `tests/monitor/test_render.py` holds; a
|
|
65
|
+
page decision that narrows the record makes the two disagree, and the next
|
|
66
|
+
surface built on the snapshot would inherit a filter it never asked for.
|
|
67
|
+
- **Keep the rows, drop only the warning framing** — rejected by the person the
|
|
68
|
+
page is for. Neutral wording does not give the row a subject: with no
|
|
69
|
+
component name there is nothing for a reader to look up, so a quiet row is
|
|
70
|
+
the same non-answer in a calmer colour.
|
|
71
|
+
- **Keep the coverage fraction** — rejected. The gap between numerator and
|
|
72
|
+
denominator *is* the count of rows the page no longer shows, so the header
|
|
73
|
+
restated by arithmetic exactly what the feed had stopped saying.
|
|
74
|
+
- **Keep the red on refusals alone** — rejected. It is the page asserting the
|
|
75
|
+
opposite of `outcome.py`'s rule about the same call, and the measured reasons
|
|
76
|
+
above are a guardrail working, not an endpoint under attack.
|
|
77
|
+
- **Reword the no-composition banner rather than remove it** — rejected after
|
|
78
|
+
trying it. "No Agent BOM found, so its components are not identified" is the
|
|
79
|
+
same claim one step back, and it sends a reader looking for rows that are no
|
|
80
|
+
longer there.
|
|
81
|
+
|
|
82
|
+
## Consequences
|
|
83
|
+
|
|
84
|
+
The page stops answering one question it used to answer badly: how much of the
|
|
85
|
+
window it could not attribute. A reader who wants that runs `stacktrace
|
|
86
|
+
correlate`, where the figure is the subject and the four causes are named
|
|
87
|
+
separately; the fleet still receives it, because the upload path is untouched.
|
|
88
|
+
|
|
89
|
+
The costs are real and worth naming. An agent kind with no Agent BOM now shows
|
|
90
|
+
fewer categories in the overview table and says nothing about why — the built-in
|
|
91
|
+
preview rows still appear, so the page does not go blank, but the absence is
|
|
92
|
+
silent. A responder cannot see from the console that an MCP call went to a
|
|
93
|
+
server no scan can find. And a denied-heavy endpoint — ADR-0025's own example of
|
|
94
|
+
a fact visible on no surface — is still visible on none.
|
|
95
|
+
|
|
96
|
+
**Watch for:** a second page-side filter added the same way, without an ADR,
|
|
97
|
+
because this one made it look routine; and the header regaining any derived
|
|
98
|
+
ratio, which is the shape this decision removed.
|
|
99
|
+
|
|
100
|
+
## When to revisit
|
|
101
|
+
|
|
102
|
+
If ADR-0015's `unsanctioned-mcp-tool-use` returns, revisit immediately: its
|
|
103
|
+
evidence is exactly the rows this decision hides, and a finding whose subject
|
|
104
|
+
cannot be seen on the page it is reported on is worse than either state alone.
|
|
105
|
+
Also if the console gains an affordance for *why something is missing* — a
|
|
106
|
+
per-kind detail view, say — which is where the coverage figure and the four
|
|
107
|
+
causes belong, or if a remote surface starts reading the local snapshot and
|
|
108
|
+
assuming the page's filtering rather than the record's contents.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 0029
|
|
3
|
+
title: Stage three returns to opt-in
|
|
4
|
+
status: accepted
|
|
5
|
+
date: 2026-09-09
|
|
6
|
+
supersedes: null
|
|
7
|
+
superseded-by: null
|
|
8
|
+
amends: 0004
|
|
9
|
+
amended-by: null
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Context
|
|
13
|
+
|
|
14
|
+
ADR-0004 was amended on 2026-09-03 to default `--escalate` **on** for
|
|
15
|
+
`stacktrace detect`. The reasoning was sound and the amendment said so plainly:
|
|
16
|
+
a stage nobody turns on never runs, and rules that depend on it — `injection-
|
|
17
|
+
marker` above all — can only ever be evaluated against zero verdicts. It also
|
|
18
|
+
named its own exit: *"Revisit once there is a measured escalation rate and
|
|
19
|
+
verdict yield to argue from; if the yield does not justify the spend, the
|
|
20
|
+
honest move is back to opt-in rather than a narrower cap."*
|
|
21
|
+
|
|
22
|
+
What forces the revisit now is not the yield. It is that the default was only
|
|
23
|
+
ever changed in one of the three places that carry it, and the other two — plus
|
|
24
|
+
everything we publish — kept saying the opposite:
|
|
25
|
+
|
|
26
|
+
| Surface | Default |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `run_detector()` | `escalate=False` |
|
|
29
|
+
| `stacktrace monitor` | `False` — *"a page left open is the wrong place for that to be implicit"* |
|
|
30
|
+
| `remote sync detect` | `False` (ADR-0023) |
|
|
31
|
+
| `stacktrace detect` | `True` |
|
|
32
|
+
|
|
33
|
+
The published quickstart tells a new user to run `stacktrace detect
|
|
34
|
+
--no-escalate`, annotated *"# Investigate without model escalation"* — a
|
|
35
|
+
documented first command whose only purpose is to undo the default. The site's
|
|
36
|
+
data-handling section makes the same promise in prose: *"Start with detection
|
|
37
|
+
that doesn't send session content to a model."* `docs/plans/004-detector.md`
|
|
38
|
+
still describes the stage as opt-in. One surface out of four, contradicted by
|
|
39
|
+
its own documentation, is not a default; it is a divergence.
|
|
40
|
+
|
|
41
|
+
Be honest about the evidence this ADR does **not** have. The escalation rate is
|
|
42
|
+
low — an audit on 2026-09-02 measured 3 escalations across 635 sessions, 1 on
|
|
43
|
+
evidence and 2 sampled — but that audit predates the amendment and so describes
|
|
44
|
+
behaviour under the opt-in default it is being used to restore. Verdict yield,
|
|
45
|
+
the other half of what ADR-0004 asked for, has not been measured. Stage 3 has
|
|
46
|
+
also still never run against a real analyzer: the `live_cli` test is opt-in and
|
|
47
|
+
deselected. So this is not the evidence-based revisit ADR-0004 anticipated. It
|
|
48
|
+
is a consistency and consent decision taken ahead of that evidence.
|
|
49
|
+
|
|
50
|
+
## Decision
|
|
51
|
+
|
|
52
|
+
`stacktrace detect` defaults `--escalate` off, matching `run_detector`,
|
|
53
|
+
`monitor` and `sync detect`. A bare `stacktrace detect` sends no session content
|
|
54
|
+
off the machine.
|
|
55
|
+
|
|
56
|
+
Two things travel with it. The verdict cache is no longer gated on `escalate`:
|
|
57
|
+
`run_detector` already states that a verdict already paid for is an answer this
|
|
58
|
+
run *has*, and that `escalate` governs whether new ones may be commissioned, not
|
|
59
|
+
whether old ones may be read — `cli.py` contradicted that, and flipping the
|
|
60
|
+
default without fixing it would have made every stored verdict silently
|
|
61
|
+
unreadable on the default path. And a run that declines to escalate still counts
|
|
62
|
+
and names the sessions that qualified, as `reasoning_not_requested`, so a run
|
|
63
|
+
without stage 3 does not read as a clean one.
|
|
64
|
+
|
|
65
|
+
## Alternatives considered
|
|
66
|
+
|
|
67
|
+
- **Leave it on and fix only the docs.** Rejected: the quickstart, the
|
|
68
|
+
data-handling copy and the plan all describe opt-in, and three of four code
|
|
69
|
+
surfaces implement it. Changing four things to match one is the wrong
|
|
70
|
+
direction, and the one is the surface that spends the user's money.
|
|
71
|
+
- **Keep it on until verdict yield is measured, as ADR-0004 asked.** Rejected on
|
|
72
|
+
consent rather than evidence: the measurement requires a bare `detect` to keep
|
|
73
|
+
sending transcript content to a provider by default, and the same measurement
|
|
74
|
+
is obtainable from users who opt in. The amendment accepted that cost
|
|
75
|
+
deliberately; what it did not anticipate is that we would simultaneously
|
|
76
|
+
publish the opposite promise.
|
|
77
|
+
- **A narrower cap instead of opt-in.** Rejected by ADR-0004 itself, in advance:
|
|
78
|
+
*"the honest move is back to opt-in rather than a narrower cap."*
|
|
79
|
+
- **Prompt interactively on first run.** Rejected: `detect` is scriptable and
|
|
80
|
+
runs unattended; a prompt makes the non-interactive path either hang or pick a
|
|
81
|
+
default, which is this decision again with extra machinery.
|
|
82
|
+
|
|
83
|
+
## Consequences
|
|
84
|
+
|
|
85
|
+
A bare `stacktrace detect` is now local plus the osv.dev coordinate lookup, and
|
|
86
|
+
nothing else leaves. That is the promise the site already makes, kept.
|
|
87
|
+
|
|
88
|
+
The cost is the one the amendment identified and it returns in full: stage 3
|
|
89
|
+
runs only when asked, so verdict yield and the rules that depend on it stay
|
|
90
|
+
unmeasured unless we go and measure them. That work does not disappear — it
|
|
91
|
+
moves from "collected passively from every user" to "collected deliberately",
|
|
92
|
+
and it should be done, because `injection-marker` cannot be evaluated at all
|
|
93
|
+
without it.
|
|
94
|
+
|
|
95
|
+
Watch for the stage going dark again. `reasoning_not_requested` in the reasoning
|
|
96
|
+
accounting is the signal: if it is the dominant outcome across real runs for a
|
|
97
|
+
release or two, the stage is not being reached and the rules behind it are still
|
|
98
|
+
untuned. That is the same failure the 2026-09-03 amendment reacted to, and the
|
|
99
|
+
answer will need to be something other than flipping the default a second time.
|
|
100
|
+
|
|
101
|
+
Users relying on the implicit default silently lose stage 3. `--no-escalate`
|
|
102
|
+
keeps working, so no invocation breaks; the release note carries the change.
|
|
103
|
+
|
|
104
|
+
## When to revisit
|
|
105
|
+
|
|
106
|
+
- **Verdict yield gets measured** and justifies the spend — then this is a
|
|
107
|
+
candidate to revert, but with the docs and the other three surfaces changed in
|
|
108
|
+
the same commit, which is what went wrong the first time.
|
|
109
|
+
- **`reasoning_not_requested` dominates** real runs for two releases, per above.
|
|
110
|
+
- **Stage 3 runs against a real analyzer** and the `live_cli` test stops being
|
|
111
|
+
deselected — until then the default-on path was shipping the least-validated
|
|
112
|
+
stage.
|
|
113
|
+
- **The escalation stops costing the user.** The whole argument is that the
|
|
114
|
+
stage spends someone else's quota and crosses a content boundary. A stage that
|
|
115
|
+
did neither would not need to be asked for.
|
|
@@ -60,3 +60,5 @@ supersedes anything yet.
|
|
|
60
60
|
- [0026](0026-the-console-becomes-a-product-surface.md) — **The console becomes a product surface, served by the engine.** Supersedes ADR-0008 on its own stated condition: the engine came first, 0.1.0 shipped, and the data is only useful if a person can follow it. `stacktrace monitor` serves a loopback page from in-process calls, so the wheel now carries a `site/` asset — the cost 0008 refused, accepted here explicitly. What survives from 0008 is the clause that matters: the console renders and never computes, so a finding on the page is one `detect` would print. Read before adding anything to the console that the detector does not produce.
|
|
61
61
|
- [0025](0025-a-denied-call-is-activity-never-an-invocation.md) — **A denied call is activity, and never an invocation.** ADR-0017 makes a declined repeat a stall while `outcome.py` keeps a denied call out of every count, so a denied-only session produced a finding with no activity and the Cloud rejected the whole run; a separate `denied` counter resolves it without either rule bending, and coverage keeps summing `invocations` alone. Read before changing what `activity[]` counts, or before folding `denied` into a coverage-like ratio.
|
|
62
62
|
- [0027](0027-a-finding-may-name-what-it-could-not-place.md) — **A finding may name the component it could not place.** Narrows ADR-0006 constraint 3 for one field: an unplaced subject carries the name the session addressed it by, never as an identity. Read before removing a name from a finding on trust-boundary grounds, or before widening this to a second field.
|
|
63
|
+
- [0028](0028-the-console-shows-what-it-placed.md) — **The console shows what it placed, and states no coverage.** Unplaceable rows, the `N/M placed` header fraction and the red on refusals are gone from `stacktrace monitor`: an unplaced row names no component, and `outcome.py`'s rule about a denied call makes reddening one the page contradicting its own counters. The snapshot contract, the upload and every rule are unchanged. Read before adding a page-side filter, before restoring a coverage ratio to the console, or if `unsanctioned-mcp-tool-use` returns.
|
|
64
|
+
- [0029](0029-stage-three-returns-to-opt-in.md) — **Stage three returns to opt-in.** Amends ADR-0004: `stacktrace detect` defaults `--escalate` off, matching `run_detector`, `monitor` and `sync detect`, all of which never changed — the 2026-09-03 amendment landed in one of four surfaces while the quickstart, the data-handling copy and `plans/004` kept promising opt-in. Taken on consistency and consent, not on the verdict yield 0004 asked for, which is still unmeasured. The verdict cache is ungated from `escalate` in the same change. Read before changing an escalation default, or before arguing stage 3 should be on again.
|
|
@@ -243,8 +243,8 @@ rewrite*.
|
|
|
243
243
|
- [x] **Step 1: Keep `sync endpoint`'s side-effect order.** Load config, refuse
|
|
244
244
|
if unconfigured, client, replay spool, **detect**, register, upload per kind.
|
|
245
245
|
Detecting before registering keeps a failed run from creating an asset.
|
|
246
|
-
- [x] **Step 2: `--escalate` defaults off
|
|
247
|
-
(ADR-0023).
|
|
246
|
+
- [x] **Step 2: `--escalate` defaults off** — a scheduled unattended run must
|
|
247
|
+
not spend provider quota or cross a content boundary implicitly (ADR-0023).
|
|
248
248
|
- [x] **Step 3: `--dry-run` prints NDJSON from the same builder.**
|
|
249
249
|
- [x] **Step 4: Cap evidence, refuse everything else.** Keep `evidence[0]` —
|
|
250
250
|
the anchor the Cloud identifies a call-scoped detection by — and order, with
|
|
@@ -177,7 +177,7 @@ def analyse(
|
|
|
177
177
|
return Analysis(run=run, view=acquired.view, window_start=window_start, window_end=window_end)
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
-
- [x] **Step 4: Rewire `cli.py`'s `detect`.** Replace the three calls with one `analyse(...)`; keep the `try/except ValueError → ClickException` around it and the `VerdictCache(default_directory()) if cache and
|
|
180
|
+
- [x] **Step 4: Rewire `cli.py`'s `detect`.** Replace the three calls with one `analyse(...)`; keep the `try/except ValueError → ClickException` around it and the `VerdictCache(default_directory()) if cache else None` argument — the cache is opened whenever `--cache` allows it and never gated on `escalate`, which governs whether new stage-3 work may be commissioned and not whether a verdict already paid for may be read. Keep `_parse_since` as a thin alias if anything else imports it; delete it if nothing does.
|
|
181
181
|
|
|
182
182
|
- [x] **Step 5: Rewire `sync_detect.py`'s `_collect_detect_run`.** One `analyse(...)` call; keep `SyncError` translation, keep the working-directory collection and the per-kind activity walk, and read `window_start`/`window_end`/`collection_failures` off the `Analysis` instead of computing them.
|
|
183
183
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 0.2.2 — what the console shows
|
|
2
|
+
|
|
3
|
+
`stacktrace monitor` shipped in 0.2.0 with two kinds of warning on it, and this
|
|
4
|
+
release removes both. Neither pointed at something a reader could act on: one
|
|
5
|
+
marked a call the correlator could not attribute, which names no component by
|
|
6
|
+
design, and the other marked a call a permission prompt had already blocked.
|
|
7
|
+
The engine is untouched — no rule, payload field, command or output shape
|
|
8
|
+
moves — and the whole delta is what one page renders.
|
|
9
|
+
|
|
10
|
+
## Highlights
|
|
11
|
+
|
|
12
|
+
- **A blocked call is no longer an alarm.** A refusal is counted in its row's
|
|
13
|
+
`×N` and says nothing more: no `⚠ N refusals` badge, no red row. On the
|
|
14
|
+
machine that prompted this, 16 declined `Bash` calls out of 4,467 turned the
|
|
15
|
+
busiest row on the page red — and all 16 were the Bash gate refusing a
|
|
16
|
+
compound command, a `cd` before `git`, or an obfuscated brace. Nothing
|
|
17
|
+
reached a tool. `sessions/outcome.py` has held since 0.1.0 that a denied call
|
|
18
|
+
reached nothing, so it is evidence of nothing; the page took that rule for
|
|
19
|
+
its counters and then reddened the row anyway, which reports the permission
|
|
20
|
+
prompt as the incident. ADR-0025 left this to each surface deliberately, and
|
|
21
|
+
the console now answers it.
|
|
22
|
+
|
|
23
|
+
- **The console shows only activity it could place.** The `⚠ unresolved` rows,
|
|
24
|
+
the `Unresolved` row in the overview table and the legend line describing
|
|
25
|
+
them are gone. An unplaced row carries no component name — that is a design
|
|
26
|
+
constraint, not an omission (ADR-0027 admits a name at one position, and an
|
|
27
|
+
activity row is not one) — so what reached the reader was "something happened
|
|
28
|
+
and nothing here claims it", with four causes behind it they could not
|
|
29
|
+
distinguish and none they could act on. The rule that would have made such a
|
|
30
|
+
call actionable was withdrawn by ADR-0015, so nothing on the page could
|
|
31
|
+
explain the warning it was showing.
|
|
32
|
+
|
|
33
|
+
- **The header states no coverage figure.** `6,867/7,055 placed` and the
|
|
34
|
+
`placing…` placeholder it used while correlation ran are both gone: the gap
|
|
35
|
+
between those two numbers *is* the count of rows the page withholds, so the
|
|
36
|
+
header restated by arithmetic exactly what the rows had stopped saying. It
|
|
37
|
+
now reports sessions and the actions it actually shows — previously it read
|
|
38
|
+
`summary.actions`, the total over every call in the window, and so claimed
|
|
39
|
+
more actions than the feed below it could account for.
|
|
40
|
+
|
|
41
|
+
- **A legend line that described nothing.** `✓ resolved to something you
|
|
42
|
+
installed` is removed. The page has never drawn that checkmark: the glyph
|
|
43
|
+
appeared in the legend and in no row, summary or card.
|
|
44
|
+
|
|
45
|
+
- **The decision is recorded rather than implied.** ADR-0028 states it, lists
|
|
46
|
+
the five alternatives and is explicit about the costs — an agent kind with no
|
|
47
|
+
Agent BOM is now silent on the page, and ADR-0025's denied-heavy endpoint is
|
|
48
|
+
still visible on no surface. `docs/specs/monitor.md` said the opposite in four
|
|
49
|
+
places and now describes what ships.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
`uv tool install stacktrace-cli==0.2.2` or `pip install stacktrace-cli==0.2.2`.
|
|
54
|
+
|
|
55
|
+
## Compatibility
|
|
56
|
+
|
|
57
|
+
Nothing to do, and nothing outside the console changes. `stacktrace detect`,
|
|
58
|
+
`stacktrace correlate` and `stacktrace sync detect` produce byte-identical
|
|
59
|
+
output to 0.2.1, the upload payload is unchanged, and every detector rule reads
|
|
60
|
+
what it always read. No finding is suppressed — ADR-0026's clause that the
|
|
61
|
+
console renders and never judges still holds, and a page that shows fewer
|
|
62
|
+
activity rows invents nothing.
|
|
63
|
+
|
|
64
|
+
The `/api/state` document is also unchanged: it still carries the unplaced
|
|
65
|
+
activity rows and both coverage figures. The filter is applied in the page, so
|
|
66
|
+
anything reading that endpoint sees the same record 0.2.1 served.
|
|
67
|
+
|
|
68
|
+
Two things you will notice if you relied on them. Coverage is no longer on the
|
|
69
|
+
console — run `stacktrace correlate`, where it is the subject and the four
|
|
70
|
+
causes of an unplaced call are named separately. And an agent kind with no
|
|
71
|
+
Agent BOM no longer raises a banner: its built-in rows still appear, so the
|
|
72
|
+
page does not go blank, but the absence is reported by `correlate` rather than
|
|
73
|
+
on screen.
|
|
74
|
+
|
|
75
|
+
Still pre-alpha, with no back-compat hedging: interfaces can change between
|
|
76
|
+
releases without a deprecation window.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# 0.2.3 — stage three is opt-in
|
|
2
|
+
|
|
3
|
+
`stacktrace detect` no longer sends anything session-derived off your machine
|
|
4
|
+
unless you ask it to. The third stage — the one that hands flagged sessions to
|
|
5
|
+
the agent's own CLI — is now behind `--escalate`, which is what the quickstart,
|
|
6
|
+
the data-handling page and three of the four code surfaces already said it was.
|
|
7
|
+
Alongside it, a fix worth reading if you installed with `install.sh`: `correlate`
|
|
8
|
+
was reaching whichever OpenACA your PATH happened to name rather than the one
|
|
9
|
+
this package pins.
|
|
10
|
+
|
|
11
|
+
## Highlights
|
|
12
|
+
|
|
13
|
+
- **`stacktrace detect` defaults `--escalate` off.** A bare run is the two
|
|
14
|
+
stages that need no model and no credential, plus the osv.dev advisory
|
|
15
|
+
lookup, which sends package coordinates only. `--escalate` turns the third
|
|
16
|
+
stage on and `--budget` still caps it. The default had been on since
|
|
17
|
+
2026-09-03 while `run_detector`, `stacktrace monitor` and `remote sync detect`
|
|
18
|
+
all defaulted it off and the published quickstart told new users to pass
|
|
19
|
+
`--no-escalate`; one surface out of four, contradicted by its own
|
|
20
|
+
documentation, was a divergence rather than a default. ADR-0029 records the
|
|
21
|
+
decision and is explicit that it is a consent decision taken ahead of the
|
|
22
|
+
verdict-yield evidence ADR-0004 asked for, which is still unmeasured.
|
|
23
|
+
|
|
24
|
+
A run that declines to escalate is not a clean run. Sessions that qualified
|
|
25
|
+
are counted in the reasoning accounting as `reasoning_not_requested`; the
|
|
26
|
+
session ids are in `--format json`, not the text output, which aggregates
|
|
27
|
+
them under the reason.
|
|
28
|
+
|
|
29
|
+
- **A verdict you already paid for is readable on the default path.** Both
|
|
30
|
+
`detect` and `remote sync detect` built their verdict cache only when
|
|
31
|
+
escalation was on, so with the new default every stored verdict would have
|
|
32
|
+
gone unread and the same sessions would have been billed twice on the next
|
|
33
|
+
`--escalate` run. `run_detector` has always held that the flag governs whether
|
|
34
|
+
new verdicts may be commissioned, not whether old ones may be read; the two
|
|
35
|
+
call sites disagreed with it. An exhaustiveness test now covers every cache
|
|
36
|
+
construction site rather than the two that were found by hand.
|
|
37
|
+
|
|
38
|
+
- **`correlate` runs the OpenACA this package pins.** Acquisition invoked the
|
|
39
|
+
bare name `openaca`, a PATH lookup — and `uv tool install stacktrace-cli`,
|
|
40
|
+
which is what `install.sh` runs, links only the `stacktrace` entry point, so
|
|
41
|
+
the pinned OpenACA sat one directory away, reachable but unnamed. A machine
|
|
42
|
+
with a stale global copy silently scanned with the wrong version; a machine
|
|
43
|
+
with none got a bare `FileNotFoundError`. `stacktrace --version` could not
|
|
44
|
+
reveal it, because it reports the metadata inside the environment while the
|
|
45
|
+
subprocess ran something else. The console script is now located through
|
|
46
|
+
`importlib.metadata`, authenticated against the digest its own install
|
|
47
|
+
recorded, and fails closed with a legible error where ownership cannot be
|
|
48
|
+
established. Verified against four real install topologies. The ADR-0007 seam
|
|
49
|
+
is unchanged.
|
|
50
|
+
|
|
51
|
+
- **One default, stated once.** The escalation default had also drifted into
|
|
52
|
+
`docs/specs/detector.md`, `docs/specs/detection-upload.md`, test descriptions,
|
|
53
|
+
wrapped help text, and `docs/plans/008-monitor.md`, which still instructed the
|
|
54
|
+
cache gate this release removes. A test now reads the active specs, plans and
|
|
55
|
+
help text and fails on a stale wording, in any of the three names the repo
|
|
56
|
+
uses for the stage.
|
|
57
|
+
|
|
58
|
+
- **The console names the log column `Agent Session Trace`,** dropping the
|
|
59
|
+
third word from `Agent Session Log Trace` — session, log and trace were three
|
|
60
|
+
words for one thing. The one-item legend above the columns (`MCP = a link to
|
|
61
|
+
an outside service`) is gone: an MCP row already carries its category tag and
|
|
62
|
+
names the server it reached.
|
|
63
|
+
|
|
64
|
+
- **`detect` stops printing the per-reason "Could not settle" breakdown.** It
|
|
65
|
+
listed internal reason ids — `mcp_transport_unavailable` dominates on a normal
|
|
66
|
+
machine — at a reader who cannot act on them one call at a time. The unsettled
|
|
67
|
+
count stays in the summary line, `--format json` still carries every `Unknown`
|
|
68
|
+
whole with its spans and detail, and the reasoning stage still names its own
|
|
69
|
+
outcomes.
|
|
70
|
+
|
|
71
|
+
## Install
|
|
72
|
+
|
|
73
|
+
`uv tool install stacktrace-cli==0.2.3` or `pip install stacktrace-cli==0.2.3`.
|
|
74
|
+
|
|
75
|
+
## Compatibility
|
|
76
|
+
|
|
77
|
+
**One behaviour change, and the patch version does not signal it: `stacktrace
|
|
78
|
+
detect` no longer escalates by default.** If you relied on a bare `detect`
|
|
79
|
+
reaching stage 3, pass `--escalate` to restore it. Nothing breaks — the
|
|
80
|
+
`--no-escalate` you may already be passing still means what it meant — but a
|
|
81
|
+
default run now produces no reasoning-stage findings, and sessions that would
|
|
82
|
+
have been analysed appear as `reasoning_not_requested` instead. `monitor` and
|
|
83
|
+
`remote sync detect` are unaffected; they already defaulted off.
|
|
84
|
+
|
|
85
|
+
If you had accumulated verdicts from earlier `--escalate` runs, they are served
|
|
86
|
+
again on the default path rather than ignored, so a `detect` after upgrading may
|
|
87
|
+
report reasoning findings without spending anything.
|
|
88
|
+
|
|
89
|
+
Text output changes in two places: the `Could not settle:` block is gone, and
|
|
90
|
+
the reasoning accounting's not-requested row names a flag rather than a reason
|
|
91
|
+
id. `--format json` is unchanged — no field added, removed or renamed — and the
|
|
92
|
+
upload payload is untouched, so anything parsing either sees what 0.2.2 served.
|
|
93
|
+
|
|
94
|
+
On the console, the log column is renamed and the legend line is removed. No
|
|
95
|
+
rule, finding, severity or payload field moves.
|
|
96
|
+
|
|
97
|
+
If `install.sh` put stacktrace on your machine and you had separately installed
|
|
98
|
+
or upgraded OpenACA to work around a scan failure, that workaround is no longer
|
|
99
|
+
needed; the pinned 0.6.0 is what runs now.
|
|
100
|
+
|
|
101
|
+
Still pre-alpha, with no back-compat hedging: interfaces can change between
|
|
102
|
+
releases without a deprecation window.
|
|
@@ -291,7 +291,7 @@ Detecting before registering keeps a failed run from creating an asset.
|
|
|
291
291
|
|---|---|---|
|
|
292
292
|
| `--agent-kind`, `--bom`, `--budget`, `--sample-budget`, `--cache/--no-cache`, `--project-map`, `--root` | as `stacktrace detect` | |
|
|
293
293
|
| `--since` | `7d` | |
|
|
294
|
-
| `--escalate/--no-escalate` | **`--no-escalate`** |
|
|
294
|
+
| `--escalate/--no-escalate` | **`--no-escalate`** | Stage 3 spends the developer's provider quota and crosses a boundary; unattended is the wrong place for that to be implicit |
|
|
295
295
|
| `--dry-run` | off | NDJSON via the same builder the real path uses, so the preview **is** the payload. ADR-0006 constraint 4 requires it |
|
|
296
296
|
| `--quiet`, `--allow-offline-cache` | off | as `sync endpoint` |
|
|
297
297
|
|
|
@@ -63,11 +63,11 @@ only stage that sends anything *session-derived* off the machine. Package
|
|
|
63
63
|
coordinates travel either way; prompts, arguments and results travel only when
|
|
64
64
|
escalation runs, and then to the session's own provider and no other.
|
|
65
65
|
|
|
66
|
-
**`reasoning` is
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
cap, the verdict cache
|
|
70
|
-
|
|
66
|
+
**`reasoning` is opt-in and capped** (ADR-0029). A stage that spends the
|
|
67
|
+
developer's quota and crosses that content boundary is asked for rather than
|
|
68
|
+
assumed, so it runs only under `--escalate`. Three things bound its cost when it
|
|
69
|
+
is asked for: the `--budget` cap, the verdict cache — so an unchanged session is
|
|
70
|
+
never paid for twice — and the flag itself.
|
|
71
71
|
|
|
72
72
|
**The ordering is the unit economics.** Microseconds, then milliseconds, then —
|
|
73
73
|
only for the residue neither could resolve — seconds of inference. The per-session
|
|
@@ -141,8 +141,11 @@ An unplaced stage is honest in two specific ways, and both are load-bearing:
|
|
|
141
141
|
property over the whole built-in vocabulary, not just the names a fixture
|
|
142
142
|
uses.
|
|
143
143
|
- **Coverage is `None`, not `0/0`.** Correlation computes coverage, so an
|
|
144
|
-
unplaced stage does not have it
|
|
145
|
-
|
|
144
|
+
unplaced stage does not have it, and the snapshot says so rather than
|
|
145
|
+
claiming a figure. The page no longer renders one either way (ADR-0028): the
|
|
146
|
+
header counts sessions and the actions it shows, and the fraction — whose gap
|
|
147
|
+
was the count of rows the page withholds — is gone, along with the `placing…`
|
|
148
|
+
placeholder that stood in for it.
|
|
146
149
|
|
|
147
150
|
Batches are then judged **newest first**, because someone watching a machine
|
|
148
151
|
cares about what just happened and should not scroll for it. The last stage
|
|
@@ -185,10 +188,18 @@ name".** Routine built-ins — Bash, Read, Edit — are the constant background
|
|
|
185
188
|
every session: 5,795 of one three-day window's 7,065 calls. They collapse **per
|
|
186
189
|
project** into one counted row for the agent, which is what makes `Claude Code ·
|
|
187
190
|
working — files, commands & searches · ×1,719` a line a person reads instead of
|
|
188
|
-
1,719 lines they do not. Skills, MCP servers, sub-agents
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
1,719 lines they do not. Skills, MCP servers, sub-agents and commands
|
|
192
|
+
are rare and consequential, so each **call** keeps its own row, keyed by span
|
|
193
|
+
and never coalesced: two runs of one skill are two things that happened. A
|
|
194
|
+
three-day window is ~66 rows.
|
|
195
|
+
|
|
196
|
+
**A call correlation could not place gets no row at all** (ADR-0028). It names
|
|
197
|
+
no component — `classify_call` returns no name for one by design — so the row
|
|
198
|
+
could only say that something happened and nothing here claims it, which is not
|
|
199
|
+
a thing a reader can act on, and the rule that would have made it actionable
|
|
200
|
+
was withdrawn by ADR-0015. The rows are dropped at the page boundary and
|
|
201
|
+
nowhere else: `_activity` still emits them, and `stacktrace correlate` still
|
|
202
|
+
reports them with each of the four causes named.
|
|
192
203
|
|
|
193
204
|
**The summary's "Most used" column names the top three, and says what it left
|
|
194
205
|
out.** A truncated list beside a total reads as a breakdown, and then the
|
|
@@ -207,8 +218,13 @@ exactly the terms the component name is: an ambiguous match names no alias,
|
|
|
207
218
|
because printing the first candidate's configured name over the second's is the
|
|
208
219
|
narrowing correlation refuses to do.
|
|
209
220
|
|
|
210
|
-
A refusal
|
|
211
|
-
of its own
|
|
221
|
+
A refusal is counted in the row's `×N` and says nothing more (ADR-0028). It
|
|
222
|
+
took neither a row of its own — `Bash ×3 denied` beside `Bash ×38` was half the
|
|
223
|
+
noise — nor a badge and a colour, which is the page asserting the opposite of
|
|
224
|
+
`outcome.py`'s rule about the same call: a denied call reached nothing, so it is
|
|
225
|
+
evidence of nothing. On the machine that prompted this, 16 declined `Bash` calls
|
|
226
|
+
out of 4,467 turned the busiest row on the page red, and all 16 were the Bash
|
|
227
|
+
gate refusing a compound command.
|
|
212
228
|
|
|
213
229
|
**Every panel is additive.** A stage re-sends every session and every finding
|
|
214
230
|
the stages before it carried, so a render that replaced the columns threw away
|
|
@@ -399,7 +415,7 @@ only on click, so the ceiling is visible before it is hit.
|
|
|
399
415
|
| No sessions on this machine | An empty page that **says so**. A blank column reads as a broken renderer |
|
|
400
416
|
| A reader failed before correlation (`collection_failures`) | Rendered as a banner. A run that never got to look must not read as a clean one |
|
|
401
417
|
| A session with no agent kind | Counted and named as unplaceable, never rendered under an invented kind |
|
|
402
|
-
| A session with no composition |
|
|
418
|
+
| A session with no composition | Its calls are read, and the page shows what it can place them to. Since ADR-0028 there is no banner and no coverage figure: the built-in preview rows still appear, and the absence itself is reported by `stacktrace correlate` rather than by the console |
|
|
403
419
|
| The port is taken | Refuse with the port named, rather than silently choosing another and printing a URL the user did not expect |
|
|
404
420
|
|
|
405
421
|
## Files
|