diff --git a/.github/workflows/publish-tasks.yml b/.github/workflows/publish-tasks.yml new file mode 100644 index 0000000..0ed808f --- /dev/null +++ b/.github/workflows/publish-tasks.yml @@ -0,0 +1,23 @@ +name: Publish tasks as issues + +on: + push: + branches: [main] + paths: + - planning/plan.yaml + - planning/tasks/** + - scripts/publish-tasks.py + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: python3 scripts/publish-tasks.py + env: + GH_TOKEN: ${{ github.token }} diff --git a/docs/adr/20260824-one-bco-campaign-executor-in-the-mvp.md b/docs/adr/20260824-one-bco-campaign-executor-in-the-mvp.md new file mode 100644 index 0000000..de52c7d --- /dev/null +++ b/docs/adr/20260824-one-bco-campaign-executor-in-the-mvp.md @@ -0,0 +1,40 @@ +# ADR-20260824: One BCO campaign executor in the MVP + +## Status + +Proposed — 2026-08-24 + +## Context + +The component design used campaign leases to let multiple BCO campaign executors share work safely. +The MVP does not need horizontal executor scaling, automatic executor failover, or overlapping +executor rollouts. Implementing leases and safe lease handoff would add work before those deployment +modes provide user value. + +## Decision + +The whole MVP deployment runs exactly one BCO campaign executor. Campaign leases are not part of the +MVP. Deployment updates stop the current executor before starting its replacement, and deployment +configuration must not allow more than one campaign executor. + +This restriction applies to the stateful campaign executor. It does not decide how other stateless +services may be deployed. + +## Consequences + +- The MVP avoids lease storage, renewal, expiry, fencing, and handoff behavior. +- The executor still saves the next intended action and completed downstream results so a later + process can resume after the previous process has stopped. +- The MVP has no automatic campaign-executor failover and no overlapping executor rollout. +- A deployment must stop the old executor before starting a replacement. Recovery begins only after + the previous executor has exited. +- Stable action keys and downstream idempotency are still needed for a crash after a downstream call + succeeds but before BCO saves its reply. A single executor does not remove that crash window. + +## Required design updates + +Update `docs/architecture.md`, `docs/bisection-data-model.md`, `docs/components.md`, +`docs/components/bco.md`, and `docs/components/state-store.md`. Remove lease behavior from +`docs/diagrams/ownership-boundary.mmd`, `docs/diagrams/recovery.mmd`, and +`docs/diagrams/single-candidate-step.mmd`. The updated documents must describe one campaign executor +and persisted next action without campaign leases. diff --git a/planning/README.md b/planning/README.md new file mode 100644 index 0000000..c55d71b --- /dev/null +++ b/planning/README.md @@ -0,0 +1,66 @@ +# Implementation plan + +[`plan.yaml`](plan.yaml) defines execution order and dependencies. Each file under [`tasks/`](tasks/) +defines one proposed GitHub issue. + +## Plan anatomy + +```yaml +version: PLAN-VERSION-NUMBER +phases: + - phase: PHASE-NUMBER, recommended execution order + goal: "OUTCOME DESCRIPTION" + tasks: + group-name/task-name.md: + stream: "STREAM-NAME, i.e working group or component" + title: "TASK TITLE" + priority: TASK-PRIORITY, high|medium|low + delivers: "concrete value produced by the task" + depends_on: + - group-name/some-other-task.md +``` + +A phase groups the tasks that deliver one milestone. A task may start when every `depends_on` task +is complete. + +## Task anatomy + +```markdown +--- +stream: "BCO" +topic: "Short classification" +priority: high +publish: false +--- + +# Task title + +## Description + +What must change and why. + +## Contribution + +- Delivers: Concrete capability or assurance. + +## Acceptance criteria + +- [ ] Short, verifiable result. + +## Sources + +- [Owning design or contract](../../../docs/example.md) +``` + +Keep acceptance criteria short and testable. Use `Sources` for the documents that define the required +behavior. + +## Publishing tasks to GitHub + +- `publish: false`: the task is a draft. A GitHub publishing action must skip it. Its path may change. +- `publish: true`: the task is approved. A GitHub publishing action may create or update its issue. +- After an issue is created, keep the task path unchanged so the action can match the file to that issue. +- The task title and body may still change after publication. + +This branch does not contain the GitHub publishing action. Changing the flag alone does not create or update +an issue. diff --git a/planning/plan.yaml b/planning/plan.yaml new file mode 100644 index 0000000..4c7b1e3 --- /dev/null +++ b/planning/plan.yaml @@ -0,0 +1,635 @@ +version: 1 + +phases: + - phase: 1 + goal: "Select the runtime and dev toolchain all later tasks use" + tasks: + design-and-docs/select-imp-env.md: + stream: "Design&Docs" + title: "Select the dev env" + priority: high + delivers: "Approved runtime and dev toolchain in `docs/imp-env.md`" + depends_on: [] + + - phase: 2 + goal: "Define the unit-test CR fields and the two service APIs so service implementation can start" + tasks: + design-and-docs/define-unit-test-cr-fields.md: + stream: "Design&Docs" + title: "Define unit-test CR fields" + priority: high + delivers: "Defined unit-test scope in CRs" + depends_on: [] + design-and-docs/define-bco-oapi-spec.md: + stream: "Design&Docs" + title: "Define BCO OpenAPI spec" + priority: high + delivers: "OpenAPI operations for CR submission and campaign reads" + depends_on: + - design-and-docs/define-unit-test-cr-fields.md + design-and-docs/define-bto-oapi-spec.md: + stream: "Design&Docs" + title: "Define BTO OpenAPI spec" + priority: high + delivers: "OpenAPI operation for build-test plan submission" + depends_on: [] + + - phase: 3 + goal: "Build BCO and BTO REST services that accept one CR and one build-test plan" + tasks: + bco/create-the-bco-service-and-store.md: + stream: "BCO" + title: "Create the BCO service, store, and REST API" + priority: high + delivers: "BCO REST service bootstrap, isolated store initialization, and startup/isolation tests" + depends_on: + - design-and-docs/define-bco-oapi-spec.md + - design-and-docs/select-imp-env.md + bto/create-bto-svc-and-store.md: + stream: "BTO" + title: "Create the BTO service, store, and REST API" + priority: high + delivers: "BTO REST service bootstrap, isolated store initialization, and startup/isolation tests" + depends_on: + - design-and-docs/define-bto-oapi-spec.md + - design-and-docs/select-imp-env.md + bco/accept-cr.md: + stream: "BCO" + title: "Accept a CR" + priority: high + delivers: "A stored campaign and `campaign_ref` from the BCO REST API" + depends_on: + - bco/create-the-bco-service-and-store.md + bto/accept-build-test-plan.md: + stream: "BTO" + title: "Accept build-test plan" + priority: high + delivers: "A stored BTO plan and plan-submission acknowledgement" + depends_on: + - bto/create-bto-svc-and-store.md + + - phase: 4 + goal: "Connect BCO to BTO" + tasks: + bco/connect-to-bto-plan-submission.md: + stream: "BCO" + title: "Connect BCO to BTO plan submission" + priority: high + delivers: "BCO plan submission through the BTO REST API" + depends_on: + - bco/accept-cr.md + - bto/accept-build-test-plan.md + + - phase: 5 + goal: "Define the execution inputs and build the boundaries and stored state the first round needs" + tasks: + design-and-docs/select-first-execution-backend.md: + stream: "Design&Docs" + title: "Select the first execution backend" + priority: high + delivers: "A selected first build-test backend with its composition, settings, and outcome map" + depends_on: [] + design-and-docs/define-bto-result-lookup-behavior.md: + stream: "Design&Docs" + title: "Define BTO result lookup behavior" + priority: high + delivers: "Defined BTO lookup responses and BCO handling" + depends_on: + - design-and-docs/define-bto-oapi-spec.md + design-and-docs/select-unit-test-result-input.md: + stream: "Design&Docs" + title: "Select unit-test result input" + priority: high + delivers: "Defined BTO output used for unit-test observation" + depends_on: + - design-and-docs/define-unit-test-cr-fields.md + design-and-docs/define-evidence-storage.md: + stream: "Design&Docs" + title: "Define evidence storage" + priority: high + delivers: "Defined owner and shape of stored decision evidence" + depends_on: [] + design-and-docs/document-source-repository-scope.md: + stream: "Design&Docs" + title: "Document the source-repository scope" + priority: medium + delivers: "A recorded public-repository scope statement in the architecture" + depends_on: [] + bco/persist-campaign-lifecycle-and-membership.md: + stream: "BCO" + title: "Persist campaign lifecycle and membership" + priority: high + delivers: "Stored CRs, campaign lifecycle state, and trigger membership" + depends_on: + - bco/accept-cr.md + bto/load-execution-compositions.md: + stream: "BTO" + title: "Load execution compositions" + priority: high + delivers: "Configured planner, builder, and tester roles for a composition" + depends_on: + - bto/create-bto-svc-and-store.md + commit-selector/build-the-commit-selector-boundary.md: + stream: "Commit selector" + title: "Build the Commit selector boundary" + priority: high + delivers: "A stateless Commit selector service boundary for BCO" + depends_on: + - design-and-docs/select-imp-env.md + results-analyzer/implement-the-results-analyzer-contract.md: + stream: "Results Analyzer" + title: "Implement the Results Analyzer contract" + priority: high + delivers: "A backend-independent boundary from plan output to decision evidence" + depends_on: + - design-and-docs/select-imp-env.md + execution-adapters/translate-plan-requests-for-the-execution-backend.md: + stream: "Execution adapters" + title: "Translate plan requests for the execution backend" + priority: high + delivers: "Backend-specific execution requests without leaking backend syntax" + depends_on: + - bto/accept-build-test-plan.md + - design-and-docs/select-first-execution-backend.md + + - phase: 6 + goal: "Produce and store the inputs a bisection step needs" + tasks: + bco/persist-steps-and-attempts.md: + stream: "BCO" + title: "Persist steps and attempts" + priority: high + delivers: "Stored candidate, attempt, and plan records" + depends_on: + - bco/persist-campaign-lifecycle-and-membership.md + commit-selector/prepare-source-history-for-selection.md: + stream: "Commit selector" + title: "Prepare source history for selection" + priority: high + delivers: "A valid, current source-history view for commit selection" + depends_on: + - commit-selector/build-the-commit-selector-boundary.md + - design-and-docs/document-source-repository-scope.md + results-analyzer/produce-unit-test-observations.md: + stream: "Results Analyzer" + title: "Produce unit-test observations" + priority: high + delivers: "Structured evidence of the expected unit-test failure signature" + depends_on: + - design-and-docs/select-unit-test-result-input.md + - results-analyzer/implement-the-results-analyzer-contract.md + results-analyzer/produce-unit-test-qualification-observations.md: + stream: "Results Analyzer" + title: "Produce unit-test qualification observations" + priority: high + delivers: "Structured evidence of whether the requested test ran successfully" + depends_on: + - design-and-docs/select-unit-test-result-input.md + - results-analyzer/implement-the-results-analyzer-contract.md + decision-engine/implement-unit-test-qualification-check.md: + stream: "Decision engine" + title: "Implement the unit-test qualification check" + priority: high + delivers: "Exclusion of unit-test results that cannot prove the expected regression" + depends_on: + - results-analyzer/produce-unit-test-qualification-observations.md + execution-adapters/run-combined-build-and-test-execution.md: + stream: "Execution adapters" + title: "Run combined build and test execution" + priority: high + delivers: "Combined backend build and test execution" + depends_on: + - execution-adapters/translate-plan-requests-for-the-execution-backend.md + + - phase: 7 + goal: "Complete each component's contract result and run the components together in the test harness" + tasks: + bco/persist-evidence-decisions-and-final-records.md: + stream: "BCO" + title: "Persist evidence, decisions, and final records" + priority: high + delivers: "Stored evidence, decisions, and terminal campaign records" + depends_on: + - bco/persist-steps-and-attempts.md + - design-and-docs/define-evidence-storage.md + commit-selector/implement-standard-bisect.md: + stream: "Commit selector" + title: "Implement standard bisect" + priority: high + delivers: "Deterministic candidate selection and terminal bisect results" + depends_on: + - commit-selector/prepare-source-history-for-selection.md + decision-engine/implement-unit-test-decisions.md: + stream: "Decision engine" + title: "Implement unit-test decisions" + priority: high + delivers: "Binary unit-test decisions for BCO and Commit selector" + depends_on: + - decision-engine/implement-unit-test-qualification-check.md + - results-analyzer/produce-unit-test-observations.md + execution-adapters/map-backend-results-to-plan-outcomes.md: + stream: "Execution adapters" + title: "Map backend results to plan outcomes" + priority: high + delivers: "Backend-independent BTO plan outcomes for BCO" + depends_on: + - execution-adapters/run-combined-build-and-test-execution.md + e2e/create-the-component-test-harness.md: + stream: "E2E" + title: "Create the component test harness" + priority: high + delivers: "Repeatable component integration tests with controlled dependencies" + depends_on: + - bco/create-the-bco-service-and-store.md + - bto/create-bto-svc-and-store.md + - commit-selector/build-the-commit-selector-boundary.md + - decision-engine/implement-unit-test-qualification-check.md + + - phase: 8 + goal: "Store a selected candidate and run one BTO plan to a final result" + tasks: + bco/store-and-apply-commit-selector-results.md: + stream: "BCO" + title: "Store and apply Commit selector results" + priority: high + delivers: "Stored selection and application of the next candidate" + depends_on: + - bco/persist-steps-and-attempts.md + - commit-selector/implement-standard-bisect.md + bto/execute-one-plan.md: + stream: "BTO" + title: "Execute one plan" + priority: high + delivers: "Backend execution and a final result for one BTO plan" + depends_on: + - bto/accept-build-test-plan.md + - bto/load-execution-compositions.md + - execution-adapters/map-backend-results-to-plan-outcomes.md + + - phase: 9 + goal: "Complete one BCO-BTO plan round trip" + tasks: + bco/submit-one-bto-plan-per-attempt.md: + stream: "BCO" + title: "Submit one BTO plan per attempt" + priority: high + delivers: "One BTO plan submission for each step attempt" + depends_on: + - bco/connect-to-bto-plan-submission.md + - bco/store-and-apply-commit-selector-results.md + - design-and-docs/select-unit-test-result-input.md + bto/keep-completed-plan-results-available-to-bco.md: + stream: "BTO" + title: "Keep completed plan results available to BCO" + priority: high + delivers: "Final BTO plan results available for lookup by BCO" + depends_on: + - bto/execute-one-plan.md + - design-and-docs/define-bto-result-lookup-behavior.md + bco/read-bto-plan-results.md: + stream: "BCO" + title: "Read BTO plan results" + priority: high + delivers: "One BTO plan result stored against its step attempt" + depends_on: + - bco/submit-one-bto-plan-per-attempt.md + - bto/keep-completed-plan-results-available-to-bco.md + + - phase: 10 + goal: "Turn one plan result into one step decision" + tasks: + bco/route-bto-plan-outcomes.md: + stream: "BCO" + title: "Route BTO plan outcomes" + priority: high + delivers: "Correct routing of BTO outcomes into analysis or campaign failure" + depends_on: + - bco/persist-evidence-decisions-and-final-records.md + - bco/read-bto-plan-results.md + - results-analyzer/implement-the-results-analyzer-contract.md + bco/run-one-analysis-attempt.md: + stream: "BCO" + title: "Run one analysis attempt" + priority: high + delivers: "One evidence record bound to the step attempt that produced it" + depends_on: + - bco/route-bto-plan-outcomes.md + - results-analyzer/produce-unit-test-observations.md + - results-analyzer/produce-unit-test-qualification-observations.md + bco/request-one-step-decision.md: + stream: "BCO" + title: "Request one step decision" + priority: high + delivers: "One durable decision per analyzed campaign step" + depends_on: + - bco/run-one-analysis-attempt.md + - decision-engine/implement-unit-test-decisions.md + + - phase: 11 + goal: "Drive the campaign to its conclusion and expose its status" + tasks: + bco/apply-decisions-and-finish-the-campaign.md: + stream: "BCO" + title: "Apply decisions and finish the campaign" + priority: high + delivers: "Campaign boundary updates and terminal conclusions from stored decisions" + depends_on: + - bco/request-one-step-decision.md + bco/drive-the-campaign-loop.md: + stream: "BCO" + title: "Drive the campaign loop" + priority: high + delivers: "One BCO loop that takes an accepted campaign to its recorded conclusion" + depends_on: + - bco/apply-decisions-and-finish-the-campaign.md + bco/expose-campaign-status.md: + stream: "BCO" + title: "Expose campaign status" + priority: high + delivers: "Campaign progress and final BCO output through the REST API" + depends_on: + - bco/persist-evidence-decisions-and-final-records.md + + - phase: 12 + goal: "Prove the minimal unit-test path E2E" + tasks: + e2e/test-the-unit-test-campaign-path.md: + stream: "E2E" + title: "Test the unit-test campaign path" + priority: high + delivers: "Proof that the unit-test path reaches a culprit E2E" + depends_on: + - bco/drive-the-campaign-loop.md + - bco/expose-campaign-status.md + - e2e/create-the-component-test-harness.md + + - phase: 13 + goal: "Check the listed MVP contract rules for the unit-test path" + tasks: + contracts/check-minimal-cr-admission-rules.md: + stream: "Contracts" + title: "Check minimal CR admission rules" + priority: high + delivers: "Listed unit-test CR errors are returned without creating campaign or step data" + depends_on: + - bco/accept-cr.md + contracts/check-mvp-bco-output-rules.md: + stream: "Contracts" + title: "Check MVP BCO output rules" + priority: high + delivers: "BCO responses for the listed campaign states contain the listed fields, timestamps, step order, and outcomes" + depends_on: + - bco/apply-decisions-and-finish-the-campaign.md + - bco/expose-campaign-status.md + contracts/check-mvp-bto-request-and-result-rules.md: + stream: "Contracts" + title: "Check MVP BTO request and result rules" + priority: high + delivers: "BTO rejects the listed request errors and returns the listed acknowledgement, lookup, and result fields" + depends_on: + - bto/keep-completed-plan-results-available-to-bco.md + contracts/check-plain-bisect-request-and-result-rules.md: + stream: "Contracts" + title: "Check plain-bisect request and result rules" + priority: high + delivers: "Plain bisect rejects the listed bad inputs and returns the listed request IDs and result fields" + depends_on: + - commit-selector/implement-standard-bisect.md + contracts/check-decision-request-and-result-rules.md: + stream: "Contracts" + title: "Check Decision request and result rules" + priority: high + delivers: "Decision requests and results use the listed fields, and BCO saves no mismatched result" + depends_on: + - bco/request-one-step-decision.md + contracts/check-unit-test-analyzer-request-and-evidence-rules.md: + stream: "Contracts" + title: "Check unit-test analyzer request and evidence rules" + priority: high + delivers: "Results Analyzer rejects the listed non-content inputs and returns the listed unit-test evidence fields and IDs" + depends_on: + - results-analyzer/produce-unit-test-observations.md + - results-analyzer/produce-unit-test-qualification-observations.md + contracts/check-unit-test-decision-rules.md: + stream: "Contracts" + title: "Check unit-test decision rules" + priority: high + delivers: "Listed unit-test evidence cases return their defined `good`, `bad`, `skip`, or `weak` decision" + depends_on: + - decision-engine/implement-unit-test-decisions.md + - results-analyzer/produce-unit-test-observations.md + - results-analyzer/produce-unit-test-qualification-observations.md + + - phase: 14 + goal: "Define the admission, limit, cancellation, auth, and recovery rules, and run one MVP campaign executor" + tasks: + bco/run-one-bco-campaign-executor-for-the-mvp.md: + stream: "BCO" + title: "Run one BCO campaign executor for the MVP" + priority: high + delivers: "One BCO campaign executor with no overlap in the MVP deployment" + depends_on: + - bco/create-the-bco-service-and-store.md + design-and-docs/define-campaign-stop-limits.md: + stream: "Design&Docs" + title: "Define campaign stop limits" + priority: medium + delivers: "Defined campaign limits and their completion outcomes" + depends_on: + - e2e/test-the-unit-test-campaign-path.md + design-and-docs/define-campaign-cancellation-behavior.md: + stream: "Design&Docs" + title: "Define campaign cancellation behavior" + priority: high + delivers: "Defined cancellation behavior using the existing campaign and step statuses" + depends_on: + - design-and-docs/define-bco-oapi-spec.md + - e2e/test-the-unit-test-campaign-path.md + design-and-docs/define-how-admission-validates-toolchains.md: + stream: "Design&Docs" + title: "Define configurable toolchain admission" + priority: medium + delivers: "Defined configurable toolchain rules for campaign admission" + depends_on: + - bco/accept-cr.md + design-and-docs/define-service-authentication.md: + stream: "Design&Docs" + title: "Define service auth" + priority: high + delivers: "Defined auth for Trigger, BCO, BTO, and execution calls" + depends_on: + - design-and-docs/define-bco-oapi-spec.md + - design-and-docs/define-bto-oapi-spec.md + design-and-docs/define-who-can-access-a-campaign.md: + stream: "Design&Docs" + title: "Define who can access a campaign" + priority: high + delivers: "Defined authorization for campaign reads and cancellation" + depends_on: + - bco/expose-campaign-status.md + design-and-docs/define-campaign-execution-profile-source.md: + stream: "Design&Docs" + title: "Define the campaign execution profile source" + priority: high + delivers: "Defined provider, format, and loading path for the campaign execution profile" + depends_on: [] + design-and-docs/define-backend-work-recovery.md: + stream: "Design&Docs" + title: "Define how BTO avoids duplicate backend work" + priority: medium + delivers: "Defined backend action identity and replay rule for BTO restart recovery" + depends_on: + - execution-adapters/run-combined-build-and-test-execution.md + + - phase: 15 + goal: "Enforce the admission, limit, cancellation, and auth rules, and make BTO plan retries safe" + tasks: + bco/load-the-campaign-execution-profile.md: + stream: "BCO" + title: "Load the campaign execution profile" + priority: high + delivers: "A loaded, validated campaign execution profile available to BCO admission" + depends_on: + - bco/create-the-bco-service-and-store.md + - design-and-docs/define-campaign-execution-profile-source.md + bco/validate-crs-before-creating-state.md: + stream: "BCO" + title: "Check requests against deployment capabilities" + priority: high + delivers: "Requests outside deployment capabilities are rejected before campaign creation" + depends_on: + - bco/build-trigger-registry-and-authentication.md + - bco/load-the-campaign-execution-profile.md + - contracts/check-minimal-cr-admission-rules.md + bco/validate-toolchains-at-admission.md: + stream: "BCO" + title: "Use configured toolchain admission rules" + priority: medium + delivers: "Requests using a toolchain the deployment cannot provide are rejected before campaign creation" + depends_on: + - design-and-docs/define-how-admission-validates-toolchains.md + bco/enforce-campaign-stop-limits.md: + stream: "BCO" + title: "Enforce campaign stop limits" + priority: medium + delivers: "Consistent campaign completion when a configured limit is reached" + depends_on: + - bco/drive-the-campaign-loop.md + - bco/run-one-bco-campaign-executor-for-the-mvp.md + - design-and-docs/define-campaign-stop-limits.md + bco/implement-campaign-cancellation.md: + stream: "BCO" + title: "Implement campaign cancellation" + priority: high + delivers: "Safe cancellation that stops work and freezes campaign decisions" + depends_on: + - bco/drive-the-campaign-loop.md + - bco/run-one-bco-campaign-executor-for-the-mvp.md + - design-and-docs/define-campaign-cancellation-behavior.md + bco/build-trigger-registry-and-authentication.md: + stream: "BCO" + title: "Authenticate Triggers and load execution settings" + priority: high + delivers: "Authenticated Trigger identity and execution settings available to campaign admission" + depends_on: + - bco/create-the-bco-service-and-store.md + - design-and-docs/define-service-authentication.md + bto/add-idempotent-plan-admission.md: + stream: "BTO" + title: "Reuse a BTO plan when BCO retries" + priority: high + delivers: "One BTO plan and one execution when BCO retries the same submission" + depends_on: + - bto/execute-one-plan.md + bto/authenticate-bto-service-calls.md: + stream: "BTO" + title: "Authenticate BCO calls to BTO" + priority: high + delivers: "Only authenticated BCO callers can submit or read BTO plans" + depends_on: + - bco/read-bto-plan-results.md + - design-and-docs/define-service-authentication.md + execution-adapters/authenticate-backend-calls.md: + stream: "Execution adapters" + title: "Authenticate BTO calls to the execution backend" + priority: medium + delivers: "Backend calls carry the credentials the service-auth design defines" + depends_on: + - design-and-docs/define-service-authentication.md + - execution-adapters/run-combined-build-and-test-execution.md + + - phase: 16 + goal: "Authorize campaign access, prevent duplicates, and recover after restart" + tasks: + bco/authorize-campaign-access.md: + stream: "BCO" + title: "Authorize campaign access" + priority: medium + delivers: "Authorized campaign reads and cancellation" + depends_on: + - bco/build-trigger-registry-and-authentication.md + - bco/implement-campaign-cancellation.md + - design-and-docs/define-who-can-access-a-campaign.md + bco/create-or-join-equivalent-campaigns-atomically.md: + stream: "BCO" + title: "Create or join equivalent campaigns atomically" + priority: high + delivers: "One shared campaign for concurrent equivalent requests" + depends_on: + - bco/persist-campaign-lifecycle-and-membership.md + - bco/validate-crs-before-creating-state.md + - bco/validate-toolchains-at-admission.md + bco/recover-plan-results-after-restart.md: + stream: "BCO" + title: "Recover plan submissions and results after restart" + priority: medium + delivers: "Restart-safe recovery of BTO plan submissions and results by BCO" + depends_on: + - bco/drive-the-campaign-loop.md + - bto/add-idempotent-plan-admission.md + bto/recover-plan-execution-after-restart.md: + stream: "BTO" + title: "Recover plan execution after restart" + priority: medium + delivers: "Restart-safe BTO plan execution" + depends_on: + - bto/add-idempotent-plan-admission.md + - bto/execute-one-plan.md + - design-and-docs/define-backend-work-recovery.md + + - phase: 17 + goal: "Test cancellation and BCO recovery" + tasks: + bco/test-bco-crash-recovery.md: + stream: "BCO" + title: "Test BCO crash recovery" + priority: high + delivers: "Evidence that BCO recovery does not duplicate campaign work" + depends_on: + - bco/run-one-bco-campaign-executor-for-the-mvp.md + - bco/create-or-join-equivalent-campaigns-atomically.md + - bco/recover-plan-results-after-restart.md + - bto/recover-plan-execution-after-restart.md + e2e/test-campaign-cancellation.md: + stream: "E2E" + title: "Test campaign cancellation" + priority: high + delivers: "Evidence that cancellation remains safe through BTO work and restart" + depends_on: + - bco/authorize-campaign-access.md + - bco/implement-campaign-cancellation.md + - bco/recover-plan-results-after-restart.md + - bto/recover-plan-execution-after-restart.md + - e2e/create-the-component-test-harness.md + + - phase: 18 + goal: "Test recovery during BTO execution" + tasks: + e2e/test-crash-recovery-during-bto-work.md: + stream: "E2E" + title: "Test crash recovery during BTO work" + priority: high + delivers: "Evidence that BCO and BTO recovery duplicates no attempt or backend work" + depends_on: + - bco/test-bco-crash-recovery.md + - e2e/test-the-unit-test-campaign-path.md diff --git a/planning/tasks/bco/accept-cr.md b/planning/tasks/bco/accept-cr.md new file mode 100644 index 0000000..3e6e050 --- /dev/null +++ b/planning/tasks/bco/accept-cr.md @@ -0,0 +1,31 @@ +--- +stream: "BCO" +topic: "Minimal admission" +priority: high +publish: false +--- + +# Accept a CR + +## Description + +Before admission is hardened, BCO must accept and store one valid unit-test CR. The hardcoded +toolchain list is a temporary test-only value shared with the E2E fixture. + +Further task(s) will replaces it with the configured catalog. + +## Contribution + +- Delivers: A stored campaign and `campaign_ref` from the BCO REST API + +## Acceptance criteria + +- [ ] Accept a valid unit-test CR through the BCO REST API. +- [ ] Accept toolchains from an implementation-owned hardcoded list. +- [ ] Store the request and return its `campaign_ref`. +- [ ] Reject a malformed request without creating campaign state. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [CR](../../../docs/contracts/campaign-request.md) diff --git a/planning/tasks/bco/apply-decisions-and-finish-the-campaign.md b/planning/tasks/bco/apply-decisions-and-finish-the-campaign.md new file mode 100644 index 0000000..15470cb --- /dev/null +++ b/planning/tasks/bco/apply-decisions-and-finish-the-campaign.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Apply decisions and finish the campaign + +## Description + +BCO must update search state from stored decisions and map terminal Commit selector results to one campaign +conclusion. + +## Contribution + +- Delivers: Campaign boundary updates and terminal conclusions from stored decisions + +## Acceptance criteria + +- [ ] A `good` decision moves the good boundary and a `bad` decision moves the bad boundary. +- [ ] A `skip` or `weak` decision moves no boundary. +- [ ] Selector convergence, blocked state, and failure produce the documented BCO output. +- [ ] A campaign with no `bad` decision records `not_confirmed` instead of a culprit. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Commit selection result](../../../docs/contracts/commit-selection-result.md) +- [BCO output](../../../docs/contracts/bco-output.md) diff --git a/planning/tasks/bco/authorize-campaign-access.md b/planning/tasks/bco/authorize-campaign-access.md new file mode 100644 index 0000000..71e2b4e --- /dev/null +++ b/planning/tasks/bco/authorize-campaign-access.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "Campaign authorization" +priority: medium +publish: false +--- + +# Authorize campaign access + +## Description + +After the unauthenticated REST workflow works, BCO must enforce the defined campaign access rules. + +## Contribution + +- Delivers: Authorized campaign reads and cancellation + +## Acceptance criteria + +- [ ] Campaign reads enforce the defined access rules. +- [ ] Cancellation enforces the defined access rules. +- [ ] A denied read or cancellation returns the same response as an unknown campaign ID. +- [ ] Rejected access writes no campaign state. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [Trigger registry and authentication](build-trigger-registry-and-authentication.md) +- [Campaign access design](../design-and-docs/define-who-can-access-a-campaign.md) diff --git a/planning/tasks/bco/build-trigger-registry-and-authentication.md b/planning/tasks/bco/build-trigger-registry-and-authentication.md new file mode 100644 index 0000000..c1b1ef5 --- /dev/null +++ b/planning/tasks/bco/build-trigger-registry-and-authentication.md @@ -0,0 +1,32 @@ +--- +stream: "BCO" +topic: "Trigger registry" +priority: high +publish: false +--- + +# Authenticate Triggers and load execution settings + +## Description + +BCO must identify the caller and load its Trigger settings before checking a campaign request. This +is authentication for campaign admission. It does not manage access to source repositories, and +credentials do not belong in the campaign request. + +## Contribution + +- Delivers: Authenticated Trigger identity and execution settings available to campaign admission + +## Acceptance criteria + +- [ ] The Trigger registry stores and loads one record containing a Trigger identity, its credential + reference, and its execution settings. +- [ ] A valid admission credential resolves to that Trigger and its settings. +- [ ] A missing, invalid, or unknown credential is rejected before campaign state is created. +- [ ] Campaign requests, responses, and logs omit credential values. + +## Sources + +- [Components: Trigger registry](../../../docs/components.md) +- [State store design](../../../docs/components/state-store.md) +- [Service-auth design](../design-and-docs/define-service-authentication.md) diff --git a/planning/tasks/bco/connect-to-bto-plan-submission.md b/planning/tasks/bco/connect-to-bto-plan-submission.md new file mode 100644 index 0000000..86a310e --- /dev/null +++ b/planning/tasks/bco/connect-to-bto-plan-submission.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "BCO-BTO integration" +priority: high +publish: false +--- + +# Connect BCO to BTO plan submission + +## Description + +BCO and BTO must exchange one build-test plan request before the remaining campaign workflow is +added. This task builds the BCO HTTP client and proves it with a valid fixture request. Building +the request from stored campaign state belongs to the later plan-submission task. + +## Contribution + +- Delivers: BCO plan submission through the BTO REST API + +## Acceptance criteria + +- [ ] BCO submits one valid build-test plan request through the BTO REST API. +- [ ] BTO stores the request and returns its `plan_id` and `request_id`. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) diff --git a/planning/tasks/bco/create-or-join-equivalent-campaigns-atomically.md b/planning/tasks/bco/create-or-join-equivalent-campaigns-atomically.md new file mode 100644 index 0000000..7637f1e --- /dev/null +++ b/planning/tasks/bco/create-or-join-equivalent-campaigns-atomically.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "Admission" +priority: high +publish: false +--- + +# Create or join equivalent campaigns atomically + +## Description + +Two Triggers may submit equivalent CRs at the same time. BCO must create one campaign instead of +starting duplicate build-test work. + +## Contribution + +- Delivers: One shared campaign for concurrent equivalent requests + +## Acceptance criteria + +- [ ] Concurrent equivalent requests create one campaign. +- [ ] Each authorized Trigger is attached once. +- [ ] Repeated requests from that Trigger add nothing. +- [ ] Unauthorized requests return no campaign ID and reveal no existing campaign. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [CR](../../../docs/contracts/campaign-request.md) +- [ADR-0007](../../../docs/adr/0007-equivalence-key-and-trigger-membership.md) diff --git a/planning/tasks/bco/create-the-bco-service-and-store.md b/planning/tasks/bco/create-the-bco-service-and-store.md new file mode 100644 index 0000000..162c1a1 --- /dev/null +++ b/planning/tasks/bco/create-the-bco-service-and-store.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "Service foundation" +priority: high +publish: false +--- + +# Create the BCO service, store, and REST API + +## Description + +BCO must run as its own service, expose its REST API, and own an isolated durable store before campaign +records and workflows are implemented. + +## Contribution + +- Delivers: BCO REST service bootstrap, isolated store initialization, and startup/isolation tests + +## Acceptance criteria + +- [ ] A fresh service starts with the defined BCO REST routes and an empty BCO store. +- [ ] The REST API can read and write the initialized BCO store. +- [ ] BCO cannot read or write the BTO store. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [BCO design](../../../docs/components/bco.md) +- [State store design](../../../docs/components/state-store.md) diff --git a/planning/tasks/bco/drive-the-campaign-loop.md b/planning/tasks/bco/drive-the-campaign-loop.md new file mode 100644 index 0000000..3b9294d --- /dev/null +++ b/planning/tasks/bco/drive-the-campaign-loop.md @@ -0,0 +1,36 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Drive the campaign loop + +## Description + +Each loop transition exists as its own task, but no task starts an accepted campaign and drives it +to a conclusion. BCO must own that loop: request a selection, create the step, submit the plan, +read the result, run analysis, request the decision, apply it, and repeat until a terminal +selector result or a failure ends the campaign. + +## Contribution + +- Delivers: One BCO loop that takes an accepted campaign to its recorded conclusion + +## Acceptance criteria + +- [ ] The loop moves an accepted campaign to running and starts its first selection round. +- [ ] Each round sends the Commit selector the current boundaries, the terminal step decisions, + and the round number assigned by BCO. +- [ ] BCO records the next intended action before each downstream call. +- [ ] A downstream failure that cannot produce a step decision fails the campaign under the + no-automatic-retry default. +- [ ] The loop repeats rounds until a terminal selector result or a campaign failure produces the + recorded conclusion. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [State store design](../../../docs/components/state-store.md) +- [Commit selection request](../../../docs/contracts/commit-selection-request.md) diff --git a/planning/tasks/bco/enforce-campaign-stop-limits.md b/planning/tasks/bco/enforce-campaign-stop-limits.md new file mode 100644 index 0000000..65da9e0 --- /dev/null +++ b/planning/tasks/bco/enforce-campaign-stop-limits.md @@ -0,0 +1,32 @@ +--- +stream: "BCO" +topic: "Resource limits" +priority: medium +publish: false +--- + +# Enforce campaign stop limits + +## Description + +When a configured campaign limit is reached, BCO must stop new work and record the result chosen by +that limit's policy. + +## Contribution + +- Delivers: Consistent campaign completion when a configured limit is reached + +## Acceptance criteria + +- [ ] Automated tests cover every limit listed by the campaign stop-limit design. +- [ ] Work below a limit continues, and the event defined as reaching the limit stops later plan + submissions. +- [ ] BCO applies a reached limit once and handles in-flight work as the design defines. +- [ ] BCO records the campaign failure or normal conclusion mapped to that limit. +- [ ] Campaign status shows the recorded terminal result. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [Campaign stop-limit design](../design-and-docs/define-campaign-stop-limits.md) diff --git a/planning/tasks/bco/expose-campaign-status.md b/planning/tasks/bco/expose-campaign-status.md new file mode 100644 index 0000000..f40ba18 --- /dev/null +++ b/planning/tasks/bco/expose-campaign-status.md @@ -0,0 +1,28 @@ +--- +stream: "BCO" +topic: "Query API" +priority: high +publish: false +--- + +# Expose campaign status + +## Description + +Triggers that create or join a campaign need its progress and result without direct access to BCO storage. + +## Contribution + +- Delivers: Campaign progress and final BCO output through the REST API + +## Acceptance criteria + +- [ ] A known campaign ID returns its BCO output. +- [ ] An unknown campaign ID returns the defined error. +- [ ] Reads write no state. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [BCO OpenAPI spec](../design-and-docs/define-bco-oapi-spec.md) diff --git a/planning/tasks/bco/implement-campaign-cancellation.md b/planning/tasks/bco/implement-campaign-cancellation.md new file mode 100644 index 0000000..d7d1298 --- /dev/null +++ b/planning/tasks/bco/implement-campaign-cancellation.md @@ -0,0 +1,35 @@ +--- +stream: "BCO" +topic: "Cancellation" +priority: high +publish: false +--- + +# Implement campaign cancellation + +## Description + +Implement the cancellation operation and state transition defined by the cancellation design task. +After cancellation is accepted, BCO must stop new work and handle pending work, in-flight work, late +results, and repeated requests exactly as that design defines. + +## Contribution + +- Delivers: Safe cancellation that stops work and freezes campaign decisions + +## Acceptance criteria + +- [ ] The BCO cancellation operation returns the response defined by the cancellation design. +- [ ] The first accepted request records the defined state transition once. +- [ ] A repeated request returns the defined reply and records no second transition. +- [ ] After acceptance, BCO starts no new selector, BTO, analyzer, decision, or verifier call. +- [ ] Pending work, in-flight work, and late results follow the rules defined by the cancellation + design; a late result is saved for audit as that design defines and changes no decision, + boundary, or campaign conclusion. +- [ ] Campaign status exposes the defined cancellation result using existing contract values. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [Cancellation design task](../design-and-docs/define-campaign-cancellation-behavior.md) diff --git a/planning/tasks/bco/load-the-campaign-execution-profile.md b/planning/tasks/bco/load-the-campaign-execution-profile.md new file mode 100644 index 0000000..9e1a0a0 --- /dev/null +++ b/planning/tasks/bco/load-the-campaign-execution-profile.md @@ -0,0 +1,33 @@ +--- +stream: "BCO" +topic: "Deployment configuration" +priority: high +publish: false +--- + +# Load the campaign execution profile + +## Description + +Admission capability checks read the campaign execution profile, but no task creates or loads a +profile instance. Implement the provider chosen by the profile design task and make the loaded +profile available to admission. + +## Contribution + +- Delivers: A loaded, validated campaign execution profile available to BCO admission + +## Acceptance criteria + +- [ ] BCO loads the profile from the provider chosen by the design task. +- [ ] A profile that fails contract validation, including an empty required capability array, is + rejected and reported as the design task defines. +- [ ] Admission can read the loaded profile's supported types, policies, compositions, evidence + paths, and decision strategies. +- [ ] The deployment ships the minimal MVP profile defined by the design task. + +## Sources + +- [Campaign execution profile](../../../docs/contracts/campaign-execution-profile.md) +- [BCO design](../../../docs/components/bco.md) +- [Profile source design](../design-and-docs/define-campaign-execution-profile-source.md) diff --git a/planning/tasks/bco/persist-campaign-lifecycle-and-membership.md b/planning/tasks/bco/persist-campaign-lifecycle-and-membership.md new file mode 100644 index 0000000..8d0353f --- /dev/null +++ b/planning/tasks/bco/persist-campaign-lifecycle-and-membership.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "State model" +priority: high +publish: false +--- + +# Persist campaign lifecycle and membership + +## Description + +Campaign execution, status reads, and campaign sharing need the CR, lifecycle state, and trigger +membership in the BCO store. + +## Contribution + +- Delivers: Stored CRs, campaign lifecycle state, and trigger membership + +## Acceptance criteria + +- [ ] BCO stores accepted, running, completed, and failed transitions. +- [ ] Invalid transitions write nothing. +- [ ] Terminal campaign state does not change. +- [ ] BCO stores each attached Trigger once per campaign; repeated attachment writes no second + record. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [Bisection data model](../../../docs/bisection-data-model.md) diff --git a/planning/tasks/bco/persist-evidence-decisions-and-final-records.md b/planning/tasks/bco/persist-evidence-decisions-and-final-records.md new file mode 100644 index 0000000..127d857 --- /dev/null +++ b/planning/tasks/bco/persist-evidence-decisions-and-final-records.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "State model" +priority: high +publish: false +--- + +# Persist evidence, decisions, and final records + +## Description + +Campaign execution and BCO output need stored evidence, step decisions, and the terminal campaign record. + +## Contribution + +- Delivers: Stored evidence, decisions, and terminal campaign records + +## Acceptance criteria + +- [ ] Reads return the stored evidence, decision references, and BCO output. +- [ ] Each step has at most one final decision. +- [ ] Exactly one terminal campaign record is stored. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [Bisection data model](../../../docs/bisection-data-model.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [Evidence storage design](../design-and-docs/define-evidence-storage.md) diff --git a/planning/tasks/bco/persist-steps-and-attempts.md b/planning/tasks/bco/persist-steps-and-attempts.md new file mode 100644 index 0000000..376d990 --- /dev/null +++ b/planning/tasks/bco/persist-steps-and-attempts.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "State model" +priority: high +publish: false +--- + +# Persist steps and attempts + +## Description + +BCO needs each selected candidate, attempt, and plan reference for campaign execution. This task +covers store behavior only. Decided transitions are proved with the later decision records, and +plan side effects with the later plan-submission task. + +## Contribution + +- Delivers: Stored candidate, attempt, and plan records + +## Acceptance criteria + +- [ ] BCO stores steps, attempt IDs and numbers, and plan IDs as nonterminal records. +- [ ] One plan ID cannot be attached to two attempts. +- [ ] Replaying a stored write changes no record. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [Bisection data model](../../../docs/bisection-data-model.md) diff --git a/planning/tasks/bco/read-bto-plan-results.md b/planning/tasks/bco/read-bto-plan-results.md new file mode 100644 index 0000000..0be4993 --- /dev/null +++ b/planning/tasks/bco/read-bto-plan-results.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "Plan result lookup" +priority: high +publish: false +--- + +# Read BTO plan results + +## Description + +BCO reads the result by plan ID after submitting a BTO plan. + +## Contribution + +- Delivers: One BTO plan result stored against its step attempt + +## Acceptance criteria + +- [ ] BCO stores the final result against its attempt exactly once. +- [ ] BCO handles a not-yet-final result as the lookup behavior defines. +- [ ] BCO handles an unknown plan ID as the lookup behavior defines. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) +- [BTO result lookup design](../design-and-docs/define-bto-result-lookup-behavior.md) diff --git a/planning/tasks/bco/recover-plan-results-after-restart.md b/planning/tasks/bco/recover-plan-results-after-restart.md new file mode 100644 index 0000000..2765d1f --- /dev/null +++ b/planning/tasks/bco/recover-plan-results-after-restart.md @@ -0,0 +1,33 @@ +--- +stream: "BCO" +topic: "Plan result recovery" +priority: medium +publish: false +--- + +# Recover plan submissions and results after restart + +## Description + +After normal result lookup works, BCO must continue an interrupted submission or lookup without +duplicating the plan. Two crash windows matter: after BTO accepts a submission but before BCO +saves the returned `plan_id`, and after the `plan_id` is saved but before the final result is +saved. + +## Contribution + +- Delivers: Restart-safe recovery of BTO plan submissions and results by BCO + +## Acceptance criteria + +- [ ] After a restart with a stored `plan_id` and no final result, BCO resumes result lookup. +- [ ] After a restart with recorded submission intent and no stored `plan_id`, BCO repeats the + submission with the stored idempotency key and saves the returned `plan_id`. +- [ ] Recovery creates no second plan or execution and no duplicate evidence or decision records. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [State store design](../../../docs/components/state-store.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) diff --git a/planning/tasks/bco/request-one-step-decision.md b/planning/tasks/bco/request-one-step-decision.md new file mode 100644 index 0000000..fac1038 --- /dev/null +++ b/planning/tasks/bco/request-one-step-decision.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Request one step decision + +## Description + +BCO must store one Decision engine result before moving search boundaries. This task implements +the ID and result checks saving needs; the remaining negative cases belong to the +contract-check tasks. + +## Contribution + +- Delivers: One durable decision per analyzed campaign step + +## Acceptance criteria + +- [ ] The request IDs, regression type, scope, expected signal, and strategy match the step. +- [ ] BCO stores one decision result against the step. +- [ ] Invalid results stop the campaign without moving boundaries. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Decision contract](../../../docs/contracts/decision-contract.md) diff --git a/planning/tasks/bco/route-bto-plan-outcomes.md b/planning/tasks/bco/route-bto-plan-outcomes.md new file mode 100644 index 0000000..7d168b8 --- /dev/null +++ b/planning/tasks/bco/route-bto-plan-outcomes.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Route BTO plan outcomes + +## Description + +BTO can return `content_result`, `infrastructure_failure`, or `invalid_request`. BCO must send only +`content_result` to Results Analyzer. This task implements the outcome-kind and correlation checks +routing needs; the remaining negative cases belong to the contract-check tasks. + +## Contribution + +- Delivers: Correct routing of BTO outcomes into analysis or campaign failure + +## Acceptance criteria + +- [ ] A `content_result` creates one Results Analyzer request. +- [ ] An `infrastructure_failure` creates no evidence or step decision. +- [ ] An `invalid_request` creates no evidence or step decision. +- [ ] Both failure outcomes fail the campaign under the current no-automatic-retry default. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) diff --git a/planning/tasks/bco/run-one-analysis-attempt.md b/planning/tasks/bco/run-one-analysis-attempt.md new file mode 100644 index 0000000..9046e37 --- /dev/null +++ b/planning/tasks/bco/run-one-analysis-attempt.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Run one analysis attempt + +## Description + +BCO must bind each Results Analyzer request and result to the correct step attempt. This task +implements the ID and evidence-shape checks analysis needs; the remaining negative cases belong to +the contract-check tasks. + +## Contribution + +- Delivers: One evidence record bound to the step attempt that produced it + +## Acceptance criteria + +- [ ] Resending the same Results Analyzer request uses the same request and attempt IDs. +- [ ] BCO stores one accepted evidence record. +- [ ] Wrong IDs or contract errors fail the campaign without a decision. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Results Analyzer request](../../../docs/contracts/results-analyzer-request.md) diff --git a/planning/tasks/bco/run-one-bco-campaign-executor-for-the-mvp.md b/planning/tasks/bco/run-one-bco-campaign-executor-for-the-mvp.md new file mode 100644 index 0000000..518ac1e --- /dev/null +++ b/planning/tasks/bco/run-one-bco-campaign-executor-for-the-mvp.md @@ -0,0 +1,43 @@ +--- +stream: "BCO" +topic: "MVP deployment" +priority: high +publish: false +--- + +# Run one BCO campaign executor for the MVP + +## Description + +The MVP does not use campaign leases. Update the design and deployment configuration so the whole +MVP deployment runs one campaign executor and never overlaps the old and replacement executors. + +## Contribution + +- Delivers: One BCO campaign executor with no overlap in the MVP deployment + +## Acceptance criteria + +- [ ] Architecture, BCO, State store, the component catalog, and the data model describe one MVP + campaign executor and no campaign leases. +- [ ] `ownership-boundary.mmd`, `recovery.mmd`, and `single-candidate-step.mmd` show persisted next + action without lease acquisition, renewal, release, expiry, or handoff. +- [ ] The MVP deployment configuration starts exactly one BCO campaign executor. +- [ ] A deployment update stops the current executor before starting its replacement. +- [ ] A CI check fails if the deployment configuration requests more than one campaign executor or + permits the old and replacement executors to overlap. +- [ ] The deployment documentation states that the MVP has no automatic campaign-executor failover + or overlapping executor rollout. +- [ ] Persisted next action remains available for restart recovery after the previous executor exits. + +## Sources + +- [Proposed MVP executor decision](../../../docs/adr/20260824-one-bco-campaign-executor-in-the-mvp.md) +- [Architecture](../../../docs/architecture.md) +- [Component catalog](../../../docs/components.md) +- [Bisection data model](../../../docs/bisection-data-model.md) +- [BCO design](../../../docs/components/bco.md) +- [State store design](../../../docs/components/state-store.md) +- [Ownership boundary source diagram](../../../docs/diagrams/ownership-boundary.mmd) +- [Recovery source diagram](../../../docs/diagrams/recovery.mmd) +- [Single-candidate step source diagram](../../../docs/diagrams/single-candidate-step.mmd) diff --git a/planning/tasks/bco/store-and-apply-commit-selector-results.md b/planning/tasks/bco/store-and-apply-commit-selector-results.md new file mode 100644 index 0000000..fc206e3 --- /dev/null +++ b/planning/tasks/bco/store-and-apply-commit-selector-results.md @@ -0,0 +1,28 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Store and apply Commit selector results + +## Description + +BCO must store each Commit selector result before starting work for a selected candidate. Mapping +terminal selector results to a campaign conclusion belongs to the campaign-finishing task. + +## Contribution + +- Delivers: Stored selection and application of the next candidate + +## Acceptance criteria + +- [ ] Every selector result is stored once against its selection round. +- [ ] A selected result creates one step. +- [ ] BCO applies each stored result once. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Commit selection result](../../../docs/contracts/commit-selection-result.md) diff --git a/planning/tasks/bco/submit-one-bto-plan-per-attempt.md b/planning/tasks/bco/submit-one-bto-plan-per-attempt.md new file mode 100644 index 0000000..d90944d --- /dev/null +++ b/planning/tasks/bco/submit-one-bto-plan-per-attempt.md @@ -0,0 +1,30 @@ +--- +stream: "BCO" +topic: "Executor" +priority: high +publish: false +--- + +# Submit one BTO plan per attempt + +## Description + +BCO submits one build-test plan request for a stored step attempt and retains the BTO acknowledgement. + +## Contribution + +- Delivers: One BTO plan submission for each step attempt + +## Acceptance criteria + +- [ ] The request carries the stored candidate, scope, and composition. +- [ ] The request asks for the unit-test result output as the input design defines. +- [ ] The idempotency key encodes the campaign, step, attempt number, and action type. +- [ ] BCO stores the returned `plan_id` and `request_id` against the attempt. +- [ ] Submission failure stores no plan reference. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) +- [Unit-test result input](../design-and-docs/select-unit-test-result-input.md) diff --git a/planning/tasks/bco/test-bco-crash-recovery.md b/planning/tasks/bco/test-bco-crash-recovery.md new file mode 100644 index 0000000..a4d35c2 --- /dev/null +++ b/planning/tasks/bco/test-bco-crash-recovery.md @@ -0,0 +1,29 @@ +--- +stream: "BCO" +topic: "Recovery" +priority: high +publish: false +--- + +# Test BCO crash recovery + +## Description + +BCO records recovery intent around downstream calls; failure-injection tests must prove that each interruption +resumes without duplicating campaign work. + +## Contribution + +- Delivers: Evidence that BCO recovery does not duplicate campaign work + +## Acceptance criteria + +- [ ] Tests interrupt before and after each downstream call and state transition. +- [ ] A crash between BTO accepting a submission and BCO saving the `plan_id` recovers without a + second plan or execution. +- [ ] Each restart reaches the same BCO output with no duplicate plans, evidence, decisions, or steps. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [State store design](../../../docs/components/state-store.md) diff --git a/planning/tasks/bco/validate-crs-before-creating-state.md b/planning/tasks/bco/validate-crs-before-creating-state.md new file mode 100644 index 0000000..b47fc0b --- /dev/null +++ b/planning/tasks/bco/validate-crs-before-creating-state.md @@ -0,0 +1,39 @@ +--- +stream: "BCO" +topic: "Admission" +priority: high +publish: false +--- + +# Check requests against deployment capabilities + +## Description + +The minimal CR admission checks cover the listed unit-test request fields. Before creating or +joining a campaign, BCO +must also resolve the composition and check the request against the campaign execution profile and +the authenticated Trigger settings. Toolchain catalog checks remain in their separate task. + +## Contribution + +- Delivers: Requests outside deployment capabilities are rejected before campaign creation + +## Acceptance criteria + +- [ ] BCO resolves the composition from the request or from the authenticated Trigger or deployment + default before checking deployment support. +- [ ] Tests reject a regression type, search policy, or resolved composition that the loaded + campaign execution profile does not support. +- [ ] For an accepted regression type, BCO selects the evidence path and decision strategy from the + loaded profile rather than from the campaign request. +- [ ] Tests reject a resolved composition that the authenticated Trigger cannot use. +- [ ] Each rejection uses the Campaign Request `Admission Rejection` response. +- [ ] Each rejection creates no campaign, membership, or step state and starts no downstream work. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [CR](../../../docs/contracts/campaign-request.md) +- [Campaign execution profile](../../../docs/contracts/campaign-execution-profile.md) +- [Trigger registry and authentication](build-trigger-registry-and-authentication.md) +- [Loaded execution profile](load-the-campaign-execution-profile.md) diff --git a/planning/tasks/bco/validate-toolchains-at-admission.md b/planning/tasks/bco/validate-toolchains-at-admission.md new file mode 100644 index 0000000..68ded9b --- /dev/null +++ b/planning/tasks/bco/validate-toolchains-at-admission.md @@ -0,0 +1,32 @@ +--- +stream: "BCO" +topic: "Toolchain catalog" +priority: medium +publish: false +--- + +# Use configured toolchain admission rules + +## Description + +Minimal admission uses a hardcoded toolchain list. Replace it with the catalog provider, identity +fields, matching rule, and admission error chosen by the toolchain design task. Do not assume that +name and version are the complete identity unless that task says so. If the design places +validation outside BCO, rewrite this task to match before implementation. + +## Contribution + +- Delivers: Requests using a toolchain the deployment cannot provide are rejected before campaign creation + +## Acceptance criteria + +- [ ] BCO loads toolchain admission rules from the provider chosen by the design task. +- [ ] A request with one configured toolchain identity passes the toolchain check. +- [ ] A missing identity field or unsupported identity returns the error chosen by the design task. +- [ ] A rejected toolchain creates no campaign state and starts no downstream work. +- [ ] The hardcoded MVP toolchain list is no longer used. + +## Sources + +- [CR](../../../docs/contracts/campaign-request.md) +- [Toolchain admission design](../design-and-docs/define-how-admission-validates-toolchains.md) diff --git a/planning/tasks/bto/accept-build-test-plan.md b/planning/tasks/bto/accept-build-test-plan.md new file mode 100644 index 0000000..8d31931 --- /dev/null +++ b/planning/tasks/bto/accept-build-test-plan.md @@ -0,0 +1,27 @@ +--- +stream: "BTO" +topic: "Minimal plan admission" +priority: high +publish: false +--- + +# Accept build-test plan + +## Description + +Before admission is hardened, BTO must accept and store one build-test plan request. + +## Contribution + +- Delivers: A stored BTO plan and plan-submission acknowledgement + +## Acceptance criteria + +- [ ] Accept a valid build-test plan request through the BTO REST API. +- [ ] Store the request and return its `plan_id` and `request_id`. +- [ ] Reject a malformed request without creating plan state. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) diff --git a/planning/tasks/bto/add-idempotent-plan-admission.md b/planning/tasks/bto/add-idempotent-plan-admission.md new file mode 100644 index 0000000..51c4a0d --- /dev/null +++ b/planning/tasks/bto/add-idempotent-plan-admission.md @@ -0,0 +1,34 @@ +--- +stream: "BTO" +topic: "Plan lifecycle" +priority: high +publish: false +--- + +# Reuse a BTO plan when BCO retries + +## Description + +BCO may retry a plan submission after a timeout or restart. When the idempotency key and execution +content are unchanged, BTO must return the plan created by the first submission and must not start +the work again. This task does not decide what happens when execution content changes under the +same key because the request contract does not define that case. + +## Contribution + +- Delivers: One BTO plan and one execution when BCO retries the same submission + +## Acceptance criteria + +- [ ] The first valid submission creates one plan and returns its `plan_id` and `request_id`. +- [ ] A retry with the same idempotency key and execution fields returns the original `plan_id` and + the `request_id` stored from the first submission. +- [ ] A different retry `request_id` is ignored as the request contract defines. +- [ ] A different retry `trace_context` does not change the plan identity or start the plan again. +- [ ] Two submissions with the same idempotency key cannot create two plan records or start the plan + twice. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) diff --git a/planning/tasks/bto/authenticate-bto-service-calls.md b/planning/tasks/bto/authenticate-bto-service-calls.md new file mode 100644 index 0000000..aa94d01 --- /dev/null +++ b/planning/tasks/bto/authenticate-bto-service-calls.md @@ -0,0 +1,33 @@ +--- +stream: "BTO" +topic: "Service auth" +priority: high +publish: false +--- + +# Authenticate BCO calls to BTO + +## Description + +Use the service-auth design for BCO plan submission and result lookup calls. BCO sends the selected +credential, and BTO checks it before returning or changing plan state. Authentication for BTO calls +to planner, builder, and tester roles is not part of this task. + +## Contribution + +- Delivers: Only authenticated BCO callers can submit or read BTO plans + +## Acceptance criteria + +- [ ] BCO sends the credential defined by the service-auth design on plan submission and result + lookup calls. +- [ ] BTO accepts that credential on both operations. +- [ ] BTO rejects a missing, invalid, or unauthorized credential on both operations. +- [ ] A rejected submission creates no plan, and a rejected lookup returns no plan details. +- [ ] Responses and logs omit credential values. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [Service-auth design](../design-and-docs/define-service-authentication.md) diff --git a/planning/tasks/bto/create-bto-svc-and-store.md b/planning/tasks/bto/create-bto-svc-and-store.md new file mode 100644 index 0000000..553f9d4 --- /dev/null +++ b/planning/tasks/bto/create-bto-svc-and-store.md @@ -0,0 +1,29 @@ +--- +stream: "BTO" +topic: "Service foundation" +priority: high +publish: false +--- + +# Create the BTO service, store, and REST API + +## Description + +BTO must run as its own service, expose its REST API, and own an isolated durable store before plan records +and execution workflows are implemented. + +## Contribution + +- Delivers: BTO REST service bootstrap, isolated store initialization, and startup/isolation tests + +## Acceptance criteria + +- [ ] A fresh service starts with the defined BTO REST routes and an empty BTO store. +- [ ] The REST API can read and write the initialized BTO store. +- [ ] BTO cannot read or write the BCO store. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [BTO design](../../../docs/components/bto.md) +- [ADR-0002](../../../docs/adr/0002-separate-bco-and-bto.md) diff --git a/planning/tasks/bto/execute-one-plan.md b/planning/tasks/bto/execute-one-plan.md new file mode 100644 index 0000000..0d70639 --- /dev/null +++ b/planning/tasks/bto/execute-one-plan.md @@ -0,0 +1,29 @@ +--- +stream: "BTO" +topic: "Execution" +priority: high +publish: false +--- + +# Execute one plan + +## Description + +BTO must execute one accepted plan through its selected composition and record the result. + +## Contribution + +- Delivers: Backend execution and a final result for one BTO plan + +## Acceptance criteria + +- [ ] BTO executes the plan through the selected composition. +- [ ] Choose and record how an accepted plan starts; normal operation starts it once. +- [ ] BTO records one final build-test plan result. +- [ ] BTO issues each backend call once on the successful execution path. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) +- [Runner outcome](../../../docs/contracts/runner-outcome.md) diff --git a/planning/tasks/bto/keep-completed-plan-results-available-to-bco.md b/planning/tasks/bto/keep-completed-plan-results-available-to-bco.md new file mode 100644 index 0000000..6594b15 --- /dev/null +++ b/planning/tasks/bto/keep-completed-plan-results-available-to-bco.md @@ -0,0 +1,28 @@ +--- +stream: "BTO" +topic: "Results" +priority: high +publish: false +--- + +# Keep completed plan results available to BCO + +## Description + +BCO needs the final result after plan execution, so BTO must expose it for lookup by plan ID. + +## Contribution + +- Delivers: Final BTO plan results available for lookup by BCO + +## Acceptance criteria + +- [ ] BTO stores one final result per plan. +- [ ] Repeated lookup returns the same result. +- [ ] A finished result cannot be replaced. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) +- [BTO result lookup design](../design-and-docs/define-bto-result-lookup-behavior.md) diff --git a/planning/tasks/bto/load-execution-compositions.md b/planning/tasks/bto/load-execution-compositions.md new file mode 100644 index 0000000..d054de7 --- /dev/null +++ b/planning/tasks/bto/load-execution-compositions.md @@ -0,0 +1,28 @@ +--- +stream: "BTO" +topic: "Execution composition" +priority: high +publish: false +--- + +# Load execution compositions + +## Description + +A composition name has no effect until BTO maps planner, builder, and tester roles to configured instances. + +## Contribution + +- Delivers: Configured planner, builder, and tester roles for a composition + +## Acceptance criteria + +- [ ] BTO loads composition configuration. +- [ ] BTO resolves known composition names and role mappings. +- [ ] BTO rejects missing, invalid, or unknown compositions before calling a backend. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) +- [ADR-0008](../../../docs/adr/0008-runtime-bto-execution-composition.md) diff --git a/planning/tasks/bto/recover-plan-execution-after-restart.md b/planning/tasks/bto/recover-plan-execution-after-restart.md new file mode 100644 index 0000000..7f533e7 --- /dev/null +++ b/planning/tasks/bto/recover-plan-execution-after-restart.md @@ -0,0 +1,32 @@ +--- +stream: "BTO" +topic: "Execution recovery" +priority: medium +publish: false +--- + +# Recover plan execution after restart + +## Description + +After the successful execution path works, BTO must resume interrupted plans without duplicating +backend work. Recovery follows the backend-work recovery design: stable action identities, saved +backend job references, and a replay rule for the window between backend acceptance and the saved +reply. + +## Contribution + +- Delivers: Restart-safe BTO plan execution + +## Acceptance criteria + +- [ ] BTO saves intent, the action identity, and the backend job reference around each planner, + builder, and tester call as the backend-work recovery design defines. +- [ ] Restart resumes the same plan. +- [ ] For a crash between backend acceptance and the saved reply, recovery reuses the accepted + work as the design defines and creates no replacement backend work. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Backend-work recovery design](../design-and-docs/define-backend-work-recovery.md) diff --git a/planning/tasks/commit-selector/build-the-commit-selector-boundary.md b/planning/tasks/commit-selector/build-the-commit-selector-boundary.md new file mode 100644 index 0000000..1d3ecf4 --- /dev/null +++ b/planning/tasks/commit-selector/build-the-commit-selector-boundary.md @@ -0,0 +1,31 @@ +--- +stream: "Commit selector" +topic: "Contract boundary" +priority: high +publish: false +--- + +# Build the Commit selector boundary + +## Description + +BCO supplies current boundaries and decision history. Commit selector must return one contract +result without reading or changing campaign state. This task implements contract checks and +dispatch with an injected deterministic fake; the real selection policy arrives with the +standard-bisect task. + +## Contribution + +- Delivers: A stateless Commit selector service boundary for BCO + +## Acceptance criteria + +- [ ] A valid request returns selected, converged, or blocked. +- [ ] Invalid input returns invalid_request with field errors. +- [ ] Replaying the same request returns the same result. + +## Sources + +- [Commit selector design](../../../docs/components/commit-selector.md) +- [Commit selection request](../../../docs/contracts/commit-selection-request.md) +- [Commit selection result](../../../docs/contracts/commit-selection-result.md) diff --git a/planning/tasks/commit-selector/implement-standard-bisect.md b/planning/tasks/commit-selector/implement-standard-bisect.md new file mode 100644 index 0000000..2499b39 --- /dev/null +++ b/planning/tasks/commit-selector/implement-standard-bisect.md @@ -0,0 +1,30 @@ +--- +stream: "Commit selector" +topic: "Selection" +priority: high +publish: false +--- + +# Implement standard bisect + +## Description + +BCO needs one deterministic candidate or terminal result from the current boundaries and recorded selector +marks. + +## Contribution + +- Delivers: Deterministic candidate selection and terminal bisect results + +## Acceptance criteria + +- [ ] Selection returns one candidate per round and converges to one commit. +- [ ] Blocked and invalid ranges return their terminal results. +- [ ] good, bad, skip, and weak marks drive selection as the contract defines. +- [ ] Merge history is supported, and replaying the same request returns the same result. + +## Sources + +- [Commit selector design](../../../docs/components/commit-selector.md) +- [Commit selection request](../../../docs/contracts/commit-selection-request.md) +- [Commit selection result](../../../docs/contracts/commit-selection-result.md) diff --git a/planning/tasks/commit-selector/prepare-source-history-for-selection.md b/planning/tasks/commit-selector/prepare-source-history-for-selection.md new file mode 100644 index 0000000..7cb8a75 --- /dev/null +++ b/planning/tasks/commit-selector/prepare-source-history-for-selection.md @@ -0,0 +1,30 @@ +--- +stream: "Commit selector" +topic: "Source history" +priority: high +publish: false +--- + +# Prepare source history for selection + +## Description + +Standard bisect needs the requested repository and commit history. Missing or stale references can select a +commit outside the requested range. + +## Contribution + +- Delivers: A valid, current source-history view for commit selection + +## Acceptance criteria + +- [ ] Refresh history before selection. +- [ ] Resolve boundaries and decision-history commits. +- [ ] Return named repository, revision, and source-read errors. +- [ ] Support concurrent refresh without corrupting the history view. + +## Sources + +- [Commit selector design](../../../docs/components/commit-selector.md) +- [Commit selection request](../../../docs/contracts/commit-selection-request.md) +- [Source-repository scope](../design-and-docs/document-source-repository-scope.md) diff --git a/planning/tasks/contracts/check-decision-request-and-result-rules.md b/planning/tasks/contracts/check-decision-request-and-result-rules.md new file mode 100644 index 0000000..3fcf877 --- /dev/null +++ b/planning/tasks/contracts/check-decision-request-and-result-rules.md @@ -0,0 +1,40 @@ +--- +stream: "Contracts" +topic: "Step decisions" +priority: high +publish: false +--- + +# Check Decision request and result rules + +## Description + +This task checks only the common request fields, result fields, and ID and evidence-reference rules +listed below. It does not check how a strategy chooses `good` or `bad`. Decision engine rejects a bad +request. BCO does not save a result when its campaign, step, attempt, or evidence references do not +match the request. + +## Contribution + +- Delivers: Decision requests and results use the listed fields, and BCO saves no mismatched result + +## Acceptance criteria + +- [ ] A `decision-request/v1` contains `request_id`, `campaign_id`, `step_id`, `attempt_id`, `commit`, + `regression_type`, `scope`, `expected_signal`, and `decision_strategy`. +- [ ] A request contains either `observation_set` or `performance_evidence`, but not both. +- [ ] Observation evidence has the same `campaign_id`, `step_id`, and `attempt_id` as the outer + request. +- [ ] A result copies `request_id`, `campaign_id`, `step_id`, and `attempt_id` from the request and + contains exactly one of `good`, `bad`, `skip`, or `weak` plus `rationale.summary`. +- [ ] A result references only supporting observation IDs or evidence IDs carried by the request. +- [ ] `good` and `bad` include `matched_expected_signal`; `skip` includes `skip_reason`; `weak` + includes `uncertainty_reason`. +- [ ] When a result is missing a required field, has a different ID, or refers to evidence that was + not in the request, BCO saves no step decision and fails the campaign under the existing + no-retry behavior. + +## Sources + +- [Decision contract](../../../docs/contracts/decision-contract.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) diff --git a/planning/tasks/contracts/check-minimal-cr-admission-rules.md b/planning/tasks/contracts/check-minimal-cr-admission-rules.md new file mode 100644 index 0000000..6254f8f --- /dev/null +++ b/planning/tasks/contracts/check-minimal-cr-admission-rules.md @@ -0,0 +1,38 @@ +--- +stream: "Contracts" +topic: "Admission and configuration" +priority: high +publish: false +--- + +# Check minimal CR admission rules + +## Description + +`Accept a CR` already tests one correct unit-test request and one malformed request. This task checks +only the missing and invalid fields listed below for the same unit-test path. Each test changes one +part of the request, sends it to BCO, checks the returned error, and checks that BCO saved no campaign +or step data. Checks that need the full deployment profile remain in the later full CR validation +task. + +## Contribution + +- Delivers: Listed unit-test CR errors are returned without creating campaign or step data + +## Acceptance criteria + +- [ ] Tests reject a `contract_version` other than `campaign-request/v1`. +- [ ] Tests remove each required top-level field in turn: `contract_version`, `regression_type`, + `source_tree`, `boundaries`, `scope`, `expected_signal`, and `search_policy`. +- [ ] Tests reject an unrecognized `regression_type` or `search_policy.type`. +- [ ] Tests remove each scope field required by the unit-test CR definition. +- [ ] Tests reject an expected signal without `type` or `signature`. +- [ ] Each bad request returns the response defined under `Admission Rejection`, with at least one + error. Every error names its field and includes a message. +- [ ] Each bad request creates no campaign or step data. + +## Sources + +- [Minimal CR admission](../bco/accept-cr.md) +- [Unit-test CR fields](../design-and-docs/define-unit-test-cr-fields.md) +- [CR](../../../docs/contracts/campaign-request.md) diff --git a/planning/tasks/contracts/check-mvp-bco-output-rules.md b/planning/tasks/contracts/check-mvp-bco-output-rules.md new file mode 100644 index 0000000..1bc250f --- /dev/null +++ b/planning/tasks/contracts/check-mvp-bco-output-rules.md @@ -0,0 +1,40 @@ +--- +stream: "Contracts" +topic: "Campaign output" +priority: high +publish: false +--- + +# Check MVP BCO output rules + +## Description + +The minimal E2E test checks one completed response with one culprit. This task checks only the +campaign states, fields, timestamps, step order, and outcomes listed below. The tests use the same +code that builds the REST API response. The optional Verifier's `verifying` state and the future +retry policy's `exhausted` state are not part of this task. + +## Contribution + +- Delivers: BCO responses for the listed campaign states contain the listed fields, timestamps, step order, and outcomes + +## Acceptance criteria + +- [ ] Tests cover campaign status `accepted`, `running`, `completed`, and `failed`, + and step status `pending`, `running`, and `decided`. +- [ ] Every response includes `contract_version: bco-output/v1`, `campaign_id`, `status`, + `regression_type`, `source_tree`, initial and latest search boundaries, `scope`, `composition`, + `expected_signal`, `search_policy`, ordered `steps`, `outcome`, and `failure`. +- [ ] Every campaign has `timestamps.accepted_at`; `started_at` is absent while status is `accepted` + and present after execution starts; `terminal_at` is present only for `completed` or `failed`. +- [ ] Every step includes `step_id`, `round`, `commit`, and `status`, and the response orders steps by + `round` and then `step_id`. +- [ ] Completed responses contain an `outcome` and set `failure` to null. Failed responses set + `outcome` to null and contain a `failure`. Accepted and running responses set both to null. +- [ ] Tests cover `single_culprit`, `narrowed_range`, `not_confirmed`, and `unresolved`, including + each result's required `culprit`, `range`, or `rationale` field. + +## Sources + +- [BCO output](../../../docs/contracts/bco-output.md) +- [State store design](../../../docs/components/state-store.md) diff --git a/planning/tasks/contracts/check-mvp-bto-request-and-result-rules.md b/planning/tasks/contracts/check-mvp-bto-request-and-result-rules.md new file mode 100644 index 0000000..4882bfa --- /dev/null +++ b/planning/tasks/contracts/check-mvp-bto-request-and-result-rules.md @@ -0,0 +1,42 @@ +--- +stream: "Contracts" +topic: "Build-test orchestration" +priority: high +publish: false +--- + +# Check MVP BTO request and result rules + +## Description + +The minimal BTO round trip checks one accepted plan and one final result. This task checks only the +request errors, acknowledgement fields, lookup cases, and final-result fields listed below. Handling +repeated submissions with the same idempotency key remains a separate later task. + +## Contribution + +- Delivers: BTO rejects the listed request errors and returns the listed acknowledgement, lookup, and result fields + +## Acceptance criteria + +- [ ] A correct `build-test-plan-request/v1` returns a submission response containing a BTO-owned + `plan_id` and the request's `request_id`. +- [ ] A request with a `contract_version` other than `build-test-plan-request/v1`, or without + `request_id`, `idempotency_key`, `source`, `scope`, or `composition`, returns the submission + error defined by the BTO OpenAPI operation and creates no plan state. +- [ ] Lookup tests check the status and response body defined by the BTO OpenAPI operation for + a known non-terminal plan, a known terminal plan, and an unknown `plan_id`. +- [ ] Every terminal `build-test-plan-result/v1` contains the looked-up `plan_id`, the accepted + request's `request_id`, and one outcome from `content_result`, `infrastructure_failure`, or + `invalid_request`. +- [ ] A `content_result` contains at least one `artifact_refs` or `raw_output_refs` entry and includes + `reported_build_identity` when the builder knows which build inputs it used. +- [ ] When the request contains `trace_context`, the terminal result returns it unchanged; when the + request omits it, the result omits it. + +## Sources + +- [BTO OpenAPI](../design-and-docs/define-bto-oapi-spec.md) +- [BTO result lookup behavior](../design-and-docs/define-bto-result-lookup-behavior.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) diff --git a/planning/tasks/contracts/check-plain-bisect-request-and-result-rules.md b/planning/tasks/contracts/check-plain-bisect-request-and-result-rules.md new file mode 100644 index 0000000..d59c024 --- /dev/null +++ b/planning/tasks/contracts/check-plain-bisect-request-and-result-rules.md @@ -0,0 +1,43 @@ +--- +stream: "Contracts" +topic: "Commit selection" +priority: high +publish: false +--- + +# Check plain-bisect request and result rules + +## Description + +Standard bisect can already select a commit and finish a search. This task checks only the request +fields, result fields, and invalid-input cases listed below. It covers the `bisect` policy and the +`git_bisect_default` history view. It does not add another selection policy. + +## Contribution + +- Delivers: Plain bisect rejects the listed bad inputs and returns the listed request IDs and result fields + +## Acceptance criteria + +- [ ] A correct `commit-selection-request/v1` uses `search_policy.type: bisect` and + `history_view.type: git_bisect_default` and contains `request_id`, `campaign_id`, + `selection_round`, `source_tree`, `boundaries.good`, `boundaries.bad`, and `decision_history`. +- [ ] Every result copies `request_id`, `campaign_id`, `selection_round`, and `search_policy` from the + request. +- [ ] A `selected` result contains exactly one candidate; `converged`, `blocked`, and + `invalid_request` contain no candidates. +- [ ] `blocked_reason` appears only on `blocked`, and `errors` is non-empty and appears only on + `invalid_request`. +- [ ] Commit references that cannot be resolved or do not form a usable Git bisect range return + `invalid_request`. +- [ ] A policy other than `bisect` or a history view other than `git_bisect_default` returns + `invalid_request`. +- [ ] Duplicate commits with conflicting marks, or marks that contradict the supplied boundaries, + return `invalid_request`. +- [ ] Every `invalid_request` contains at least one error. Every error contains `field`, `code`, and + `message`. + +## Sources + +- [Commit selection request](../../../docs/contracts/commit-selection-request.md) +- [Commit selection result](../../../docs/contracts/commit-selection-result.md) diff --git a/planning/tasks/contracts/check-unit-test-analyzer-request-and-evidence-rules.md b/planning/tasks/contracts/check-unit-test-analyzer-request-and-evidence-rules.md new file mode 100644 index 0000000..e54864a --- /dev/null +++ b/planning/tasks/contracts/check-unit-test-analyzer-request-and-evidence-rules.md @@ -0,0 +1,37 @@ +--- +stream: "Contracts" +topic: "Results analysis" +priority: high +publish: false +--- + +# Check unit-test analyzer request and evidence rules + +## Description + +This task checks only the request, rejection, evidence, and observation fields listed below for the +unit-test path. It does not change how Results Analyzer turns raw test output into a qualification or +error-signature observation. The two earlier Results Analyzer tasks implement those rules. + +## Contribution + +- Delivers: Results Analyzer rejects the listed non-content inputs and returns the listed unit-test evidence fields and IDs + +## Acceptance criteria + +- [ ] A correct `results-analyzer-request/v1` contains `request_id`, `campaign_id`, `step_id`, + `attempt_id`, `regression_type: unit_test`, `scope`, `expected_signal`, and an inline + `build-test-plan-result/v1` whose outcome is `content_result`. +- [ ] Requests containing `infrastructure_failure` or `invalid_request` plan outcomes are rejected by + Results Analyzer without returning evidence. +- [ ] Returned evidence copies `campaign_id`, `step_id`, and `attempt_id` from the request and contains + a non-empty `observations` list. +- [ ] A non-`parse_error` set contains exactly one `qualification` observation; a `parse_error` set + contains exactly one observation, of type `parse_error`. +- [ ] Every observation has `observation_id`, a contract-defined `observation_type`, `name`, `value`, + and `source_refs.artifact_ref`. `value` contains JSON data, not source-specific free-form text. + +## Sources + +- [Results Analyzer request](../../../docs/contracts/results-analyzer-request.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) diff --git a/planning/tasks/contracts/check-unit-test-decision-rules.md b/planning/tasks/contracts/check-unit-test-decision-rules.md new file mode 100644 index 0000000..087b007 --- /dev/null +++ b/planning/tasks/contracts/check-unit-test-decision-rules.md @@ -0,0 +1,39 @@ +--- +stream: "Contracts" +topic: "Binary decisions" +priority: high +publish: false +--- + +# Check unit-test decision rules + +## Description + +This task checks the unit-test evidence cases listed below and their `good`, `bad`, `skip`, or `weak` +results. The separate Decision engine rules task checks the common request and result fields and +makes sure their IDs match. + +## Contribution + +- Delivers: Listed unit-test evidence cases return their defined `good`, `bad`, `skip`, or `weak` decision + +## Acceptance criteria + +- [ ] When `qualification.reached` is true and the error-signature observation matches the requested + signature, Decision engine returns `bad` with `matched_expected_signal: true`. +- [ ] When `qualification.reached` is true and the error-signature observation says the requested + signature is absent, Decision engine returns `good` with `matched_expected_signal: false`. +- [ ] Conflicting observations return `weak` with `uncertainty_reason: conflicting_observations`; an + unexpected failure uses `unexpected_failure`; a flaky result uses `flaky_result`. +- [ ] When `qualification.reached` is false, Decision engine returns `skip`. It copies `not_built`, + `not_booted`, `did_not_run`, or `crashed` from the qualification observation into `skip_reason`. +- [ ] A parse error returns `skip_reason: parse_error`; a missing required observation returns + `missing_required_observation`; an unsupported observation returns `unsupported_observation`; + an incompatible evidence shape or regression type returns `strategy_not_applicable`. +- [ ] Every result sets `decision_details.strategy: binary` when the binary rules run and cites + only observation IDs present in the request. + +## Sources + +- [Decision contract](../../../docs/contracts/decision-contract.md) +- [Binary decision strategy](../../../docs/contracts/binary-decision-strategy.md) diff --git a/planning/tasks/decision-engine/implement-unit-test-decisions.md b/planning/tasks/decision-engine/implement-unit-test-decisions.md new file mode 100644 index 0000000..fda51c9 --- /dev/null +++ b/planning/tasks/decision-engine/implement-unit-test-decisions.md @@ -0,0 +1,29 @@ +--- +stream: "Decision engine" +topic: "Binary strategy" +priority: high +publish: false +--- + +# Implement unit-test decisions + +## Description + +A qualified unit-test observation must become the step decision used by BCO and Commit selector. + +## Contribution + +- Delivers: Binary unit-test decisions for BCO and Commit selector + +## Acceptance criteria + +- [ ] A matched expected signal returns bad. +- [ ] An absent signal returns good. +- [ ] Conflicts and unexpected failures return weak. +- [ ] Missing or unsupported observations and parse_error return skip. +- [ ] Replay returns the same result. + +## Sources + +- [Decision engine design](../../../docs/components/decision-engine.md) +- [Binary decision strategy](../../../docs/contracts/binary-decision-strategy.md) diff --git a/planning/tasks/decision-engine/implement-unit-test-qualification-check.md b/planning/tasks/decision-engine/implement-unit-test-qualification-check.md new file mode 100644 index 0000000..741572e --- /dev/null +++ b/planning/tasks/decision-engine/implement-unit-test-qualification-check.md @@ -0,0 +1,30 @@ +--- +stream: "Decision engine" +topic: "Contract and qualification" +priority: high +publish: false +--- + +# Implement the unit-test qualification check + +## Description + +A unit-test result is usable only if the candidate built, booted, and ran the requested test. An +earlier failure cannot prove the expected regression. This task dispatches qualified evidence to +an injected fake strategy; the real binary strategy arrives with the unit-test decisions task. + +## Contribution + +- Delivers: Exclusion of unit-test results that cannot prove the expected regression + +## Acceptance criteria + +- [ ] Validate request and evidence IDs and require one evidence object. +- [ ] Unqualified unit-test evidence returns skip with its reason. +- [ ] Qualified evidence reaches the binary strategy once. + +## Sources + +- [Decision engine design](../../../docs/components/decision-engine.md) +- [Decision contract](../../../docs/contracts/decision-contract.md) +- [ADR-0009](../../../docs/adr/0009-two-stage-step-decision.md) diff --git a/planning/tasks/design-and-docs/define-backend-work-recovery.md b/planning/tasks/design-and-docs/define-backend-work-recovery.md new file mode 100644 index 0000000..d0f1a4a --- /dev/null +++ b/planning/tasks/design-and-docs/define-backend-work-recovery.md @@ -0,0 +1,32 @@ +--- +stream: "Design&Docs" +topic: "Execution recovery" +priority: medium +publish: false +--- + +# Define how BTO avoids duplicate backend work + +## Description + +BTO can crash after a backend accepts planner, builder, or tester work but before BTO saves the +reply. An intent record alone cannot tell recovery whether to submit again. The design must give +each backend action a stable identity and a replay rule before BTO restart recovery is +implemented. + +## Contribution + +- Delivers: Defined backend action identity and replay rule for BTO restart recovery + +## Acceptance criteria + +- [ ] Give each planner, builder, and tester action a stable identity. +- [ ] Choose the replay rule for the crash window: idempotent backend submission by that identity, + or lookup of the saved backend job reference before retrying. +- [ ] Define where BTO saves the action identity and the backend job reference. +- [ ] Define what recovery does when the backend cannot confirm whether it accepted the work. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) diff --git a/planning/tasks/design-and-docs/define-bco-oapi-spec.md b/planning/tasks/design-and-docs/define-bco-oapi-spec.md new file mode 100644 index 0000000..39fa00a --- /dev/null +++ b/planning/tasks/design-and-docs/define-bco-oapi-spec.md @@ -0,0 +1,30 @@ +--- +stream: "Design&Docs" +topic: "BCO REST API" +priority: high +publish: false +--- + +# Define BCO OpenAPI spec + +## Description + +BCO needs an OpenAPI spec before its REST service is implemented. + +## Contribution + +- Delivers: OpenAPI operations for CR submission and campaign reads + +## Acceptance criteria + +- [ ] Define methods, paths, request bodies, responses, and errors for CR submission. +- [ ] Define methods, paths, responses, and errors for campaign reads. +- [ ] Define timeouts and response codes. +- [ ] Name the OpenAPI document's path in the repository. +- [ ] Validate the OpenAPI document. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [CR](../../../docs/contracts/campaign-request.md) +- [BCO output](../../../docs/contracts/bco-output.md) diff --git a/planning/tasks/design-and-docs/define-bto-oapi-spec.md b/planning/tasks/design-and-docs/define-bto-oapi-spec.md new file mode 100644 index 0000000..7254361 --- /dev/null +++ b/planning/tasks/design-and-docs/define-bto-oapi-spec.md @@ -0,0 +1,29 @@ +--- +stream: "Design&Docs" +topic: "BTO REST API" +priority: high +publish: false +--- + +# Define BTO OpenAPI spec + +## Description + +BTO needs an OpenAPI spec before its REST service is implemented. This spec covers plan +submission; the result-lookup operation is added by the result-lookup design task. + +## Contribution + +- Delivers: OpenAPI operation for build-test plan submission + +## Acceptance criteria + +- [ ] Define the method, path, request body, acknowledgement, and errors for plan submission. +- [ ] Define timeouts and response codes. +- [ ] Name the OpenAPI document's path in the repository. +- [ ] Validate the OpenAPI document. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) diff --git a/planning/tasks/design-and-docs/define-bto-result-lookup-behavior.md b/planning/tasks/design-and-docs/define-bto-result-lookup-behavior.md new file mode 100644 index 0000000..c6c760a --- /dev/null +++ b/planning/tasks/design-and-docs/define-bto-result-lookup-behavior.md @@ -0,0 +1,32 @@ +--- +stream: "Design&Docs" +topic: "BTO result lookup" +priority: high +publish: false +--- + +# Define BTO result lookup behavior + +## Description + +BCO asks BTO for a plan result after submission. The proposal does not define what BTO returns before the +result exists or for an unrecognized plan ID. + +## Contribution + +- Delivers: Defined BTO lookup responses and BCO handling + +## Acceptance criteria + +- [ ] Define what BTO returns when a known plan has no final result. +- [ ] Define what BTO returns when a known plan has a final result. +- [ ] Define what BTO returns when the plan ID is unknown. +- [ ] Define how BCO handles each result. +- [ ] Decide how BCO learns that a plan finished in the MVP: polling only, or the terminal-state + notification with polling fallback, and record the replay rule for a repeated notification. +- [ ] Add the lookup operation to the BTO OpenAPI spec. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) diff --git a/planning/tasks/design-and-docs/define-campaign-cancellation-behavior.md b/planning/tasks/design-and-docs/define-campaign-cancellation-behavior.md new file mode 100644 index 0000000..4a4574d --- /dev/null +++ b/planning/tasks/design-and-docs/define-campaign-cancellation-behavior.md @@ -0,0 +1,31 @@ +--- +stream: "Design&Docs" +topic: "Campaign cancellation" +priority: high +publish: false +--- + +# Define campaign cancellation behavior + +## Description + +Cancellation is not defined by the campaign lifecycle or BCO output contracts. Its behavior must be +defined before implementation without adding new campaign or step statuses. + +## Contribution + +- Delivers: Defined cancellation behavior using the existing campaign and step statuses + +## Acceptance criteria + +- [ ] Define how cancellation maps to existing campaign status, outcome, or failure fields. +- [ ] Define how BCO handles pending and in-flight work and late results. +- [ ] Define where a late result is kept for audit and how it links to its plan and attempt. +- [ ] Define repeated-request behavior. +- [ ] Update the State store and BCO output documents without adding status values. +- [ ] Add cancellation to the BCO OpenAPI spec before implementation. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [BCO output](../../../docs/contracts/bco-output.md) diff --git a/planning/tasks/design-and-docs/define-campaign-execution-profile-source.md b/planning/tasks/design-and-docs/define-campaign-execution-profile-source.md new file mode 100644 index 0000000..1f1f97b --- /dev/null +++ b/planning/tasks/design-and-docs/define-campaign-execution-profile-source.md @@ -0,0 +1,31 @@ +--- +stream: "Design&Docs" +topic: "Deployment configuration" +priority: high +publish: false +--- + +# Define the campaign execution profile source + +## Description + +Admission must check each request against the campaign execution profile. The contract defines the +profile fields, but no document says who provides a profile instance, in what format, or how BCO +loads it. + +## Contribution + +- Delivers: Defined provider, format, and loading path for the campaign execution profile + +## Acceptance criteria + +- [ ] Choose the profile provider: a deployment file, the BCO store, or the Trigger registry. +- [ ] Define the profile format, its location, and when BCO loads it. +- [ ] Define what BCO does when the profile is missing or fails contract validation. +- [ ] Write the minimal MVP profile content: the unit-test regression type, the `bisect` policy, + the minimal composition, and their evidence path and decision strategy. + +## Sources + +- [Campaign execution profile](../../../docs/contracts/campaign-execution-profile.md) +- [BCO design](../../../docs/components/bco.md) diff --git a/planning/tasks/design-and-docs/define-campaign-stop-limits.md b/planning/tasks/design-and-docs/define-campaign-stop-limits.md new file mode 100644 index 0000000..0f7bb6f --- /dev/null +++ b/planning/tasks/design-and-docs/define-campaign-stop-limits.md @@ -0,0 +1,29 @@ +--- +stream: "Design&Docs" +topic: "Resource limits" +priority: medium +publish: false +--- + +# Define campaign stop limits + +## Description + +BCO must know when campaign policy stops further work. The proposal says every limit chooses failure or a +normal conclusion but does not define the supported limits. + +## Contribution + +- Delivers: Defined campaign limits and their completion outcomes + +## Acceptance criteria + +- [ ] List the limits supported by this implementation and each limit's configuration source. +- [ ] Define each limit's value, when it starts counting, and the exact event that counts toward it. +- [ ] Define what happens to in-flight work when a limit is reached. +- [ ] Define whether reaching each limit fails the campaign or produces a normal conclusion. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [Open questions: oq-006](../../../oq.md) diff --git a/planning/tasks/design-and-docs/define-evidence-storage.md b/planning/tasks/design-and-docs/define-evidence-storage.md new file mode 100644 index 0000000..74c3bc2 --- /dev/null +++ b/planning/tasks/design-and-docs/define-evidence-storage.md @@ -0,0 +1,30 @@ +--- +stream: "Design&Docs" +topic: "Evidence storage" +priority: high +publish: false +--- + +# Define evidence storage + +## Description + +BCO must reload the exact evidence used for a decision, but the proposal only requires stored +evidence references. It does not say whether BCO stores the full evidence object, a reference, or +both, or who owns a referenced payload. + +## Contribution + +- Delivers: Defined owner and shape of stored decision evidence + +## Acceptance criteria + +- [ ] Choose what the BCO store keeps: the full evidence object, an immutable reference with the + IDs and digest needed to verify it, or compact evidence with large artifacts kept externally. +- [ ] Name the owner of any external evidence store. +- [ ] State what the Decision engine input and BCO audit read, consistent with that choice. + +## Sources + +- [State store design](../../../docs/components/state-store.md) +- [Results Analyzer design](../../../docs/components/results-analyzer.md) diff --git a/planning/tasks/design-and-docs/define-how-admission-validates-toolchains.md b/planning/tasks/design-and-docs/define-how-admission-validates-toolchains.md new file mode 100644 index 0000000..a137914 --- /dev/null +++ b/planning/tasks/design-and-docs/define-how-admission-validates-toolchains.md @@ -0,0 +1,32 @@ +--- +stream: "Design&Docs" +topic: "Toolchain catalog" +priority: medium +publish: false +--- + +# Define configurable toolchain admission + +## Description + +Minimal admission uses an implementation-owned toolchain list. The toolchain catalog owner, +identity fields, and admission error are open (oq-025). The owner choice decides whether BCO loads +the rules or validation happens before a request reaches BCO. + +## Contribution + +- Delivers: Defined configurable toolchain rules for campaign admission + +## Acceptance criteria + +- [ ] Choose the toolchain catalog provider and decide whether name and version are sufficient identity. +- [ ] Define exact-match rules and the admission error for a missing or unsupported value. +- [ ] State where admission reads the rules, or that the chosen provider validates toolchains + before requests reach BCO. +- [ ] Record the decision and remove oq-025. + +## Sources + +- [CR](../../../docs/contracts/campaign-request.md) +- [Campaign execution profile](../../../docs/contracts/campaign-execution-profile.md) +- [Open questions: oq-025](../../../oq.md) diff --git a/planning/tasks/design-and-docs/define-service-authentication.md b/planning/tasks/design-and-docs/define-service-authentication.md new file mode 100644 index 0000000..6ffef32 --- /dev/null +++ b/planning/tasks/design-and-docs/define-service-authentication.md @@ -0,0 +1,31 @@ +--- +stream: "Design&Docs" +topic: "Credentials and access" +priority: high +publish: false +--- + +# Define service auth + +## Description + +BCO must authenticate trigger calls and BCO-to-BTO calls. BTO must authenticate calls to configured planner, +builder, and tester instances. The proposal does not define how. + +## Contribution + +- Delivers: Defined auth for Trigger, BCO, BTO, and execution calls + +## Acceptance criteria + +- [ ] Choose the credential source for each caller boundary and record the decision for oq-012. +- [ ] Define how BCO authenticates Triggers and calls BTO, and how BTO authenticates configured instances. +- [ ] Add the selected security schemes to the BCO and BTO OpenAPI specs. +- [ ] CRs, responses, and logs contain no passwords, tokens, or private keys. +- [ ] Remove oq-012 after its decision is recorded in the owning document. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [Open questions: oq-012](../../../oq.md) diff --git a/planning/tasks/design-and-docs/define-unit-test-cr-fields.md b/planning/tasks/design-and-docs/define-unit-test-cr-fields.md new file mode 100644 index 0000000..feb86d2 --- /dev/null +++ b/planning/tasks/design-and-docs/define-unit-test-cr-fields.md @@ -0,0 +1,28 @@ +--- +stream: "Design&Docs" +topic: "Unit-test input" +priority: high +publish: false +--- + +# Define unit-test CR fields + +## Description + +The data model requires a test suite and test case, but the CR does not state which fields carry +them. Admission cannot validate unit-test scope without that mapping. + +## Contribution + +- Delivers: Defined unit-test scope in CRs + +## Acceptance criteria + +- [ ] Map test suite and test case to CR fields. +- [ ] Define required values and equivalence-key use. +- [ ] Give accepted and rejected examples. + +## Sources + +- [CR](../../../docs/contracts/campaign-request.md) +- [Bisection data model](../../../docs/bisection-data-model.md) diff --git a/planning/tasks/design-and-docs/define-who-can-access-a-campaign.md b/planning/tasks/design-and-docs/define-who-can-access-a-campaign.md new file mode 100644 index 0000000..8ca508d --- /dev/null +++ b/planning/tasks/design-and-docs/define-who-can-access-a-campaign.md @@ -0,0 +1,28 @@ +--- +stream: "Design&Docs" +topic: "Campaign access" +priority: high +publish: false +--- + +# Define who can access a campaign + +## Description + +Triggers can create or join a campaign, but campaign reads and cancellation need access rules. + +## Contribution + +- Delivers: Defined authorization for campaign reads and cancellation + +## Acceptance criteria + +- [ ] Triggers attached to a campaign can read its BCO output. +- [ ] Define which Triggers may cancel a campaign. +- [ ] Other Triggers receive the same response as an unknown campaign ID. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [CR](../../../docs/contracts/campaign-request.md) +- [BCO output](../../../docs/contracts/bco-output.md) diff --git a/planning/tasks/design-and-docs/document-source-repository-scope.md b/planning/tasks/design-and-docs/document-source-repository-scope.md new file mode 100644 index 0000000..4eef5a6 --- /dev/null +++ b/planning/tasks/design-and-docs/document-source-repository-scope.md @@ -0,0 +1,30 @@ +--- +stream: "Design&Docs" +topic: "Source scope" +priority: medium +publish: false +--- + +# Document the source-repository scope + +## Description + +The MVP bisects publicly readable open-source Linux kernel repositories, but no design document +states that boundary. Without it, repository access can look like an unfinished auth design. + +## Contribution + +- Delivers: A recorded public-repository scope statement in the architecture + +## Acceptance criteria + +- [ ] The architecture states that the MVP bisects publicly readable open-source Linux kernel Git + repositories. +- [ ] It states that repository credential management and repository-level authorization are out + of scope, and that a private deployment may use a non-public repository only when its + environment already provides read access. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [Commit selector design](../../../docs/components/commit-selector.md) diff --git a/planning/tasks/design-and-docs/select-first-execution-backend.md b/planning/tasks/design-and-docs/select-first-execution-backend.md new file mode 100644 index 0000000..cd237bb --- /dev/null +++ b/planning/tasks/design-and-docs/select-first-execution-backend.md @@ -0,0 +1,30 @@ +--- +stream: "Design&Docs" +topic: "Execution backend" +priority: high +publish: false +--- + +# Select the first execution backend + +## Description + +The proposal lists possible execution systems but selects none. The adapter, the minimal +composition, and the outcome map cannot be built without one concrete target. + +## Contribution + +- Delivers: A selected first build-test backend with its composition, settings, and outcome map + +## Acceptance criteria + +- [ ] Select the first combined build-test backend and instance. +- [ ] Define its private request and response and the minimal composition it supports. +- [ ] Define its endpoint and capability settings and its credential reference. +- [ ] Map its native terminal states to the plan-result outcomes. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) diff --git a/planning/tasks/design-and-docs/select-imp-env.md b/planning/tasks/design-and-docs/select-imp-env.md new file mode 100644 index 0000000..970eca7 --- /dev/null +++ b/planning/tasks/design-and-docs/select-imp-env.md @@ -0,0 +1,31 @@ +--- +stream: "Design&Docs" +topic: "Dev env" +priority: high +publish: false +--- + +# Select the dev env + +## Description + +Select the dev env that all project services and tests will use. +Record the decision in `docs/imp-env.md` before implementation starts. +We can take KernelCI as a reference for the dev env, but we should not be constrained by it. + +## Contribution + +- Delivers: Approved runtime and dev toolchain in `docs/imp-env.md` + +## Acceptance criteria + +- [ ] The document names the primary programming language and supported version. +- [ ] The document names the API framework. +- [ ] The document defines initial dependency and packaging tools. +- [ ] The document defines formatting, linting, type-checking, and test tools. +- [ ] The document defines how a developer runs the project locally. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [Components](../../../docs/components.md) diff --git a/planning/tasks/design-and-docs/select-unit-test-result-input.md b/planning/tasks/design-and-docs/select-unit-test-result-input.md new file mode 100644 index 0000000..7e83463 --- /dev/null +++ b/planning/tasks/design-and-docs/select-unit-test-result-input.md @@ -0,0 +1,31 @@ +--- +stream: "Design&Docs" +topic: "Unit-test results" +priority: high +publish: false +--- + +# Select unit-test result input + +## Description + +Results Analyzer needs a defined BTO output to decide whether the expected unit-test failure signature +appeared. The proposal does not select that input. + +## Contribution + +- Delivers: Defined BTO output used for unit-test observation + +## Acceptance criteria + +- [ ] Select one artifact_refs or raw_output_refs entry. +- [ ] Define the selected input's format. +- [ ] Define how Results Analyzer identifies the test suite, test case, and signature. +- [ ] Define how the plan request asks for this output so every unit-test attempt returns it. +- [ ] Define errors for missing or unsupported input. + +## Sources + +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) +- [Results Analyzer request](../../../docs/contracts/results-analyzer-request.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) diff --git a/planning/tasks/e2e/create-the-component-test-harness.md b/planning/tasks/e2e/create-the-component-test-harness.md new file mode 100644 index 0000000..c32eac2 --- /dev/null +++ b/planning/tasks/e2e/create-the-component-test-harness.md @@ -0,0 +1,29 @@ +--- +stream: "E2E" +topic: "Harness" +priority: high +publish: false +--- + +# Create the component test harness + +## Description + +Component boundaries need repeatable integration tests. Isolated mocks hide incompatible contracts and +state ownership violations. + +## Contribution + +- Delivers: Repeatable component integration tests with controlled dependencies + +## Acceptance criteria + +- [ ] The harness runs BCO, BTO, Commit selector, Results Analyzer, and Decision engine. +- [ ] The harness uses controlled dependencies and resets both stores. +- [ ] The harness captures exchanged contracts. +- [ ] One command runs the harness locally and in CI with the same controlled dependencies. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [Components](../../../docs/components.md) diff --git a/planning/tasks/e2e/test-campaign-cancellation.md b/planning/tasks/e2e/test-campaign-cancellation.md new file mode 100644 index 0000000..41e4f4a --- /dev/null +++ b/planning/tasks/e2e/test-campaign-cancellation.md @@ -0,0 +1,34 @@ +--- +stream: "E2E" +topic: "Cancellation scenario" +priority: high +publish: false +--- + +# Test campaign cancellation + +## Description + +Cancellation must stop future campaign work and prevent in-flight results from changing decisions or the +campaign conclusion. + +## Contribution + +- Delivers: Evidence that cancellation remains safe through BTO work and restart + +## Acceptance criteria + +- [ ] Tests cancel before work and during BTO execution. +- [ ] Tests check that only an authorized Trigger can cancel. +- [ ] Tests check that no new selector, BTO, analyzer, decision, or verifier call starts after + cancellation. +- [ ] Tests deliver a late result and find it kept for audit with no decision, boundary, or + conclusion change. +- [ ] After a service restart during cancellation, the campaign still ends in the defined + cancelled state and no new work starts. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [State store design](../../../docs/components/state-store.md) +- [Cancellation design task](../design-and-docs/define-campaign-cancellation-behavior.md) diff --git a/planning/tasks/e2e/test-crash-recovery-during-bto-work.md b/planning/tasks/e2e/test-crash-recovery-during-bto-work.md new file mode 100644 index 0000000..9e66086 --- /dev/null +++ b/planning/tasks/e2e/test-crash-recovery-during-bto-work.md @@ -0,0 +1,31 @@ +--- +stream: "E2E" +topic: "Recovery scenario" +priority: high +publish: false +--- + +# Test crash recovery during BTO work + +## Description + +BCO or BTO may restart while a plan is running or after its result is stored, including between a +backend accepting work and BTO saving the reply. Recovery must not duplicate the plan, evidence, +decision, step, or backend job. + +## Contribution + +- Delivers: Evidence that BCO and BTO recovery duplicates no attempt or backend work + +## Acceptance criteria + +- [ ] Tests restart BCO and BTO before and after plan submission and result lookup. +- [ ] Tests stop BTO before and after each planner, builder, and tester call. +- [ ] The backend receives no replacement job for work it already accepted. +- [ ] Each case reaches the same BCO output with one plan, evidence record, decision, and step per attempt. + +## Sources + +- [BCO design](../../../docs/components/bco.md) +- [BTO design](../../../docs/components/bto.md) +- [State store design](../../../docs/components/state-store.md) diff --git a/planning/tasks/e2e/test-the-unit-test-campaign-path.md b/planning/tasks/e2e/test-the-unit-test-campaign-path.md new file mode 100644 index 0000000..aa739bb --- /dev/null +++ b/planning/tasks/e2e/test-the-unit-test-campaign-path.md @@ -0,0 +1,33 @@ +--- +stream: "E2E" +topic: "Functional scenario" +priority: high +publish: false +--- + +# Test the unit-test campaign path + +## Description + +The unit-test vertical slice needs proof that one expected test failure reaches the expected culprit through +every component boundary. + +## Contribution + +- Delivers: Proof that the unit-test path reaches a culprit E2E + +## Acceptance criteria + +- [ ] The test admits one `unit_test` campaign and reaches the expected culprit. +- [ ] The requested test suite and test case reach execution unchanged. +- [ ] The test checks the happy-path shape of each exchange: CR and BCO output, selection request + and result, plan request and result, analyzer request and evidence, decision request and + result. Negative cases stay in the contract-check tasks. +- [ ] The final BCO output matches the expected campaign result. + +## Sources + +- [Architecture](../../../docs/architecture.md) +- [CR](../../../docs/contracts/campaign-request.md) +- [BCO output](../../../docs/contracts/bco-output.md) +- [Unit-test CR fields](../design-and-docs/define-unit-test-cr-fields.md) diff --git a/planning/tasks/execution-adapters/authenticate-backend-calls.md b/planning/tasks/execution-adapters/authenticate-backend-calls.md new file mode 100644 index 0000000..6f334d3 --- /dev/null +++ b/planning/tasks/execution-adapters/authenticate-backend-calls.md @@ -0,0 +1,31 @@ +--- +stream: "Execution adapters" +topic: "Service auth" +priority: medium +publish: false +--- + +# Authenticate BTO calls to the execution backend + +## Description + +The service-auth design covers BTO calls to configured planner, builder, and tester instances, but +no task attaches those credentials. Use the design's credential references on every backend call +made for a plan. + +## Contribution + +- Delivers: Backend calls carry the credentials the service-auth design defines + +## Acceptance criteria + +- [ ] Each planner, builder, and tester call carries the credential the service-auth design defines + for that instance. +- [ ] A missing or invalid configured credential fails the plan without starting backend work. +- [ ] Plans, results, and logs omit credential values. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) +- [Service-auth design](../design-and-docs/define-service-authentication.md) diff --git a/planning/tasks/execution-adapters/map-backend-results-to-plan-outcomes.md b/planning/tasks/execution-adapters/map-backend-results-to-plan-outcomes.md new file mode 100644 index 0000000..05a78cb --- /dev/null +++ b/planning/tasks/execution-adapters/map-backend-results-to-plan-outcomes.md @@ -0,0 +1,30 @@ +--- +stream: "Execution adapters" +topic: "Outcome normalization" +priority: high +publish: false +--- + +# Map backend results to plan outcomes + +## Description + +BTO must translate backend terminal states to content_result, infrastructure_failure, or invalid_request so +BCO never receives backend-specific states. + +## Contribution + +- Delivers: Backend-independent BTO plan outcomes for BCO + +## Acceptance criteria + +- [ ] Each documented backend terminal state maps to one plan outcome. +- [ ] Each outcome includes plan and request IDs; content results include analyzable output + references, and failures keep any available diagnostic references. +- [ ] No good, bad, skip, or weak logic is added. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Runner outcome](../../../docs/contracts/runner-outcome.md) +- [Build-test plan result](../../../docs/contracts/build-test-plan-result.md) diff --git a/planning/tasks/execution-adapters/run-combined-build-and-test-execution.md b/planning/tasks/execution-adapters/run-combined-build-and-test-execution.md new file mode 100644 index 0000000..122f975 --- /dev/null +++ b/planning/tasks/execution-adapters/run-combined-build-and-test-execution.md @@ -0,0 +1,29 @@ +--- +stream: "Execution adapters" +topic: "Combined execution" +priority: high +publish: false +--- + +# Run combined build and test execution + +## Description + +A deployment may use one backend for planning, building, and testing. BTO must run that combined execution. + +## Contribution + +- Delivers: Combined backend build and test execution + +## Acceptance criteria + +- [ ] One plan creates one backend job. +- [ ] Repeated plan submissions create no second job. +- [ ] Output references and errors are retained. +- [ ] Logs omit credentials. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) +- [Runner outcome](../../../docs/contracts/runner-outcome.md) diff --git a/planning/tasks/execution-adapters/translate-plan-requests-for-the-execution-backend.md b/planning/tasks/execution-adapters/translate-plan-requests-for-the-execution-backend.md new file mode 100644 index 0000000..18a8352 --- /dev/null +++ b/planning/tasks/execution-adapters/translate-plan-requests-for-the-execution-backend.md @@ -0,0 +1,30 @@ +--- +stream: "Execution adapters" +topic: "Planning" +priority: high +publish: false +--- + +# Translate plan requests for the execution backend + +## Description + +BTO must translate a build-test plan request into the selected backend format without exposing backend syntax +in the public contract. + +## Contribution + +- Delivers: Backend-specific execution requests without leaking backend syntax + +## Acceptance criteria + +- [ ] Map source, scope, composition, requested artifacts, and correlation IDs. +- [ ] Reject unsupported input before submission. +- [ ] Repeating the request produces the same backend plan. +- [ ] Logs omit credential values. + +## Sources + +- [BTO design](../../../docs/components/bto.md) +- [Build-test plan request](../../../docs/contracts/build-test-plan-request.md) +- [Execution composition](../../../docs/contracts/execution-composition.md) diff --git a/planning/tasks/results-analyzer/implement-the-results-analyzer-contract.md b/planning/tasks/results-analyzer/implement-the-results-analyzer-contract.md new file mode 100644 index 0000000..4b18939 --- /dev/null +++ b/planning/tasks/results-analyzer/implement-the-results-analyzer-contract.md @@ -0,0 +1,33 @@ +--- +stream: "Results Analyzer" +topic: "Contract boundary" +priority: high +publish: false +--- + +# Implement the Results Analyzer contract + +## Description + +Results Analyzer is the only boundary between plan output and Decision engine evidence, so Decision +engine must never read backend-specific data. This task implements contract checks and dispatch +with injected fakes; real parsing arrives with the unit-test observation tasks. The +analyzer handler owns the final observation set: it combines the producers' target and +qualification observations, assigns observation IDs, and returns one set per request. + +## Contribution + +- Delivers: A backend-independent boundary from plan output to decision evidence + +## Acceptance criteria + +- [ ] Accept only content_result plan results. +- [ ] Validate campaign, step, attempt, scope, and expected signal. +- [ ] Emit exactly one documented evidence contract. +- [ ] Return one observation set per request that satisfies the contract's set rules. + +## Sources + +- [Results Analyzer design](../../../docs/components/results-analyzer.md) +- [Results Analyzer request](../../../docs/contracts/results-analyzer-request.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) diff --git a/planning/tasks/results-analyzer/produce-unit-test-observations.md b/planning/tasks/results-analyzer/produce-unit-test-observations.md new file mode 100644 index 0000000..59f9496 --- /dev/null +++ b/planning/tasks/results-analyzer/produce-unit-test-observations.md @@ -0,0 +1,30 @@ +--- +stream: "Results Analyzer" +topic: "Binary evidence" +priority: high +publish: false +--- + +# Produce unit-test observations + +## Description + +The binary strategy needs a structured observation showing whether the expected unit-test failure +signature appeared. The analyzer handler assembles these observations into the final +observation set. + +## Contribution + +- Delivers: Structured evidence of the expected unit-test failure signature + +## Acceptance criteria + +- [ ] A matched signature and an absent signature each produce a target observation. +- [ ] Conflicting results produce the observations the binary strategy needs to decide weak. +- [ ] An unparseable input produces a parse_error set. +- [ ] Each observation identifies the test suite and test case and points to its source. + +## Sources + +- [Results Analyzer design](../../../docs/components/results-analyzer.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) diff --git a/planning/tasks/results-analyzer/produce-unit-test-qualification-observations.md b/planning/tasks/results-analyzer/produce-unit-test-qualification-observations.md new file mode 100644 index 0000000..c385d4f --- /dev/null +++ b/planning/tasks/results-analyzer/produce-unit-test-qualification-observations.md @@ -0,0 +1,31 @@ +--- +stream: "Results Analyzer" +topic: "Qualification" +priority: high +publish: false +--- + +# Produce unit-test qualification observations + +## Description + +A candidate that does not build, boot, or run the requested test cannot show the expected unit-test +failure. Results Analyzer must record that distinction. The analyzer handler adds the single +qualification observation this task produces to the final observation set. + +## Contribution + +- Delivers: Structured evidence of whether the requested test ran successfully + +## Acceptance criteria + +- [ ] A test that ran gets reached=true. +- [ ] not_built, not_booted, did_not_run, and crashed cases get the qualification observation stage + and reason. +- [ ] A parse_error remains separate. + +## Sources + +- [Results Analyzer design](../../../docs/components/results-analyzer.md) +- [Observation contract](../../../docs/contracts/observation-contract.md) +- [ADR-0009](../../../docs/adr/0009-two-stage-step-decision.md) diff --git a/scripts/publish-tasks.py b/scripts/publish-tasks.py new file mode 100644 index 0000000..42d03eb --- /dev/null +++ b/scripts/publish-tasks.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2026 Linaro Limited +# Author: Konstantin Belov + +"""Create plan tasks as GitHub issues when accepted. + +Reads planning/plan.yaml and the task files under planning/tasks. + +Creates one issue for each task marked publish: true, labeled with its +phase, and skips tasks that already have an issue. Then links each +published task to its published dependencies with blocked-by +relationships, adding only the links the issue does not carry yet. +Dependencies without a published issue are reported and skipped. + +Script requires gh CLI installed on host. +""" + +from __future__ import annotations + +import argparse +import json +import re +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +PLAN = ROOT / "planning" / "plan.yaml" +TASKS = ROOT / "planning" / "tasks" + +PHASE_LINE = re.compile(r"^ - phase: (\d+)$") +TASK_LINE = re.compile(r"^ ([a-z0-9][a-z0-9-/]*\.md):$") +DEP_LINE = re.compile(r"^ - (\S+\.md)$") +TITLE_LINE = re.compile(r"^# (.+)$") +PUBLISH_LINE = re.compile(r"^publish: true$", re.MULTILINE) +MARKER = re.compile(r"") +LABEL_COLOR = "1d76db" + + +def parse_plan() -> tuple[dict[str, int], dict[str, list[str]]]: + """Read plan.yaml into task-to-phase and task-to-dependencies maps""" + phases: dict[str, int] = {} + deps: dict[str, list[str]] = {} + current_phase: int | None = None + current_task: str | None = None + for line in PLAN.read_text(encoding="utf-8").splitlines(): + if match := PHASE_LINE.match(line): + current_phase = int(match.group(1)) + elif match := TASK_LINE.match(line): + if current_phase is None: + raise ValueError(f"Task outside a phase: {line}") + current_task = match.group(1) + phases[current_task] = current_phase + elif match := DEP_LINE.match(line): + if current_task is None: + raise ValueError(f"Dependency outside a task: {line}") + deps.setdefault(current_task, []).append(match.group(1)) + if not phases: + raise ValueError("No tasks found in plan") + return phases, deps + + +def existing_tasks() -> dict[str, int]: + """Map task files to issue numbers using the task markers in issue bodies""" + result = subprocess.run( + ["gh", "issue", "list", "--state", "all", "--limit", "1000", "--json", "body,number"], + check=True, + capture_output=True, + text=True, + ) + return { + marker: issue["number"] + for issue in json.loads(result.stdout) + for marker in MARKER.findall(issue["body"] or "") + } + + +def blocked_by(issue: int) -> set[int]: + """Return the issue numbers the given issue is already blocked by""" + result = subprocess.run( + [ + "gh", "api", + f"repos/{{owner}}/{{repo}}/issues/{issue}/dependencies/blocked_by", + "--jq", ".[].number", + ], + check=True, + capture_output=True, + text=True, + ) + return {int(number) for number in result.stdout.split()} + + +def issue_content(task: str) -> tuple[str, str]: + """Build the issue title and body from a task file""" + text = (TASKS / task).read_text(encoding="utf-8") + title = next(match.group(1) for line in text.splitlines() if (match := TITLE_LINE.match(line))) + body = text.split("---\n", 2)[2].lstrip() + body = re.sub(r"^# .+\n+", "", body) + body += f"\n---\nTask file: `planning/tasks/{task}`\n\n" + return title, body + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Publish tasks marked publish: true as issues and link their dependencies" + ) + parser.add_argument("--dry-run", action="store_true", help="list what would be created") + args = parser.parse_args() + + phases, deps = parse_plan() + publishable = [ + (task, phase) + for task, phase in sorted(phases.items()) + if PUBLISH_LINE.search((TASKS / task).read_text(encoding="utf-8")) + ] + if not publishable: + print("no tasks marked publish: true") + return + + if args.dry_run: + for task, phase in publishable: + print(f"would create: {task} (phase-{phase})") + return + + existing = existing_tasks() + created = False + for task, phase in publishable: + if task in existing: + print(f"exists, skipped: {task}") + continue + title, body = issue_content(task) + label = f"phase-{phase}" + subprocess.run( + ["gh", "label", "create", label, "--color", LABEL_COLOR], + check=False, + capture_output=True, + ) + subprocess.run( + ["gh", "issue", "create", "--title", title, "--body", body, "--label", label], + check=True, + ) + created = True + print(f"created: {task} ({label})") + + issues = existing_tasks() if created else existing + for task, _ in publishable: + blockers = [] + for dependency in deps.get(task, []): + dependency_issue = issues.get(dependency) + if dependency_issue is None: + print(f"dependency issue missing, skipped: {task} -> {dependency}") + continue + blockers.append(dependency_issue) + new = [b for b in blockers if b not in blocked_by(issues[task])] if blockers else [] + if new: + numbers = ",".join(map(str, new)) + subprocess.run( + ["gh", "issue", "edit", str(issues[task]), "--add-blocked-by", numbers], + check=True, + ) + print(f"linked: {task} blocked by {numbers}") + + +if __name__ == "__main__": + main()