sourcecode 5.9.31__tar.gz → 5.9.32__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.
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.github/workflows/build-windows.yml +4 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.github/workflows/perf-gate.yml +4 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.github/workflows/windows-battery.yml +4 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.github/workflows/windows-regression.yml +4 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/CHANGELOG.md +15 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/PKG-INFO +3 -3
- {sourcecode-5.9.31 → sourcecode-5.9.32}/README.md +2 -2
- sourcecode-5.9.32/SPEC-update-notifications.md +85 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/USER_GUIDE.md +1 -1
- sourcecode-5.9.32/docs/investigations/2026-09-15-telemetry-audit.md +50 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/privacy.md +19 -4
- sourcecode-5.9.32/docs/update.md +22 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/pyproject.toml +1 -1
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/__init__.py +1 -1
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cli.py +121 -23
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/license.py +1 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/runner.py +10 -2
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/server.py +47 -2
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/__init__.py +24 -5
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/config.py +54 -18
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/events.py +6 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/filters.py +14 -4
- sourcecode-5.9.32/src/sourcecode/telemetry/lifecycle.py +30 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/transport.py +38 -3
- sourcecode-5.9.32/src/sourcecode/update.py +155 -0
- sourcecode-5.9.32/supabase/functions/telemetry/contract.test.ts +46 -0
- sourcecode-5.9.31/supabase/functions/telemetry/index.ts → sourcecode-5.9.32/supabase/functions/telemetry/contract.ts +32 -67
- sourcecode-5.9.32/supabase/functions/telemetry/index.ts +71 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/sql/telemetry_events.sql +15 -0
- sourcecode-5.9.32/supabase/sql/telemetry_product_metrics.sql +135 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.gitignore +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/.ruff.toml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/CLAUDE.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/CODE_OF_CONDUCT.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/CONTRIBUTING.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/LICENSE +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/NOTICE +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/SECURITY.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-22-5.8.22.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-5.8.24.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-COMMERCIAL.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-CORPUS-AMPLIADO.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-EXTERNAL-5.8.25.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-EXTERNAL-5.8.26.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-23-THINGSBOARD-FINDINGS.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.26.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.27.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.28.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.31.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.8.32.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-EXTERNAL-5.9.0.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-26-MONETIZATION.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-27-EXTERNAL-5.9.2.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-27-EXTERNAL-5.9.3.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-28-EXTERNAL-5.9.10.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-31-EXTERNAL-5.9.16.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-31-EXTERNAL-5.9.17.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-08-31-REMEDIATION-5.9.18.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-01-ALTERNATIVE-5.9.23.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-01-EXTERNAL-5.9.22.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-01-EXTERNAL-5.9.23.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-ALTERNATIVE-5.9.25.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-ALTERNATIVE-5.9.27.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-ALTERNATIVE-5.9.28.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-ALTERNATIVE-5.9.29.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-EXTERNAL-5.9.25.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-EXTERNAL-5.9.26.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-2026-09-02-EXTERNAL-5.9.29.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/AUDIT-TESTING-CORPUS-2026-08-22.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/CACHE.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/COMMERCIAL-OFFER.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/CUSTOMER-VALIDATION.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/DEFECT-LEDGER.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/DEMO-5MIN.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/DEVELOPMENT-ROADMAP.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/DOCUMENTATION-HYGIENE-2026-08-23.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/EXECUTION-PLAN-12MO.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/EXECUTIVE-ROADMAP.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/MANUAL-USUARIO.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/MODERNIZATION.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/PRODUCT-ROUTE.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/PRODUCT_AUDIT.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/PRODUCT_IDENTITY.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/PRODUCT_TIERS.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/RC1-CHECKLIST.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/RD-JVM-ASK-TRIAGE-2026-08-31.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/RELEASE-CHECKLIST.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/RELEASE-VERIFICATION.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/STRATEGY-2026-08-26-AGENT-CONTEXT.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/CATALOG-retrieval-intents.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-assessment-deployment-evidence.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-assessment-report.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-build-closure-provenance.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-knowledge-provider-integration.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-p5.3b-statement-surface.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-p5.5-span-index.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-p6-semantic-impact-engine.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-p6-semantic-integration-engine.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-p7-semantic-services.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-pack-gate-ci.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-pack-manifest.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-pack-mcp-api.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-robustness-security-inference.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/DESIGN-semantic-retrieval.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/EPV-p6-class-typeref.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/REPORT-p6-flow-analyzer-comparison.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/REPORT-p6-integration-detector-comparison.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/REPORT-p8-flow-analyzer-migration.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/REPORT-p9-integration-detector-migration.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0001-semantic-ir.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0002-source-evidence-boundary.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0003-architectural-characterization.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0004-semantic-retrieval.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0005-evidence-reconciliation.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0006-performance-harness.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0007-composition-semantics.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/adr/0008-answer-coherence.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/consumer-disposition-inventory.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/overview.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/product-architecture-review.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/product-strategy-layering.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/semantic-ir-consumer-matrix.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/architecture/semantic-ir-roadmap.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/baseline-ci.yml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/commercial-pipeline-audit.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/contracts-ci.yml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/contracts.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-15-petclinic-rest-issue11-vets-pagination.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-15-petclinic-rest-issue147-validation.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-15-petclinic-rest-workflow.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-15-phase18-openapi-surface.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-15-phase20-validation-surface.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-16-broadleaf-checkout-impact-fieldtest.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-16-petclinic-rest-issue11-weakness2-closed.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/eval/2026-06-16-spring-petclinic-issue2333-dead-vets.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/investigations/2026-09-11-ask-mcp-telemetry.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/licensing-schema.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/migrate-check.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/pack-gate-github-actions.yml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/pack-gate-gitlab.yml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/README.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/REGRESSION-GATE.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/SUMMARY.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/alfresco__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/alfresco__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/broadleaf__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/eureka__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/eureka__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/jenkins__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/jenkins__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/jobrunr__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/jobrunr__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/keycloak__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/keycloak__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/neo4j__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/neo4j__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/ofbiz__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/ofbiz__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/openmrs__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/openmrs__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/petclinic__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.15/petclinic__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/SUMMARY.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/alfresco__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/alfresco__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/broadleaf__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/eureka__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/eureka__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/jenkins__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/jenkins__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/jobrunr__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/jobrunr__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/keycloak__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/keycloak__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/neo4j__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/neo4j__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/ofbiz__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/ofbiz__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/openmrs__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/openmrs__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/petclinic__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/2.5.16/petclinic__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/5.9.22/petclinic__ask__cold.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/5.9.22/petclinic__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/README.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__endpoints__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__migrate-check__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__posture__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__spring-audit__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/gate-latest/broadleaf__validation__warm.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/baselines/reference-best/README.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/perf/corpus-testing-2026-08-22.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/posture.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/pro-experience-audit.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/schema.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/spec/envelope-v1.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/docs/spring-audit-ci.yml +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/hatch_build.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/context_cost_harness.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/perf_gate.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/perf_harness.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/sync_gate_anchors.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/test_fast.sh +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/scripts/windows_reliability_matrix.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/__main__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/access_drift.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/analysis_budget.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/answer_bounds.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/archetype.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/audit_clusters.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/audit_recipe.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/audit_report.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/audit_since.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/audit_verify.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/baseline_attestation.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/breaking_changes.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/build_modules.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/build_stamp.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/bundled_docs.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/c4_render.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cache.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cache_model.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cache_observation.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/change_plan.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/ci_output.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/classifier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/click_runtime.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/compare.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/concurrency.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/consumer_join.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/container_wiring.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/context_cache.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cve_feed.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/cve_reachability.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/data_exposure.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/declarations.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/defect_classes/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/defect_classes/registry.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/degradation.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detach.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/empty_answer_diagnostics.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/empty_reach.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/endpoint_disposition.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/envelope.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/environment_resolution.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/execution_plan.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/explain.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/explain_endpoint.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/field_deprecations.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/findings_baseline.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/functional_routes.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/gate_anchors.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/github_diff.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/inflight.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/intent_router.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/jvm_inventory.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/manifest_cache.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/dependency_import.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/migration_apply.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/non_coverage.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/output_bounds.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/output_ceiling.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/output_encoding.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/output_sink.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/pack_manifest.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/packs.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/parallel.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/partial_contract.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/path_display.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/perf.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/phased_run.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/posture.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/pr_risk.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/product_info.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/progress.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/provenance.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/readonly.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/redactor.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/regress.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/regulatory_pack.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/release_info.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/remediation_diff.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/remediation_flow.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/remediation_report.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/remedies.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/resource_budget.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/ris.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/risk.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/risk_model.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/rule_catalog.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/rule_pass.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/runs.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/sarif.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/sarif_emit.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/scanner.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schema.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schema_producers.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schema_registry.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/core-analysis-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/cve-reachability-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/endpoints-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/pr-impact-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/verify-edit-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/schemas/verify-v1.schema.json +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/security_chain.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/security_config.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/selection_contract.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/self_audit.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/selftest.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/serializer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/servlet_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/source_text.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_security_audit.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/sql_taint.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/text_input.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/timeline.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/timeline_cache.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/verify_edit.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/verify_repo.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/version_check.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/vex.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/waivers.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/watch_loop.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/wired_surface.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/src/sourcecode/workspace.py +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/functions/README.md +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-5.9.31 → sourcecode-5.9.32}/supabase/sql/licensing_schema.sql +0 -0
|
@@ -10,6 +10,10 @@ on:
|
|
|
10
10
|
# observe Git Bash rewriting a route argument such as `/owners` to an absolute
|
|
11
11
|
# Windows path. Keep both the normal Python regression suite and the actual
|
|
12
12
|
# Git Bash invocation on a Windows runner.
|
|
13
|
+
env:
|
|
14
|
+
SOURCECODE_TELEMETRY: "0"
|
|
15
|
+
SOURCECODE_TELEMETRY_CONTEXT: "ci"
|
|
16
|
+
|
|
13
17
|
jobs:
|
|
14
18
|
windows-cli:
|
|
15
19
|
runs-on: windows-latest
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.9.32] — 2026-09-15
|
|
4
|
+
|
|
5
|
+
*Patch release adding safe, explicit PyPI update notifications and installation.*
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `ask version` and `ask update --check` report when a newer ASK release exists.
|
|
10
|
+
- `ask update` asks for confirmation; `ask update --yes` is the explicit
|
|
11
|
+
non-interactive form.
|
|
12
|
+
- MCP agents can use `check_for_updates()` and `update_ask(confirm=true)`.
|
|
13
|
+
- Updates use the active Python interpreter, serialize concurrent installs,
|
|
14
|
+
verify the installed distribution, and attempt rollback after a failed pip run.
|
|
15
|
+
- Update checks are cached for 24 hours and can be disabled with
|
|
16
|
+
`SOURCECODE_UPDATE_DISABLED=1`.
|
|
17
|
+
|
|
3
18
|
## [5.9.31] — 2026-09-12
|
|
4
19
|
|
|
5
20
|
*Patch release correcting MCP/CLI telemetry outcomes and the telemetry schema.*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.9.
|
|
3
|
+
Version: 5.9.32
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/HarounDominique/sourcecode
|
|
6
6
|
Project-URL: Repository, https://github.com/HarounDominique/sourcecode
|
|
@@ -59,7 +59,7 @@ Description-Content-Type: text/markdown
|
|
|
59
59
|
> question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
|
|
60
60
|
> before inspecting a repository whose telemetry policy you need to control.
|
|
61
61
|
|
|
62
|
-

|
|
63
63
|

|
|
64
64
|
|
|
65
65
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -290,7 +290,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
290
290
|
# pip / pipx
|
|
291
291
|
pipx install sourcecode # or: pip install sourcecode
|
|
292
292
|
|
|
293
|
-
ask version # ask 5.9.
|
|
293
|
+
ask version # ask 5.9.32 — and, on a build that has aged,
|
|
294
294
|
# how many releases have probably shipped since
|
|
295
295
|
```
|
|
296
296
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
> question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
|
|
11
11
|
> before inspecting a repository whose telemetry policy you need to control.
|
|
12
12
|
|
|
13
|
-

|
|
14
14
|

|
|
15
15
|
|
|
16
16
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -241,7 +241,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
241
241
|
# pip / pipx
|
|
242
242
|
pipx install sourcecode # or: pip install sourcecode
|
|
243
243
|
|
|
244
|
-
ask version # ask 5.9.
|
|
244
|
+
ask version # ask 5.9.32 — and, on a build that has aged,
|
|
245
245
|
# how many releases have probably shipped since
|
|
246
246
|
```
|
|
247
247
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Spec: ASK update notifications and opt-in self-update
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
Informar de forma no intrusiva cuando existe una versión más reciente de ASK y
|
|
6
|
+
permitir actualizarla únicamente tras una confirmación explícita. El mismo estado
|
|
7
|
+
debe estar disponible para un agente MCP sin identificar al usuario ni bloquear un
|
|
8
|
+
análisis normal.
|
|
9
|
+
|
|
10
|
+
## Commands and interfaces
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
ask update --check # consulta y muestra la versión disponible; no instala
|
|
14
|
+
ask update # consulta; pide confirmación en TTY; instala solo con sí
|
|
15
|
+
ask update --yes # instala tras la intención explícita del operador
|
|
16
|
+
MCP check_for_updates() # respuesta estructurada, sin instalar
|
|
17
|
+
MCP update_ask(confirm) # confirm=false informa; confirm=true instala
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
La comprobación automática, si se habilita más adelante, tendrá como máximo una
|
|
21
|
+
consulta cacheada al día y nunca se ejecutará durante un comando de análisis.
|
|
22
|
+
|
|
23
|
+
## Project structure
|
|
24
|
+
|
|
25
|
+
- `src/sourcecode/update.py` — consulta, comparación, caché y actualización.
|
|
26
|
+
- `src/sourcecode/cli.py` — comandos y confirmación TTY.
|
|
27
|
+
- `src/sourcecode/mcp/server.py` — herramientas MCP estructuradas.
|
|
28
|
+
- `tests/test_update.py` — red, caché, comparación, confirmación e instalación.
|
|
29
|
+
- `docs/update.md` — comportamiento, permisos y recuperación.
|
|
30
|
+
|
|
31
|
+
## Safety and behavior
|
|
32
|
+
|
|
33
|
+
- Consultar únicamente el endpoint oficial HTTPS de PyPI:
|
|
34
|
+
`https://pypi.org/pypi/sourcecode/json`, y aceptar respuestas JSON con versión
|
|
35
|
+
semántica válida.
|
|
36
|
+
- No ejecutar código descargado directamente: delegar en
|
|
37
|
+
`sys.executable -m pip install --upgrade sourcecode`.
|
|
38
|
+
- Mostrar versión actual, versión objetivo, intérprete y comando antes de instalar.
|
|
39
|
+
- No actualizar si el entorno es CI, pytest, desarrollo editable o si
|
|
40
|
+
`SOURCECODE_TELEMETRY_CONTEXT` no es `production`.
|
|
41
|
+
- No usar `sudo`, no modificar archivos del proyecto y no enviar credenciales.
|
|
42
|
+
- Timeout corto, errores silenciosos en la comprobación y errores explícitos en una
|
|
43
|
+
actualización solicitada.
|
|
44
|
+
- Una sola actualización por entorno a la vez, validación de la distribución
|
|
45
|
+
instalada y recuperación al intentar restaurar la versión anterior si pip falla.
|
|
46
|
+
- `--yes` solo evita la pregunta; no convierte una comprobación en actualización.
|
|
47
|
+
- Tras instalar, verificar que la versión cargada coincide con la objetivo y sugerir
|
|
48
|
+
reiniciar procesos MCP persistentes.
|
|
49
|
+
|
|
50
|
+
## Testing strategy
|
|
51
|
+
|
|
52
|
+
- Respuestas inválidas, timeout y versiones iguales/no válidas.
|
|
53
|
+
- Caché diaria y ausencia de red en CI/tests.
|
|
54
|
+
- Confirmación no interactiva sin `--yes` no instala.
|
|
55
|
+
- `--yes` ejecuta exactamente el intérprete actual y el paquete `sourcecode`.
|
|
56
|
+
- MCP nunca instala con `confirm=false` y devuelve resultado estructurado.
|
|
57
|
+
- Nunca se muestran ni transmiten rutas, tokens o datos del usuario.
|
|
58
|
+
|
|
59
|
+
## Boundaries
|
|
60
|
+
|
|
61
|
+
- Always: pedir consentimiento antes de instalar, usar el intérprete actual y
|
|
62
|
+
verificar el resultado.
|
|
63
|
+
- Ask first: activar comprobación automática al inicio de comandos de análisis;
|
|
64
|
+
cambiar el paquete o índice consultado.
|
|
65
|
+
- Never: autoactualizar sin consentimiento, usar `sudo`, ejecutar scripts remotos o
|
|
66
|
+
actualizar un proceso MCP en caliente.
|
|
67
|
+
- `SOURCECODE_UPDATE_DISABLED=1` desactiva tanto las comprobaciones como las
|
|
68
|
+
instalaciones solicitadas (útil para políticas corporativas).
|
|
69
|
+
|
|
70
|
+
## Success criteria
|
|
71
|
+
|
|
72
|
+
1. Un usuario puede conocer la última versión con `ask update --check`.
|
|
73
|
+
2. `ask update` ofrece actualizar y solo instala tras “sí”.
|
|
74
|
+
3. Un agente puede consultar el estado mediante MCP y solicitar la actualización
|
|
75
|
+
con `confirm=true`.
|
|
76
|
+
4. CI/tests/desarrollo no generan consultas ni instalaciones.
|
|
77
|
+
5. Los tests cubren todos los casos de seguridad anteriores.
|
|
78
|
+
|
|
79
|
+
## Open questions
|
|
80
|
+
|
|
81
|
+
- ¿Debe la notificación automática aparecer al inicio de todos los comandos o solo
|
|
82
|
+
en `ask version`/`ask update`? Esta especificación propone no interrumpir análisis
|
|
83
|
+
hasta obtener una decisión explícita.
|
|
84
|
+
- PyPI oficial es el único índice soportado inicialmente. Un índice alternativo
|
|
85
|
+
requerirá una especificación y decisión separadas.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Auditoría de telemetría ASK — diagnóstico previo (2026-09-15)
|
|
2
|
+
|
|
3
|
+
Diagnóstico escrito antes de modificar productores, receptor o tests. Revisión local;
|
|
4
|
+
no se ha accedido a la base de producción ni a los logs de Actions. Los números
|
|
5
|
+
históricos son evidencia aportada por el solicitante, no mediciones verificadas aquí.
|
|
6
|
+
|
|
7
|
+
## Mapa
|
|
8
|
+
|
|
9
|
+
CLI `cli.py:_get_command_with_preprocessing/_cmd_main` → `telemetry.record`
|
|
10
|
+
→ `TelemetryEvent` → `filters.sanitize` → `transport.send` (hilo daemon por evento,
|
|
11
|
+
sin cola persistente/reintentos) → HTTPS Supabase `functions/telemetry/index.ts`
|
|
12
|
+
→ INSERT `public.telemetry_events` → `sql/telemetry_events.sql` (retención 90 días).
|
|
13
|
+
|
|
14
|
+
MCP `server.py:FastMCP.Tool.run` → herramienta → `runner.run_command/CliRunner`
|
|
15
|
+
→ wrapper CLI anterior; además `_record_tool_invocation` emite `mcp_tool_invoked`.
|
|
16
|
+
Licensing `license.py:_emit_telemetry` → activation / gate_blocked → mismo recorder.
|
|
17
|
+
`cli.py:telemetry_enable` emite telemetry_enabled. No productor actual de
|
|
18
|
+
command_executed, execution_failed ni telemetry_disabled. El receptor convierte
|
|
19
|
+
nombres desconocidos a command_executed.
|
|
20
|
+
|
|
21
|
+
## Hallazgos
|
|
22
|
+
|
|
23
|
+
| Finding / estado | Evidence | Root cause | Impact on analytics | Severity | Proposed fix |
|
|
24
|
+
|---|---|---|---|---|---|
|
|
25
|
+
| CONFIRMED: tests/CI pueden enviar a producción | config.is_enabled devuelve True en CI; test_telemetry_on_by_default_in_ci lo exige; conftest no aísla red; workflows Windows ejecutan pytest/CLI sin exclusión | default-on sin detección ni defensa en transporte | tests cuentan como instalaciones/ejecuciones | P0 | contexto runtime, bloqueo de red sintética, env global suite/workflows |
|
|
26
|
+
| HIGH-CONFIDENCE: ráfagas Windows compatibles con batería | windows-battery ejecuta pytest en runner efímero, varios procesos xdist; endpoint por defecto real | HOME del runner nuevo + UUID por configuración | adquisición inflada | P0 | excluir CI antes de crear ID; no atribuir filas concretas sin logs |
|
|
27
|
+
| CONFIRMED: carrera creando ID | config.get_install_id lee JSON, escribe sin lock, devuelve UUID propio aunque otro proceso haya sobrescrito | read-modify-write no atómico; _save trunca config | múltiples IDs / corrupción | P0 | identidad independiente publicada atómicamente; migrar UUID legado |
|
|
28
|
+
| CONFIRMED: NULL intencional por fallo de persistencia | get_install_id devuelve cadena vacía; sanitize omite install; receptor uuid devuelve null | degradación deliberada a evento sin identidad | días con eventos y cero instalaciones | P0 | no enviar si identidad estable no disponible; validar v2 en receptor |
|
|
29
|
+
| NOT-REPRODUCED: actualizar versión regenera ID | ruta fija ~/.config/sourcecode/config.json, no usa versión/venv | no hay ruta de actualización que regenere | no atribuir rotación a pip sin pruebas | P0 | test de actualización; documentar HOME/volúmenes/config compartidos |
|
|
30
|
+
| CONFIRMED histórico: éxito marcado false | git show 129fd04^:cli.py captura BaseException incluyendo SystemExit(0); investigación 2026-09-11 reproduce MCP | Click termina con SystemExit incluso con éxito | tasa de éxito histórica inválida | P0 | conservar fix 129fd04; versionar contrato; no reparar filas por suposición |
|
|
31
|
+
| CONFIRMED: failed=0 pese a errores | _cmd_main siempre emite execution_completed; ningún productor execution_failed | evento terminal único sin resultado tipado | errores/negativos/excepciones mezclados | P0 | outcome explícito, inicio correlacionado, failed para error real detectado |
|
|
32
|
+
| CONFIRMED: MCP doble dimensión sin correlación | Tool.run emite y CliRunner emite; session global de 8 hex por proceso | sumar eventos duplica acciones; sesión no es llamada ni usuario | engagement inflado | P1 | UUID ejecución, parent, interface mcp; separar herramientas y comandos |
|
|
33
|
+
| CONFIRMED: sesión por proceso importado | telemetry._SESSION inicializado al importar | 32 bits y herencia por fork | colisiones y sesiones indistinguibles | P1 | 128 bits, renovar por PID; documentar proceso MCP persistente |
|
|
34
|
+
| CONFIRMED: licensing ya separado por evento | activate_license emite activation InvalidLicense; gates emiten gate_blocked | agregación success/error_kind sin event mezcla dominios | atribuir incapacidad/churn sin evidencia | P1 | outcome de dominio y excluir licensing de errores de ejecución |
|
|
35
|
+
| CONFIRMED: flags usa allowlist | filters._SAFE_FLAGS y receptor FLAGS descartan valores | protección existente adecuada; comando buscado entre todos los tokens puede tomar un valor como comando | privacidad preservada para flags, dimensión comando incorrecta | P1 | mantener allowlist, usar contexto Click para comando; capacidades semánticas |
|
|
36
|
+
| CONFIRMED: falta versión de schema | v es versión producto; schema sin campo de contrato | cambios de significado no distinguibles | mezcla de generaciones | P1 | schema_version 2, filas anteriores legacy/unknown |
|
|
37
|
+
| CONFIRMED: pérdidas no medibles | transporte daemon sin flush/retry; rate limit 120/min por IP | salida rápida, red, NAT y límites descartan eventos | conteos observados son incompletos | P1 | flush acotado, documentar límite y no inferir crash de inicio huérfano |
|
|
38
|
+
| SUSPECTED: receptor remoto antiguo | investigación previa documenta coerción de mcp_tool_invoked y falta de tool en esquema antiguo | despliegue posiblemente desincronizado | MCP perdido o inserts fallidos | P1 | migración antes de receptor, no afirmar estado remoto |
|
|
39
|
+
|
|
40
|
+
## Identidad y límites de atribución
|
|
41
|
+
|
|
42
|
+
La identidad actual pertenece a la configuración del HOME, no al paquete instalado.
|
|
43
|
+
CLI y MCP usan el mismo módulo en el mismo proceso/HOME. pip/pipx/venv no intervienen;
|
|
44
|
+
HOME temporal, borrado de configuración o contenedor sin volumen sí cambian identidad.
|
|
45
|
+
Copiar un HOME/imagen con ID fusiona instalaciones. No hay prueba de qué UUID histórico
|
|
46
|
+
creó qué job. Tests que parchean _CONFIG_FILE generan UUID en tmp_path; otros CLI tests
|
|
47
|
+
usan directamente el HOME del runner. No se han visto fixtures que envíen UUID fijados.
|
|
48
|
+
|
|
49
|
+
No deducir humano/bot del uso MCP ni del volumen. Contexto production significa
|
|
50
|
+
«sin señales sintéticas detectadas», nunca prueba de persona externa.
|
|
@@ -63,7 +63,12 @@ When telemetry is enabled, these fields are sent per command invocation:
|
|
|
63
63
|
| `success` | `true` | Whether the command succeeded |
|
|
64
64
|
| `error_kind` | `FileNotFoundError` | Exception class name only, no message |
|
|
65
65
|
| `tool` | `get_compact_context` | MCP tool name only, on `mcp_tool_invoked` events (see below) |
|
|
66
|
-
| `session` | `
|
|
66
|
+
| `session` | `7f…` | 32-char random hex, process-scoped and never persisted |
|
|
67
|
+
| `schema_version` | `2` | Telemetry contract version, distinct from ASK `v` |
|
|
68
|
+
| `telemetry_context` | `production` | Runtime origin; `test`, `ci`, and `development` are suppressed |
|
|
69
|
+
| `interface` | `cli` / `mcp` | Invocation surface, never a person identifier |
|
|
70
|
+
| `outcome` | `succeeded` | `started`, `succeeded`, `negative`, `expected_error`, `internal_error`, or `cancelled` |
|
|
71
|
+
| `execution_id` | UUID | Per invocation correlation token; `parent_execution_id` links nested MCP CLI calls |
|
|
67
72
|
|
|
68
73
|
### Interpreting execution outcomes
|
|
69
74
|
|
|
@@ -105,7 +110,7 @@ File counts are converted to anonymous ranges before sending:
|
|
|
105
110
|
|
|
106
111
|
### Session identifier
|
|
107
112
|
|
|
108
|
-
The `session` field is
|
|
113
|
+
The `session` field is a 32-character random hex string generated fresh for each process (and refreshed after a fork). It is:
|
|
109
114
|
- **Never persisted** to disk
|
|
110
115
|
- **Never reused** across invocations
|
|
111
116
|
- Only useful for correlating multiple events within a single run (e.g., start + completion)
|
|
@@ -193,12 +198,22 @@ The first time you run `ask` interactively (not in CI, not piped), you are shown
|
|
|
193
198
|
|
|
194
199
|
---
|
|
195
200
|
|
|
196
|
-
## CI environments
|
|
201
|
+
## CI, tests, and development environments
|
|
197
202
|
|
|
198
|
-
|
|
203
|
+
Production telemetry is suppressed whenever a standard CI marker (`CI`, `GITHUB_ACTIONS`, and similar), pytest, or an explicit `SOURCECODE_TELEMETRY_CONTEXT` of `test`, `ci`, or `development` is present. This happens before an install ID is created and before the transport opens a connection. A deliberate production deployment must run outside these markers; `SOURCECODE_TELEMETRY=1` cannot override the origin guard. The first-run notice is also skipped:
|
|
199
204
|
|
|
200
205
|
`CI`, `CONTINUOUS_INTEGRATION`, `GITHUB_ACTIONS`, `CIRCLECI`, `TRAVIS`, `JENKINS_URL`, `BUILDKITE`, `GITLAB_CI`, `TF_BUILD`, `TEAMCITY_VERSION`, `DRONE`, `SEMAPHORE`
|
|
201
206
|
|
|
207
|
+
## Contract and analytics limits
|
|
208
|
+
|
|
209
|
+
Schema 2 is the population used by the product queries. Legacy rows remain
|
|
210
|
+
queryable with unknown origin/outcome and are never retroactively relabelled.
|
|
211
|
+
`install_id` identifies a persisted ASK configuration, not a person: cloned homes
|
|
212
|
+
merge installations and deleted or ephemeral homes create new ones. Counts are
|
|
213
|
+
observed installations and lower bounds on activity, not a count of real users.
|
|
214
|
+
MCP intensity is agentic usage evidence, never evidence that a human or bot initiated
|
|
215
|
+
it. See [telemetry_product_metrics.sql](../supabase/sql/telemetry_product_metrics.sql).
|
|
216
|
+
|
|
202
217
|
---
|
|
203
218
|
|
|
204
219
|
## Open source auditability
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# ASK updates
|
|
2
|
+
|
|
3
|
+
`ask update --check` consults the official PyPI JSON endpoint and reports the
|
|
4
|
+
installed and latest versions. Results are cached for 24 hours. A normal
|
|
5
|
+
`ask update` asks for confirmation in an interactive terminal; `ask update --yes`
|
|
6
|
+
is the explicit non-interactive form.
|
|
7
|
+
|
|
8
|
+
The installer runs `sys.executable -m pip install --upgrade sourcecode`, so the
|
|
9
|
+
same Python environment that launched ASK is updated. It never uses `sudo`, runs
|
|
10
|
+
remote scripts, or changes the repository. Persistent MCP servers must be
|
|
11
|
+
restarted after an update.
|
|
12
|
+
|
|
13
|
+
Checks and installations are suppressed in CI, pytest, editable development
|
|
14
|
+
checkouts, and other non-production telemetry contexts. Network failures leave
|
|
15
|
+
ASK unchanged. The MCP equivalents are `check_for_updates()` and
|
|
16
|
+
`update_ask(confirm=true)`; `confirm=false` only checks status.
|
|
17
|
+
|
|
18
|
+
Only one update may run for an environment at a time. After pip returns, ASK
|
|
19
|
+
verifies the installed distribution metadata. If installation fails, it attempts
|
|
20
|
+
to restore the previously installed version and reports whether restoration
|
|
21
|
+
succeeded. Set `SOURCECODE_UPDATE_DISABLED=1` to disable update checks and
|
|
22
|
+
installation for managed environments.
|
|
@@ -1790,6 +1790,8 @@ def _emit_error_json(error: str, message: str, **context: object) -> None:
|
|
|
1790
1790
|
All CLI validation and runtime errors must go through this helper so that
|
|
1791
1791
|
agents and tools can parse stderr reliably regardless of error type.
|
|
1792
1792
|
"""
|
|
1793
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
1794
|
+
mark("internal_error" if error in {"INTERNAL_ERROR", "EXECUTION_FAILED"} else "expected_error")
|
|
1793
1795
|
import json as _json
|
|
1794
1796
|
payload = build_error_envelope(error, message, **context)
|
|
1795
1797
|
sys.stderr.write(_json.dumps(payload, ensure_ascii=_json_ensure_ascii()) + "\n")
|
|
@@ -4863,17 +4865,14 @@ def _get_command_with_preprocessing(typer_instance: Any) -> Any:
|
|
|
4863
4865
|
"enrich", "audit-report", "audit-verify", "migrate-recipe", "data-exposure", "posture", "migrate-check",
|
|
4864
4866
|
"impact-chain", "pr-impact", "explain", "onboard", "review-pr", "fix-bug", "modernize",
|
|
4865
4867
|
"rename-class", "chunk-file", "activate", "selftest", "explain-endpoint", "regress", "version",
|
|
4866
|
-
"schema", "config", "archetype", "cold-start", "telemetry", "mcp", "cache", "baseline",
|
|
4868
|
+
"schema", "config", "update", "archetype", "cold-start", "telemetry", "mcp", "cache", "baseline",
|
|
4867
4869
|
"auth", "retrieve", "prepare-context", "pack",
|
|
4868
4870
|
})
|
|
4869
4871
|
|
|
4870
4872
|
def _telemetry_command(args_for_command: Optional[list[str]]) -> str:
|
|
4871
4873
|
"""Extract only a registered CLI command, never a path or option value."""
|
|
4872
4874
|
tokens = list(args_for_command) if args_for_command is not None else sys.argv[1:]
|
|
4873
|
-
|
|
4874
|
-
if token in _TELEMETRY_COMMANDS:
|
|
4875
|
-
return token
|
|
4876
|
-
return "analyze"
|
|
4875
|
+
return tokens[0] if tokens and tokens[0] in _TELEMETRY_COMMANDS else "analyze"
|
|
4877
4876
|
|
|
4878
4877
|
def _telemetry_flags(args_for_command: Optional[list[str]]) -> list[str]:
|
|
4879
4878
|
tokens = list(args_for_command) if args_for_command is not None else sys.argv[1:]
|
|
@@ -4896,35 +4895,59 @@ def _get_command_with_preprocessing(typer_instance: Any) -> Any:
|
|
|
4896
4895
|
# args=None → Click reads sys.argv; _preprocess_argv() in main_entry handled it.
|
|
4897
4896
|
started = time.monotonic()
|
|
4898
4897
|
command = _telemetry_command(args)
|
|
4899
|
-
|
|
4898
|
+
from sourcecode import telemetry as _tel
|
|
4899
|
+
from sourcecode.telemetry.lifecycle import Execution, current, exit_outcome
|
|
4900
|
+
parent = current.get()
|
|
4901
|
+
scope = Execution(interface=parent.interface if parent else "cli",
|
|
4902
|
+
parent=parent.id if parent else "", command=command)
|
|
4903
|
+
token = current.set(scope)
|
|
4904
|
+
fields = dict(cmd=("mcp" if command == "mcp" else "telemetry" if command == "telemetry" else "analyze"),
|
|
4905
|
+
command=command, flags=_telemetry_flags(args))
|
|
4906
|
+
_tel.record("execution_started", **fields, outcome="started")
|
|
4900
4907
|
error_kind = None
|
|
4901
4908
|
try:
|
|
4902
|
-
|
|
4909
|
+
result = _orig_cmd_main(args=args, **kwargs)
|
|
4910
|
+
# Click standalone_mode=False returns the exit code for explicit Exit.
|
|
4911
|
+
if isinstance(result, int) and not isinstance(result, bool):
|
|
4912
|
+
scope.outcome = exit_outcome(result, scope)
|
|
4913
|
+
return result
|
|
4903
4914
|
except SystemExit as exc:
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4915
|
+
scope.outcome = exit_outcome(exc.code, scope)
|
|
4916
|
+
import click
|
|
4917
|
+
cause = exc.__context__
|
|
4918
|
+
seen = set()
|
|
4919
|
+
while cause is not None and id(cause) not in seen:
|
|
4920
|
+
seen.add(id(cause))
|
|
4921
|
+
if isinstance(cause, KeyboardInterrupt):
|
|
4922
|
+
scope.outcome = "cancelled"
|
|
4923
|
+
error_kind = "KeyboardInterrupt"
|
|
4924
|
+
break
|
|
4925
|
+
if isinstance(cause, click.ClickException) and scope.outcome == "unknown_error":
|
|
4926
|
+
scope.outcome = "expected_error"
|
|
4927
|
+
cause = cause.__context__
|
|
4928
|
+
if scope.outcome in {"expected_error", "unknown_error"}:
|
|
4929
|
+
error_kind = "SystemExit"
|
|
4909
4930
|
raise
|
|
4910
4931
|
except BaseException as exc:
|
|
4911
|
-
|
|
4932
|
+
import click
|
|
4933
|
+
scope.outcome = ("cancelled" if isinstance(exc, (KeyboardInterrupt, click.Abort))
|
|
4934
|
+
else "expected_error" if isinstance(exc, click.ClickException)
|
|
4935
|
+
else "internal_error")
|
|
4912
4936
|
error_kind = type(exc).__name__
|
|
4913
4937
|
raise
|
|
4914
4938
|
finally:
|
|
4915
4939
|
try:
|
|
4916
|
-
|
|
4940
|
+
ok = scope.outcome in {"succeeded", "negative"}
|
|
4917
4941
|
_tel.record(
|
|
4918
|
-
"execution_completed",
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
flags=_telemetry_flags(args),
|
|
4922
|
-
duration_s=time.monotonic() - started,
|
|
4923
|
-
success=success,
|
|
4924
|
-
error_kind=error_kind,
|
|
4942
|
+
"execution_completed" if ok else "execution_failed",
|
|
4943
|
+
**fields, duration_s=time.monotonic() - started,
|
|
4944
|
+
success=ok, outcome=scope.outcome, error_kind=error_kind,
|
|
4925
4945
|
)
|
|
4926
4946
|
except Exception:
|
|
4927
4947
|
pass
|
|
4948
|
+
if parent and scope.outcome != "succeeded":
|
|
4949
|
+
parent.outcome = scope.outcome
|
|
4950
|
+
current.reset(token)
|
|
4928
4951
|
if _previous_invocation is None:
|
|
4929
4952
|
_tls.__dict__.pop("invocation_args", None)
|
|
4930
4953
|
else:
|
|
@@ -13631,6 +13654,9 @@ def verify_edit_cmd(
|
|
|
13631
13654
|
output = _serialize_dict(v.to_dict(), format)
|
|
13632
13655
|
_emit_command_output(output, output_path, copy,
|
|
13633
13656
|
success_msg=f"verify-edit verdict written to {output_path}")
|
|
13657
|
+
if v.exit_code != 0:
|
|
13658
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
13659
|
+
mark("negative" if v.exit_code == 1 else "expected_error")
|
|
13634
13660
|
if ci and v.exit_code != 0:
|
|
13635
13661
|
raise typer.Exit(code=v.exit_code)
|
|
13636
13662
|
|
|
@@ -13974,6 +14000,9 @@ def verify_cmd(
|
|
|
13974
14000
|
copy,
|
|
13975
14001
|
success_msg=f"verify report written to {output_path}",
|
|
13976
14002
|
)
|
|
14003
|
+
if report.exit_code != 0:
|
|
14004
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
14005
|
+
mark("negative" if report.exit_code == 1 else "expected_error")
|
|
13977
14006
|
if ci and report.exit_code != 0:
|
|
13978
14007
|
raise typer.Exit(code=report.exit_code)
|
|
13979
14008
|
|
|
@@ -14795,6 +14824,8 @@ def audit_verify_cmd(
|
|
|
14795
14824
|
success_msg="audit signature verified" if verdict["valid"] else "audit signature mismatch",
|
|
14796
14825
|
)
|
|
14797
14826
|
if not verdict["valid"]:
|
|
14827
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
14828
|
+
mark("negative")
|
|
14798
14829
|
raise typer.Exit(code=1)
|
|
14799
14830
|
|
|
14800
14831
|
|
|
@@ -15186,6 +15217,8 @@ def migrate_apply_cmd(
|
|
|
15186
15217
|
),
|
|
15187
15218
|
)
|
|
15188
15219
|
if ci and data["gate"]["exit_code"]:
|
|
15220
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
15221
|
+
mark("negative")
|
|
15189
15222
|
raise typer.Exit(code=1)
|
|
15190
15223
|
return
|
|
15191
15224
|
|
|
@@ -16233,6 +16266,9 @@ def migrate_check_cmd(
|
|
|
16233
16266
|
)
|
|
16234
16267
|
if ci:
|
|
16235
16268
|
_gate = (payload or report.to_dict()).get("metadata", {}).get("gate", {})
|
|
16269
|
+
if _gate.get("exit_code", 0):
|
|
16270
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
16271
|
+
mark("negative")
|
|
16236
16272
|
raise typer.Exit(code=int(_gate.get("exit_code", 0)))
|
|
16237
16273
|
|
|
16238
16274
|
|
|
@@ -16749,6 +16785,8 @@ def pr_impact_cmd(
|
|
|
16749
16785
|
# UNKNOWN means the analysis could not see everything it was asked about.
|
|
16750
16786
|
# A gate must not read that as "below threshold".
|
|
16751
16787
|
if report.risk_level == "UNKNOWN" or _actual >= _threshold:
|
|
16788
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
16789
|
+
mark("negative")
|
|
16752
16790
|
raise typer.Exit(code=1)
|
|
16753
16791
|
|
|
16754
16792
|
|
|
@@ -17862,8 +17900,12 @@ def self_audit_cmd(
|
|
|
17862
17900
|
)
|
|
17863
17901
|
|
|
17864
17902
|
if fail_on == "fail" and data["verdict"] == "fail":
|
|
17903
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
17904
|
+
mark("negative")
|
|
17865
17905
|
raise typer.Exit(code=1)
|
|
17866
17906
|
if fail_on == "unknown" and data["verdict"] in ("fail", "unknown"):
|
|
17907
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
17908
|
+
mark("negative")
|
|
17867
17909
|
raise typer.Exit(code=1)
|
|
17868
17910
|
|
|
17869
17911
|
|
|
@@ -18003,8 +18045,12 @@ def drift_cmd(
|
|
|
18003
18045
|
+ data["counts"]["added_without_a_matching_rule"]
|
|
18004
18046
|
)
|
|
18005
18047
|
if fail_on_exposure and _exposed:
|
|
18048
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18049
|
+
mark("negative")
|
|
18006
18050
|
raise typer.Exit(code=1)
|
|
18007
18051
|
if fail_on_drift and data["drifted"]:
|
|
18052
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18053
|
+
mark("negative")
|
|
18008
18054
|
raise typer.Exit(code=1)
|
|
18009
18055
|
|
|
18010
18056
|
|
|
@@ -18274,10 +18320,16 @@ def pr_risk_cmd(
|
|
|
18274
18320
|
# that nobody could answer the question, and a gate that passes on that
|
|
18275
18321
|
# is a gate that passes on a blind spot.
|
|
18276
18322
|
if result.verdict == VERDICT_UNKNOWN:
|
|
18323
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18324
|
+
mark("negative")
|
|
18277
18325
|
raise typer.Exit(code=1)
|
|
18278
18326
|
if fail_on == "block" and result.verdict == VERDICT_BLOCK:
|
|
18327
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18328
|
+
mark("negative")
|
|
18279
18329
|
raise typer.Exit(code=1)
|
|
18280
18330
|
if fail_on == "review" and result.verdict in (VERDICT_BLOCK, VERDICT_REVIEW):
|
|
18331
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18332
|
+
mark("negative")
|
|
18281
18333
|
raise typer.Exit(code=1)
|
|
18282
18334
|
|
|
18283
18335
|
|
|
@@ -18691,8 +18743,12 @@ def cve_cmd(
|
|
|
18691
18743
|
)
|
|
18692
18744
|
|
|
18693
18745
|
if fail_on == "reachable" and _reachable > 0:
|
|
18746
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18747
|
+
mark("negative")
|
|
18694
18748
|
raise typer.Exit(code=1)
|
|
18695
18749
|
if fail_on == "any" and _affected_total > 0:
|
|
18750
|
+
from sourcecode.telemetry.lifecycle import mark
|
|
18751
|
+
mark("negative")
|
|
18696
18752
|
raise typer.Exit(code=1)
|
|
18697
18753
|
|
|
18698
18754
|
|
|
@@ -19265,6 +19321,8 @@ def version_cmd(
|
|
|
19265
19321
|
"""
|
|
19266
19322
|
from sourcecode.release_info import advisory_line, build_status
|
|
19267
19323
|
from sourcecode.product_info import COPYRIGHT, PRODUCT, TAGLINE, build_provenance
|
|
19324
|
+
from sourcecode.update import check as check_for_update
|
|
19325
|
+
_update_status = check_for_update()
|
|
19268
19326
|
|
|
19269
19327
|
if getattr(sys.stdout, "isatty", lambda: False)():
|
|
19270
19328
|
_lines = [f"{PRODUCT} {__version__}", TAGLINE, COPYRIGHT]
|
|
@@ -19274,11 +19332,13 @@ def version_cmd(
|
|
|
19274
19332
|
_advisory = advisory_line()
|
|
19275
19333
|
if _advisory:
|
|
19276
19334
|
_lines.append(_advisory)
|
|
19335
|
+
if _update_status.get("status") == "available":
|
|
19336
|
+
_lines.append(f"A newer ASK version is available: {_update_status['latest_version']} (run `ask update`)")
|
|
19277
19337
|
_emit_text_output("\n".join(_lines), copy, output_path)
|
|
19278
19338
|
else:
|
|
19279
19339
|
import json as _json_ver
|
|
19280
19340
|
from sourcecode.envelope import ENVELOPE_VERSION, available_schemas
|
|
19281
|
-
|
|
19341
|
+
_version_payload = {
|
|
19282
19342
|
"cli_version": __version__,
|
|
19283
19343
|
"mcp_schema_version": __version__,
|
|
19284
19344
|
"compatibility_schema_version": "1.0",
|
|
@@ -19295,7 +19355,10 @@ def version_cmd(
|
|
|
19295
19355
|
# about what this release publishes.
|
|
19296
19356
|
"registries": published_registries(),
|
|
19297
19357
|
"provenance": build_provenance(),
|
|
19298
|
-
}
|
|
19358
|
+
}
|
|
19359
|
+
if _update_status.get("status") == "available":
|
|
19360
|
+
_version_payload["update_available"] = _update_status["latest_version"]
|
|
19361
|
+
_emit_text_output(_json_ver.dumps(_version_payload, ensure_ascii=_json_ensure_ascii()), copy, output_path)
|
|
19299
19362
|
|
|
19300
19363
|
|
|
19301
19364
|
def published_registries() -> "list[str]":
|
|
@@ -19485,6 +19548,41 @@ def schema_cmd(
|
|
|
19485
19548
|
)
|
|
19486
19549
|
|
|
19487
19550
|
|
|
19551
|
+
# ── update / config ───────────────────────────────────────────────────────────
|
|
19552
|
+
|
|
19553
|
+
@app.command("update")
|
|
19554
|
+
def update_cmd(
|
|
19555
|
+
check_only: bool = typer.Option(False, "--check", help="Check PyPI without installing."),
|
|
19556
|
+
yes: bool = typer.Option(False, "--yes", help="Confirm installation without prompting."),
|
|
19557
|
+
force: bool = typer.Option(False, "--force", help="Ignore the 24-hour check cache."),
|
|
19558
|
+
) -> None:
|
|
19559
|
+
"""Check for a newer ASK release and optionally install it."""
|
|
19560
|
+
from sourcecode.update import check, install
|
|
19561
|
+
result = check(force=force)
|
|
19562
|
+
if result.get("status") == "available" and not check_only:
|
|
19563
|
+
target = result["latest_version"]
|
|
19564
|
+
if not yes:
|
|
19565
|
+
if not sys.stdin.isatty() or not sys.stderr.isatty():
|
|
19566
|
+
_emit_error_json(INVALID_INPUT_CODE, "Updating requires confirmation.", hint="Run `ask update --yes` explicitly in automation.")
|
|
19567
|
+
raise typer.Exit(code=2)
|
|
19568
|
+
if not typer.confirm(f"ASK {target} is available. Install it now?", err=True):
|
|
19569
|
+
result = {**result, "status": "declined"}
|
|
19570
|
+
else:
|
|
19571
|
+
result = install(target)
|
|
19572
|
+
else:
|
|
19573
|
+
result = install(target)
|
|
19574
|
+
if result.get("status") == "available":
|
|
19575
|
+
message = f"ASK {result['latest_version']} is available (current: {result['current_version']}). Run `ask update` to install."
|
|
19576
|
+
elif result.get("status") == "current":
|
|
19577
|
+
message = f"ASK is up to date ({result['current_version']})."
|
|
19578
|
+
elif result.get("status") == "declined":
|
|
19579
|
+
message = "Update declined; ASK was not changed."
|
|
19580
|
+
elif result.get("status") == "updated":
|
|
19581
|
+
message = f"ASK updated to {result.get('target_version')}. Restart persistent MCP processes."
|
|
19582
|
+
else:
|
|
19583
|
+
message = f"ASK update status: {result.get('status')} ({result.get('reason', 'no additional details')})."
|
|
19584
|
+
_emit_command_output(json.dumps({**result, "message": message}, ensure_ascii=False), None, False, fmt="json")
|
|
19585
|
+
|
|
19488
19586
|
# ── config ────────────────────────────────────────────────────────────────────
|
|
19489
19587
|
|
|
19490
19588
|
@app.command("config")
|