Repository navigation
Fix commercial-readiness false gap exhaustion from partial capability evidence #128
Description
Root cause
The current commercial-readiness audit computes unresolved_gaps from capability-manifest evidence that has not reached target_maturity. It does not independently represent canonical buyer-visible gaps whose registered core capability may already have evidence at target maturity.
Protected main can therefore report 22/22 capabilities, configured weighted maturity 100%, and unresolved buyer gaps: 0 while live repository state still contains accepted incomplete customer/operator journeys such as:
- Add complete tenant export and deletion orchestration #55 — complete tenant export/deletion productization
- Add durable Today workspace synchronization with optimistic concurrency #121 — durable multi-device Today synchronization/conflict recovery
- Add encrypted per-user calendar credential lifecycle and provider selection #129 — hosted encrypted per-user calendar credential lifecycle
- Complete plugin installation, secrets, and outbound delivery trust boundary #130 — plugin installation/secrets/SSRF-safe outbound delivery
The defect is semantic: configured capability-evidence maturity and whole-product gap exhaustion are currently collapsed into one claim.
Narrow deterministic design
Add a small repository-owned versioned buyer-gap registry (preferred over scraping arbitrary issue text) and reconcile it with the already bounded/paginated GitHub issue snapshot.
Suggested contract shape, subject to test-first refinement:
{
"schema": "life-os.commercial-buyer-gaps.v1",
"gaps": [
{
"gap_id": "today_multi_device_sync",
"issue_number": 121,
"capability_ids": ["today.action-loop", "planning.durable-data"]
}
]
}Rules:
gap_idis stable, unique, bounded, repository-owned policy data.issue_numberpoints to one canonical GitHub issue; issue title/body is not executable policy.capability_idsmust exist in the validated capability manifest but do not downgrade the configured maturity calculation by themselves.- The bounded GitHub snapshot supplies current issue state for registered issue numbers.
- A registered canonical issue that is
openproduces an unresolved buyer gap. - A registered issue closed as completed/duplicate/not-planned is no longer unresolved; the registry entry may remain for lineage or be superseded by another explicit entry.
- Missing registered issue evidence fails closed or reports
gap_state_unknown; it must never silently become resolved. - Unregistered ordinary GitHub issues do not automatically become product policy.
- Report output clearly separates:
- configured capability evidence at target / weighted maturity;
- unresolved canonical buyer gaps;
- unknown gap-state evidence, if any.
- The living issue LifeOS commercial readiness #21 rendering must not say
unresolved buyer gaps: 0while any canonical registered gap remains open.
This keeps offline capability auditing deterministic while allowing the GitHub-backed report to make a defensible whole-product gap claim.
Required outcome
Make the commercial-readiness report distinguish configured capability-evidence maturity from whole-product buyer-gap exhaustion. Never render zero whole-product gaps merely because every registered evidence probe exists while repository-owned canonical gaps remain open.
Acceptance evidence
- RED regression using a manifest whose capabilities all reach target while a registered canonical gap issue is open; expected report still contains that unresolved gap.
- RED regression for missing/unknown registered issue evidence; it cannot be treated as resolved.
- Closed completed/duplicate/not-planned canonical issues no longer count as unresolved, with deterministic supersession handling.
- Schema rejects duplicate
gap_id, duplicate canonical issue ownership where ambiguous, unknowncapability_ids, numeric/string/path abuse, oversized collections, and malformed external snapshot evidence. - GitHub snapshot remains bounded/paginated and retains no raw review/issue body as executable policy.
audit.mjscontinues to compute configured capability maturity exactly as before, but returns separately named product-gap evidence.render.mjs, issue LifeOS commercial readiness #21 synchronization, PRD/traceability and tests use the separated terminology consistently.- Register current canonical gaps Add complete tenant export and deletion orchestration #55, Add durable Today workspace synchronization with optimistic concurrency #121, Add encrypted per-user calendar credential lifecycle and provider selection #129 and Complete plugin installation, secrets, and outbound delivery trust boundary #130 without claiming unregistered issues are automatically product gaps.
- Existing symlink/path/size/security boundaries remain intact.
- Exact 100% owned production statement/branch/function/line coverage remains meaningful.
- Exact-head CI, AppGuardrail, SAST Semgrep, Security Scan, Commercial Readiness, CodeRabbit and all actionable review findings pass before merge.
Migration / compatibility
Treat the new registry/report fields as additive versioned evidence. Existing capability IDs and maturity targets keep their current meaning; do not silently reinterpret target_maturity as a promise that all downstream buyer journeys are complete.
Refs #21, #55, #121, #129, #130, and documentation baseline PR #126.
Activity