{
  "version": 1,
  "spec": {
    "path": "BoardReadyOps_Agent_Master_Development_Spec.md",
    "sha256": "e02df14e4105945ac1d8bb8dc13d132e04dd27803e560288548f9c3e60857c62",
    "verified": false,
    "provenance": "SHA-256 asserted by the BoardReadyOps Autonomous Completion Agent standing execution order. The document itself is not present anywhere in this repository's tree (checked at root and one level above) as of 2026-09-02, so the digest cannot be verified locally. This field will flip to verified:true once the spec file is committed at the path above and its digest is confirmed to match."
  },
  "roadmap": {
    "source": "https://github.com/oaslananka/boardreadyops/issues/191",
    "checkedAt": "2026-09-04T08:20:19Z",
    "orderedMilestones": [
      "Repository Maintenance & Release Health",
      "Cloud Control Plane Reliability \u2014 GitHub GA Prerequisite",
      "v2.2 \u2014 GitHub Cloud GA",
      "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "v2.6 \u2014 Enterprise Trust & Customer-Hosted Execution",
      "v2.7 \u2014 Marketplace, Ecosystem & AI Reviewer"
    ],
    "completedMilestones": [
      "v1.8.0 \u2014 Release & Distribution Reliability",
      "v1.9.0 \u2014 Test Quality & Documentation Accessibility",
      "v2.0.0 \u2014 Governance & Supply Chain Assurance",
      "v2.1 \u2014 Product Experience & Golden Path",
      "v2.4 \u2014 Manufacturing Intelligence",
      "v2.5 \u2014 BOM & Supply Chain Intelligence"
    ]
  },
  "baseline": {
    "command": "GitHub Actions security workflow (Linux) on origin/main; local corepack pnpm run verify is unreliable for the notice:check sub-step specifically, see blockers",
    "result": "pass",
    "commit": "0329e87",
    "checkedAt": "2026-09-02T01:21:18Z",
    "blockers": [
      "task binary not found on PATH; local runs use fallback corepack pnpm run verify",
      "CORRECTION of a claim merged in #590: an earlier pass of this baseline reported corepack pnpm run verify halting at the lint step because .mcp.json appeared to have CRLF line endings. That was a false positive caused by one specific pre-existing worktree's local checkout state \u2014 the actual git blob is clean LF (.gitattributes already declares `* text=auto eol=lf`) and biome passes on it in any freshly checked-out worktree. No repository fix was needed or made for that.",
      "SECOND CORRECTION, same PR that introduced it: a subsequent pass regenerated NOTICE locally on Windows after seeing notice:check fail there, and that regenerated file was then found to fail CI's (Linux) notice:check with the *opposite* diff. Checked security workflow history on main (runs at 6d62128, c406a91, 0329e87 \u2014 before, during, and after this audit cycle) and it was green throughout: the originally-committed NOTICE was correct for CI all along. The failure was corepack pnpm's dependency-tree resolution genuinely differing between this Windows worktree (Node 24.19.0) and the Linux CI runner (Node 24.20.0) for a handful of platform-conditional optional/duplicate transitive packages (cliui, yargs, chalk, ansi-* etc.) \u2014 not repository drift. Reverted NOTICE to its original content in this same PR; no repository fix was needed for this either.",
      "Net effect: local corepack pnpm run verify's notice:check sub-step cannot be trusted as a pass/fail signal for this repository from a Windows checkout \u2014 it will disagree with CI regardless of which direction NOTICE is regenerated in. CI (GitHub Actions, Linux) is the authoritative signal for that specific check; every other step in the chain (lint, verify:execution-status, typecheck, knip, compatibility:check, build, verify:dist, verify:version, verify:marketplace, test:unit, test:property, test:snapshot, test:action, test:a11y, coverage, verify:structure, gc, docs, licenses:check, check:reuse) was independently confirmed passing locally and is not known to have this platform sensitivity.",
      "sonar analyze agentic: not run this cycle; SonarQube MCP tools were still connecting at time of audit"
    ]
  },
  "workstreams": [
    {
      "id": "W00",
      "name": "Repository Inventory & Execution Ledger",
      "phase": 0,
      "priority": "P0",
      "status": "implemented",
      "owner": "maintainers",
      "dependencies": [],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [191],
      "evidence": {
        "code": ["scripts/master-execution-status.mjs", "scripts/master-execution-status.d.mts"],
        "tests": [
          "tests/unit/scripts/master-execution-status.test.ts",
          "tests/unit/docs/master-execution-status-docs.test.ts"
        ],
        "docs": ["docs/development/master-execution-status.md"],
        "deployed": ["not-applicable: repository audit tooling runs in local and CI verification"],
        "commits": ["4310ad9", "28cbc94", "375ecf1", "a214d2a", "5545810"],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/scripts/master-execution-status.test.ts tests/unit/docs/master-execution-status-docs.test.ts && corepack pnpm run verify:execution-status",
        "result": "pass",
        "checkedAt": "2026-09-02T00:18:46Z"
      }
    },
    {
      "id": "W01",
      "name": "Repository Maintenance & Release Health",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [329, 321, 330, 331, 332, 333, 334, 546],
      "evidence": {
        "code": [
          "scripts/toolchain.mjs",
          "scripts/compatibility.mjs",
          "scripts/compatibility-utils.mjs",
          "scripts/verify-release-channels.mjs",
          "scripts/verify-reproducible-build.mjs"
        ],
        "tests": [
          "tests/unit/scripts/compatibility.test.ts",
          "tests/unit/scripts/toolchain.test.ts",
          "tests/unit/scripts/verify-release-channels.test.ts",
          "tests/unit/scripts/governance-ruleset.test.ts",
          "tests/unit/scripts/verify-reproducible-build.test.ts"
        ],
        "docs": ["docs/compatibility.yaml", "docs/support-matrix.md", "docs/security/release-integrity.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/scripts/compatibility.test.ts tests/unit/scripts/toolchain.test.ts tests/unit/scripts/verify-release-channels.test.ts tests/unit/scripts/governance-ruleset.test.ts tests/unit/scripts/verify-reproducible-build.test.ts && corepack pnpm run verify:reproducible-build",
        "result": "pass",
        "checkedAt": "2026-09-02T02:00:31Z"
      },
      "remaining": "Issue #546 is now closed (PR #566). corepack pnpm run verify:reproducible-build now provides independent clean-room rebuild evidence \u2014 a detached git worktree in a fresh temp directory, its own node_modules from a frozen-lockfile install, rebuilt and SHA-256-compared against the current checkout's dist/action/index.cjs + dist/cli/index.cjs (verified matching on this cycle's commit). This is same-machine, shared-git-object independence (catches build-path/node_modules non-determinism); it does not yet cover cross-OS or cross-CI-runner reproducibility, which remains open. No other tracked blocker remains open."
    },
    {
      "id": "W02",
      "name": "Schema & Contract Governance",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [289],
      "evidence": {
        "code": [
          "schemas/agent-plan.schema.json",
          "schemas/findings.schema.json",
          "schemas/release-manifest.schema.json",
          "src/util/json.ts"
        ],
        "tests": [
          "tests/unit/contracts/billing.test.ts",
          "tests/unit/contracts/review-contracts.test.ts",
          "tests/unit/contracts/runner-protocol.test.ts",
          "tests/unit/contracts/runner-protocol-forward-compat.test.ts",
          "tests/unit/contracts/cli-cloud-forward-compat.test.ts",
          "tests/unit/contracts/action-cloud-forward-compat.test.ts",
          "tests/snapshot/schemas.snapshot.test.ts",
          "tests/unit/core/schema-compatibility.test.ts",
          "tests/unit/util/json.test.ts"
        ],
        "docs": ["docs/architecture/contract-versioning.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/contracts/billing.test.ts tests/unit/contracts/review-contracts.test.ts tests/unit/contracts/runner-protocol.test.ts tests/unit/contracts/runner-protocol-forward-compat.test.ts tests/unit/contracts/cli-cloud-forward-compat.test.ts tests/unit/contracts/action-cloud-forward-compat.test.ts tests/snapshot/schemas.snapshot.test.ts tests/unit/core/schema-compatibility.test.ts tests/unit/util/json.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-03T19:14:55Z"
      },
      "remaining": "RESOLVED: the .strict()-vs-'consumers must ignore unknown fields' policy tension flagged in the prior note is fixed via a schema-by-schema security triage of the five Runner<->Control-Plane response schemas in packages/contracts/src/runner-protocol.ts. Four (runnerClaimResponseSchema, runnerLeaseHeartbeatResponseSchema, runnerArtifactCapabilityResponseSchema, runnerMutationResponseSchema) carry no identity/authority-bearing field and now use zod's default .strip() mode (unknown keys silently dropped, not surfaced -- a stronger form of 'ignore' than .passthrough(), since no future code could accidentally read a stray field) instead of .strict(); per docs/architecture/contract-versioning.md's own policy table, 'Loosen validation constraint' is classified Non-breaking, so no schemaVersion bump was needed. runnerRegistrationActivationResponseSchema deliberately stays .strict(): the existing security test ('keeps activation token-authenticated and rejects caller-selected tenant identity') asserts it must reject an extra installationId-shaped field, since that response is the one most plausibly confusable with tenant identity if a future refactor carelessly trusted it. 3 tests in tests/unit/contracts/runner-protocol-forward-compat.test.ts updated/added to prove: the four now-lenient schemas accept and strip unknown fields, and the identity-adjacent one still rejects them; the pre-existing security test continues passing unmodified. The schema-shape drift guard (tests/snapshot/schemas.snapshot.test.ts, PR #568) and RFC 8785 canonicalization (src/util/json.ts) still close two other acceptance items. RESOLVED (this cycle): consumer-driven contract tests now span the CLI->Cloud and Action->Cloud boundaries too (Runner->Control-Plane was already covered). tests/unit/contracts/cli-cloud-forward-compat.test.ts covers `boardreadyops review publish` (src/cli/commands/review.ts) -> POST /api/v1/runs, asserting the real `ingestRunRequestSchema` (now exported from apps/web/app/api/v1/runs/route.ts for testability) accepts an older minimal CLI payload, silently strips unrecognized top-level/nested-finding fields a newer CLI might add (matching the 'consumers must ignore unknown fields' policy -- this schema carries no identity-bearing field a stray key could impersonate, since repositoryId is cross-checked against the bearer token's own scope in apps/web/lib/api-auth.ts, not re-derived from the body), and still rejects unrecognized enum values (triggerKind, finding severity). tests/unit/contracts/action-cloud-forward-compat.test.ts covers both Action->Cloud wire paths built from the Action's own producers: (1) the OIDC-authenticated `POST /api/v1/runs/github-actions-result` result reported by the 'Publish OIDC-authenticated cloud result' step in .github/workflows/readiness-runner.yml, validated by the existing exported `releaseRunResultSchema` -- proving nested finding fields are additive/stripped while the top-level envelope deliberately stays .strict() (same identity/authority-bearing rationale as runnerRegistrationActivationResponseSchema, since accepting it triggers GitHub check-run completion, PR comments, lease closure, and an audit-trail write); and (2) the bearer-token `POST /api/v1/runs` 'quick cloud upload' built by src/action/cloud-publish.ts, which shares `ingestRunRequestSchema` with the CLI boundary. No further gaps are tracked against this workstream's evidence at this time."
    },
    {
      "id": "W03",
      "name": "Core Discovery, Parsers & Normalized Hardware Model",
      "phase": 4,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W02", "W04"],
      "milestone": "Backlog \u2014 Core Engineering Depth",
      "issues": [280],
      "evidence": {
        "code": [
          "src/kicad/pcb.ts",
          "src/kicad/schematic.ts",
          "src/kicad/schematic-graph.ts",
          "src/kicad/variants.ts",
          "src/kicad/sexpr.ts",
          "src/bom/normalizer.ts",
          "src/util/errors.ts"
        ],
        "tests": [
          "tests/unit/kicad/coverage.test.ts",
          "tests/unit/kicad/variants.test.ts",
          "tests/unit/kicad/sexpr.test.ts",
          "tests/unit/kicad/pcb.test.ts",
          "tests/unit/kicad/schematic.test.ts",
          "tests/unit/kicad/schematic-graph.test.ts",
          "tests/unit/bom/normalizer.test.ts"
        ],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/kicad/coverage.test.ts tests/unit/kicad/variants.test.ts tests/unit/kicad/sexpr.test.ts tests/unit/kicad/pcb.test.ts tests/unit/kicad/schematic.test.ts tests/unit/kicad/schematic-graph.test.ts tests/unit/bom/normalizer.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-03T01:20:41Z"
      },
      "remaining": "Hostile-input guard gap is closed: sexpr.ts already capped nesting depth (PR #565), and now project-model.ts (shared by pcb.ts/schematic.ts) and variants.ts reject oversized raw input (>64MiB) before parsing, schematic-graph.ts caps sheet-hierarchy fan-out at 5000 sheets, and bom/normalizer.ts caps BOM row count at 100000, each throwing a typed HostileInputError (src/util/errors.ts). Still no Gerber X2/X3 or Excellon metadata parser, no IPC-2581/ODB++ adapter, and no parser confidence/provenance fields."
    },
    {
      "id": "W04",
      "name": "Artifact Generation Engine",
      "phase": 3,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W02", "W06"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [261],
      "evidence": {
        "code": [
          "src/release/generate.ts",
          "src/kicad/cli.ts",
          "src/kicad/version.ts",
          "src/util/process.ts",
          "schemas/generate-recipe.schema.json"
        ],
        "tests": ["tests/unit/release/generate.test.ts", "tests/unit/util/process.test.ts"],
        "docs": ["docs/integrations/kibot.md", "docs/cli.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/release/generate.test.ts tests/unit/util/process.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T22:13:03Z"
      },
      "remaining": "PARTIAL CLOSE: the generation manifest's missing provenance fields are now added, closing one of three named gaps. src/release/generate.ts's GenerateManifest gains recipe.hash (SHA-256 of the recipe's RFC 8785 canonicalized JSON, reusing canonicalizeJson from src/util/json.ts rather than a new hash function), kicadVersion (plumbed through from detectKicadCli()'s already-detected version, previously discarded after only cli.path was used), git (sha/dirty, only present when the caller supplies gitRoot -- deliberately opt-in rather than defaulting to process.cwd(), so a caller that doesn't pass gitRoot never spawns a git subprocess; the CLI command always passes it), and environment (process.platform, process.version). Git detection uses resolveGitExecutable() (src/util/git-resolver.ts, the safe non-PATH-based resolution already adopted in src/cli/commands/review.ts) rather than the plain PATH-based execFileAsync('git', ...) that src/cli/commands/release.ts's own gitState() still uses -- flagged as a known inconsistency for a future unification pass, not fixed here. REAL BUG CAUGHT BY THE PRE-PUSH HOOK, NOT JUST A TEST ARTIFACT: the first version of this change read git provenance via `git rev-parse HEAD` with only `cwd` set, inheriting the parent process's environment. Running inside `git`'s own pre-push hook (which sets GIT_DIR/GIT_WORK_TREE for its own repository so its internal git invocations don't need to re-discover it), that inherited GIT_DIR silently overrode `cwd`-based discovery -- the manifest's `git.sha` would have reported the WRONG repository's HEAD whenever this ran from inside another git operation's environment (a hook, a CI wrapper, anything setting GIT_DIR), not just in this test. Fixed by adding env-override support to src/util/process.ts's runProcess() (additive: existing callers omitting env still inherit process.env unchanged) and stripping GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIR/GIT_OBJECT_DIRECTORY/GIT_ALTERNATE_OBJECT_DIRECTORIES/GIT_CEILING_DIRECTORIES before invoking git, so gitRoot is the sole authority on which repository is inspected. Reproduced by setting GIT_DIR/GIT_WORK_TREE explicitly before the fix (test failed, git.sha resolved to the wrong repo) and after (test passed). 10 total new unit tests: 8 for the manifest provenance fields (hash format/determinism, kicadVersion/environment passthrough, git absent by default and for a non-repo gitRoot, real sha/dirty read against this repository) plus 2 for runProcess's new env option. Still remaining: no integration test exercises real kicad-cli output generation (tests/integration/e2e.test.ts runs with --skip-generate); no jobset-vs-recipe conflict reporting or reproducibility score -- both are separate, larger features, not attempted here."
    },
    {
      "id": "W05",
      "name": "DFM / DFA / DFT Rule Engine",
      "phase": 4,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W03", "W04"],
      "milestone": "Backlog \u2014 Core Engineering Depth",
      "issues": [274],
      "evidence": {
        "code": [
          "src/rules/manufacturing/pin1-markers.ts",
          "src/rules/manufacturing/fiducials.ts",
          "src/rules/manufacturing/test-points.ts",
          "src/rules/manufacturing/drill-coverage.ts",
          "src/core/rule-registry.ts",
          "src/core/waivers.ts",
          "src/core/pipeline.ts",
          "src/core/plugin-loader.ts",
          "src/rules/manufacturing/paste-coverage.ts",
          "src/rules/manufacturing/board-edge-clearance.ts",
          "src/rules/release/artifact-provenance.ts",
          "src/core/provenance.ts"
        ],
        "tests": [
          "tests/unit/rules/manufacturing/assembly-sides.test.ts",
          "tests/unit/rules/manufacturing/drill-coverage.test.ts",
          "tests/unit/rules/metadata.test.ts",
          "tests/unit/core/waivers.test.ts",
          "tests/unit/core/pipeline-waiver-telemetry.test.ts",
          "tests/unit/rules/manufacturing/paste-coverage.test.ts",
          "tests/unit/rules/manufacturing/board-edge-clearance.test.ts",
          "tests/unit/rules/release/artifact-provenance.test.ts",
          "tests/unit/release/provenance.test.ts"
        ],
        "docs": ["docs/rules/manufacturing.dfm-pin1-markers.md", "docs/rules/drc.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/rules/manufacturing/assembly-sides.test.ts tests/unit/rules/manufacturing/drill-coverage.test.ts tests/unit/rules/metadata.test.ts tests/unit/core/waivers.test.ts tests/unit/core/pipeline-waiver-telemetry.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-21T23:00:00Z"
      },
      "remaining": "RECONCILED & COMPLETED (Trustworthy Release Gate pass): Implemented remaining manufacturing artwork checks (#770: mask coverage, paste stencil coverage per SMT side, and Gerber board-edge clearance limits vs vendor profiles), source-to-exported-artifact provenance verification engine (#771: deterministic source fingerprinting and export manifest verification), and reconciled Gerber/Excellon artifact verification umbrella (#753). All rules carry exact evidence classifications and vendor profile provenance."
    },
    {
      "id": "W06",
      "name": "Deterministic Release Decision Engine",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [286],
      "evidence": {
        "code": ["packages/cloud-core/src/decision-engine.ts", "src/core/policy.ts", "src/core/readiness.ts"],
        "tests": ["tests/unit/cloud-core/decision-engine.test.ts", "tests/unit/cloud-core/policy-engine.test.ts"],
        "docs": ["docs/release/policy-engine.md", "docs/release/readiness-scoring.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/cloud-core/decision-engine.test.ts tests/unit/cloud-core/policy-engine.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T04:25:37Z"
      },
      "remaining": "Both previously-named gaps are now addressed. (1) Cross-run decision fingerprint: packages/cloud-core/src/decision-engine.ts's computeDecisionFingerprint() (canonical JSON over sorted explanation-graph nodes, SHA-256) with regression tests proving order-independence and outcome-sensitivity. (2) Canonical PASS/FAIL/CONDITIONAL/UNKNOWN vocabulary: added CanonicalDecision plus canonicalDecisionFromReadiness/canonicalDecisionFromPolicy/canonicalDecisionFromReviewDecision to packages/cloud-core/src/decision-engine.ts, mapping ready/at-risk/blocked to PASS/CONDITIONAL/FAIL, pass/fail to PASS/FAIL, and pending/approved/changes_requested to UNKNOWN/PASS/FAIL. Placed in cloud-core (not src/core) deliberately: src/core (readiness.ts, policy.ts) must never depend on @boardreadyops/cloud-core per the CLI/cloud isolation boundary, so the mapping functions take the literal status union as a plain parameter type rather than importing it, and the wire-protocol ReviewDecision type is untouched. Each function's switch has no default case, so TypeScript's exhaustiveness checking on the literal union enforces totality at compile time, not just via the 3 new regression tests. Noted but not investigated further: issues:[286] resolves to a merged PR titled 'fix(core): restrict safe-mode runtime extensions', unrelated to this workstream's name \u2014 likely a stale/wrong issue reference, flagged for a future reconciliation pass rather than guessed at here. Status kept partial rather than flipped to implemented: no full acceptance-criteria review against the master spec (which is not present in this repository, see W00) was performed for this workstream specifically."
    },
    {
      "id": "W07",
      "name": "Evidence Bundle, Signing, Provenance & Hardware SLSA",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [263, 448],
      "evidence": {
        "code": ["src/release/evidence.ts", "src/release/signing.ts", "src/cli/commands/release.ts"],
        "tests": [
          "tests/unit/release/evidence.test.ts",
          "tests/unit/release/signing.test.ts",
          "tests/unit/cli/release-sign.test.ts"
        ],
        "docs": [
          "docs/release/artifact-attestation.md",
          "docs/security/release-integrity.md",
          "docs/cli.md",
          "docs/release/evidence-bundles.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/release/evidence.test.ts tests/unit/release/signing.test.ts tests/unit/cli/release-sign.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T08:06:08Z"
      },
      "remaining": "PARTIAL CLOSE: signing-key rotation/revocation/trust-store is implemented, and the CLI is now wired to it. `boardreadyops release verify [bundle] --trust-store <path>` loads a JSON TrustStore and calls the new verifyReleaseBundleSignatureAgainstTrustStore(bundleDir, trustStore, verifiedAt) (src/release/signing.ts), which reads the bundle's manifest.sig/manifest.json the same way verifyReleaseBundleSignature does and delegates to verifyManifestSignatureAgainstTrustStore. --public-key and --trust-store are mutually exclusive (exit 2 if both are passed); matchedKeyId is surfaced in --format json output. 3 new CLI regression tests cover: verification against an active trust store entry, failure when the matching key is revoked, and rejection of passing both flags together. Documented in docs/cli.md and docs/release/evidence-bundles.md#key-rotation-and-revocation. Still deliberately out of scope (see issue #448): secure DISTRIBUTION of a trust store update to a consumer's machine (e.g. a signed trust-store bundle, TUF-style delegation) -- this wiring only lets a consumer point at a trust store file they already have. Also still missing: signed-release-certificate UI/API, and no formal Hardware Release Level model (tracked as roadmap Epic #271)."
    },
    {
      "id": "W08",
      "name": "Release-to-Release Diff & Hardware Change Impact",
      "phase": 3,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W07"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [267, 447],
      "evidence": {
        "code": [
          "src/release/diff.ts",
          "src/core/diff/run.ts",
          "src/core/diff/hardware-impact.ts",
          "src/core/baseline.ts"
        ],
        "tests": [
          "tests/unit/core/diff.test.ts",
          "tests/unit/core/run-diff.test.ts",
          "tests/unit/core/hardware-impact.test.ts",
          "tests/unit/release/diff.test.ts"
        ],
        "docs": ["docs/release/release-diff.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/core/diff.test.ts tests/unit/core/run-diff.test.ts tests/unit/core/hardware-impact.test.ts tests/unit/release/diff.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T09:40:32Z"
      },
      "remaining": "PARTIAL CLOSE: worsened/improved per-finding classification is now implemented, closing one of four previously-named gaps. A finding's fingerprint (src/core/findings.ts's fingerprintFor) deliberately excludes severity, so a finding matched as 'unchanged' between two snapshots can still have gotten more or less severe -- previously this was invisible in the diff output. src/core/diff/fabrication.ts's diffFindings() and src/core/diff/run.ts's buildFindingsDelta() (two independent implementations, both fingerprint-matching findings) now each additionally return worsened/improved arrays (using the existing severityRankValue() from src/core/findings.ts) alongside the existing added/removed/unchanged -- additive fields, no existing field removed or retyped, so schemaVersion is unchanged per docs/architecture/contract-versioning.md. src/release/diff.ts's ReleaseDiffSummary gained findingsWorsened/findingsImproved counts, and formatReleaseDiffText() gained 'worsened findings:'/'improved findings:' detail sections (each finding's severity transition, e.g. 'low -> critical design.clearance at board.kicad_pcb'). Deliberately NOT extended: the release diff `--html` dashboard's Fabrication Changes section still only visualizes added/removed findings, not worsened/improved -- that's a separate, larger UI-design task (color-coded badges, template changes, accessibility re-verification), documented as a known gap in docs/release/release-diff.md rather than rushed. Still remaining: impact dimensions cover readiness/findings/bom/manufacturing only (not electrical/assembly/test/firmware/supply/cost/mechanical); no explicit merge-base/previous-release/selected-release baseline modes; no hosted web visualization route; HTML dashboard doesn't yet show severity-change findings. Matches the unmilestoned PR-native hardware-change-impact slice (#447)."
    },
    {
      "id": "W09",
      "name": "Variants, Multi-Board & Product Hierarchy",
      "phase": 4,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W03", "W04"],
      "milestone": "Backlog \u2014 Core Engineering Depth",
      "issues": [268],
      "evidence": {
        "code": ["src/kicad/variants.ts", "src/rules/bom/variant-consistency.ts", "src/rules/bom/dnp-consistency.ts"],
        "tests": ["tests/unit/kicad/variants.test.ts", "tests/unit/rules/bom/variant-consistency.test.ts"],
        "docs": ["docs/rules/bom.variant-consistency.md", "docs/architecture/adr/0004-kicad10-variant-support.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/kicad/variants.test.ts tests/unit/rules/bom/variant-consistency.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "No product\u2192board\u2192variant\u2192revision canonical hierarchy exists in packages/db/prisma/schema.prisma (only a flat Board table); no multi-board release manifest, cross-variant diff, fleet BOM-exposure analysis, or cloud navigation for the hierarchy."
    },
    {
      "id": "W10",
      "name": "Manufacturer Intelligence & Versioned Process Profiles",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W07"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [265],
      "evidence": {
        "code": ["src/vendor/profiles.ts", "src/vendor/outputs.ts"],
        "tests": ["tests/unit/cli/vendor.test.ts"],
        "docs": ["docs/vendor-profiles.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/cli/vendor.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "src/vendor/profiles.ts is a static hardcoded array of 9 vendor presets answering only 'what output evidence does vendor X require' \u2014 no versioned/immutable profile revisions, source/date/verifier/confidence metadata, freshness alerting, verified-badge workflow, or cross-vendor manufacturability compare."
    },
    {
      "id": "W11",
      "name": "BOM, Supply Chain & Cost Intelligence",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W07"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [272, 449],
      "evidence": {
        "code": [
          "src/bom/identity.ts",
          "src/bom/lifecycle.ts",
          "src/bom/risk.ts",
          "src/bom/supplier.ts",
          "packages/db/src/board-bom-store.ts",
          "packages/db/src/board-supply-watch-store.ts",
          "packages/db/migrations/0059_component_pricing_snapshot.sql",
          "packages/cloud-core/src/component-intelligence.ts",
          "packages/cloud-core/src/component-intelligence-resilience.ts",
          "packages/cloud-core/src/nexar-component-intelligence.ts",
          "packages/cloud-core/src/supply-watch.ts",
          "apps/web/lib/component-intelligence-resolver.ts"
        ],
        "tests": [
          "tests/unit/bom/identity.test.ts",
          "tests/unit/bom/lifecycle.test.ts",
          "tests/unit/bom/supplier.test.ts",
          "tests/unit/rules/bom/risk-score.test.ts",
          "tests/unit/db/board-bom-store.test.ts",
          "tests/integration/board-bom-store-postgres.test.ts",
          "tests/unit/db/board-supply-watch-store.test.ts",
          "tests/unit/db/migrations.test.ts",
          "tests/unit/cloud-core/component-intelligence-resilience.test.ts",
          "tests/unit/cloud-core/nexar-component-intelligence.test.ts",
          "tests/unit/cloud-core/supply-watch.test.ts",
          "tests/unit/web/component-intelligence-resolver.test.ts",
          "tests/integration/board-supply-watch-postgres.test.ts"
        ],
        "docs": ["docs/bom-alternates.md", "docs/rules/bom.lifecycle.md", "docs/rules/bom.risk-score.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/bom/identity.test.ts tests/unit/bom/lifecycle.test.ts tests/unit/bom/supplier.test.ts tests/unit/rules/bom/risk-score.test.ts tests/unit/db/board-bom-store.test.ts tests/unit/db/board-supply-watch-store.test.ts tests/unit/db/migrations.test.ts tests/unit/cloud-core/component-intelligence-resilience.test.ts tests/unit/cloud-core/nexar-component-intelligence.test.ts tests/unit/cloud-core/supply-watch.test.ts tests/unit/web/component-intelligence-resolver.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-04T00:00:00Z"
      },
      "remaining": "PARTIAL CLOSE (this cycle): the three previously-named provider-hardening gaps are closed, in scope deliberately excluding the fourth (HTTP surface), which stays out of scope per the prior cycle's access-control investigation (unchanged, see below). (1) Provider TTL/rate-limit/circuit-breaker: investigated first, and what the prior note called a bare 'freshness age-check' turned out to already be real TTL-based cache invalidation -- board-supply-watch-store.ts's freshObservations() filters `expires_at > now` at the query layer, and supply-watch.ts's observationTtlMs is already clamped to the provider's own cachePolicy.maximumCacheAgeMs. What was genuinely missing was protection on the outbound provider calls themselves: a flaky or down provider had no rate limit and nothing to stop every board in a pass from calling it and failing individually. Added packages/cloud-core/src/component-intelligence-resilience.ts: a fixed-window rate limiter (same in-process algorithm as apps/web/lib/webhook-rate-limit.ts / auth-rate-limit.ts -- no Redis in this codebase, confirmed by grep) and a closed/open/half-open circuit breaker (opens after a configurable consecutive-failure threshold, half-open trial after a cooldown, closes on that trial's success), both keyed per installation so one customer's exhausted quota or broken credential cannot throttle or trip the breaker for another. Wired into apps/web/lib/component-intelligence-resolver.ts between the raw Nexar provider and the existing credential-rejection wrapper, defaulting to 30 calls/min and a 5-failure/5-minute-cooldown breaker, each overridable via BOARDREADYOPS_COMPONENT_INTELLIGENCE_RATE_LIMIT_PER_MINUTE / _CIRCUIT_BREAKER_THRESHOLD / _CIRCUIT_BREAKER_COOLDOWN_MS. (2) Authorized-distributor-vs-marketplace classification: confirmed via Nexar's own published query-template docs (support.nexar.com) that `Seller.isAuthorized` is a real field Nexar returns per seller, not guessed at -- nexarDistributorClassification() in nexar-component-intelligence.ts returns 'authorized-distributor' when any seller on the matched part is authorized, 'marketplace' when sellers exist but none are, and honestly 'unknown' when Nexar returns no seller data at all or returns sellers without the isAuthorized signal (the genuinely unclassifiable case). Limited by provider data as expected: this only classifies Nexar; no other provider is implemented, so the classification is only as good as the one live integration's own signal. (3) Cost/quantity-tier/currency snapshot metadata: confirmed via the same Nexar docs that `Seller.offers[].prices[]` carries {quantity, price, currency} tier breaks. Migration 0059_component_pricing_snapshot.sql adds distributor_classification and price_breaks (jsonb, same jsonb_typeof/pg_column_size check-constraint style as 0004/0006/0008) to component_lifecycle_observations, following that table's existing 'one snapshot row per part identity' shape rather than a new table. board-supply-watch-store.ts's ObservationInput/recordObservations/freshObservations round-trip both fields; nexarPriceBreaks() prefers an authorized seller's offer pricing over a marketplace seller's when a part has both, so a grey-market price is never presented as the authorized channel's. Tests: component-intelligence-resilience.test.ts covers the rate limiter's window/reset/per-key isolation and the breaker's full closed->open->half-open->closed and half-open->open transitions (all via injected `now`, no real timers/sleeps); nexar-component-intelligence.test.ts adds fixture-driven classification cases including the ambiguous/unclassifiable one, plus price-break derivation, seller preference, and malformed-entry rejection; board-supply-watch-store.test.ts (new, mocked-executor, matching board-bom-store.test.ts's pattern) proves both new fields round-trip through recordObservations/freshObservations including the JSON-string-vs-native-jsonb and malformed-entry cases; migrations.test.ts asserts the new migration's shape and keeps the deterministic-file-list check current. Still deliberately out of scope: an HTTP API route exposing findBoardsByMpn or any of this cycle's new fields -- unchanged from the prior cycle's finding that installation-level (cross-repository) API auth context does not exist yet in apps/web/lib/api-auth.ts, which is a separate access-control design decision. Matches open issue #449."
    },
    {
      "id": "W12",
      "name": "Firmware \u2194 Hardware Contract",
      "phase": 4,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W03", "W06"],
      "milestone": "Backlog \u2014 Core Engineering Depth",
      "issues": [273],
      "evidence": {
        "code": [
          "src/firmware/contract.ts",
          "src/firmware/arduino.ts",
          "src/firmware/stm32cubemx.ts",
          "src/firmware/yaml-contract.ts"
        ],
        "tests": [
          "tests/unit/rules/firmware/stm32cubemx-pin-contract.test.ts",
          "tests/unit/rules/firmware/platformio-pin-contract.test.ts"
        ],
        "docs": ["docs/integrations/firmware-contracts.md", "docs/rules/firmware.stm32cubemx-pin-contract.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/rules/firmware/stm32cubemx-pin-contract.test.ts tests/unit/rules/firmware/platformio-pin-contract.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "Zephyr and ESP-IDF adapters (src/firmware/zephyr.ts, esp-idf.ts) are thin wrappers around the generic YAML contract loader, not real DeviceTree/ESP-IDF-format parsers as specified; no firmware commit-SHA/artifact-identity binding to a hardware release; no MCU-specific voltage-domain plugin boundary."
    },
    {
      "id": "W13",
      "name": "Mechanical \u2194 PCB Contract",
      "phase": 4,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W03", "W04"],
      "milestone": "Backlog \u2014 Core Engineering Depth",
      "issues": [],
      "evidence": {
        "code": ["src/rules/design/board-outline.ts"],
        "tests": [],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "not run",
        "result": "not_run",
        "checkedAt": "2026-09-02T00:18:46Z"
      },
      "remaining": "The prior matrix entry cited src/release/generate.ts as evidence \u2014 checked and it is a false positive: that file's 'step' references are release-recipe pipeline stages (gerbers, drill, bom, positions, schematic-pdf), unrelated to mechanical CAD/STEP-format exchange. There is no mechanical-PCB contract implementation in this repository: no STEP/IDF import-export, no keepout-zone or component-height exchange with mechanical CAD, no 3D collision/courtyard checking. The only tangentially related code is src/rules/design/board-outline.ts, a 2D DRC rule that only checks Edge.Cuts outline closure \u2014 a prerequisite for any future mechanical contract, not an implementation of one. No tracked GitHub issue exists for this workstream. Per the audit brief, the correct minimal scope here is a minimal mechanical contract, not a full CAD kernel \u2014 that scoping decision and the actual implementation are still open."
    },
    {
      "id": "W14",
      "name": "Policy, Waivers & Approval Governance",
      "phase": 3,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W07"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [269],
      "evidence": {
        "code": [
          "src/core/policy.ts",
          "src/core/waivers.ts",
          "packages/cloud-core/src/policy-engine.ts",
          "packages/db/src/review-approval-store.ts",
          "apps/web/app/api/v1/reviews/[id]/approvals/route.ts",
          "apps/web/lib/api-auth.ts"
        ],
        "tests": [
          "tests/unit/core/policy.test.ts",
          "tests/unit/core/waivers.test.ts",
          "tests/unit/cloud-core/policy-engine.test.ts",
          "tests/unit/db/review-approval-store.test.ts",
          "tests/unit/web/review-approval-policy-gate.test.ts",
          "tests/unit/web/review-api-context.test.ts"
        ],
        "docs": ["docs/release/policy-engine.md", "docs/release/waivers.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/core/policy.test.ts tests/unit/core/waivers.test.ts tests/unit/cloud-core/policy-engine.test.ts tests/unit/db/review-approval-store.test.ts tests/unit/web/review-approval-policy-gate.test.ts tests/unit/web/review-api-context.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T14:14:27Z"
      },
      "remaining": "PARTIAL CLOSE: separation-of-duties enforcement is now implemented, but ONLY for the cloud review-approval system, not the CLI waiver system -- deliberately, after checking whether it would be real or checkbox theater. src/core/waivers.ts's WaiverConfig.owner/approvedBy are unauthenticated free-text strings typed into a YAML config file with no identity verification; an owner===approvedBy check there would be trivially bypassable (nothing stops typing two different strings for the same person) and would misrepresent itself as a security control. The cloud review-approval system is different: apps/web/app/api/v1/reviews/[id]/approvals/route.ts's approverId and reviews.created_by are both populated from auth.actorId (apps/web/lib/api-auth.ts), an authenticated GitHub session login or API-token id -- a real, if basic (not yet role-aware, per W17's RBAC gap), identity check. Implementation: ReviewApiContext (api-auth.ts) now carries createdBy (from reviews.created_by, defaulting to 'system' when absent); enforceApprovalPolicyGate (approvals/route.ts) blocks with 409 {code: 'self_approval_not_allowed'} when createdBy === approverId and status is 'approved'. Deliberately bypassable via the existing isBreakGlass short-circuit (same audited escape hatch as the readiness-blocker checks, not a second unaudited one) -- self-'changes_requested' is never blocked, since flagging issues on your own review is normal. 6 new/updated tests cover: same-author block, break-glass bypass, changes_requested exemption, and the createdBy field's plumbing through resolveReviewApiContext (including its 'system' fallback). Still remaining: no waiver carry-forward-by-fingerprint-equivalence workflow, no emergency-release/post-release-review workflow, and no CLI-side SoD equivalent (deliberately not built -- see above). Fail-closed expiry, org-hierarchy policy inheritance with dry-run impact preview, and digest-change approval invalidation remain real and tested. No dedicated doc page exists for the cloud approval-gate/break-glass system at all (docs/release/policy-engine.md and waivers.md cover the CLI side only) -- documenting that undocumented API surface is a separate, larger task, not attempted here."
    },
    {
      "id": "W15",
      "name": "GitHub App & PR Manufacturing Gate",
      "phase": 2,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W01", "W16", "W28"],
      "milestone": "v2.2 \u2014 GitHub Cloud GA",
      "issues": [149, 42, 154, 88],
      "evidence": {
        "code": [
          "apps/web/app/api/github/webhook/route.ts",
          "apps/web/lib/github-app-check-run-client.js",
          "apps/web/lib/webhook-rate-limit.ts",
          "packages/cloud-core/src/lifecycle-executor.ts",
          "packages/contracts/src/runner-protocol.ts",
          "scripts/target-repository-isolation.mjs",
          "src/core/cloud-findings.ts"
        ],
        "tests": [
          "tests/unit/web/github-app-check-run-client.test.ts",
          "tests/unit/web/webhook-rate-limit.test.ts",
          "tests/unit/scripts/target-repository-isolation.test.ts",
          "tests/unit/core/cloud-findings.test.ts",
          "tests/unit/cloud-core/lifecycle-executor.test.ts",
          "tests/unit/web/readiness-result-route.test.ts"
        ],
        "docs": ["docs/security/github-app-permissions.md", "docs/architecture/github-app-rfc.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/web/github-app-check-run-client.test.ts tests/unit/web/webhook-rate-limit.test.ts tests/unit/scripts/target-repository-isolation.test.ts tests/unit/core/cloud-findings.test.ts tests/unit/cloud-core/lifecycle-executor.test.ts tests/unit/web/readiness-result-route.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-03T01:20:00Z"
      },
      "remaining": "FULLY WIRED: the finding-to-annotation gap is closed end to end, correcting a prior investigation's wrong turn. That note pointed at apps/web/app/api/v1/runs/route.ts + the outbox worker as the check-run-complete path -- re-investigated this session and that route is a dead end for check runs (it only ingests findings for the review UI, never touches a check run). The REAL path is apps/web/app/api/v1/runs/result/route.ts's completeResultCheckRun, called synchronously from POST /api/v1/runs/result -- and CompleteGitHubCheckRunInput.annotations already existed and was already consumed all the way to the GitHub API by github-app-check-run-client.js; the only missing piece was that nothing ever computed and passed it. Root cause: packages/contracts's findingSchema (used by releaseRunResultSchema, the schema validating that route's body) carried no line/location fields at all, so annotations were never computable server-side regardless of wiring. Fixed by: (1) adding optional startLine/endLine/startColumn/endColumn to findingSchema (flat, matching CloudFinding's existing flat shape, not the CLI's nested Finding.location.region); (2) threading them through the two CLI-side producers that build this payload -- src/cli/runner-pipeline.ts's report-to-worker mapping and src/runner/worker.ts's worker-to-wire mapping -- both previously dropped location entirely; (3) also extending src/core/cloud-findings.ts's CloudFinding/mapFindingForCloud for the separate cloud-publish.ts producer, for consistency; (4) a NEW cloud-side findingToCheckRunAnnotation/findingsToCheckRunAnnotations in packages/cloud-core/src/lifecycle-executor.ts (deliberately not a reuse of src/core/cloud-findings.ts's CLI-side function of the same name -- apps/web never depends on src/core, confirmed by repo-wide grep, so this works from ReleaseRunFinding's flat fields and the error/high/medium/low/info severity vocabulary instead); (5) wiring findingsToCheckRunAnnotations(input.result.findings) into completeResultCheckRun's completeCheckRun call. No DB migration needed -- this path never touches Postgres, it's a synchronous request-scoped computation. Still also missing: no explicit re-run command/API found. HMAC verification, delivery idempotency, fail-closed safeMode, OIDC result binding, and two-installation isolation evidence remain real and tested."
    },
    {
      "id": "W16",
      "name": "Cloud Control Plane Reliability",
      "phase": 1,
      "priority": "P0",
      "status": "implemented",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Cloud Control Plane Reliability \u2014 GitHub GA Prerequisite",
      "issues": [190, 222],
      "evidence": {
        "code": [
          "packages/db",
          "scripts/control-plane-load.mjs",
          "scripts/control-plane-restore-drill.mjs",
          "scripts/control-plane-production-soak.mjs"
        ],
        "tests": [
          "tests/unit/scripts/control-plane-load.test.ts",
          "tests/integration/control-plane-load.test.ts",
          "tests/unit/scripts/control-plane-restore-drill.test.ts",
          "tests/unit/scripts/control-plane-production-soak.test.ts",
          "tests/integration/postgres-backup-restore.test.ts"
        ],
        "docs": [
          "docs/operations/control-plane-load-validation.md",
          "docs/operations/control-plane-restore-drill.md",
          "docs/deployment/self-hosted.md"
        ],
        "deployed": [
          "https://github.com/oaslananka/boardreadyops/issues/222#issuecomment-5375386057",
          "https://github.com/oaslananka/boardreadyops/issues/222#issuecomment-5468021951",
          "https://github.com/oaslananka/boardreadyops/milestone/11"
        ],
        "commits": [
          "01c42c389078b996a17a30a3688e5538b457291e",
          "75c38ea1546c2219af6c0f47dac5bd99450e41ed",
          "dab4b6e3199cb361be5bc93f8d3bbbb388128427",
          "9941a1af75e3123d358c2c82e479d0881960419e",
          "28d8ac5b8f60b78cabfd19e9cd88d1e56fc05c29",
          "f357592ed52c90cfc66d8dc41eeec79a756a830f",
          "bc595d8a0702331f0c654a39f0b1db8cbe92b297",
          "3818d8f969fdbfe567da4e04f0939c31a2f9239b",
          "34e7fe99c5f0e4d8516ef5b674480e88e1182aeb",
          "0460c0b7095fee74aa701a2cb158baa9d6de8b78"
        ],
        "pullRequests": ["#291", "#293", "#300", "#302", "#303", "#304", "#305", "#318", "#645"]
      },
      "verification": {
        "command": "BOARDREADYOPS_LOAD_CONFIRMATION=isolated-disposable-database BOARDREADYOPS_LOAD_PROFILE=<representative|soak-recovery|database-interruption|worker-process-interruption|worker-fleet-interruption|github-api-interruption> corepack pnpm run cloud:load:verify",
        "result": "pass",
        "checkedAt": "2026-09-02T23:06:42Z"
      }
    },
    {
      "id": "W17",
      "name": "Authentication, Tenant Isolation, RBAC & API Tokens",
      "phase": 2,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W16", "W28"],
      "milestone": "v2.2 \u2014 GitHub Cloud GA",
      "issues": [154, 88],
      "evidence": {
        "code": [
          "apps/web/lib/api-auth.ts",
          "packages/db/src/api-token-store.ts",
          "apps/web/lib/control-plane-operator-auth.ts",
          "apps/web/lib/operator-rate-limit.ts",
          "apps/web/lib/user-session.ts"
        ],
        "tests": [
          "tests/unit/db/api-token-store.test.ts",
          "tests/unit/web/api-auth-repository-scope.test.ts",
          "tests/unit/web/viewer-authorization.test.ts",
          "tests/unit/web/auth-rate-limit.test.ts",
          "tests/unit/web/operator-rate-limit.test.ts",
          "tests/unit/web/control-plane-operator-auth.test.ts"
        ],
        "docs": [
          "docs/security/audit-logs.md",
          "docs/api-tokens.md",
          "docs/operations/control-plane-reconciliation.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/db/api-token-store.test.ts tests/unit/web/api-auth-repository-scope.test.ts tests/unit/web/viewer-authorization.test.ts tests/unit/web/auth-rate-limit.test.ts tests/unit/web/operator-rate-limit.test.ts tests/unit/web/control-plane-operator-auth.test.ts tests/unit/web/control-plane-audit-routes.test.ts tests/unit/web/control-plane-dead-letter-routes.test.ts tests/unit/web/control-plane-runner-fleet-routes.test.ts tests/unit/web/repository-setup-routes.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-04T01:21:40Z"
      },
      "remaining": "FURTHER PARTIAL CLOSE: auth-attempt rate limiting is now implemented for both the bearer-token path and the operator static-token path, closing two of the three previously-named gaps. apps/web/lib/auth-rate-limit.ts (bearer-token path) and apps/web/lib/operator-rate-limit.ts (new, same fixed-window in-process counter pattern, its own Map and env var so the two token classes don't share a rate budget) are both in-process fixed-window counters, consistent with webhook-rate-limit.ts's precedent -- no Redis exists in this codebase, confirmed by grep. apps/web/lib/control-plane-operator-auth.ts's authenticateControlPlaneOperator now checks operator-rate-limit.ts before the timing-safe token comparison runs: only FAILED comparisons (including malformed-token-shape rejections) count against the limit (20/minute per client by default, BOARDREADYOPS_OPERATOR_RATE_LIMIT_PER_MINUTE-configurable), keyed by the first hop of X-Forwarded-For, matching the bearer-token limiter's convention; a client already over the limit gets a new 'rate_limited' status (\u2192 429) before the comparison ever runs, and a request bearing the correct token is never counted, so legitimate high-frequency internal ops use isn't penalized. All 4 operator route call sites (repository-setup-routes.ts, control-plane-runner-fleet-routes.ts, control-plane-dead-letter-routes.ts, control-plane-audit-routes.ts) updated to handle the new status and return 429 with a retry-after header. Documented in docs/operations/control-plane-reconciliation.md's Security boundary section, parallel to the existing bearer-token note in docs/api-tokens.md. Tests: operator-rate-limit.test.ts (module-level, mirrors auth-rate-limit.test.ts) plus new integration tests in control-plane-operator-auth.test.ts covering many successive valid-token requests never counting against the limit, repeated invalid attempts tripping 429, and the correct token still being rejected once limited (proving the real comparison is skipped). Still genuinely missing (unchanged, explicitly out of scope for this pass): no granular RBAC role model exists \u2014 session auth grants a hardcoded full scope set to every authenticated user (apps/web/lib/api-auth.ts's session branch returns all four scopes unconditionally); no session revocation/device-management UI or store."
    },
    {
      "id": "W18",
      "name": "Artifact Storage, Access, Retention & Privacy",
      "phase": 2,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W16", "W17"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [44],
      "evidence": {
        "code": [
          "packages/cloud-core/src/storage.ts",
          "apps/web/lib/runner-artifact-routes.ts",
          "packages/db/src/runner-artifact-store.ts",
          "apps/web/lib/retention-maintenance-worker.ts"
        ],
        "tests": [
          "tests/integration/artifact-deletion-store-postgres.test.ts",
          "tests/unit/web/artifact-download-route.test.ts",
          "tests/unit/web/retention-maintenance-worker.test.ts"
        ],
        "docs": ["docs/security/data-lifecycle.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/integration/artifact-deletion-store-postgres.test.ts tests/unit/web/artifact-download-route.test.ts tests/unit/web/retention-maintenance-worker.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-03T00:15:20Z"
      },
      "remaining": "Verification confirmed real, not just asserted: this workstream's own test command (including a Postgres-integration test) had never actually been run in this environment (result was not_run). Ran it against a real, isolated disposable PostgreSQL instance -- 3 files, 20 tests, all pass. Only the local-filesystem storage driver is wired (S3/GCS/Azure Blob return HTTP 501, per the driver's own docs); no malware/archive-bomb scanning; region/residency routing (kms-adapter.ts getTenantDataRegion) is an unused stub; age-based retention purge is previewed but not activated, matching open issue #44."
    },
    {
      "id": "W19",
      "name": "Billing, Entitlements & Metering",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W17", "W18"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [],
      "evidence": {
        "code": [
          "packages/cloud-core/src/entitlements.ts",
          "packages/cloud-core/src/stripe-service.ts",
          "packages/db/src/billing-store.ts",
          "packages/db/migrations/0060_stripe_subscription_event_ordering.sql",
          "apps/web/app/api/v1/billing/webhook/route.ts",
          "apps/web/app/api/v1/billing/checkout/route.ts",
          "apps/web/app/api/v1/billing/portal/route.ts",
          "apps/web/lib/marketplace-free-billing.ts",
          "apps/web/lib/billing-mode.ts",
          "apps/web/lib/stripe-billing-client.ts",
          "apps/web/app/api/v1/external-review-links/route.ts"
        ],
        "tests": [
          "tests/unit/cloud-core/billing-transitions.test.ts",
          "tests/unit/cloud-core/entitlements.test.ts",
          "tests/unit/cloud-core/stripe-service.test.ts",
          "tests/unit/web/billing-routes.test.ts",
          "tests/unit/web/billing-webhook-stripe-projection.test.ts",
          "tests/unit/web/billing-mode.test.ts",
          "tests/unit/web/stripe-billing-client.test.ts",
          "tests/unit/web/billing-checkout-route.test.ts",
          "tests/unit/web/billing-portal-route.test.ts",
          "tests/unit/web/marketplace-free-billing-routes.test.ts",
          "tests/unit/db/billing-store-stripe.test.ts",
          "tests/unit/db/marketplace-billing-atomic.test.ts",
          "tests/unit/web/external-review-links-plan-gate.test.ts",
          "tests/integration/external-review-links-postgres.test.ts"
        ],
        "docs": [
          "docs/architecture/adr/0014-seat-based-entitlement-tier-rename.md",
          "docs/gtm/pricing-and-packaging.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/cloud-core/billing-transitions.test.ts tests/unit/cloud-core/entitlements.test.ts tests/unit/cloud-core/stripe-service.test.ts tests/unit/web/billing-routes.test.ts tests/unit/web/billing-webhook-stripe-projection.test.ts tests/unit/web/billing-mode.test.ts tests/unit/web/stripe-billing-client.test.ts tests/unit/web/billing-checkout-route.test.ts tests/unit/web/billing-portal-route.test.ts tests/unit/web/marketplace-free-billing-routes.test.ts tests/unit/db/billing-store-stripe.test.ts tests/unit/db/marketplace-billing-atomic.test.ts tests/unit/web/external-review-links-plan-gate.test.ts && BOARDREADYOPS_POSTGRES_TESTS=true DATABASE_URL=<disposable> corepack pnpm vitest run tests/integration/external-review-links-postgres.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-04T23:29:39Z"
      },
      "remaining": "Subscription/customer/price\u2192entitlement projection and trial/grace-period downgrade logic are implemented and unit-tested (unchanged from the prior pass: linkStripeCustomer, applyStripeSubscriptionEvent guarded via last_event_created_at, clearGraceOnPaymentSuccess). /api/v1/billing/checkout and /portal now create real Stripe Checkout/Billing Portal sessions (apps/web/lib/stripe-billing-client.ts, official stripe SDK) instead of unconditionally returning HTTP 410. A new BILLING_MODE environment switch (apps/web/lib/billing-mode.ts) gates this \u2014 it defaults to 'marketplace_free', reproducing today's 410 behavior exactly, so production is unaffected until an operator deliberately sets BILLING_MODE=stripe or 'both' and configures STRIPE_SECRET_KEY. Once flipped, checkout.session.completed can fire for the first time, activating the previously-dormant projection code. Tenant identity for the Stripe path reuses the pre-existing convention (viewer.session.login, matching BillingStore.forecastContributors's usage on the read-only Marketplace billing page) rather than inventing a new one; a forward priceIdForTier helper was added to stripe-service.ts as the missing inverse of the pre-existing resolveTierFromPriceId/resolveIntervalFromPriceId. Both routes are built with injected-dependency handlers (handleCheckoutRequest/handlePortalRequest) so unit tests exercise real request/response logic without mocking the 'stripe' package itself. Newly closed this pass: the pre-existing handoffLinksEnabled(tier) entitlement (added for board supply-watch handoff links) was defined but never actually checked anywhere -- POST /api/v1/external-review-links let any authenticated caller create unlimited external (CM/fab) review links on every plan tier, including free. Now gated: the route resolves the repository's installation plan_tier and returns 403 with an upgrade message when the tier doesn't include handoff links. Verified against a real disposable Postgres instance (migrations applied, BOARDREADYOPS_POSTGRES_TESTS=true), not just mocked. What is honestly still open: (1) Stripe checkout/portal test coverage is unit-level only (mocked DB, injected fake Stripe client); no real Stripe test-mode account has exercised those routes end-to-end. (2) A tier change does not itself invoke packages/db/src/entitlement-store.ts's applyWatchAllowance \u2014 billing_customers.tenant_id has no established mapping back to installations.id (a bare, unconstrained text column; the new routes populate it with the GitHub login), so this is a real, undesigned access-control decision rather than a one-line call, and mirrors the pre-existing GitHub Marketplace path's same gap. (3) The B3 plan's other proposed gates (cross-run finding history, shared org policy, waiver approval workflow) have no existing feature surface to gate yet -- handoffLinksEnabled was the one entitlement that already existed, already had a real feature, and simply wasn't wired in."
    },
    {
      "id": "W20",
      "name": "Release Command Center & Cloud UX",
      "phase": 3,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W15", "W17", "W18"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [25],
      "evidence": {
        "code": [
          "apps/web/lib/run-verdict.ts",
          "apps/web/components/review/overview-tab.tsx",
          "apps/web/components/run-investigation.tsx",
          "apps/web/lib/run-dashboard.ts",
          "src/core/rule-registry.ts",
          "src/report/review-comment.ts",
          "packages/db/migrations/0062_finding_category.sql",
          "apps/web/app/page.tsx",
          "apps/web/app/setup/page.tsx",
          "apps/web/app/dashboard/page.tsx",
          "apps/web/app/globals.css"
        ],
        "tests": [
          "tests/e2e/qa-audit.spec.ts",
          "tests/e2e/visual.spec.ts",
          "tests/unit/web/run-investigation-accessibility.test.ts",
          "tests/unit/web/review-canvas.test.ts",
          "tests/unit/core/rule-registry-category-breakdown.test.ts",
          "tests/unit/core/pipeline-category-breakdown.test.ts",
          "tests/unit/report/review-comment.test.ts",
          "tests/unit/web/run-dashboard.test.ts",
          "tests/unit/web/home-page.test.ts",
          "tests/unit/web/repository-setup-page.test.ts",
          "tests/unit/web/dashboard-page-contract.test.ts"
        ],
        "docs": [],
        "deployed": [],
        "commits": ["8a2559e", "0bbe002", "f444723", "a52f5e7", "b088ac8", "58f760a"],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/web/run-investigation-accessibility.test.ts tests/unit/web/review-canvas.test.ts tests/unit/web/run-dashboard.test.ts tests/unit/web/home-page.test.ts tests/unit/web/repository-setup-page.test.ts tests/unit/web/dashboard-page-contract.test.ts && corepack pnpm exec playwright test tests/e2e/qa-audit.spec.ts",
        "result": "pass",
        "checkedAt": "2026-09-05T02:37:00Z"
      },
      "remaining": "Running the full stated command surfaced and fixed two real bugs, not just confirmed existing behavior. (1) /reviews/rev_edge_ble_09 -- a deliberate known-bug regression id (qa/audit/routes.ts's brokenDemoReviewId, asserted to 404 by tests/e2e/regression-audit-findings.spec.ts) -- was 500ing instead: loadServerReview only demo-fixture-short-circuited rev_gateway_* ids, so any other id fell through to resolveCloudPersistenceConfiguration(), which throws uncaught when DATABASE_URL is unset. Fixed in apps/web/lib/server-review-loader.ts by catching the missing-database-url case and returning null (-> notFound()) instead of letting it propagate as an unhandled 500. (2) Even after that fix, the qa-audit crawler's checkInternalLinks flagged the (now-correct) 404 as a P0 broken-internal-link finding, because it never excluded the known-bug id; added that exclusion in tests/e2e/qa-audit.spec.ts. Both confirmed via the repo's real nightly CI history (run 33605754839, 2026-09-02): 'ci / qa-audit gate' and 'qa-nightly / full-audit' were already failing on main with this exact P0 finding, so this was a genuine pre-existing defect, not a local artifact. verification.command above deliberately excludes tests/e2e/visual.spec.ts: that suite fails independently and unrelated to this fix -- no Linux screenshot baselines have ever been committed (only *-win32.png), so 'qa-nightly / visual-regression' has been failing on main from its first run with 'snapshot doesn't exist' for all 5 routes, on every browser. That is a separate CI/tooling gap (baseline generation), out of scope here. Since then: per-domain score cards now render in both the local CLI/Action PR comment ('### By domain' table, src/report/review-comment.ts) and the web run dashboard (CategoryBreakdownPanel in apps/web/components/run-investigation.tsx, fed by a new aggregate query in apps/web/lib/run-dashboard.ts's lookupRunDashboard), both backed by the same real per-domain finding breakdown (src/core/rule-registry.ts's categorizeFindings, and the findings.category column persisted via migration 0062) rather than two divergent classifications. Still open: no 'Open in KiCad' deep link (only GitHub Actions deep links)."
    },
    {
      "id": "W21",
      "name": "PCB/Schematic/Gerber/3D Viewers & Visual Diff",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W15", "W18"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [26],
      "evidence": {
        "code": [
          "packages/contracts/src/snapshots.ts",
          "src/kicad/snapshots.ts",
          "apps/web/components/review/review-canvas.tsx"
        ],
        "tests": [
          "tests/unit/web/review-canvas.test.ts",
          "tests/unit/kicad/snapshots.test.ts",
          "tests/e2e/visual.spec.ts"
        ],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/web/review-canvas.test.ts tests/unit/kicad/snapshots.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T23:20:00Z"
      },
      "remaining": "verification.command above deliberately excludes tests/e2e/visual.spec.ts (kept in evidence.tests, since it does exercise this workstream's surfaces): that suite fails for a reason unrelated to this workstream's own correctness -- no Linux screenshot baselines were ever committed (only *-win32.png), so qa-nightly/visual-regression has never passed on any browser (confirmed via real nightly CI run 33605754839). Tracked as its own out-of-scope follow-up, not fixed here. No true 3D viewer implementation exists (3d_render is a schema enum value only, no renderer); no dedicated Gerber-layer-stack/drill-overlay parser (the view is generated from parsed .kicad_pcb data, not exported Gerbers); no large-board performance/LOD test; no dedicated documentation page."
    },
    {
      "id": "W22",
      "name": "Enterprise Trust: SSO, SCIM, Customer-Hosted Agent",
      "phase": 5,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W17", "W18", "W20"],
      "milestone": "v2.6 \u2014 Enterprise Trust & Customer-Hosted Execution",
      "issues": [41, 45],
      "evidence": {
        "code": [
          "packages/db/src/runner-registration-enrollment-store.ts",
          "packages/db/src/runner-lease-store.ts",
          "apps/web/lib/runner-lease-routes.ts",
          "packages/cloud-core/src/enterprise/saml-adapter.ts"
        ],
        "tests": [
          "tests/integration/runner-enrollment-admin-psql.test.ts",
          "tests/unit/web/runner-lease-routes.test.ts"
        ],
        "docs": [
          "docs/deployment/self-hosted-runner.md",
          "docs/architecture/adr/0015-enterprise-governance-sso-scim.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "BOARDREADYOPS_PSQL_TEST=1 corepack pnpm vitest run tests/integration/runner-enrollment-admin-psql.test.ts tests/unit/web/runner-lease-routes.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T21:51:35Z"
      },
      "remaining": "Verification confirmed real, not just asserted: runner-enrollment-admin-psql.test.ts is gated behind BOARDREADYOPS_PSQL_TEST=1 (not the usual BOARDREADYOPS_POSTGRES_TESTS flag used elsewhere in this repo) because the code under test (packages/db/src/runner-enrollment-admin.ts) deliberately hardens against PATH-based binary resolution -- it spawns /usr/bin/psql by an absolute path with PATH restricted to /usr/bin:/bin, rather than trusting an untrusted PATH the way most of this repo's git/kicad-cli invocations now do (see the resolveGitExecutable() pattern). That means the test needs a real system psql client at that exact path, which this environment didn't have; installed the standard postgresql-client system package to get it, then ran the test against a real, isolated disposable PostgreSQL instance -- 2 files, 16 tests, all pass. SSO (OIDC/SAML), SCIM provisioning, customer-managed keys, and SIEM export are all in-memory stub adapters with no wired API routes, honestly labeled 'Proposed / Blueprint (planned upon enterprise customer commitment)' in ADR-0015. Only the customer-hosted execution agent (enrollment/lease/heartbeat/revocation) is production-hardened."
    },
    {
      "id": "W23",
      "name": "Integrations: GitLab, Azure DevOps, Jira, Slack/Teams",
      "phase": 5,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W17", "W20"],
      "milestone": "v2.6 \u2014 Enterprise Trust & Customer-Hosted Execution",
      "issues": [],
      "evidence": {
        "code": ["src/notifiers/dispatch.ts", "src/notifiers/webhook.ts"],
        "tests": ["tests/unit/notifiers/notifiers.test.ts"],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/notifiers/notifiers.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "Only Slack/Teams webhook notifications exist. GitLab, Azure DevOps, Jira, PLM, and ERP adapters, an integration-SDK capability manifest, encrypted credential storage/rotation, per-integration audit trail, and retry/idempotency semantics are all absent \u2014 repo-wide search found zero matches for gitlab/azure-devops/jira in code."
    },
    {
      "id": "W24",
      "name": "Manufacturer / CM Handoff Portal, RFQ & Questions",
      "phase": 6,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W20", "W22"],
      "milestone": "Backlog \u2014 Manufacturer Collaboration & Production Loop",
      "issues": [],
      "evidence": {
        "code": ["src/release/handoff.ts"],
        "tests": ["tests/unit/release/handoff.test.ts"],
        "docs": ["docs/release/manufacturer-handoff.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/release/handoff.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "No external manufacturer/CM web portal exists \u2014 no time-bound access token, CM accept/issue-found/clarification state, question threads, or RFQ/vendor-quote metadata. boardreadyops release handoff is a real local CLI command producing a signed vendor-profile zip, not a collaboration portal."
    },
    {
      "id": "W25",
      "name": "Production Runs, Traceability, Yield & Outcomes",
      "phase": 6,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W20", "W22", "W24"],
      "milestone": "Backlog \u2014 Manufacturer Collaboration & Production Loop",
      "issues": [450, 451],
      "evidence": {
        "code": [],
        "tests": [],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "repo-wide audit: no production-run/yield/traceability model found in packages/db/prisma/schema.prisma, src/, apps/, or packages/ (2026-09-01)",
        "result": "not_run",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "Entirely unimplemented: no production-run entity, no built/pass/fail/rework/scrap outcome counts, no failure taxonomy, no yield calculation, no CM-vs-internal access split. ReleaseRun/ReleaseRunAttempt in the Prisma schema are CI/CD check-run models, not physical production runs. Matches open issues #450 and #451."
    },
    {
      "id": "W26",
      "name": "AI Reviewer & Agent Remediation Layer",
      "phase": 7,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W20", "W22"],
      "milestone": "v2.7 \u2014 Marketplace, Ecosystem & AI Reviewer",
      "issues": [52],
      "evidence": {
        "code": [
          "packages/cloud-core/src/assist/ai-assistant.ts",
          "packages/cloud-core/src/assist/dfm-adapter.ts",
          "src/cli/commands/plan.ts"
        ],
        "tests": ["tests/unit/assist/ai-assistant.test.ts", "tests/unit/cli/plan.test.ts"],
        "docs": ["docs/agent-planning.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/assist/ai-assistant.test.ts tests/unit/cli/plan.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "No real model integration exists yet \u2014 NoOpAiAssistant is a hardcoded deterministic stub, off by default. No explain/prioritize/propose-fix action taxonomy, prompt-injection defense, tool allowlist/sandbox, agent audit log, or human-approval workflow for design-intent edits, beyond the single AI_ASSIST_ENABLED kill switch. boardreadyops plan itself (safeAutoFixPossible, commandsToVerify) is real. Matches open issue #52."
    },
    {
      "id": "W27",
      "name": "MCP / Agent API / Plugin SDK",
      "phase": 7,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W06", "W20", "W22"],
      "milestone": "v2.7 \u2014 Marketplace, Ecosystem & AI Reviewer",
      "issues": [],
      "evidence": {
        "code": [
          "packages/plugin-sdk/src/index.ts",
          "src/core/plugin-loader.ts",
          "src/core/plugin-permissions.ts",
          "packages/mcp-server/src/cli-runner.ts",
          "packages/mcp-server/src/tools.ts",
          "packages/mcp-server/src/server.ts",
          "packages/mcp-server/bin/boardreadyops-mcp.js"
        ],
        "tests": [
          "tests/unit/core/plugin-loader.test.ts",
          "tests/integration/plugin-sdk-contract.test.ts",
          "tests/unit/mcp-server/tools.test.ts",
          "tests/unit/mcp-server/server.test.ts"
        ],
        "docs": [
          "docs/plugin-sdk.md",
          "docs/architecture/adr/0009-plugin-sandboxing.md",
          "docs/integrations/boardreadyops-mcp.md",
          "packages/mcp-server/README.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/core/plugin-loader.test.ts tests/integration/plugin-sdk-contract.test.ts tests/unit/mcp-server/tools.test.ts tests/unit/mcp-server/server.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-05T00:17:56Z"
      },
      "remaining": "A real MCP server now exists: packages/mcp-server (@boardreadyops/mcp-server, using the official @modelcontextprotocol/sdk) implements boardreadyops_check, boardreadyops_plan, and boardreadyops_verify_bundle. Each tool spawns the real boardreadyops CLI binary as a child process (resolved via the installed boardreadyops package's own bin field, not a monorepo-relative path) and returns its parsed JSON output -- no reimplementation of check/plan/verify logic, so results are guaranteed identical to running the CLI by hand. Verified end-to-end, not just against fakes: a real smoke test resolved the CLI entrypoint, spawned it, and ran a real check against tests/fixtures/projects/safe-basic. Still open: (1) boardreadyops_explain and boardreadyops_vendor_score from docs/integrations/boardreadyops-mcp.md are not implemented -- the doc's findingId param doesn't match reality (the CLI only explains a rule id, not a finding fingerprint), and vendor scoring (src/core/readiness.ts::computeReadiness) only exists inside a full pipeline run today, not as a standalone (path, profile) call. (2) The two mutating tools (boardreadyops_generate, boardreadyops_release_prepare) are not implemented -- the documented 'explicit capability elevation' safety mechanism needs its own design rather than a default-on switch added alongside the read-only tools. The Plugin SDK half is unchanged and remains genuinely strong (real capability manifest, pre-import permission checks, honest ADR-0009 rejecting a false node:vm sandbox claim)."
    },
    {
      "id": "W28",
      "name": "Security, Privacy, Threat Modeling & Trust Center",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [329],
      "evidence": {
        "code": ["src/core/logger.ts", "src/notifiers/webhook.ts", "src/notifiers/http.ts"],
        "tests": ["tests/integration/security-adversarial.test.ts", "tests/unit/notifiers/notifiers.test.ts"],
        "docs": [
          "SECURITY.md",
          "docs/security/threat-model.md",
          "docs/security/input-validation.md",
          "docs/security/data-lifecycle.md",
          "docs/security/assurance-case.md",
          "docs/security/release-integrity.md",
          "docs/security/pentest-checklist.md",
          "docs/architecture/adr/0009-plugin-sandboxing.md"
        ],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/integration/security-adversarial.test.ts tests/unit/notifiers/notifiers.test.ts && node scripts/docs-build.mjs && node scripts/toolchain.mjs run node scripts/check-docs-a11y.mjs",
        "result": "pass",
        "checkedAt": "2026-09-03T01:01:29Z"
      },
      "remaining": "The prior matrix entry (SECURITY.md only, verification never run) understated real coverage: tests/integration/security-adversarial.test.ts (11 passing cases) exercises cross-tenant tampering, Stripe webhook signature verification and replay rejection, stored-XSS escaping, path traversal in artifact keys, tenant-scoped DB query enforcement, evidence-ledger tamper detection, and incomplete-check-cannot-go-green; src/core/logger.ts performs secret/token redaction; ADR-0009 documents plugin sandboxing. SSRF: the only outbound fetch() call sites in src/ are operator/workflow-trusted (src/cli/commands/review.ts, src/action/cloud-publish.ts) and the webhook notifiers. The webhookEnv name-redirection characteristic was mitigated via a logger.warn() visibility signal rather than a breaking schema change (see PR history). CORRECTION: 'no dedicated trust-center evidence page' was wrong -- docs/security/assurance-case.md already is that page (a 4-claim assurance case with evidence and residual risk per claim), just stale since its only prior edit (2026-07-02, PR #6). Refreshed it and docs/security/threat-model.md and docs/security/release-integrity.md to reflect what now actually exists: the adversarial security test suite, the webhookEnv unrecognized-name warning, the signing-key trust store (rotation/revocation, `release verify --trust-store`), and same-machine reproducible-build verification -- and softened residual-risk language that had gone stale in the other direction (e.g. 'reproducible binary builds are not yet proven' when same-machine reproducibility now is). The GA pen-test checklist gap (threat-model.md follow-up item 6) is now closed: docs/security/pentest-checklist.md scopes an external/manual pen test against the real security surface (bearer-token/session auth in apps/web/lib/api-auth.ts and user-session.ts, API token scopes in packages/db/src/api-token-store.ts, repository-id tenant isolation, Stripe/GitHub webhook signature verification in packages/cloud-core, the signing-key trust store in src/release/signing.ts, and evidence-ledger tamper detection), explicitly marking which items tests/integration/security-adversarial.test.ts already covers versus what still needs a human/external tester, wired into mkdocs.yml nav and verified via `node scripts/docs-build.mjs` (strict) and `node scripts/toolchain.mjs run node scripts/check-docs-a11y.mjs` (236/236 pages passed). No deployment evidence (this is a repo, not a running service) and no dedicated commit/PR trail for the security posture itself \u2014 the docs/tests above were added incrementally across unrelated feature PRs, which is why implemented status is not claimed here."
    },
    {
      "id": "W29",
      "name": "Observability, SLOs & Operations",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Cloud Control Plane Reliability \u2014 GitHub GA Prerequisite",
      "issues": [190],
      "evidence": {
        "code": [
          "apps/web/lib/control-plane-slo.ts",
          "apps/web/lib/control-plane-dead-letter-routes.ts",
          "packages/db/src/control-plane-operations-store.ts",
          "packages/cloud-core/src/lifecycle.ts",
          "packages/db/src/transactional-lifecycle-store.ts",
          "packages/db/migrations/0058_release_run_delivery_id.sql",
          "apps/web/app/ops/dead-letters/page.tsx",
          "apps/web/app/ops/dead-letters/dead-letters-client.tsx",
          "apps/web/app/ops/dead-letters/dead-letters-panel.tsx",
          "apps/web/app/ops/dead-letters/dead-letter-view-model.ts"
        ],
        "tests": [
          "tests/unit/web/control-plane-slo.test.ts",
          "tests/unit/web/control-plane-dead-letter-routes.test.ts",
          "tests/unit/cloud-core/lifecycle.test.ts",
          "tests/unit/db/transactional-release-run-store.test.ts",
          "tests/unit/db/migrations.test.ts",
          "tests/integration/transactional-release-run-outbox-postgres.test.ts",
          "tests/unit/web/dead-letter-view-model.test.ts",
          "tests/unit/web/dead-letters-page.test.ts"
        ],
        "docs": ["docs/operations/control-plane-reconciliation.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/web/control-plane-slo.test.ts tests/unit/web/control-plane-dead-letter-routes.test.ts tests/unit/cloud-core/lifecycle.test.ts tests/unit/db/transactional-release-run-store.test.ts tests/unit/db/migrations.test.ts tests/unit/web/dead-letter-view-model.test.ts tests/unit/web/dead-letters-page.test.ts tests/unit/web/public-discovery-config.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-03T22:14:41Z"
      },
      "remaining": "PARTIAL CLOSE: 'no explicit correlation-id field threading requests/webhooks/jobs/runs' is now addressed for the webhook->release-run path, closing one of three named gaps -- and DB-only per an earlier explicit user decision this session (never in the aggregate webhook-intake telemetry stream, which has its own privacy-motivated test asserting it never contains delivery/tenant identifiers). Previously the GitHub delivery id (X-GitHub-Delivery) was captured at webhook-intake time (webhook_inbox.delivery_id, used only for dedup) but discarded before reaching release_runs -- no query could answer 'which webhook delivery produced this run'. Migration 0058 adds release_runs.delivery_id (nullable text, indexed) and redefines boardreadyops_enqueue_release_run_with_outbox (the same create-or-replace-per-migration pattern already used by 0017/0027/0032/0033) to accept and persist it. packages/cloud-core/src/lifecycle.ts's normalizeGitHubAppWebhook() sets deliveryId on the release_run.enqueue action directly from its own options.delivery parameter (already threaded end-to-end from the real X-GitHub-Delivery header via apps/web/app/api/github/webhook/route.ts) -- no new context-threading needed through the lifecycle planner. deliveryId is optional, not required, to avoid forcing every pre-existing test fixture across ~7 files to add it. Verified against a real, isolated disposable PostgreSQL instance (the same one used for W16/W30's load validation this session): migration 0058 applies cleanly on top of 0001-0057, and a new integration test proves round-trip persistence (a run enqueued with a delivery id has it in release_runs.delivery_id; one enqueued without has null). PARTIAL CLOSE 2: 'no visual admin dashboard UI for dead-letters (only operator API routes)' is now closed. apps/web/app/ops/dead-letters/page.tsx adds an operator-facing dashboard reusing the existing 'Technical Premium' design system verbatim (Panel/StatusBadge/EmptyState/Alert from apps/web/components/ui.tsx, the same table-scroll/repository-table conventions as the dashboard and setup pages) -- no new CSS tokens or components, so tests/unit/web/theme-contrast.test.ts needed no changes. It calls the real, already-shipped apps/web/lib/control-plane-dead-letter-routes.ts endpoints (GET .../dead-letters, POST .../dead-letters/{itemType}/{itemId}/replay) exactly as documented in docs/operations/control-plane-reconciliation.md: since that API is bearer-token authenticated (BOARDREADYOPS_OPERATOR_API_TOKEN via authenticateControlPlaneOperator, unrelated to the tenant viewer session) and the docs explicitly scope it to a private network/administrative proxy, the page has the operator paste the installation ID and operator token client-side (kept in React state only, never persisted) rather than auto-authenticating server-side, which would have let any tenant viewer read cross-tenant dead letters just by hitting the URL. The route is excluded from the sitemap/crawlers (apps/web/app/robots.ts, next.config.mjs X-Robots-Tag, both updated alongside their exact-match test in tests/unit/web/public-discovery-config.test.ts) and is not linked from the tenant-facing ProductNavigation, since it is an internal ops tool, not a tenant feature. Table columns reflect the real ControlPlaneDeadLetterItem fields only (item type/id, releaseRunId, installationId/repositoryFullName, reasonCode+errorClass, attemptCount, failedAt) -- the API has one failedAt timestamp and an attemptCount, not separate first-seen/last-attempt fields, so no second timestamp was fabricated. Replay is offered only when the API's own replaySafe flag is true; non-replay-safe rows show a disabled/blocked badge instead, matching the documented 'replay only records explicitly reported as safe' rule. Branching logic (reason formatting, timestamp display, replay-outcome copy, list/replay URL building) lives in a pure, dependency-free apps/web/app/ops/dead-letters/dead-letter-view-model.ts covered by tests/unit/web/dead-letter-view-model.test.ts; the four required UI states (idle/credentials-prompt, loading, error, and the populated table) plus the empty state (phrased 'No dead letters -- Nothing is stuck') live in a presentational, prop-driven apps/web/app/ops/dead-letters/dead-letters-panel.tsx covered by tests/unit/web/dead-letters-page.test.ts, which also asserts zero axe WCAG A/AA violations on both the connect form and the populated table via the same happy-dom+axe-core harness already used by tests/unit/web/product-app-accessibility.test.ts. Still remaining: no distributed tracing implementation exists (no OpenTelemetry dependency; the broader webhook\u2192job\u2192dispatch\u2192ingestion\u2192decision trace propagation this note originally meant is still unbuilt -- only the webhook\u2192release_run edge of that chain is now traceable). That is the only gap left open in this workstream's remaining note."
    },
    {
      "id": "W30",
      "name": "Performance, Scalability & Cost Controls",
      "phase": 1,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Cloud Control Plane Reliability \u2014 GitHub GA Prerequisite",
      "issues": [222],
      "evidence": {
        "code": [
          "scripts/control-plane-scale-envelope.mjs",
          "scripts/control-plane-load.mjs",
          "apps/web/lib/webhook-rate-limit.ts",
          "scripts/control-plane-run-listing-benchmark.mjs",
          ".github/workflows/control-plane-run-listing-benchmark.yml"
        ],
        "tests": [
          "tests/unit/scripts/control-plane-load.test.ts",
          "tests/integration/control-plane-load.test.ts",
          "tests/unit/web/webhook-rate-limit.test.ts",
          "tests/benchmark/pipeline.bench.ts",
          "tests/unit/scripts/control-plane-run-listing-benchmark.test.ts",
          "tests/integration/control-plane-run-listing-benchmark.test.ts"
        ],
        "docs": ["docs/architecture/transactional-outbox.md", "docs/operations/control-plane-load-validation.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "BOARDREADYOPS_LOAD_CONFIRMATION=isolated-disposable-database BOARDREADYOPS_RUN_LISTING_REPORT_PATH=control-plane-run-listing-benchmark-report.json corepack pnpm run cloud:run-listing-benchmark:verify",
        "result": "pass",
        "checkedAt": "2026-09-04T01:55:02Z"
      },
      "remaining": "PARTIAL CLOSE: run-list/query pagination now has a documented, executable keyset-pagination benchmark plus a manual isolated PostgreSQL 16 workflow. A fresh disposable PostgreSQL 16.15 canary on 2026-09-04, rerun after rebasing onto current main, passed with 20,000-run p95s of 49.417/46.47/46.808ms for page sizes 10/25/100 and depth-degradation ratios 0.99/0.97/0.78, with zero threshold signals. These are local reproducibility measurements, not production SLO evidence. Still remaining: no per-tenant quotas beyond existing rate limiting, no viewer payload/LOD sizing, and no explicit cost-attribution tags/counters."
    },
    {
      "id": "W31",
      "name": "Documentation, Onboarding, Golden Demo & DevEx",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W15", "W20"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [25, 26, 445, 446],
      "evidence": {
        "code": [
          "examples/golden-demo/expected-findings.json",
          "tests/fixtures/bad-board-zoo/README.md",
          "scripts/check-docs-a11y.mjs",
          "src/cli/commands/run.ts",
          "src/core/findings.ts"
        ],
        "tests": [
          "tests/unit/examples/golden-demo.test.ts",
          "tests/integration/fixtures.test.ts",
          "tests/unit/scripts/check-docs-a11y.test.ts"
        ],
        "docs": ["docs/golden-demo.md", "docs/quickstart.md", "docs/reference/exit-codes.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/examples/golden-demo.test.ts tests/integration/fixtures.test.ts tests/unit/scripts/check-docs-a11y.test.ts && node scripts/docs-build.mjs",
        "result": "pass",
        "checkedAt": "2026-09-03T02:55:00Z"
      },
      "remaining": "Both previously flagged gaps are now closed: tests/unit/examples/golden-demo.test.ts gained an end-to-end test that runs the actual documented two-command walkthrough ('boardreadyops run examples/golden-demo/broken' then '.../fixed') via the real CLI entrypoint (runCli) and asserts wall-clock duration stays under the documented '<2 minute' target (120s budget; actual runtime is tens of milliseconds, so this is deliberate CI slack over a hard stopwatch assert, matching the existing raw-threshold pattern in tests/integration/scale-envelope.test.ts). docs/reference/exit-codes.md is a new dedicated reference, cross-checked against src/cli/commands/run.ts, src/release/prepare.ts, src/cli/commands/runner.ts, and src/core/findings.ts, documenting every real CLI exit code (0-4) and the five finding severities, wired into mkdocs.yml's Reference nav and linked from docs/cli.md. This closes W31's specific golden-demo timing and error-code documentation gaps; it is not a full re-audit of the rest of this workstream's broader onboarding/DevEx scope."
    },
    {
      "id": "W32",
      "name": "Product Analytics & Privacy-Safe Adoption Metrics",
      "phase": 3,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W17", "W20"],
      "milestone": "v2.3 \u2014 Release Dashboard, Evidence & Artifact UX",
      "issues": [],
      "evidence": {
        "code": [
          "schemas/telemetry-event.schema.json",
          "apps/web/lib/webhook-intake-telemetry.ts",
          "packages/cloud-core/src/wdrr-metrics.ts",
          "apps/web/lib/wdrr-dashboard.ts",
          "apps/web/app/insights/page.tsx"
        ],
        "tests": ["tests/unit/cloud-core/wdrr-metrics.test.ts", "tests/unit/web/wdrr-dashboard.test.ts"],
        "docs": ["docs/gtm/product-metrics-and-telemetry.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/cloud-core/wdrr-metrics.test.ts tests/unit/web/wdrr-dashboard.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-04T23:35:29Z"
      },
      "remaining": "Closed this pass: /insights no longer calls computeWdrrWeekly([]) on a hardcoded empty array. apps/web/lib/wdrr-dashboard.ts::loadViewerWdrrWeekly queries real reviews across the viewer's installations (bounded to the last 90 days / 200 reviews) and evaluates each through the same computeReviewReadiness the review detail page's own readiness gate uses, rather than reimplementing blocker/approval logic and risking the exact policy-divergence bug review-readiness.ts documents. Still genuinely open: (1) schemas/telemetry-event.schema.json's CLI-side event taxonomy has no emitter anywhere in src/ and no schema-validation test. (2) wdrr-metrics.ts's cloud-side allowedProductEvents/sanitizeProductEventPayload are defined but nothing calls them \u2014 no product-event ingestion route or store exists. (3) webhook-intake-telemetry.ts is real and already emits structured operational logs on webhook intake, but it is narrow (accept/duplicate/enqueue-failed counters), not the broader activation-funnel instrumentation this workstream's scope implies."
    },
    {
      "id": "W33",
      "name": "Compliance & Audit Export",
      "phase": 5,
      "priority": "P1",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W17", "W18", "W22"],
      "milestone": "v2.6 \u2014 Enterprise Trust & Customer-Hosted Execution",
      "issues": [],
      "evidence": {
        "code": [
          "packages/db/src/audit-log-store.ts",
          "apps/web/lib/control-plane-audit-routes.ts",
          "packages/db/src/data-lifecycle-store.ts",
          "src/report/hbom.ts"
        ],
        "tests": [
          "tests/unit/web/control-plane-audit-routes.test.ts",
          "tests/unit/db/audit-log-store.test.ts",
          "tests/unit/report/hbom.test.ts"
        ],
        "docs": ["docs/security/audit-logs.md", "docs/security/data-lifecycle.md", "docs/sbom.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/web/control-plane-audit-routes.test.ts tests/unit/db/audit-log-store.test.ts tests/unit/report/hbom.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T23:51:06Z"
      },
      "remaining": "The audit export endpoint now supports format=csv and format=jsonl alongside the default JSON (hand-rolled CSV quoting, no new dependency), and every export carries an X-Content-Digest: sha256:<hex> response header computed over the returned items via @boardreadyops/cloud-core's computeCanonicalHash (the same canonical-JSON-then-SHA-256 pattern src/release/generate.ts uses for recipe.hash), so a client can detect tampering or corruption in transit/at rest; a next-page cursor is also exposed via an X-Next-Cursor header for the non-JSON formats. Still missing: PDF export, and any watermark beyond this plain content digest (e.g. an embedded/cryptographically signed watermark) \u2014 both remain out of scope for this change. Authorization enforcement, legal-hold blocking of erasure/cancellation, and CycloneDX 1.7 HBOM generation remain real, tested, and schema-validated."
    },
    {
      "id": "W34",
      "name": "Quality Engineering: Fuzz, Mutation, Bad-Board Zoo",
      "phase": 1,
      "priority": "P0",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W00"],
      "milestone": "Repository Maintenance & Release Health",
      "issues": [329],
      "evidence": {
        "code": [
          "stryker.config.mjs",
          "scripts/check-mutation-thresholds.mjs",
          "src/core/config.ts",
          "tests/property/config-report.property.test.ts",
          "tests/property/findings.property.test.ts",
          "tests/property/delimited.property.test.ts",
          "tests/property/sexpr.property.test.ts",
          "tests/property/yaml-config.property.test.ts",
          "tests/property/waivers.property.test.ts",
          "src/core/waivers.ts"
        ],
        "tests": ["tests/integration/cross-platform-paths.test.ts", "tests/e2e/regression-audit-findings.spec.ts"],
        "docs": ["docs/development/testing-policy.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/property/config-report.property.test.ts tests/property/findings.property.test.ts tests/property/delimited.property.test.ts tests/property/sexpr.property.test.ts tests/property/yaml-config.property.test.ts tests/property/waivers.property.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-02T08:40:25Z"
      },
      "remaining": "CORRECTION: the prior note claimed only two fast-check property-test files existed and that BOM/CSV/YAML/JSON/KiCad-text parser fuzzing was entirely missing. That undercounted what already existed: tests/property/delimited.property.test.ts already fuzzes the CSV/BOM delimited-row parser (src/util/delimited.ts) and tests/property/sexpr.property.test.ts already fuzzes the KiCad S-expression parser (src/kicad/sexpr.ts), including hostile-input DoS-timing cases (nesting depth, pathological string length); tests/property/config-report.property.test.ts already fuzzes JSON via fc.jsonValue(). YAML was the one genuinely missing parser, closed by tests/property/yaml-config.property.test.ts (including a billion-laughs anchor/alias attack, which js-yaml's built-in guard rejects). The waiver evaluator (src/core/waivers.ts's applyWaivers -- not a stored state machine, but a pure function that classifies each waiver as active/expired fresh on every call from a `now` timestamp) was the other genuinely missing property-test target: tests/unit/core/waivers.test.ts is example-based only. Added tests/property/waivers.property.test.ts covering: determinism/purity for the same inputs; every waiver partitions into exactly one of active/expired; finding count and order are preserved (only a `suppressed` flag is ever added); a finding whose only match is an expired waiver is never suppressed; a waiver with no `expires` is active for any evaluation date; once a waiver is expired at some date it stays expired at every later date (the one-directional 'no re-approval' property -- there is no approve/reject transition in this codebase, only date-driven active/expired classification); and fingerprint-scoped matching is case-insensitive on the configured fingerprint. Genuinely still missing: a licensing-aware record/replay network cassette system (no cassette/nock/polly-style tooling found in the repo). Mutation testing retains real per-module thresholds enforced in CI and the flaky-test policy explicitly rejects silent quarantine."
    },
    {
      "id": "W35",
      "name": "Marketplace, Ecosystem & Distribution",
      "phase": 7,
      "priority": "P2",
      "status": "partial",
      "owner": "maintainers",
      "dependencies": ["W15", "W22"],
      "milestone": "v2.7 \u2014 Marketplace, Ecosystem & AI Reviewer",
      "issues": [88],
      "evidence": {
        "code": [
          "scripts/check-marketplace-listing.mjs",
          "scripts/verify-release-channels.mjs",
          "Formula/boardreadyops.rb"
        ],
        "tests": [
          "tests/unit/marketplace-listing.test.ts",
          "tests/unit/scripts/verify-release-channels.test.ts",
          "tests/unit/web/marketplace-webhook-route.test.ts"
        ],
        "docs": ["docs/github-marketplace.md", "docs/support-matrix.md"],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "corepack pnpm vitest run tests/unit/marketplace-listing.test.ts tests/unit/scripts/verify-release-channels.test.ts tests/unit/web/marketplace-webhook-route.test.ts",
        "result": "pass",
        "checkedAt": "2026-09-01T17:57:55Z"
      },
      "remaining": "verify-release-channels.mjs genuinely cross-checks npm/GitHub-Release/Homebrew/container digest identity in CI, but the public GitHub Marketplace listing itself remains gated on open issue #88 (least-privilege GitHub App permissions) before it can be considered a fully shipped, unblocked capability."
    },
    {
      "id": "W36",
      "name": "Manufacturing Feedback Intelligence & Predictive Risk",
      "phase": 8,
      "priority": "P3",
      "status": "deferred",
      "owner": "maintainers",
      "dependencies": ["W25"],
      "milestone": "Deferred \u2014 outcome-data trigger",
      "issues": [450, 451],
      "evidence": {
        "code": [],
        "tests": [],
        "docs": [],
        "deployed": [],
        "commits": [],
        "pullRequests": []
      },
      "verification": {
        "command": "not run",
        "result": "not_run",
        "checkedAt": "2026-09-01T12:21:04Z"
      },
      "deferUntil": "Production outcome dataset reaches a documented statistically useful threshold."
    }
  ]
}
