← all audits

What is wrong with the spec

Contradictions, impossible requirements and rules that block work without protecting anyone.

OSL full-spec logic audit

Audit date: 2026-08-16. Code basis: local canonical branch integration/full at 4d13b8a04f48767eb9c72c2432ae9ef01caf814a. Plan basis: all 4,597 numbered task blocks in OSL-AUDITS/todo/[0-9][0-9]-*.txt, all 72 rendered design pages, and the owner rulings through D68.

Headline

The spec's main poison is that V1 is defined as an all-or-nothing proof of several products at once, so one honest unavailable carrier, one deferred feature, or one stale proof task can prevent the working core from ever shipping. [01-FULL-SPEC.md:364-384; TASK 7791]

Bottom line

There is no literal dependency cycle in the 4,597-task gates: graph. The circularity is in status and acceptance: failed tasks remain checked, decisions wait for the implementation they authorized, and superseded behavior remains a prerequisite of the final gate. The result can be permanently red where the product is honest, and falsely green where the proof is known not to have happened. [TASK 7200; TASK 4402; TASK 7791]

The release should be reduced to a product that can be exercised end to end: account creation and recovery, native direct messages, one external chat carrier, one mail carrier, and attended Scrub. A carrier becomes actionable only after real proof on the exact artifact. Everything else can remain visible as unavailable or be deferred. This preserves the two non-negotiable lines: never contact a real third party, and never report a proof that did not happen. [RULING D38; 01-FULL-SPEC.md:236,340,368]

Findings ranked by development cost

1. The V1 release gate forbids an honest partial release

Type: contradiction / circular release gate.

“A carrier is included in the release UI as actionable only when its real two-identity insertion/readback/receive evidence matches the exact artifact; otherwise the same V1 specification requires honest unavailable/refusal state.” [01-FULL-SPEC.md:368]
“The generated ledger reports 61 satisfied, 0 partial and 0 unmet; all 13 carrier rows have named live receipts.” [TASK 7791, todo/49-native-surfaces-release.txt:322-335]

The first clause says an unproved carrier may ship honestly unavailable. The second says any unavailable carrier makes release fail. TASK 7786 also feeds the excluded X carrier into the final chain through TASK 7765, while the spec says X is design-only and outside V1. [01-FULL-SPEC.md:376; TASK 7786, todo/49-native-surfaces-release.txt:185-186]

This is the largest time sink because every unfinished carrier blocks every working carrier and the native product. It also turns a truthful “unavailable” state into a release failure, even though that state prevents a false claim.

Recommendation: REWRITE. Release the core and promote carriers independently. Require real stored-row/readback/receive proof before a carrier becomes actionable; do not require deferred or unavailable carriers to release the rest.

2. V1 is a private messenger, a Discord replacement, a social network, a cleanup product, and a payment system

Type: dead weight / over-constraint.

OSL Chats V1 includes “voice, screen sharing, channels, threads, forums, events, stage voice, customizable roles, moderation, signed participant bots, profiles, stories, and chosen-audience posts.” [01-FULL-SPEC.md:21,367]
V1 also includes every external carrier, attended Scrub, AutoScrub, data packs, and voucher purchase. [01-FULL-SPEC.md:368-370]

TASK 7783 alone requires real E2EE voice, screen share, a shared browser, stage voice, forums, events, bots, a Discord bridge, and AutoMod before the final release gate. [TASK 7783, todo/49-native-surfaces-release.txt:101-125; TASK 7791]

None of those features is needed to prove that account recovery, native direct messaging, one carrier transaction, and attended cleanup work. Making all of them V1 prevents focused end-to-end testing of the product's reason to exist.

Recommendation: DEFER. V1 should contain recovery, native DM, one proved chat carrier, one proved mail carrier, and attended Scrub. Defer groups beyond basic chat, Enclaves, profiles, posts, stories, beacons, forums, events, voice/stage, screen sharing, bots, AutoMod, remaining carriers, AutoScrub, and payments.

3. The task status model cannot represent a known failure

Type: circular gate / false proof.

TASK 7200 [x] is followed by: “untick: ... Not one gate was executed ... 3,239 rows all NOT RUNNABLE HERE.” [TASK 7200, todo/39-unfailable-gates.txt:89-100]

A mechanical read finds 156 task blocks whose heading remains [x] after an untick: says the proof was rejected. TASK 4757 is another direct example: it is checked, then says its proof used a deterministic in-memory classifier instead of the real privacy study. [TASK 4757, todo/22-discovery.txt:193-208]

Later gates consume the checked heading, not the owner-approved failure. A task can therefore be both complete and explicitly not complete. This is not administrative untidiness; it permits a release proof that the plan itself says did not happen.

Recommendation: REWRITE. Give every task one current machine-readable status. An owner-approved untick must make it open. Keep old ticks and proofs as history, never as the status consumed by gates.

4. Windows AI Covertext is required by tasks but absent from the Windows binary

Type: contradiction / untestable requirement / false proof.

“The canonical Windows artifact is therefore built WITHOUT it ... no amount of Windows-side testing will reach it.” [RULING D66, RULINGS.txt:2864-2879]
TASK 3524 requires Windows UIA to invoke AI Covertext 20 times with the local model pack and repeats until Liam passes it. [TASK 3524, todo/12-final-audit.txt:620-628]
TASK 6332 requires the installed AI button to work for every release carrier at three message lengths. [TASK 6332, todo/12-final-audit.txt:8267-8276]

The full spec gets this right: the Windows feature is absent and must not be advertised. [01-FULL-SPEC.md:17,330,377] The task corpus still requires the impossible Windows proof and keeps older shipping-AI tasks checked. TASK 3522 also says the writer receives message-derived “length and shape,” while TASK 6332 calls that a direct contradiction and forbids length, shape, or required capacity reaching the writer; both are checked and 6332 gates on 3522. [TASK 3522, todo/12-final-audit.txt:572-580; TASK 6332, todo/12-final-audit.txt:8267-8276]

Recommendation: DEFER. Keep only D66's Linux real-model library proof. Hide or explicitly disable AI Covertext in Windows. Remove every Windows AI task from V1 until the exact Windows artifact contains the writer; never substitute a template path and call that proof of the model.

5. UI authority requires a page both to match and to reject the design

Type: contradiction / over-constraint.

“The shipping UI uses ... only six semantic accents ... 0–3 px radius ... no shadows or gradients. Where current design pages use larger radii, filled cyan buttons, shadows, or gradients, this bar wins.” [01-FULL-SPEC.md:302; TASK 0118]
“Rendered geometry, structure, computed text, interaction state, and route behavior ... are compared to the correct design page ... A page with missing reference, wrong route, or wrong interaction fails.” [01-FULL-SPEC.md:304; RULING D26]

The rendered Scrub authority itself uses danger #e5383b, outside the six-color task palette, while the spec's danger token is #e05656. [DESIGN Scrub.dc.html:125; 01-FULL-SPEC.md:302] A faithful design match therefore violates the palette gate, while a palette-compliant page violates parity.

D26 also says a missing design is a failure, while D65 says five routes with no design page ship and are not parity work. [RULING D26, RULINGS.txt:1529-1551; RULING D65, RULINGS.txt:2844-2857; 01-FULL-SPEC.md:304,356]

Recommendation: REWRITE. The rendered design wins where it exists. Palette tokens are defaults only where the design is silent. Explicitly exempt D65's five routes from visual parity and keep behavioral tests for them.

6. AutoScrub's final gate requires behavior the controlling safety rule forbids

Type: contradiction / circular gate.

“AutoScrub finds possible matches for review; it does not delete them automatically.” [TASK 6093; 01-FULL-SPEC.md:260]
TASK 7785: “Wire ... AutoScrub ... to ... real provider deleters,” and fail if a run deletes zero. [TASK 7785, todo/49-native-surfaces-release.txt:157-181]

The spec says TASK 6093 supersedes the deletion product and says TASK 7785 conflicts with it. [01-FULL-SPEC.md:260-262] TASK 7791 nevertheless gates directly on 7785. [TASK 7791, todo/49-native-surfaces-release.txt:322-324]

The current canonical UI still says “Discovery + deletion, reviewed batches,” and the Pro consent path filters only Discord accounts. [CODE integration/full:apps/osl-hub-ui/src/scrub-discovery-screen.ts:429-450,503-525] This is both a release contradiction and a misleading product surface.

Recommendation: REWRITE. Scheduled AutoScrub ends at a review finding. Replace TASK 7785 in the final gate with TASK 6093. Any deletion remains a fresh, attended, exact-message Scrub decision.

7. Blanket “acceptance hardening” multiplied proof work without proving the product

Type: over-constraint / self-defeating gate.

“403 tasks carry the acceptance-hardening clause ... 378 of them are ticked and 301 ... have evidence mentioning neither a Windows capture tool nor a colour count.” [TASK 7106, todo/38-reverification.txt:261-271]

The repeated clause demands a shipping Windows capture, live signed-in account behavior, a production handler, UI Automation, and at least 32 decoded colors even for tasks whose subject is copy or a decision. TASK 1410, nominally “confirm consent wording,” now also demands a live real-account scan, deletion, scheduled run, provider refresh, UIA interaction, and image-color proof. [TASK 1410, todo/08-scrub-website-release.txt:139-148]

The clause did not strengthen the old evidence: it created hundreds of checked tasks whose proof predates the new bar. It also mixes visual nonblankness with backend correctness and forces unrelated features to be present before wording can be accepted.

Recommendation: CUT. Remove the blanket retrofit. Keep targeted exact-artifact tests for real send/readback, destructive actions, recovery, crypto, payment if it later ships, and the two non-negotiables. Use ordinary component or UI tests for ordinary copy and layout.

8. Universal future-carrier self-healing has no finite finish line

Type: untestable requirement / over-constraint.

“Every screen-driven carrier must detect behavioral and appearance drift, repair only a proved variant, and refuse visibly...” [01-FULL-SPEC.md:328]

The safe part is exact account, conversation, recipient, composer, and stored-row proof. The poisoned part is requiring automatic detection and repair of unknown future carrier changes. No current test can enumerate future layouts or prove that every unseen variant will be repaired. [RULING D30; 01-FULL-SPEC.md:98,226,328]

The task corpus compounds this with carrier proofs that remain blocked indefinitely when login or a human check prevents automation. TASK 1410 shows the repeated “stays blocked until a dated artifact” form. [TASK 1410, todo/08-scrub-website-release.txt:148]

Recommendation: REWRITE. Keep exact-target proof, stored-row readback, and fail-closed refusal. Test named carrier versions and settings. Defer automatic repair of unknown variants; ship compatibility updates after a new variant is measured.

9. Scrub is specified as a real provider reader but the reachable command fabricates a registry-only success

Type: spec/reality gap / false proof risk.

“It reads messages through real provider readers ... streams findings locally ... [and] the person ... sees the exact provider message.” [01-FULL-SPEC.md:258; TASK 7784]

The canonical read_scrub_discovery_page command does not read provider content. It looks up an account in the local registry, then returns readable: 1, exposures: 0, complete: true; its own comment calls this “registry-only discovery.” [CODE integration/full:apps/osl-hub/src/main.rs:1366-1396] The UI converts that fabricated count into “1 items readable,” “0 exposures look public,” and a safe-toned completion line. [CODE integration/full:apps/osl-hub-ui/src/scrub-discovery-screen.ts:357-407] That is an unearned proof, not a truthful zero.

The checked task's own evidence admits there was no provider login, cookie, or token, says it “does not claim that provider content was read,” and leaves the browser/profile/provider run unchecked. [TASK 7784; evidence/7784.md:47-49,61-66; todo/49-native-surfaces-release.txt:129] The task status therefore claims completion while its evidence disclaims the feature.

The protocol cannot carry the evidence the spec requires. Its request contains only account ID and cursor; its response contains only account ID, source, aggregate counts, completion, and next cursor. There is no provider message ID, content, location, or finding row to open, review, or delete. [CODE integration/full:apps/osl-hub/src/main.rs:2721-2737; CODE integration/full:apps/osl-hub-ui/src/scrub-discovery-screen.ts:248-278] TASK 7994 nevertheless requires every returned row to carry a provider message ID that resolves in the real account. [TASK 7994, todo/57-the-capabilities-nobody-built.txt:105-115]

The shared service catalogue requires eight service kinds—Discord, Telegram, WhatsApp, Instagram, X, Messenger, Email, and Signal—but Scrub's active contracts and fixtures repeatedly narrow behavior to Discord, Telegram, and Email, while AutoScrub consent narrows again to Discord only. [CODE integration/full:apps/osl-hub/tests/task_7754_linked_service_catalogue.rs:16-27; CODE integration/full:apps/osl-hub-ui/src/scrub-plan.test.ts:6-29; CODE integration/full:apps/osl-hub-ui/src/scrub-discovery-screen.ts:441-444]

The rendered Scrub page separately advertises Discord, Gmail, Outlook, X, and Reddit accounts. [DESIGN Scrub.dc.html:110-137] There is no one coherent Scrub source roster.

Recommendation: REWRITE. For V1 expose only sources with a real reader. Replace the aggregate IPC with exact finding rows for one provider. Return a truthful unavailable/error state for registry-only accounts. Do not count a configured account as one readable item. Add sources one at a time after a real nonempty read and exact-message review proof.

10. The cover-detection gate is both failed and quantified over an undefined adversary

Type: untestable requirement / false completion.

“Every MACHINE method ... and any service moderation signal ... must not exceed 50 PERCENT recognition.” [TASK 0073, todo/01-foundation.txt:1020-1039]
The recorded result is 100/100 accuracy=100.00%, which D37 says is total separation and must not ship under a camouflage claim. [RULING D37, RULINGS.txt:1888-1913]

The phrase “every machine method” has no finite model/version/corpus boundary. A classifier trained on the exact generator can always be added after the test. TASK 0073 is also still checked despite its own untick: saying the setting must change, and TASK 0073b still tests the superseded five-percent bound. [TASK 0073/0073b, todo/01-foundation.txt:1020-1051]

TASK 6030 expands this into every writer × mode × language × five lengths × benign/adversarial classes, at least 69 seeds per stratum, 50 participants per candidate, and a wholly fresh study after one breach. [TASK 6030, todo/12-final-audit.txt:8064-8086] At the minimum one-writer/one-mode/one-language matrix, that is already 34,500 candidate-participant judgments before coder review.

Recommendation: REWRITE. Keep the current 100% result red and remove any claim that wordbank cover evades moderation. Define a fixed versioned corpus, named baseline classifiers, held-out split, and repeatable command. Defer population-scale human certification and AI cover with the AI feature.

11. TASK 1619 cannot comply with either unsigned shipping or the no-third-party rule

Type: contradiction / impossible evidence.

“the release installer is the exact signed artifact under test.” [TASK 1619, todo/08-scrub-website-release.txt:1920-1928]
“This release ships unsigned.” [01-FULL-SPEC.md:344,379; TASK 1603]

TASK 1619 also says to send the installer to a real friend. D38 says never message anyone who is not the owner and expressly excludes a friend. [TASK 1619, todo/08-scrub-website-release.txt:1927; RULING D38, RULINGS.txt:1923-1927]

“Signed artifact” is also used ambiguously elsewhere for an offline-signed manifest, even though the executable is not Authenticode-signed. [TASK 1603, todo/08-scrub-website-release.txt:1707-1716]

Recommendation: CUT. Delete TASK 1619. Run the exact unsigned installer in an owner-controlled clean Windows VM or Sandbox and verify its SHA-256 plus offline-signed manifest. Never contact a friend or other third party.

12. Decisions are parked behind the implementation that the decision authorized

Type: circular gate.

“ALL SEVEN open groups B1 to B7 are YES ... This task STAYS OPEN ... [because] shipping-build=not-run.” [TASK 4402, todo/16-eye-and-switch-on.txt:75-90]

TASK 7450 later built the missing shipping exercise and is checked, but implementation TASK 4404 still gates on the deliberately open decision TASK 4402. [TASK 7450, todo/45-ship-the-observers.txt:57-68; TASK 4404, todo/16-eye-and-switch-on.txt:116-130]

TASK 1410 has the same shape. The owner ruled its consent wording passed, D64 says the task is settled, and D64(a) confirms all four facts are present; TASK 1410 remains open because unrelated live scan/delete/schedule hardening was appended to it. [RULING D64/D64(a), RULINGS.txt:2824-2842,2957-2977; TASK 1410]

Recommendation: REWRITE. A decision task closes when the named decision is made. Gate the implementation on the decision and gate release on the later behavior test. Mark TASK 4402 and TASK 1410 settled; do not make their answer depend on downstream implementation.

13. Release-limit copy is wired to a dead onboarding route and required byte-for-byte everywhere

Type: over-constraint / spec leakage into product.

“Independent self-service installation and friend setup have not been validated; setup may require support.” [TASK 6334, todo/13-receive.txt:3138-3151]

TASK 6334 asks for that release-status sentence on installation/friend-setup help surfaces and in release disclosure. The implementation contains a mount at the start of the onboarding apps page, before that page's own heading. [CODE integration/full:apps/osl-hub-ui/src/shipping-limit-disclosures.ts:5-24; CODE integration/full:apps/osl-hub-ui/src/main.ts:2642-2643]

The test then freezes onboarding-shell as the required location. [CODE integration/full:apps/osl-hub-ui/src/task_6334_shipping_limits.test.ts:17,55,80] TASK 6334b requires throwaway builds for every missing, paraphrased, clipped, contradictory, and omitted-surface variation. [TASK 6334b, todo/13-receive.txt:3153-3161]

TASK 6334 is checked even though its own evidence says installed Windows/UIA acceptance was unavailable, makes no claim that the disclosure was observed there, and leaves the finish line unchecked. [evidence/6334.md:63-80,94-103; TASK 6334] TASK 6334b likewise tested source and copy mutations without installed UIA observation. [evidence/6334b.md:38-57; TASK 6334b]

The reported current overlap cannot be established on canonical integration/full: the apps route is redirected to detected before render, so the mount is dead in the current route graph. [CODE integration/full:apps/osl-hub-ui/src/first-run-spine.ts:55-72] The checked test proves only that the helper and interpolation text exist in source; it does not prove that the shipping screen renders the disclosure. [CODE integration/full:apps/osl-hub-ui/src/task_6334_shipping_limits.test.ts:43-62,77-86] An older artifact may show the title overlap, but no current exact-artifact receipt establishing that was found.

The truth matters; leaking release-status prose into a fixed onboarding layout does not. Exact punctuation on every surface buys no additional protection.

Recommendation: REWRITE. Keep the fact in release limits and reachable setup help. Remove it from the onboarding page body. Test that the limitation is stated plainly and that the product never claims validated unaided setup; do not require byte identity or duplicate mutation campaigns.

14. “No maximum” Enclaves is not a testable product promise

Type: untestable requirement.

“Enclaves have no maximum member count.” [TASK 6576, todo/24-enclaves-beacons-roles.txt:333; 01-FULL-SPEC.md:244]
The acceptance bar requires admission above measured N to succeed and forbids calling N a cap. [TASK 6587, todo/24-enclaves-beacons-roles.txt:663-670; TASK 6586, todo/30-owner-rulings.txt:15-16]

Every machine, identifier space, relay, and storage system is finite. Testing N and one generated value above N cannot prove there is no maximum or that every larger removal completes.

Recommendation: REWRITE. Say OSL has no arbitrary marketing cap, publish the largest measured supported size, show cost/progress above the fast threshold, and refuse honestly when capacity is exhausted. Never report removal complete while a removed member still has new-key access.

15. Onboarding forbids preselection while also defining defaults

Type: contradiction / needless setup friction.

“Explicitly choose Tor or Direct; there is no preselected switch. The current task proof says Tor became the default.” [01-FULL-SPEC.md:214]
“Choose whether old messages stay locked forever or stay readable; locked forever is the ruled default.” [01-FULL-SPEC.md:215]
“Choose exactly one of Clipboard, Double Enter, or Single Enter. Nothing is preselected.” [01-FULL-SPEC.md:216; RULING D42]

A setting cannot be both an operational default and not selected. For Tor and old-message policy, forcing a choice adds onboarding work but does not prevent harm. The send triggers are different: Single/Double Enter can cause an unintended send and deserve explicit acknowledgement. [RULING D42, RULINGS.txt:2012-2016; 01-FULL-SPEC.md:216]

Recommendation: REWRITE. Use visible recommended defaults for Tor/Direct and old-message policy, changeable later. Require explicit acknowledgement only for automatic send triggers.

16. The public-name validator has two incompatible authorities

Type: contradiction.

The final design says 3–30 lowercase letters/numbers; the earlier ruling says 1–16 letters/numbers/underscore. [01-FULL-SPEC.md:320]

The spec correctly admits that this collision is unresolved, but leaving it unresolved means the client, server, recovery flow, and uniqueness registry cannot share one validator. [RULING 11, RULINGS.txt:82-83; RULING D47, RULINGS.txt:2372-2376]

Recommendation: REWRITE. Adopt the later specific D47 contract now: lowercase letters, digits, underscore, 3–30 characters, exact lookup. Use one shared validator and migration rule.

17. Absolute payment unlinkability is stronger than the observable payment journey

Type: over-constraint / untestable requirement / dead weight.

A purchase produces a voucher that “must not be linkable by OSL to the purchase,” while the product must expose confirmations, underpayment, overpayment, failures, and refunds. [01-FULL-SPEC.md:282,348]

The canonical code is only an in-memory model and labels packs “/month”; no Card, BTC, or XMR rail is established. [01-FULL-SPEC.md:284,346]

It is possible to separate payment and account identifiers, but absolute non-linkability cannot be proved when one service observes a rare payment, voucher issuance, network timing, and immediate redemption. The absolute claim is unnecessary; the useful rule is no stable account/payment join and no false privacy claim.

Recommendation: DEFER. Remove payment rails from V1. Later require separate data stores/services, no OSL account identifier in payment records, short retention, minimized logs, and an honest timing/network-correlation disclosure. Do not claim absolute unlinkability.

18. Low-value V1 detail is consuming release attention

Type: dead weight.

Window and Sounds requires three reopen modes and four named sounds, each with Preview. [01-FULL-SPEC.md:275]
Every user-facing string must be externalized although V1 ships English only. [01-FULL-SPEC.md:354]
Five behavior-only routes ship without designs. [01-FULL-SPEC.md:356; RULING D65]

These do not prevent user harm or a false claim, and they do not establish protected messaging, recovery, carrier put/get, or Scrub. They are valid later product work, not V1 closure.

Recommendation: DEFER. Keep basic accessible settings and error text. Move sound variants, reopen-mode breadth, full localization plumbing, and undesigned secondary routes behind the working end-to-end release.

Requirements to keep

These pass the owner's stated bar because they stop direct harm or stop OSL shipping a lie:

Recommended V1 finish line

One exact unsigned Windows artifact passes these journeys on owner-controlled identities and accounts:

1. Fresh install, create account, save and verify recovery material, restart, sign in, recover, and reach Home. [TASK 5193; TASK 7757]

2. Two owner-controlled identities become friends, verify keys, exchange native text and one attachment, restart, and read the same history. [TASK 7780; RULING D38]

3. One chat carrier completes exact account/conversation proof, protected insertion, provider stored-row readback, receive, authentication, and local reveal. [01-FULL-SPEC.md:69-82,226-232]

4. One mail carrier completes the same put/get path with honest email deletion limits. [01-FULL-SPEC.md:150-200; RULING D25]

5. Attended Scrub reads one real approved nonempty source, shows exact findings, stops/resumes, and deletes only one exact sender-owned message after a fresh confirmation and provider recheck. AutoScrub, if present, finds only. [01-FULL-SPEC.md:258-262; TASK 6093; TASK 7784]

6. Every unavailable carrier and deferred feature is absent or visibly unavailable, and no release copy claims it passed. [01-FULL-SPEC.md:236,340,368,384]

That finish line tests the working product. It preserves the real safety boundaries and removes proof work that neither prevents harm nor prevents a lie.