stacktrace-cli 0.2.0__tar.gz → 0.2.2__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.0 → stacktrace_cli-0.2.2}/CLAUDE.md +27 -6
- stacktrace_cli-0.2.2/PKG-INFO +154 -0
- stacktrace_cli-0.2.2/README.md +129 -0
- stacktrace_cli-0.2.2/docs/adrs/0028-the-console-shows-what-it-placed.md +108 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/INDEX.md +1 -0
- stacktrace_cli-0.2.2/docs/cutover-openaca-remote.md +87 -0
- stacktrace_cli-0.2.2/docs/releases/v0.2.1.md +49 -0
- stacktrace_cli-0.2.2/docs/releases/v0.2.2.md +76 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/monitor.md +25 -9
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/pyproject.toml +8 -4
- stacktrace_cli-0.2.2/src/stacktrace_cli/__init__.py +3 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/render.py +6 -2
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/app.js +48 -46
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/index.html +0 -2
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/feed_harness.mjs +62 -12
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_feed_model.py +55 -31
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_render.py +19 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_site_assets.py +8 -4
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/uv.lock +1 -1
- stacktrace_cli-0.2.0/PKG-INFO +0 -228
- stacktrace_cli-0.2.0/README.md +0 -207
- stacktrace_cli-0.2.0/src/stacktrace_cli/__init__.py +0 -3
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.agents/skills/release-stacktrace/SKILL.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.claude/settings.json +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.claude/skills/release-stacktrace/SKILL.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.codex/hooks.json +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.github/workflows/autofix.yml +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.github/workflows/ci.yml +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.github/workflows/claude.yml +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.github/workflows/publish-pypi.yml +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/.gitignore +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/AGENTS.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0001-session-telemetry-as-input.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0002-session-collection-in-openaidr.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0003-runtime-edges.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0004-three-stage-detector.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0005-detection-family-and-report-assembly.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0006-trust-boundary-and-detection-upload.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0007-proprietary-package-on-open-dependencies.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0008-console-in-separate-demo-package.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0010-detection-severity-and-confidence-ladders.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0011-verdict-cache.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0012-observation-evidence-kinds-and-transport.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0013-rule-catalogue-triage-and-per-rule-context.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0014-declared-project-mapping.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0015-narrow-the-security-catalogue.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0016-stall-grouping-is-session-wide.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0017-a-declined-repeat-is-a-stall.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0018-remote-sync-config-and-facade-consumption.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0019-delegated-commands-are-openaca-objects.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0020-openaca-consumption-boundary.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0021-two-command-kinds.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0022-detection-scope-is-a-catalogue-column.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0023-sync-detect-collects-and-does-not-escalate.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0024-the-upload-carries-observations.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0025-a-denied-call-is-activity-never-an-invocation.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0026-the-console-becomes-a-product-surface.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/0027-a-finding-may-name-what-it-could-not-place.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/HOOK-PROMPT.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/adrs/TEMPLATE.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/002-session-input.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/003-correlation.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/004-detector.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/005-remote-sync.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/006-cli-composition.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/007-detection-upload.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/plans/008-monitor.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/releases/v0.0.1.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/releases/v0.1.0.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/releases/v0.2.0.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/aidr.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/cli-composition.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/correlation.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/detection-upload.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/detector.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/remote-sync.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/docs/specs/session-input.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/scripts/git-hooks/pre-push +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/scripts/install-hooks.sh +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/__main__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/analysis.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/acquire.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/composition.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/join.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/observed.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/orchestrate.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/project_map.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/record.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/correlate/render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/analyzer.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/cache.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/deterministic.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/finding.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/markers.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/priors.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/v1/exclusions.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/v1/framing.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/v1/stacktrace-deceptive-completion.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/v1/stacktrace-injected-instruction-followed.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/prompts/v1/stacktrace-intent-drift.md +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/reasoning.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/rules.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/run.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/secrets.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/detector/verdict.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/escalate.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/server.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/fonts/OFL.txt +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/fonts/dm-mono-400-latin.woff2 +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/fonts/dm-mono-500-latin.woff2 +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/fonts/dm-sans-latin.woff2 +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/site/styles.css +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/state.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/verdicts.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/monitor/watch.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/client.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/config.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/detect_payload.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/payload.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/policy.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/redact.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/spool.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/sync.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/sync_detect.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/remote/upload_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/sessions/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/sessions/access.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/sessions/outcome.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/sessions/protocols.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/src/stacktrace_cli/sessions/render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/agent_bom_fixture.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/detector_session_fixture.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_escalation_gates.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_server.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_state.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_verdicts.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/monitor/test_watch.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/__init__.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/helpers.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_client.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_config.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_activity.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_client.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_contract_is_exhaustive.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_gate_matches_the_cloud.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_layers_compose.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_payload_reaches_the_cloud_model.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_redaction.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_spool.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_upload_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_detect_wire_payload.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_facade_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_payload.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_policy.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_redact_payload.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_seam.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_spool.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_sync.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_sync_detect.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/remote/test_upload_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_acquire.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_agent_instance_id.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_analysis.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_bom_shape.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_call_status_conventions.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_composition.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_correlate_orchestrate.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_correlate_render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_correlated_session.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detection_components.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detection_subject.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_analyzer_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_analyzer_live.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_cache.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_deterministic.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_end_to_end.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_finding.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_liveness.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_markers.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_priors.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_reasoning.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_run.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_secrets.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_detector_verdict.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_fingerprint_covers_what_the_analyzer_reads.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_help_sections.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_join.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_monitor_cli.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_observed.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_openaca_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_openaidr_contract.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_option_arity_matches_the_binary.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_project_map.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_readme_examples_are_real_output.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_release_readiness.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_seam_boundary.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_sessions_access.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_sessions_end_to_end.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_sessions_protocol_typing.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_sessions_protocols.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_sessions_render.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_shell_separators_match_the_shell.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_untrusted_content_never_travels.py +0 -0
- {stacktrace_cli-0.2.0 → stacktrace_cli-0.2.2}/tests/test_verification_subcommands_match_the_binary.py +0 -0
|
@@ -11,8 +11,8 @@ and by CI pipelines that invoke `stacktrace`, and it builds on the open-source
|
|
|
11
11
|
It is also the **design home for Stacktrace Detect** — the AIDR product this CLI
|
|
12
12
|
grows into. The specs in `docs/specs/` and the decisions in `docs/adrs/` describe
|
|
13
13
|
the whole system: session input, correlation against the composition graph, the
|
|
14
|
-
three-stage detector, and the combined report. The code here
|
|
15
|
-
|
|
14
|
+
three-stage detector, and the combined report. The code here implements them
|
|
15
|
+
incrementally.
|
|
16
16
|
|
|
17
17
|
## Common commands
|
|
18
18
|
|
|
@@ -52,11 +52,13 @@ the single source of truth for the version string reported by `--version`.
|
|
|
52
52
|
|
|
53
53
|
Build backend is hatchling with a src layout; the wheel's contents are declared
|
|
54
54
|
explicitly by `[tool.hatch.build.targets.wheel] packages = ["src/stacktrace_cli"]`.
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
Runtime dependencies are `openaca` for the Agent Composition Analysis
|
|
56
|
+
primitives this CLI drives, `openaidr` for session collection, and `httpx` for
|
|
57
|
+
the remote channel. Each is pinned exactly before a release; see
|
|
58
|
+
`docs/cutover-openaca-remote.md`.
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
`sessions`, `detect`, `monitor` and `remote` are native; `bom`, `policy` and
|
|
61
|
+
`scan` are OpenACA's own command objects.
|
|
60
62
|
|
|
61
63
|
**The design that functionality implements is in this repo.** Read
|
|
62
64
|
`docs/specs/aidr.md` first — it is the umbrella: components, contracts, the two
|
|
@@ -121,6 +123,25 @@ nothing about detection.
|
|
|
121
123
|
a review names a site, fix the invariant and extend the exhaustive test — a
|
|
122
124
|
second finding of the same class means the first fix was at the wrong level.
|
|
123
125
|
|
|
126
|
+
## Adding a command
|
|
127
|
+
|
|
128
|
+
A command is a **pass-through** or it is **native**, never both — and a
|
|
129
|
+
pass-through never gains a flag of its own. See
|
|
130
|
+
[ADR-0021](docs/adrs/0021-two-command-kinds.md) for why.
|
|
131
|
+
|
|
132
|
+
- **Pass-through** — add one string to `PASSTHROUGH` in
|
|
133
|
+
`src/stacktrace_cli/cli.py`, having decided it belongs. The loop registers
|
|
134
|
+
OpenACA's own command object under that name; there is nothing else to
|
|
135
|
+
write and nothing to keep in step with OpenACA.
|
|
136
|
+
- **Native** — write a Click command or group and `add_command` it, the way
|
|
137
|
+
`remote` is. If it needs OpenACA it calls `openaca.core`
|
|
138
|
+
([ADR-0020](docs/adrs/0020-openaca-consumption-boundary.md)), and whatever
|
|
139
|
+
it names there is added to the contract test in `tests/remote/`, because it
|
|
140
|
+
now holds duplicated knowledge of an interface.
|
|
141
|
+
|
|
142
|
+
The section a command lands under in `--help` follows from which kind it is;
|
|
143
|
+
there is no second list to update.
|
|
144
|
+
|
|
124
145
|
---
|
|
125
146
|
|
|
126
147
|
## Behavioral guidelines
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: stacktrace-cli
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: CLI for Stacktrace — Detection and Response platform for AI Agents.
|
|
5
|
+
Project-URL: Homepage, https://stacktrace.ai
|
|
6
|
+
Author-email: "Stacktrace AI, Inc" <founders@stacktrace.ai>
|
|
7
|
+
License-Expression: LicenseRef-Proprietary
|
|
8
|
+
Keywords: agent-security,ai-security,openaca,stacktrace
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: Other/Proprietary License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: click>=8.1
|
|
21
|
+
Requires-Dist: httpx<1.0.dev0,>=0.28.1
|
|
22
|
+
Requires-Dist: openaca==0.6.0
|
|
23
|
+
Requires-Dist: openaidr==0.1.0
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# stacktrace-cli
|
|
27
|
+
|
|
28
|
+
Detection and response for AI coding agents, from the command line.
|
|
29
|
+
|
|
30
|
+
Coding agents read files, run shell commands and call MCP servers on their own
|
|
31
|
+
initiative, and they write a transcript of every bit of it to disk.
|
|
32
|
+
`stacktrace` reads those transcripts, correlates what ran against the
|
|
33
|
+
components the agent is built from, and reports the security and reliability
|
|
34
|
+
findings in it — locally, on the machine the agent worked on.
|
|
35
|
+
|
|
36
|
+
The PyPI distribution is `stacktrace-cli`; the command it installs is
|
|
37
|
+
`stacktrace`. The two names differ because the bare `stacktrace` name on PyPI
|
|
38
|
+
belongs to an unrelated project.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv tool install stacktrace-cli # isolated; recommended
|
|
44
|
+
# or
|
|
45
|
+
pip install stacktrace-cli
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Requires Python 3.11 or newer.
|
|
49
|
+
|
|
50
|
+
```console
|
|
51
|
+
$ stacktrace --version
|
|
52
|
+
stacktrace 0.2.1 (openaca 0.6.0)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
stacktrace sessions # what the agents on this machine did
|
|
59
|
+
stacktrace detect # what is wrong with it
|
|
60
|
+
stacktrace monitor # the same, live in a browser
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
| Command | |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `sessions` | Print what the agents on this machine actually did. |
|
|
68
|
+
| `detect` | Find security and reliability findings in what agents did. |
|
|
69
|
+
| `monitor` | Watch this machine's agents in a browser, live. |
|
|
70
|
+
| `remote` | Configure remote endpoint services and upload to Stacktrace Cloud. |
|
|
71
|
+
| `scan` | Scan a repository or endpoint for agent-composition findings. |
|
|
72
|
+
| `bom` | Generate an Agent BOM for a repository or endpoint. |
|
|
73
|
+
| `policy` | Validate and compile restrictive endpoint policies. |
|
|
74
|
+
|
|
75
|
+
The last three are composition analysis, supplied by
|
|
76
|
+
[`openaca`](https://pypi.org/project/openaca/) and available under either
|
|
77
|
+
name.
|
|
78
|
+
|
|
79
|
+
## What it looks like
|
|
80
|
+
|
|
81
|
+
```console
|
|
82
|
+
$ stacktrace sessions --since 2d --include-content
|
|
83
|
+
claude-code:s1 [claude-code] 2026-08-27T09:00:00+00:00 2 turns 2 calls
|
|
84
|
+
assistant: Reading the changelog before drafting the release notes.
|
|
85
|
+
ok 28c Read
|
|
86
|
+
result: ## 0.4.0 - correlate, detect
|
|
87
|
+
assistant: Filing the release-notes follow-up.
|
|
88
|
+
- github/create_issue
|
|
89
|
+
|
|
90
|
+
Summary — 1 sessions, 2 turns, 2 tool calls
|
|
91
|
+
|
|
92
|
+
agent kinds
|
|
93
|
+
1 claude-code
|
|
94
|
+
|
|
95
|
+
tools called (2 distinct)
|
|
96
|
+
1 Read
|
|
97
|
+
1 github/create_issue
|
|
98
|
+
|
|
99
|
+
MCP servers reached (1 distinct)
|
|
100
|
+
1 github
|
|
101
|
+
|
|
102
|
+
0 subagent turns · 0 results abridged upstream · 1 ok
|
|
103
|
+
|
|
104
|
+
1 of 2 calls returned with no outcome the collector could establish; the agent's parser supplies no success signal.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
A blank status column is the collector's `unknown`, not a pending call: the
|
|
108
|
+
client recorded no outcome that could be established, and the closing line
|
|
109
|
+
counts those rather than filling one in.
|
|
110
|
+
|
|
111
|
+
## What `detect` finds
|
|
112
|
+
|
|
113
|
+
Four kinds of finding, under two families that carry separate severity
|
|
114
|
+
ladders — a stalled loop and a leaked credential do not belong on one scale.
|
|
115
|
+
|
|
116
|
+
**Security** — a credential reaching an outbound call; an injected instruction
|
|
117
|
+
the agent then followed; a vulnerable component actually reached, with the
|
|
118
|
+
vulnerability behind it.
|
|
119
|
+
|
|
120
|
+
**Reliability** — a loop that stalled; a call that hung.
|
|
121
|
+
|
|
122
|
+
Findings are correlated against an Agent BOM before they are judged, so a
|
|
123
|
+
vulnerable component is reported when something actually used it rather than
|
|
124
|
+
because it is installed.
|
|
125
|
+
|
|
126
|
+
## What leaves your machine
|
|
127
|
+
|
|
128
|
+
Two of `detect`'s three stages run entirely locally and need no model or
|
|
129
|
+
credential. The third sends flagged sessions to the agent's *own* CLI — the
|
|
130
|
+
provider that produced the transcript, never a different one — capped by
|
|
131
|
+
`--budget`; `--no-escalate` turns it off and leaves the two local stages.
|
|
132
|
+
|
|
133
|
+
`sessions` omits prompts, tool arguments and results unless you pass
|
|
134
|
+
`--include-content`. `monitor` binds to loopback only, refuses a non-loopback
|
|
135
|
+
address rather than warning about it, and escalates nothing unless `--escalate`
|
|
136
|
+
is given.
|
|
137
|
+
|
|
138
|
+
## Status
|
|
139
|
+
|
|
140
|
+
Beta, and under active development.
|
|
141
|
+
|
|
142
|
+
`sessions`, `detect` and `monitor` work end to end today. Session collection
|
|
143
|
+
currently reads Claude Code transcripts; further agent kinds are in progress
|
|
144
|
+
upstream in [OpenAIDR](https://github.com/open-agent-security/openaidr).
|
|
145
|
+
|
|
146
|
+
## Built on
|
|
147
|
+
|
|
148
|
+
Two Apache-2.0 packages, neither of which depends on this one:
|
|
149
|
+
[`openaca`](https://pypi.org/project/openaca/) for agent composition analysis,
|
|
150
|
+
and [`openaidr`](https://pypi.org/project/openaidr/) for session collection.
|
|
151
|
+
|
|
152
|
+
## Licence
|
|
153
|
+
|
|
154
|
+
Proprietary. © Stacktrace AI, Inc. — [stacktrace.ai](https://stacktrace.ai)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# stacktrace-cli
|
|
2
|
+
|
|
3
|
+
Detection and response for AI coding agents, from the command line.
|
|
4
|
+
|
|
5
|
+
Coding agents read files, run shell commands and call MCP servers on their own
|
|
6
|
+
initiative, and they write a transcript of every bit of it to disk.
|
|
7
|
+
`stacktrace` reads those transcripts, correlates what ran against the
|
|
8
|
+
components the agent is built from, and reports the security and reliability
|
|
9
|
+
findings in it — locally, on the machine the agent worked on.
|
|
10
|
+
|
|
11
|
+
The PyPI distribution is `stacktrace-cli`; the command it installs is
|
|
12
|
+
`stacktrace`. The two names differ because the bare `stacktrace` name on PyPI
|
|
13
|
+
belongs to an unrelated project.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv tool install stacktrace-cli # isolated; recommended
|
|
19
|
+
# or
|
|
20
|
+
pip install stacktrace-cli
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Python 3.11 or newer.
|
|
24
|
+
|
|
25
|
+
```console
|
|
26
|
+
$ stacktrace --version
|
|
27
|
+
stacktrace 0.2.1 (openaca 0.6.0)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
stacktrace sessions # what the agents on this machine did
|
|
34
|
+
stacktrace detect # what is wrong with it
|
|
35
|
+
stacktrace monitor # the same, live in a browser
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Commands
|
|
39
|
+
|
|
40
|
+
| Command | |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `sessions` | Print what the agents on this machine actually did. |
|
|
43
|
+
| `detect` | Find security and reliability findings in what agents did. |
|
|
44
|
+
| `monitor` | Watch this machine's agents in a browser, live. |
|
|
45
|
+
| `remote` | Configure remote endpoint services and upload to Stacktrace Cloud. |
|
|
46
|
+
| `scan` | Scan a repository or endpoint for agent-composition findings. |
|
|
47
|
+
| `bom` | Generate an Agent BOM for a repository or endpoint. |
|
|
48
|
+
| `policy` | Validate and compile restrictive endpoint policies. |
|
|
49
|
+
|
|
50
|
+
The last three are composition analysis, supplied by
|
|
51
|
+
[`openaca`](https://pypi.org/project/openaca/) and available under either
|
|
52
|
+
name.
|
|
53
|
+
|
|
54
|
+
## What it looks like
|
|
55
|
+
|
|
56
|
+
```console
|
|
57
|
+
$ stacktrace sessions --since 2d --include-content
|
|
58
|
+
claude-code:s1 [claude-code] 2026-08-27T09:00:00+00:00 2 turns 2 calls
|
|
59
|
+
assistant: Reading the changelog before drafting the release notes.
|
|
60
|
+
ok 28c Read
|
|
61
|
+
result: ## 0.4.0 - correlate, detect
|
|
62
|
+
assistant: Filing the release-notes follow-up.
|
|
63
|
+
- github/create_issue
|
|
64
|
+
|
|
65
|
+
Summary — 1 sessions, 2 turns, 2 tool calls
|
|
66
|
+
|
|
67
|
+
agent kinds
|
|
68
|
+
1 claude-code
|
|
69
|
+
|
|
70
|
+
tools called (2 distinct)
|
|
71
|
+
1 Read
|
|
72
|
+
1 github/create_issue
|
|
73
|
+
|
|
74
|
+
MCP servers reached (1 distinct)
|
|
75
|
+
1 github
|
|
76
|
+
|
|
77
|
+
0 subagent turns · 0 results abridged upstream · 1 ok
|
|
78
|
+
|
|
79
|
+
1 of 2 calls returned with no outcome the collector could establish; the agent's parser supplies no success signal.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A blank status column is the collector's `unknown`, not a pending call: the
|
|
83
|
+
client recorded no outcome that could be established, and the closing line
|
|
84
|
+
counts those rather than filling one in.
|
|
85
|
+
|
|
86
|
+
## What `detect` finds
|
|
87
|
+
|
|
88
|
+
Four kinds of finding, under two families that carry separate severity
|
|
89
|
+
ladders — a stalled loop and a leaked credential do not belong on one scale.
|
|
90
|
+
|
|
91
|
+
**Security** — a credential reaching an outbound call; an injected instruction
|
|
92
|
+
the agent then followed; a vulnerable component actually reached, with the
|
|
93
|
+
vulnerability behind it.
|
|
94
|
+
|
|
95
|
+
**Reliability** — a loop that stalled; a call that hung.
|
|
96
|
+
|
|
97
|
+
Findings are correlated against an Agent BOM before they are judged, so a
|
|
98
|
+
vulnerable component is reported when something actually used it rather than
|
|
99
|
+
because it is installed.
|
|
100
|
+
|
|
101
|
+
## What leaves your machine
|
|
102
|
+
|
|
103
|
+
Two of `detect`'s three stages run entirely locally and need no model or
|
|
104
|
+
credential. The third sends flagged sessions to the agent's *own* CLI — the
|
|
105
|
+
provider that produced the transcript, never a different one — capped by
|
|
106
|
+
`--budget`; `--no-escalate` turns it off and leaves the two local stages.
|
|
107
|
+
|
|
108
|
+
`sessions` omits prompts, tool arguments and results unless you pass
|
|
109
|
+
`--include-content`. `monitor` binds to loopback only, refuses a non-loopback
|
|
110
|
+
address rather than warning about it, and escalates nothing unless `--escalate`
|
|
111
|
+
is given.
|
|
112
|
+
|
|
113
|
+
## Status
|
|
114
|
+
|
|
115
|
+
Beta, and under active development.
|
|
116
|
+
|
|
117
|
+
`sessions`, `detect` and `monitor` work end to end today. Session collection
|
|
118
|
+
currently reads Claude Code transcripts; further agent kinds are in progress
|
|
119
|
+
upstream in [OpenAIDR](https://github.com/open-agent-security/openaidr).
|
|
120
|
+
|
|
121
|
+
## Built on
|
|
122
|
+
|
|
123
|
+
Two Apache-2.0 packages, neither of which depends on this one:
|
|
124
|
+
[`openaca`](https://pypi.org/project/openaca/) for agent composition analysis,
|
|
125
|
+
and [`openaidr`](https://pypi.org/project/openaidr/) for session collection.
|
|
126
|
+
|
|
127
|
+
## Licence
|
|
128
|
+
|
|
129
|
+
Proprietary. © Stacktrace AI, Inc. — [stacktrace.ai](https://stacktrace.ai)
|
|
@@ -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.
|
|
@@ -60,3 +60,4 @@ 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.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# The openaca 0.6.0 cutover
|
|
2
|
+
|
|
3
|
+
Moved out of `README.md`, which is the PyPI long description and therefore a
|
|
4
|
+
public page: this is operator and maintainer detail for a private repository.
|
|
5
|
+
|
|
6
|
+
## Dependency resolution
|
|
7
|
+
|
|
8
|
+
Both `openaca` and `openaidr` resolve from PyPI now, like any other
|
|
9
|
+
dependency — no sibling checkout, no `[tool.uv.sources]` override. What still
|
|
10
|
+
gates a release is narrower: both float on `>=` during normal development but
|
|
11
|
+
must be pinned exactly (`==`) before a version is published, so a built wheel
|
|
12
|
+
names precisely what it was tested against.
|
|
13
|
+
`uv run pytest tests/test_release_readiness.py -m release_gate` checks that —
|
|
14
|
+
the `release-stacktrace` skill runs it as part of cutting a release.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Cutover from `openaca remote`
|
|
18
|
+
|
|
19
|
+
`stacktrace remote` is the hosted-service client OpenACA is removing. The
|
|
20
|
+
behaviour, the payload and the Cloud endpoints are unchanged; only the code
|
|
21
|
+
that produces them moved. Machines already running `openaca remote sync
|
|
22
|
+
endpoint` need four steps each.
|
|
23
|
+
|
|
24
|
+
1. **Have the collector token to hand, or mint a new one.** A collector token
|
|
25
|
+
cannot be recovered from the Cloud — it is returned once at issuance and
|
|
26
|
+
only a hash and its last four characters are kept — so it has to come from
|
|
27
|
+
wherever it was stored (an MDM secret store, a password manager). If it was
|
|
28
|
+
not stored, mint a new one and deploy that; nothing goes down while you do,
|
|
29
|
+
because the existing token keeps working until it is revoked.
|
|
30
|
+
2. **Configure this machine.** `stacktrace remote configure --token …`, or set
|
|
31
|
+
`STACKTRACE_REMOTE_TOKEN` and `STACKTRACE_REMOTE_API_URL` for a scripted
|
|
32
|
+
deployment.
|
|
33
|
+
3. **Repoint whatever schedules the sync** at `stacktrace remote sync
|
|
34
|
+
endpoint`.
|
|
35
|
+
4. **Delete `~/.config/openaca/remote.toml`.** Once OpenACA has no `remote`
|
|
36
|
+
command, that file is an unused plaintext credential sitting on disk.
|
|
37
|
+
Nothing breaks if it stays, which is exactly why it will be forgotten.
|
|
38
|
+
|
|
39
|
+
### What takes care of itself
|
|
40
|
+
|
|
41
|
+
- **The asset converges.** Registration is idempotent on `(org, asset_type,
|
|
42
|
+
external_id)` with the host name as `external_id`, so registering from here
|
|
43
|
+
resolves to the same asset OpenACA registered — one extra round trip on the
|
|
44
|
+
first run, no duplicate machine in the console.
|
|
45
|
+
- **Both commands may coexist during the overlap**, producing two BOM rows per
|
|
46
|
+
sync. That is noise rather than corruption.
|
|
47
|
+
|
|
48
|
+
> These two statements, and the unrecoverability of a collector token in step
|
|
49
|
+
> 1, describe what the deployed Cloud does. They have **not** been confirmed
|
|
50
|
+
> against the running service for this release — they are read from the
|
|
51
|
+
> hosted side's design, which records what some revision implements rather
|
|
52
|
+
> than what production does today. Confirm them before an operator acts on
|
|
53
|
+
> step 1 in particular: discarding the only copy of a token on the strength of
|
|
54
|
+
> an unverified sentence leaves no recovery.
|
|
55
|
+
|
|
56
|
+
### What does not
|
|
57
|
+
|
|
58
|
+
- **A pending OpenACA spool is orphaned.** Its files are in
|
|
59
|
+
`~/.local/state/openaca`, and this channel never reads them. Drain it by
|
|
60
|
+
running the old command once before cutting over, or accept losing what it
|
|
61
|
+
holds. Do not assume that is one sync's worth: the spool keeps one file per
|
|
62
|
+
failed agent and accumulates across offline runs, so count the files first.
|
|
63
|
+
- **The MDM deploy scripts and the scheduled agent** do not exist here yet.
|
|
64
|
+
|
|
65
|
+
## Release obligations
|
|
66
|
+
|
|
67
|
+
Finishing the remote-sync work was **not** the same as being releasable, and
|
|
68
|
+
the gap was structural rather than a matter of polish: while `pyproject.toml`
|
|
69
|
+
carried a path source to a sibling checkout, `pip install stacktrace-cli` from
|
|
70
|
+
PyPI would have resolved an `openaca` without the consumption facade, and every
|
|
71
|
+
`remote` command would have failed at import.
|
|
72
|
+
|
|
73
|
+
All three are discharged, at `openaca` 0.6.0 — the first release carrying the
|
|
74
|
+
facade:
|
|
75
|
+
|
|
76
|
+
1. `[tool.uv.sources]` is gone; `uv.lock` resolves `openaca` from PyPI.
|
|
77
|
+
2. `.github/workflows/ci.yml` checks out this repository alone. The sibling
|
|
78
|
+
checkout and its pinned-revision assertion went with the path source.
|
|
79
|
+
3. The floor is `openaca>=0.6.0`, which is where plan 005 Task 1's
|
|
80
|
+
required-import probe first reports no missing name. Re-run that probe
|
|
81
|
+
against any candidate release before moving the floor again; it passes only
|
|
82
|
+
when it reports nothing missing.
|
|
83
|
+
|
|
84
|
+
One proof retired with them. The payload-equivalence test imported openaca's
|
|
85
|
+
`tools.remote` — the module 0.6.0 removed — so it cannot run against any
|
|
86
|
+
release that carries the facade. What it established is a fact about the
|
|
87
|
+
migration, not a property that a later release could re-check.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 0.2.1 — the page in front of the CLI
|
|
2
|
+
|
|
3
|
+
For a distribution, the PyPI listing is the product surface a reader meets
|
|
4
|
+
first. This release treats it as one. Nothing about what `stacktrace` does
|
|
5
|
+
changes here — no command, flag, rule or output shape moves — and the whole
|
|
6
|
+
delta is what the page in front of it claims.
|
|
7
|
+
|
|
8
|
+
## Highlights
|
|
9
|
+
|
|
10
|
+
- **The package metadata describes the product rather than a placeholder.**
|
|
11
|
+
The summary line said "Placeholder CLI for Stacktrace.ai — installs the
|
|
12
|
+
`stacktrace` command", written when that was true and left standing after
|
|
13
|
+
0.1.0 and 0.2.0 made it false. It now says what the CLI is for. Authorship
|
|
14
|
+
moves from an individual to Stacktrace AI, Inc., and
|
|
15
|
+
`Development Status :: 2 - Pre-Alpha` becomes `4 - Beta`, matching the
|
|
16
|
+
README's own Status section rather than contradicting it two clicks away.
|
|
17
|
+
`Operating System :: OS Independent` and per-minor Python classifiers for
|
|
18
|
+
3.11, 3.12 and 3.13 are added, so PyPI's own filters can find the package
|
|
19
|
+
under the versions `requires-python` already accepted.
|
|
20
|
+
|
|
21
|
+
- **The README is written for someone deciding whether to install.** It was a
|
|
22
|
+
contributor's design document — Design, Adding a command, Development,
|
|
23
|
+
Release obligations — that happened to be the `readme` field, so the long
|
|
24
|
+
description on PyPI opened by explaining the repository to people who
|
|
25
|
+
already had it checked out. It now opens with what the tool does in three
|
|
26
|
+
sentences and continues into install, a three-command quick start, the
|
|
27
|
+
command table, real sample output, what `detect` finds, and what leaves your
|
|
28
|
+
machine. That last section is the one a security reader arrives looking for
|
|
29
|
+
and previously had to infer.
|
|
30
|
+
|
|
31
|
+
- **The contributor material moved rather than being deleted.** The design and
|
|
32
|
+
workflow content is in `CLAUDE.md`, and the openaca 0.6.0 cutover notes and
|
|
33
|
+
release obligations are in `docs/cutover-openaca-remote.md`. Both stay in the
|
|
34
|
+
repository and neither is in the wheel.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
`uv tool install stacktrace-cli==0.2.1` or `pip install stacktrace-cli==0.2.1`.
|
|
39
|
+
|
|
40
|
+
## Compatibility
|
|
41
|
+
|
|
42
|
+
Nothing to do. This release changes no behaviour: the CLI's commands, flags,
|
|
43
|
+
output and upload payloads are identical to 0.2.0, and an existing install has
|
|
44
|
+
no reason to upgrade beyond the version string.
|
|
45
|
+
|
|
46
|
+
One note on the `Development Status :: 4 - Beta` classifier. It is a claim
|
|
47
|
+
about the project's stage, not a back-compat promise — the terms 0.2.0 shipped
|
|
48
|
+
under still hold, and interfaces can still change between releases without a
|
|
49
|
+
deprecation window.
|
|
@@ -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.
|