blq-cli 0.11.2__tar.gz → 1.0.0__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.
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.gitignore +2 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/CLAUDE.md +9 -9
- {blq_cli-0.11.2 → blq_cli-1.0.0}/PKG-INFO +1 -1
- blq_cli-1.0.0/docs/api-reference.md +601 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/capture.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/completions.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/exec.md +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/index.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/init.md +5 -5
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/maintenance.md +8 -8
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/registry.md +6 -6
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/run.md +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/sql.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/sync.md +6 -6
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/watch.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/getting-started.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/index.md +5 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/integration.md +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/mcp.md +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/plans/roadmap-to-1.0.md +2 -2
- blq_cli-1.0.0/docs/plugin-guide.md +354 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/python-api.md +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/sandbox.md +1 -1
- blq_cli-1.0.0/docs/schema-stability.md +150 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/schema.md +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/pyproject.toml +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/bird.py +12 -7
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/bird_schema.sql +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/cli.py +6 -6
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/ci_cmd.py +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/clean_cmd.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/config_cmd.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/core.py +66 -37
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/execution.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/hooks_cmd.py +17 -17
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/hooks_gen.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/init_cmd.py +28 -24
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/management.py +6 -6
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/migrate.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/query_cmd.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/registry.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/serve_cmd.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/sync_cmd.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/locks.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/query.py +14 -14
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/schema.sql +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/serve.py +15 -10
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/storage.py +22 -14
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/templates/drone.yml.j2 +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/templates/git_hook.sh.j2 +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/templates/github_workflow.yml.j2 +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/templates/gitlab_ci.yml.j2 +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/templates/hook_script.sh.j2 +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/user_config.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/conftest.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_attempts_outcomes.py +31 -31
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_auto_init.py +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_autoprune.py +10 -10
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_bird.py +19 -19
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ci_generators.py +5 -5
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_core.py +20 -20
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ext_integration.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ext_types.py +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_hooks.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_hooks_gen.py +5 -5
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_inspect.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_phase2_command_registry.py +4 -4
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_query_api.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_query_filter.py +3 -3
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_record_invocation.py +7 -7
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_ext.py +1 -1
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_storage.py +2 -2
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.claude/hooks/blq-suggest.sh +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.github/workflows/ci.yml +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.github/workflows/docs.yml +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.github/workflows/publish.yml +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.mcp.json +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/.readthedocs.yml +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/AGENT.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/AGENTS.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/CONTRIBUTING.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/README.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/SKILL.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/ci.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/errors.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/filter.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/query.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/report.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/commands/status.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-bird-migration.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-commands.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-config-command.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-extensions.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-git-integration.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-hooks-v2.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-live-inspection.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-parameterized-commands.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-run-args.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-sandbox-specs.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-sync.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/design-track-save.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/duck-hunt-v2-migration.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/duck-hunt-v3-migration.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/proposal-bird-v5.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/design/skill-inspect-enrichment.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/plans/explore-nsjail-python-wrapper.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/plans/explore-nsjail-spack-package.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/plans/patterns-integration-prompt.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/query-guide.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/requirements.txt +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-22-extension-system.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-28-bwrap-engine.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-28-command-locks.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-29-annotators-and-tighten.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-29-service-layer-phase1.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/plans/2026-03-29-strace-profiling.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/specs/2026-03-22-extension-system-design.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/docs/superpowers/specs/2026-03-29-unified-service-layer-design.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/experiments/agent-build-test.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/mkdocs.yml +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/__main__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/README.md +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/events.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/management_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/mcp_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/record_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/report_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/sandbox_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/commands/watch_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/config_format.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/ext/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/ext/annotator.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/ext/discovery.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/ext/local_executor.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/ext/pipeline.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/git.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/github.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/output.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/services/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/services/execution.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/services/inspect.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/services/query.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq/services/refs.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/engines.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/profile.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/source_annotator.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/spec.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/strace_parser.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/tighten.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox/violations.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox_bwrap/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox_bwrap/args.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/src/blq_sandbox_systemd/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/__init__.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/sql/test_duck_hunt_v2_migration.sql +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_annotator.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_bwrap_args.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_bwrap_engine.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ci.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_command_args.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_command_lock_field.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_execution_locks.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_exit_code_reason.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ext_discovery.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ext_local_executor.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_ext_pipeline.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_git.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_json_null_filter.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_locks.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_mcp_ci_tools.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_mcp_merge.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_mcp_server.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_phase1_structured_output.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_report.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_cmd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_events.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_profile.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_register.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_systemd.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_tighten.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_sandbox_violations.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_services_execution.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_services_inspect.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_services_query.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_services_refs.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_source_annotator.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_storage_prune.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_strace_parser.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_user_config.py +0 -0
- {blq_cli-0.11.2 → blq_cli-1.0.0}/tests/test_watch.py +0 -0
|
@@ -98,7 +98,7 @@ This is the initial scaffolding for `blq` (Build Log Query) - a CLI tool for cap
|
|
|
98
98
|
- [ ] Consider integration with duckdb_mcp for ATTACH/DETACH workflow
|
|
99
99
|
|
|
100
100
|
**BIRD Spec:**
|
|
101
|
-
- [
|
|
101
|
+
- [x] Migrated from `.lq/` to `.bird/` directory (auto-migration from legacy)
|
|
102
102
|
- [ ] Running process tracking (pending BIRD spec)
|
|
103
103
|
- [ ] Migrate to updated BIRD spec (when ready)
|
|
104
104
|
|
|
@@ -111,13 +111,13 @@ This is the initial scaffolding for `blq` (Build Log Query) - a CLI tool for cap
|
|
|
111
111
|
```
|
|
112
112
|
blq (Python CLI)
|
|
113
113
|
│
|
|
114
|
-
├── .
|
|
114
|
+
├── .bird/blq.duckdb - BIRD database with tables and macros
|
|
115
115
|
│ ├── sessions - Invoker sessions (shell, CLI, MCP)
|
|
116
116
|
│ ├── invocations - Command executions with metadata
|
|
117
117
|
│ ├── outputs - Captured stdout/stderr (content-addressed)
|
|
118
118
|
│ └── events - Parsed diagnostics (errors, warnings)
|
|
119
119
|
│
|
|
120
|
-
├── .
|
|
120
|
+
├── .bird/blobs/ - Content-addressed blob storage
|
|
121
121
|
│ └── content/ab/{hash}.bin
|
|
122
122
|
│
|
|
123
123
|
├── Uses duckdb Python API directly
|
|
@@ -171,7 +171,7 @@ All SQL macros use the `blq_` prefix:
|
|
|
171
171
|
|
|
172
172
|
Direct DuckDB access:
|
|
173
173
|
```bash
|
|
174
|
-
duckdb .
|
|
174
|
+
duckdb .bird/blq.duckdb "SELECT * FROM blq_status()"
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
## Run Metadata
|
|
@@ -193,7 +193,7 @@ Each `blq run` captures comprehensive execution context:
|
|
|
193
193
|
|
|
194
194
|
### Environment Capture
|
|
195
195
|
|
|
196
|
-
Configurable in `.
|
|
196
|
+
Configurable in `.bird/config.toml`:
|
|
197
197
|
```toml
|
|
198
198
|
capture_env = [
|
|
199
199
|
"PATH",
|
|
@@ -221,7 +221,7 @@ SELECT ci['provider'], ci['run_id'] FROM blq_load_events() WHERE ci IS NOT NULL
|
|
|
221
221
|
|
|
222
222
|
## Project Identification
|
|
223
223
|
|
|
224
|
-
Detected at `blq init` and stored in `.
|
|
224
|
+
Detected at `blq init` and stored in `.bird/config.toml`:
|
|
225
225
|
|
|
226
226
|
```toml
|
|
227
227
|
[project]
|
|
@@ -265,7 +265,7 @@ Runtime override: `blq run --no-capture <cmd>` or `blq run --capture <cmd>`
|
|
|
265
265
|
|
|
266
266
|
1. **BIRD as default storage**: DuckDB tables for simpler queries, content-addressed blobs for outputs
|
|
267
267
|
2. **Parquet mode available**: For multi-writer scenarios (legacy, use `--parquet` flag)
|
|
268
|
-
3. **Project-local storage**: `.
|
|
268
|
+
3. **Project-local storage**: `.bird/` directory in project root
|
|
269
269
|
4. **blq.duckdb for everything**: Tables, views, and macros in single database file
|
|
270
270
|
5. **Table-returning macros**: `blq_load_events()` evaluated at query time, not view creation
|
|
271
271
|
6. **Backward-compatible views**: `blq_events_flat` provides v1-compatible schema
|
|
@@ -334,7 +334,7 @@ blq mcp serve -D exec,clean # Disable specific tools
|
|
|
334
334
|
blq mcp serve -S -D custom_tool # Combine safe mode with additional tools
|
|
335
335
|
```
|
|
336
336
|
|
|
337
|
-
Or via `.
|
|
337
|
+
Or via `.bird/config.toml`:
|
|
338
338
|
```toml
|
|
339
339
|
[mcp]
|
|
340
340
|
disabled_tools = ["clean", "register_command", "unregister_command"]
|
|
@@ -441,7 +441,7 @@ ruff format src/blq/
|
|
|
441
441
|
|
|
442
442
|
### Config Options
|
|
443
443
|
|
|
444
|
-
Key `.
|
|
444
|
+
Key `.bird/config.toml` options:
|
|
445
445
|
```toml
|
|
446
446
|
[storage]
|
|
447
447
|
keep_raw = true # Always keep raw output
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blq-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Buidl Log Query - capture and query build/test logs with DuckDB
|
|
5
5
|
Project-URL: Homepage, https://blq-cli.readthedocs.com/
|
|
6
6
|
Project-URL: Repository, https://github.com/teaguesterling/blq-cli
|
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for blq's Python API and MCP tool schemas. For tutorial-style usage, see [Python API Guide](python-api.md) and [MCP Guide](mcp.md).
|
|
4
|
+
|
|
5
|
+
Source files: [`src/blq/query.py`](../src/blq/query.py), [`src/blq/storage.py`](../src/blq/storage.py), [`src/blq/services/`](../src/blq/services/), [`src/blq/serve.py`](../src/blq/serve.py)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## BlqStorage
|
|
10
|
+
|
|
11
|
+
**Module:** `blq.storage`
|
|
12
|
+
|
|
13
|
+
Low-level storage interface backed by BIRD (DuckDB tables + content-addressed blobs). Query methods return `DuckDBPyRelation` objects -- call `.df()` for DataFrame or `.fetchall()` for tuples.
|
|
14
|
+
|
|
15
|
+
### Construction
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from blq.storage import BlqStorage
|
|
19
|
+
|
|
20
|
+
storage = BlqStorage.open() # auto-find .bird from cwd
|
|
21
|
+
storage = BlqStorage.open("/path/to/.bird") # explicit path
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Supports context manager:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
with BlqStorage.open() as storage:
|
|
28
|
+
errors = storage.errors().df()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Properties
|
|
32
|
+
|
|
33
|
+
| Property | Type | Description |
|
|
34
|
+
|----------|------|-------------|
|
|
35
|
+
| `path` | `Path` | Path to `.bird` directory |
|
|
36
|
+
| `connection` | `duckdb.DuckDBPyConnection` | Underlying DuckDB connection |
|
|
37
|
+
|
|
38
|
+
### Data Checks
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
storage.has_data() -> bool # any runs exist
|
|
42
|
+
storage.has_runs() -> bool # alias for has_data()
|
|
43
|
+
storage.has_events() -> bool # any parsed events exist
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Run Queries
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
storage.runs(limit: int | None = None) -> DuckDBPyRelation
|
|
50
|
+
```
|
|
51
|
+
All runs with aggregated event counts, newest first. Columns: `run_id`, `source_name`, `source_type`, `command`, `tag`, `started_at`, `completed_at`, `exit_code`, `cwd`, `executable_path`, `hostname`, `platform`, `arch`, `git_commit`, `git_branch`, `git_dirty`, `ci`, `event_count`, `error_count`, `warning_count`.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
storage.run(run_id: int) -> DuckDBPyRelation
|
|
55
|
+
storage.latest_run_id() -> int | None
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Event Queries
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
storage.events(
|
|
62
|
+
run_id: int | None = None,
|
|
63
|
+
severity: str | list[str] | None = None,
|
|
64
|
+
limit: int | None = None,
|
|
65
|
+
) -> DuckDBPyRelation
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
storage.errors(run_id: int | None = None, limit: int = 20) -> DuckDBPyRelation
|
|
70
|
+
storage.warnings(run_id: int | None = None, limit: int = 20) -> DuckDBPyRelation
|
|
71
|
+
storage.event(run_serial: int, event_id: int) -> dict[str, Any] | None
|
|
72
|
+
storage.error_count(run_id: int | None = None) -> int
|
|
73
|
+
storage.warning_count(run_id: int | None = None) -> int
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Status
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
storage.status() -> DuckDBPyRelation # blq_status() summary
|
|
80
|
+
storage.source_status() -> DuckDBPyRelation # per-source latest run
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Output
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
storage.get_output(run_id: str | int, stream: str | None = None) -> bytes | None
|
|
87
|
+
storage.get_output_info(run_id: str | int) -> list[dict[str, Any]]
|
|
88
|
+
```
|
|
89
|
+
`stream` accepts `'stdout'`, `'stderr'`, `'combined'`, or `None` (any).
|
|
90
|
+
|
|
91
|
+
### SQL
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
storage.sql(query: str, params: list | None = None)
|
|
95
|
+
-> DuckDBPyRelation | DuckDBPyConnection
|
|
96
|
+
```
|
|
97
|
+
Without `params`, returns a relation. With `params` (using `?` placeholders), returns a connection result. Both support `.fetchall()` and `.fetchone()`.
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
storage.sql("SELECT * FROM blq_load_events() WHERE fingerprint = ?", [fp])
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Write Operations
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
storage.write_run(
|
|
107
|
+
run_meta: dict[str, Any],
|
|
108
|
+
events: list[dict[str, Any]] | None = None,
|
|
109
|
+
output: bytes | None = None,
|
|
110
|
+
) -> str # returns invocation UUID
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`run_meta` keys: `command`, `source_name`, `source_type`, `exit_code`, `started_at`, `completed_at`, `cwd`, `hostname`, `platform`, `arch`, `git_commit`, `git_branch`, `git_dirty`, `ci`, `environment`.
|
|
114
|
+
|
|
115
|
+
### Maintenance
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
storage.prune(days: int = 30) -> int # remove old data
|
|
119
|
+
storage.prune_by_max_runs(max_runs: int) -> int # keep N per source
|
|
120
|
+
storage.prune_by_size(max_size_mb: int) -> int # cap total output size
|
|
121
|
+
storage.cleanup_blobs() -> tuple[int, int] # (deleted, bytes_freed)
|
|
122
|
+
storage.total_output_size() -> int # total bytes
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## LogStore
|
|
128
|
+
|
|
129
|
+
**Module:** `blq.query`
|
|
130
|
+
|
|
131
|
+
Higher-level query API with fluent `LogQuery` builder. Returns pandas DataFrames.
|
|
132
|
+
|
|
133
|
+
### Construction
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from blq.query import LogStore
|
|
137
|
+
|
|
138
|
+
store = LogStore.open() # auto-find .bird
|
|
139
|
+
store = LogStore.open("/path/to/.bird") # explicit path
|
|
140
|
+
store = LogStore("/path/to/.bird") # direct init
|
|
141
|
+
store = LogStore.from_parquet_root("path") # raw parquet directory
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Properties
|
|
145
|
+
|
|
146
|
+
| Property | Type | Description |
|
|
147
|
+
|----------|------|-------------|
|
|
148
|
+
| `path` | `Path` | `.bird` directory path |
|
|
149
|
+
| `logs_path` | `Path` | Logs subdirectory path |
|
|
150
|
+
| `connection` | `duckdb.DuckDBPyConnection` | DuckDB connection |
|
|
151
|
+
|
|
152
|
+
### Query Methods
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
store.events() -> LogQuery # all events
|
|
156
|
+
store.errors() -> LogQuery # severity='error'
|
|
157
|
+
store.warnings() -> LogQuery # severity='warning'
|
|
158
|
+
store.run(run_id: int) -> LogQuery # events from one run
|
|
159
|
+
store.runs() -> pd.DataFrame # run summaries
|
|
160
|
+
store.latest_run() -> int | None # most recent run_id
|
|
161
|
+
store.event(run_id: int, event_id: int) -> dict[str, Any] | None
|
|
162
|
+
store.has_data() -> bool
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## LogQuery
|
|
168
|
+
|
|
169
|
+
**Module:** `blq.query`
|
|
170
|
+
|
|
171
|
+
Fluent query builder wrapping a DuckDB relation. All operations are deferred until a terminal method is called.
|
|
172
|
+
|
|
173
|
+
### Construction
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from blq.query import LogQuery
|
|
177
|
+
|
|
178
|
+
LogQuery.from_file(path, format="auto", conn=None) -> LogQuery
|
|
179
|
+
LogQuery.from_content(content: str, format="auto", conn=None) -> LogQuery
|
|
180
|
+
LogQuery.from_sql(conn, sql, params=None) -> LogQuery
|
|
181
|
+
LogQuery.from_table(conn, table_name) -> LogQuery
|
|
182
|
+
LogQuery.from_parquet(path, conn=None, hive_partitioning=True) -> LogQuery
|
|
183
|
+
LogQuery.from_relation(rel, conn) -> LogQuery
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Filtering
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
.filter(severity="error") # exact match
|
|
190
|
+
.filter(severity=["error", "warning"]) # IN clause
|
|
191
|
+
.filter(ref_file="%main%") # ILIKE pattern
|
|
192
|
+
.filter(severity="!info") # NOT equal
|
|
193
|
+
.filter(ref_line=100) # numeric equality
|
|
194
|
+
.filter(severity=None) # IS NULL
|
|
195
|
+
.filter("ref_line > 100") # raw SQL condition
|
|
196
|
+
.exclude(severity="info") # NOT (severity = 'info')
|
|
197
|
+
.where("ref_line BETWEEN 10 AND 50") # raw SQL WHERE
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Projection
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
.select(*columns: str) -> LogQuery
|
|
204
|
+
.order_by(*columns: str, desc: bool = False) -> LogQuery
|
|
205
|
+
.limit(n: int) -> LogQuery
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Terminal Methods
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
.df() -> pd.DataFrame
|
|
212
|
+
.fetchall() -> list[tuple]
|
|
213
|
+
.fetchone() -> tuple | None
|
|
214
|
+
.count() -> int
|
|
215
|
+
.exists() -> bool
|
|
216
|
+
.show(n: int = 10) -> None # print to stdout
|
|
217
|
+
.explain() -> str # query plan
|
|
218
|
+
.describe() -> pd.DataFrame # statistics
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Inspection
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
.columns -> list[str]
|
|
225
|
+
.dtypes -> list[str]
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Aggregation
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
.group_by(*columns) -> LogQueryGrouped
|
|
232
|
+
.value_counts(column: str) -> pd.DataFrame
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## LogQueryGrouped
|
|
238
|
+
|
|
239
|
+
**Module:** `blq.query`
|
|
240
|
+
|
|
241
|
+
Returned by `LogQuery.group_by()`. All methods return `pd.DataFrame`.
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
grouped = query.group_by("ref_file")
|
|
245
|
+
grouped.count() -> pd.DataFrame
|
|
246
|
+
grouped.sum(column: str) -> pd.DataFrame
|
|
247
|
+
grouped.avg(column: str) -> pd.DataFrame
|
|
248
|
+
grouped.min(column: str) -> pd.DataFrame
|
|
249
|
+
grouped.max(column: str) -> pd.DataFrame
|
|
250
|
+
grouped.agg(**aggregations: str) -> pd.DataFrame
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`agg` example: `.agg(total="COUNT(*)", first_line="MIN(ref_line)")`
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Service Layer
|
|
258
|
+
|
|
259
|
+
**Module:** `blq.services`
|
|
260
|
+
|
|
261
|
+
Pure business logic shared by CLI and MCP. All query functions take `BlqStorage` as the first argument and return structured dicts/lists.
|
|
262
|
+
|
|
263
|
+
### Refs
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from blq.services import parse_ref, resolve_run_ref, ParsedRef
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
parse_ref(ref: str) -> ParsedRef
|
|
271
|
+
```
|
|
272
|
+
Parses ref strings into structured form. Raises `ValueError` on invalid input.
|
|
273
|
+
|
|
274
|
+
| Input | Result |
|
|
275
|
+
|-------|--------|
|
|
276
|
+
| `"5"` | `ParsedRef(run_serial=5)` |
|
|
277
|
+
| `"build:3"` | `ParsedRef(tag="build", run_serial=3)` |
|
|
278
|
+
| `"test:5:2"` | `ParsedRef(tag="test", run_serial=5, event_id=2)` |
|
|
279
|
+
| `"5:2"` | `ParsedRef(run_serial=5, event_id=2)` |
|
|
280
|
+
| `"~1"` | `ParsedRef(relative=1)` |
|
|
281
|
+
| `"test:~2"` | `ParsedRef(tag="test", relative=2)` |
|
|
282
|
+
| UUID | `ParsedRef(uuid="...")` |
|
|
283
|
+
|
|
284
|
+
`ParsedRef` properties: `is_relative -> bool`, `run_ref -> str`.
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
resolve_run_ref(storage: BlqStorage, ref: str) -> dict | None
|
|
288
|
+
```
|
|
289
|
+
Resolves a ref string to a run data dict. Returns `None` if not found.
|
|
290
|
+
|
|
291
|
+
### Queries
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from blq.services import query_status, query_history, query_events, query_diff
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
query_status(storage: BlqStorage) -> list[dict[str, Any]]
|
|
299
|
+
```
|
|
300
|
+
Returns per-source status: `name`, `status`, `error_count`, `warning_count`, `last_run`, `run_ref`, `run_serial`.
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
query_history(
|
|
304
|
+
storage: BlqStorage,
|
|
305
|
+
limit: int = 20,
|
|
306
|
+
source: str | None = None,
|
|
307
|
+
status: str | None = None, # 'running', 'completed', 'orphaned'
|
|
308
|
+
) -> list[dict[str, Any]]
|
|
309
|
+
```
|
|
310
|
+
Returns: `run_ref`, `run_serial`, `source_name`, `status`, `error_count`, `warning_count`, `started_at`, `exit_code`, `command`, `git_commit`, `git_branch`, `git_dirty`.
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
query_events(
|
|
314
|
+
storage: BlqStorage,
|
|
315
|
+
severity: str | None = None, # 'error', 'warning', or comma-separated
|
|
316
|
+
run_id: int | None = None,
|
|
317
|
+
source: str | None = None,
|
|
318
|
+
file_pattern: str | None = None,
|
|
319
|
+
limit: int = 20,
|
|
320
|
+
default_to_latest: bool = False,
|
|
321
|
+
suppressed_fingerprints: list[str] | None = None,
|
|
322
|
+
all_runs: bool = False,
|
|
323
|
+
) -> dict[str, Any] # {"events": [...], "total_count": int}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
query_diff(storage: BlqStorage, run1: int, run2: int) -> dict[str, Any]
|
|
328
|
+
```
|
|
329
|
+
Returns: `summary` (`run1_errors`, `run2_errors`, `fixed`, `new`, `unchanged`), `fixed` (list), `new` (list).
|
|
330
|
+
|
|
331
|
+
### Inspect
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
from blq.services import (
|
|
335
|
+
get_source_context, get_log_context,
|
|
336
|
+
get_git_context, get_fingerprint_history,
|
|
337
|
+
)
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
get_source_context(
|
|
342
|
+
ref_file: str | None, ref_line: int | None,
|
|
343
|
+
source_root: Path, context_lines: int = 3,
|
|
344
|
+
) -> str | None
|
|
345
|
+
|
|
346
|
+
get_log_context(
|
|
347
|
+
storage: BlqStorage | None, run_id: int,
|
|
348
|
+
log_line_start: int | None, log_line_end: int | None,
|
|
349
|
+
context_lines: int = 3,
|
|
350
|
+
) -> str | None
|
|
351
|
+
|
|
352
|
+
get_git_context(
|
|
353
|
+
ref_file: str | None, ref_line: int | None,
|
|
354
|
+
source_root: Path, history_limit: int = 2,
|
|
355
|
+
) -> dict[str, Any] | None # {file, line, blame, recent_commits}
|
|
356
|
+
|
|
357
|
+
get_fingerprint_history(
|
|
358
|
+
storage: BlqStorage | None, fingerprint: str | None,
|
|
359
|
+
) -> dict[str, Any] | None # {fingerprint, first_seen, last_seen, occurrences, is_regression}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Execution
|
|
363
|
+
|
|
364
|
+
```python
|
|
365
|
+
from blq.services import run_result_to_concise
|
|
366
|
+
|
|
367
|
+
run_result_to_concise(full_result: dict[str, Any], source_name: str) -> dict[str, Any]
|
|
368
|
+
```
|
|
369
|
+
Converts a `RunResult.to_json()` dict into the concise response format with keys: `run_ref`, `cmd`, `status`, `exit_code`, `duration_sec`, `summary`, `output_stats`. Conditionally includes `errors` (max 10), `warnings` (max 5), `infos` (max 5).
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## MCP Tools
|
|
374
|
+
|
|
375
|
+
MCP server started via `blq mcp serve`. Tools are callable by any MCP client.
|
|
376
|
+
|
|
377
|
+
### run
|
|
378
|
+
|
|
379
|
+
Run a registered command and capture output.
|
|
380
|
+
|
|
381
|
+
| Parameter | Type | Default | Description |
|
|
382
|
+
|-----------|------|---------|-------------|
|
|
383
|
+
| `command` | `str` | required | Registered command name |
|
|
384
|
+
| `args` | `dict[str,str] \| list[str] \| None` | `None` | Named args (dict) or positional args (list) |
|
|
385
|
+
| `extra` | `list[str] \| None` | `None` | Passthrough arguments appended to command |
|
|
386
|
+
| `timeout` | `int \| None` | `None` | Timeout in seconds |
|
|
387
|
+
| `lines` | `str \| None` | `None` | Line selection for inline output (e.g. `'+20-'`) |
|
|
388
|
+
| `commands` | `list[str] \| None` | `None` | Batch mode: run multiple commands in sequence |
|
|
389
|
+
| `stop_on_failure` | `bool` | `True` | Stop batch on first failure |
|
|
390
|
+
|
|
391
|
+
**Returns:** `{run_ref, cmd, status, exit_code, duration_sec, summary, output_stats, errors?, warnings?}`
|
|
392
|
+
|
|
393
|
+
### exec
|
|
394
|
+
|
|
395
|
+
Execute an ad-hoc shell command. Do not use pipes/redirects -- use `output()` tool instead.
|
|
396
|
+
|
|
397
|
+
| Parameter | Type | Default | Description |
|
|
398
|
+
|-----------|------|---------|-------------|
|
|
399
|
+
| `command` | `str` | required | Shell command (no pipes) |
|
|
400
|
+
| `args` | `list[str] \| None` | `None` | Additional arguments |
|
|
401
|
+
| `timeout` | `int \| None` | `None` | Timeout in seconds |
|
|
402
|
+
| `shell` | `bool` | `False` | Allow shell syntax |
|
|
403
|
+
| `lines` | `str \| None` | `None` | Inline output line selection |
|
|
404
|
+
|
|
405
|
+
**Returns:** Same shape as `run`.
|
|
406
|
+
|
|
407
|
+
### status
|
|
408
|
+
|
|
409
|
+
No parameters. Returns `{sources: [{name, status, error_count, warning_count, last_run, run_ref}]}`.
|
|
410
|
+
|
|
411
|
+
### events
|
|
412
|
+
|
|
413
|
+
| Parameter | Type | Default | Description |
|
|
414
|
+
|-----------|------|---------|-------------|
|
|
415
|
+
| `limit` | `int` | `20` | Max events |
|
|
416
|
+
| `run_id` | `int \| None` | `None` | Filter by run serial |
|
|
417
|
+
| `source` | `str \| None` | `None` | Filter by source name |
|
|
418
|
+
| `severity` | `str \| None` | `None` | `'error'`, `'warning'`, or comma-separated |
|
|
419
|
+
| `file_pattern` | `str \| None` | `None` | SQL LIKE pattern for `ref_file` |
|
|
420
|
+
| `all_runs` | `bool` | `False` | Show all runs (default: most recent only) |
|
|
421
|
+
| `run_ids` | `list[int] \| None` | `None` | Batch mode: multiple run IDs |
|
|
422
|
+
| `limit_per_run` | `int` | `10` | Max events per run in batch mode |
|
|
423
|
+
|
|
424
|
+
**Returns:** `{events: [...], total_count: int}`
|
|
425
|
+
|
|
426
|
+
### inspect
|
|
427
|
+
|
|
428
|
+
| Parameter | Type | Default | Description |
|
|
429
|
+
|-----------|------|---------|-------------|
|
|
430
|
+
| `ref` | `str` | required | Event ref (e.g. `"build:1:3"`) |
|
|
431
|
+
| `lines` | `int` | `5` | Context lines before/after |
|
|
432
|
+
| `include_log_context` | `bool` | `True` | Include log output context |
|
|
433
|
+
| `include_source_context` | `bool` | `True` | Include source file context |
|
|
434
|
+
| `include_git_context` | `bool` | `False` | Include git blame/history |
|
|
435
|
+
| `include_fingerprint_history` | `bool` | `False` | Include occurrence history |
|
|
436
|
+
| `refs` | `list[str] \| None` | `None` | Batch mode: multiple refs |
|
|
437
|
+
|
|
438
|
+
**Returns:** `{ref, severity, ref_file, ref_line, message, log_context?, source_context?, git_context?, fingerprint_history?}`
|
|
439
|
+
|
|
440
|
+
### info
|
|
441
|
+
|
|
442
|
+
| Parameter | Type | Default | Description |
|
|
443
|
+
|-----------|------|---------|-------------|
|
|
444
|
+
| `ref` | `str \| None` | `None` | Run ref or UUID. `None` = most recent |
|
|
445
|
+
| `head` | `int \| None` | `None` | First N lines of output |
|
|
446
|
+
| `tail` | `int \| None` | `None` | Last N lines of output |
|
|
447
|
+
| `errors` | `bool` | `False` | Include error events |
|
|
448
|
+
| `warnings` | `bool` | `False` | Include warning events |
|
|
449
|
+
| `severity` | `str \| None` | `None` | Filter events by severity |
|
|
450
|
+
| `limit` | `int` | `20` | Max events |
|
|
451
|
+
| `context` | `int \| None` | `None` | Log context lines around each event |
|
|
452
|
+
|
|
453
|
+
**Returns:** `{run_ref, status, exit_code, command, started_at, events?, output?, summary?}`
|
|
454
|
+
|
|
455
|
+
### history
|
|
456
|
+
|
|
457
|
+
| Parameter | Type | Default | Description |
|
|
458
|
+
|-----------|------|---------|-------------|
|
|
459
|
+
| `limit` | `int` | `20` | Max runs |
|
|
460
|
+
| `source` | `str \| None` | `None` | Filter by source name |
|
|
461
|
+
| `status` | `str \| None` | `None` | `'running'`, `'completed'`, `'orphaned'` |
|
|
462
|
+
|
|
463
|
+
**Returns:** `{runs: [...]}`
|
|
464
|
+
|
|
465
|
+
### query
|
|
466
|
+
|
|
467
|
+
| Parameter | Type | Default | Description |
|
|
468
|
+
|-----------|------|---------|-------------|
|
|
469
|
+
| `sql` | `str \| None` | `None` | Raw SQL query |
|
|
470
|
+
| `filter` | `str \| None` | `None` | Filter expression (e.g. `"severity=error ref_file~test"`) |
|
|
471
|
+
| `limit` | `int` | `100` | Max rows |
|
|
472
|
+
|
|
473
|
+
Filter syntax: `key=value` (exact), `key=v1,v2` (IN), `key~pattern` (ILIKE), `key!=value` (not equal). Space-separated filters are AND'd.
|
|
474
|
+
|
|
475
|
+
**Returns:** `{columns, rows, row_count}`
|
|
476
|
+
|
|
477
|
+
### output
|
|
478
|
+
|
|
479
|
+
| Parameter | Type | Default | Description |
|
|
480
|
+
|-----------|------|---------|-------------|
|
|
481
|
+
| `ref` | `str` | required | Run ref (e.g. `'5'`, `'test:3'`, `'+1'`) |
|
|
482
|
+
| `stream` | `str \| None` | `None` | `'stdout'`, `'stderr'`, `'combined'` |
|
|
483
|
+
| `tail` | `int \| None` | `None` | Last N lines |
|
|
484
|
+
| `head` | `int \| None` | `None` | First N lines |
|
|
485
|
+
| `grep` | `str \| None` | `None` | Regex search pattern |
|
|
486
|
+
| `context` | `int` | `0` | Context lines around grep matches |
|
|
487
|
+
| `lines` | `str \| None` | `None` | Line spec (e.g. `'100-200'`) |
|
|
488
|
+
| `debug_formats` | `bool` | `False` | Show format detection info |
|
|
489
|
+
|
|
490
|
+
**Returns:** `{output, byte_length, total_lines, ...}`
|
|
491
|
+
|
|
492
|
+
### diff
|
|
493
|
+
|
|
494
|
+
| Parameter | Type | Default | Description |
|
|
495
|
+
|-----------|------|---------|-------------|
|
|
496
|
+
| `run1` | `int` | required | Baseline run serial |
|
|
497
|
+
| `run2` | `int` | required | Comparison run serial |
|
|
498
|
+
|
|
499
|
+
**Returns:** `{summary: {run1_errors, run2_errors, fixed, new, unchanged}, fixed: [...], new: [...]}`
|
|
500
|
+
|
|
501
|
+
### commands
|
|
502
|
+
|
|
503
|
+
No parameters. Returns `{commands: [{name, cmd, description, ...}]}`.
|
|
504
|
+
|
|
505
|
+
### register_command
|
|
506
|
+
|
|
507
|
+
| Parameter | Type | Default | Description |
|
|
508
|
+
|-----------|------|---------|-------------|
|
|
509
|
+
| `name` | `str` | required | Command name |
|
|
510
|
+
| `cmd` | `str \| None` | `None` | Command string |
|
|
511
|
+
| `tpl` | `str \| None` | `None` | Template with `{param}` placeholders |
|
|
512
|
+
| `defaults` | `dict[str,str] \| None` | `None` | Default template parameter values |
|
|
513
|
+
| `description` | `str` | `""` | Description |
|
|
514
|
+
| `timeout` | `int \| None` | `None` | Timeout in seconds |
|
|
515
|
+
| `capture` | `bool` | `True` | Capture and parse output |
|
|
516
|
+
| `force` | `bool` | `False` | Overwrite existing |
|
|
517
|
+
| `format` | `str \| None` | `None` | Log format hint |
|
|
518
|
+
| `run_now` | `bool` | `False` | Run immediately after registering |
|
|
519
|
+
| `lines` | `str \| None` | `None` | Default output line selection |
|
|
520
|
+
| `sandbox` | `str \| dict \| None` | `None` | Sandbox preset or spec dict |
|
|
521
|
+
| `lock` | `str \| None` | `None` | Lock name for concurrency control |
|
|
522
|
+
|
|
523
|
+
**Returns:** `{success, command, run?}`
|
|
524
|
+
|
|
525
|
+
### unregister_command
|
|
526
|
+
|
|
527
|
+
| Parameter | Type | Default |
|
|
528
|
+
|-----------|------|---------|
|
|
529
|
+
| `name` | `str` | required |
|
|
530
|
+
|
|
531
|
+
**Returns:** `{success: bool}`
|
|
532
|
+
|
|
533
|
+
### clean
|
|
534
|
+
|
|
535
|
+
| Parameter | Type | Default | Description |
|
|
536
|
+
|-----------|------|---------|-------------|
|
|
537
|
+
| `mode` | `str` | `"data"` | `'data'`, `'prune'`, `'schema'`, `'full'` |
|
|
538
|
+
| `confirm` | `bool` | `False` | Must be `True` to proceed |
|
|
539
|
+
| `days` | `int \| None` | `None` | Prune: remove older than N days |
|
|
540
|
+
| `max_runs` | `int \| None` | `None` | Prune: keep N per source |
|
|
541
|
+
| `max_size_mb` | `int \| None` | `None` | Prune: cap total output size |
|
|
542
|
+
|
|
543
|
+
**Returns:** `{success, message, mode}`
|
|
544
|
+
|
|
545
|
+
### report
|
|
546
|
+
|
|
547
|
+
| Parameter | Type | Default | Description |
|
|
548
|
+
|-----------|------|---------|-------------|
|
|
549
|
+
| `ref` | `str \| None` | `None` | Run ref (default: latest) |
|
|
550
|
+
| `baseline` | `str \| None` | `None` | Baseline run, branch, or commit |
|
|
551
|
+
| `warnings` | `bool` | `False` | Include warnings |
|
|
552
|
+
| `summary_only` | `bool` | `False` | Omit individual error details |
|
|
553
|
+
| `error_limit` | `int` | `20` | Max errors in details |
|
|
554
|
+
| `file_limit` | `int` | `10` | Max files in breakdown |
|
|
555
|
+
|
|
556
|
+
**Returns:** `{report: "markdown...", run_id, total_errors, total_warnings, has_baseline}`
|
|
557
|
+
|
|
558
|
+
### ci_check
|
|
559
|
+
|
|
560
|
+
| Parameter | Type | Default | Description |
|
|
561
|
+
|-----------|------|---------|-------------|
|
|
562
|
+
| `baseline` | `str \| None` | `None` | Baseline (auto-detects main/master) |
|
|
563
|
+
| `fail_on_any` | `bool` | `False` | Fail on any errors |
|
|
564
|
+
| `run_id` | `int \| None` | `None` | Run to check (default: auto-detect) |
|
|
565
|
+
|
|
566
|
+
**Returns:** `{status: 'OK'|'FAIL', current_run_id, new_errors?, fixed?}`
|
|
567
|
+
|
|
568
|
+
### ci_generate
|
|
569
|
+
|
|
570
|
+
| Parameter | Type | Default | Description |
|
|
571
|
+
|-----------|------|---------|-------------|
|
|
572
|
+
| `commands` | `list[str] \| None` | `None` | Commands to generate (default: all) |
|
|
573
|
+
| `shell` | `str` | `"bash"` | `'bash'`, `'sh'`, `'zsh'` |
|
|
574
|
+
|
|
575
|
+
**Returns:** `{scripts: [{name, content, ...}]}`
|
|
576
|
+
|
|
577
|
+
### sandbox_info
|
|
578
|
+
|
|
579
|
+
| Parameter | Type | Default | Description |
|
|
580
|
+
|-----------|------|---------|-------------|
|
|
581
|
+
| `command` | `str \| None` | `None` | Command name (omit for all) |
|
|
582
|
+
|
|
583
|
+
**Returns:** JSON with sandbox spec, grades, and resource metrics.
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## MCP Resources
|
|
588
|
+
|
|
589
|
+
| URI | Type | Description |
|
|
590
|
+
|-----|------|-------------|
|
|
591
|
+
| `blq://status` | JSON | Current per-source status |
|
|
592
|
+
| `blq://runs` | JSON | Run history (up to 100) |
|
|
593
|
+
| `blq://events` | JSON | Recent error events |
|
|
594
|
+
| `blq://event/{ref}` | JSON | Single event details |
|
|
595
|
+
| `blq://errors` | JSON | Recent errors (up to 50) |
|
|
596
|
+
| `blq://errors/{run_serial}` | JSON | Errors for a specific run |
|
|
597
|
+
| `blq://warnings` | JSON | Recent warnings (up to 50) |
|
|
598
|
+
| `blq://warnings/{run_serial}` | JSON | Warnings for a specific run |
|
|
599
|
+
| `blq://context/{ref}` | JSON | Log context around an event |
|
|
600
|
+
| `blq://commands` | JSON | Registered commands |
|
|
601
|
+
| `blq://guide` | Markdown | Agent usage guide |
|
|
@@ -140,7 +140,7 @@ Usually auto-detection works well. Specify format when:
|
|
|
140
140
|
All captured logs are stored in the BIRD database (DuckDB tables with content-addressed blob storage):
|
|
141
141
|
|
|
142
142
|
```
|
|
143
|
-
.
|
|
143
|
+
.bird/
|
|
144
144
|
├── blq.duckdb # DuckDB database (events, runs, metadata)
|
|
145
145
|
├── blobs/ # Content-addressed blob storage
|
|
146
146
|
│ └── content/
|